* Parse DTD internal subset with validation. * Validates whitespace requirements per XML 1.0 spec.
()
| 201 | * Validates whitespace requirements per XML 1.0 spec. |
| 202 | */ |
| 203 | function parseDTDInternalSubset(): void { |
| 204 | while (pos < len) { |
| 205 | const code = input.charCodeAt(pos); |
| 206 | |
| 207 | if (code === CC_RBRACKET) { |
| 208 | pos++; |
| 209 | return; // End of internal subset |
| 210 | } |
| 211 | |
| 212 | if (isWhitespace(code)) { |
| 213 | // Batch-skip whitespace for better performance |
| 214 | skipWhitespace(); |
| 215 | continue; |
| 216 | } |
| 217 | |
| 218 | if (code === CC_LT) { |
| 219 | pos++; |
| 220 | if (pos >= len) { |
| 221 | error("Unexpected end of input in DTD"); |
| 222 | } |
| 223 | |
| 224 | const nextCode = input.charCodeAt(pos); |
| 225 | if (nextCode === CC_BANG) { |
| 226 | pos++; |
| 227 | parseDTDMarkupDeclaration(); |
| 228 | } else if (nextCode === CC_QUESTION) { |
| 229 | pos++; |
| 230 | // Processing instruction in DTD |
| 231 | while (pos < len) { |
| 232 | if ( |
| 233 | input.charCodeAt(pos) === CC_QUESTION && |
| 234 | pos + 1 < len && |
| 235 | input.charCodeAt(pos + 1) === CC_GT |
| 236 | ) { |
| 237 | pos += 2; |
| 238 | break; |
| 239 | } |
| 240 | pos++; |
| 241 | } |
| 242 | } else { |
| 243 | error(`Unexpected character '${input[pos]}' after '<' in DTD`); |
| 244 | } |
| 245 | continue; |
| 246 | } |
| 247 | |
| 248 | if (code === CC_LBRACKET) { |
| 249 | // Conditional sections are not allowed in internal subset |
| 250 | error( |
| 251 | "Conditional sections (INCLUDE/IGNORE) are not allowed in internal DTD subset", |
| 252 | ); |
| 253 | } |
| 254 | |
| 255 | // Parameter entity reference: %name; |
| 256 | // These are valid in internal subset and must be skipped |
| 257 | if (code === CC_PERCENT) { |
| 258 | pos++; |
| 259 | while (pos < len) { |
| 260 | const c = input.charCodeAt(pos); |
no test coverage detected