parse5 7.1.1 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/dist/cjs/common/doctype.d.ts +0 -1
  2. package/dist/cjs/common/doctype.js +2 -4
  3. package/dist/cjs/common/error-codes.d.ts +1 -2
  4. package/dist/cjs/common/error-codes.js +1 -2
  5. package/dist/cjs/common/foreign-content.d.ts +0 -1
  6. package/dist/cjs/common/foreign-content.js +7 -9
  7. package/dist/cjs/common/html.d.ts +32 -31
  8. package/dist/cjs/common/html.js +41 -42
  9. package/dist/cjs/common/token.d.ts +1 -2
  10. package/dist/cjs/common/token.js +3 -4
  11. package/dist/cjs/common/unicode.d.ts +1 -8
  12. package/dist/cjs/common/unicode.js +7 -14
  13. package/dist/cjs/index.d.ts +2 -4
  14. package/dist/cjs/index.js +5 -6
  15. package/dist/cjs/parser/formatting-element-list.d.ts +1 -2
  16. package/dist/cjs/parser/formatting-element-list.js +1 -2
  17. package/dist/cjs/parser/index.d.ts +72 -8
  18. package/dist/cjs/parser/index.js +301 -119
  19. package/dist/cjs/parser/open-element-stack.d.ts +2 -2
  20. package/dist/cjs/parser/open-element-stack.js +98 -90
  21. package/dist/cjs/serializer/index.d.ts +1 -2
  22. package/dist/cjs/serializer/index.js +8 -9
  23. package/dist/cjs/tokenizer/index.d.ts +130 -131
  24. package/dist/cjs/tokenizer/index.js +89 -282
  25. package/dist/cjs/tokenizer/preprocessor.d.ts +3 -4
  26. package/dist/cjs/tokenizer/preprocessor.js +10 -8
  27. package/dist/cjs/tree-adapters/default.d.ts +4 -5
  28. package/dist/cjs/tree-adapters/default.js +9 -10
  29. package/dist/cjs/tree-adapters/interface.d.ts +7 -2
  30. package/dist/cjs/tree-adapters/interface.js +0 -1
  31. package/dist/common/doctype.d.ts +0 -1
  32. package/dist/common/doctype.js +0 -1
  33. package/dist/common/error-codes.d.ts +1 -2
  34. package/dist/common/error-codes.js +1 -2
  35. package/dist/common/foreign-content.d.ts +0 -1
  36. package/dist/common/foreign-content.js +0 -2
  37. package/dist/common/html.d.ts +32 -31
  38. package/dist/common/html.js +38 -38
  39. package/dist/common/token.d.ts +1 -2
  40. package/dist/common/token.js +1 -2
  41. package/dist/common/unicode.d.ts +1 -8
  42. package/dist/common/unicode.js +1 -8
  43. package/dist/index.d.ts +2 -4
  44. package/dist/index.js +1 -3
  45. package/dist/parser/formatting-element-list.d.ts +1 -2
  46. package/dist/parser/formatting-element-list.js +1 -2
  47. package/dist/parser/index.d.ts +72 -8
  48. package/dist/parser/index.js +302 -120
  49. package/dist/parser/open-element-stack.d.ts +2 -2
  50. package/dist/parser/open-element-stack.js +99 -91
  51. package/dist/serializer/index.d.ts +1 -2
  52. package/dist/serializer/index.js +6 -6
  53. package/dist/tokenizer/index.d.ts +130 -131
  54. package/dist/tokenizer/index.js +90 -283
  55. package/dist/tokenizer/preprocessor.d.ts +3 -4
  56. package/dist/tokenizer/preprocessor.js +10 -8
  57. package/dist/tree-adapters/default.d.ts +4 -5
  58. package/dist/tree-adapters/default.js +9 -10
  59. package/dist/tree-adapters/interface.d.ts +7 -2
  60. package/dist/tree-adapters/interface.js +0 -1
  61. package/package.json +4 -4
@@ -1,39 +1,9 @@
1
1
  import { Preprocessor } from './preprocessor.js';
2
2
  import { CODE_POINTS as $, SEQUENCES as $$, REPLACEMENT_CHARACTER, isSurrogate, isUndefinedCodePoint, isControlCodePoint, } from '../common/unicode.js';
3
3
  import { TokenType, getTokenAttr, } from '../common/token.js';
4
- import { htmlDecodeTree, BinTrieFlags, determineBranch } from 'entities/lib/decode.js';
4
+ import { htmlDecodeTree, EntityDecoder, DecodingMode } from 'entities/lib/decode.js';
5
5
  import { ERR } from '../common/error-codes.js';
6
6
  import { TAG_ID, getTagID } from '../common/html.js';
7
- //C1 Unicode control character reference replacements
8
- const C1_CONTROLS_REFERENCE_REPLACEMENTS = new Map([
9
- [0x80, 8364],
10
- [0x82, 8218],
11
- [0x83, 402],
12
- [0x84, 8222],
13
- [0x85, 8230],
14
- [0x86, 8224],
15
- [0x87, 8225],
16
- [0x88, 710],
17
- [0x89, 8240],
18
- [0x8a, 352],
19
- [0x8b, 8249],
20
- [0x8c, 338],
21
- [0x8e, 381],
22
- [0x91, 8216],
23
- [0x92, 8217],
24
- [0x93, 8220],
25
- [0x94, 8221],
26
- [0x95, 8226],
27
- [0x96, 8211],
28
- [0x97, 8212],
29
- [0x98, 732],
30
- [0x99, 8482],
31
- [0x9a, 353],
32
- [0x9b, 8250],
33
- [0x9c, 339],
34
- [0x9e, 382],
35
- [0x9f, 376],
36
- ]);
37
7
  //States
38
8
  var State;
39
9
  (function (State) {
@@ -109,13 +79,7 @@ var State;
109
79
  State[State["CDATA_SECTION_BRACKET"] = 69] = "CDATA_SECTION_BRACKET";
110
80
  State[State["CDATA_SECTION_END"] = 70] = "CDATA_SECTION_END";
111
81
  State[State["CHARACTER_REFERENCE"] = 71] = "CHARACTER_REFERENCE";
112
- State[State["NAMED_CHARACTER_REFERENCE"] = 72] = "NAMED_CHARACTER_REFERENCE";
113
- State[State["AMBIGUOUS_AMPERSAND"] = 73] = "AMBIGUOUS_AMPERSAND";
114
- State[State["NUMERIC_CHARACTER_REFERENCE"] = 74] = "NUMERIC_CHARACTER_REFERENCE";
115
- State[State["HEXADEMICAL_CHARACTER_REFERENCE_START"] = 75] = "HEXADEMICAL_CHARACTER_REFERENCE_START";
116
- State[State["HEXADEMICAL_CHARACTER_REFERENCE"] = 76] = "HEXADEMICAL_CHARACTER_REFERENCE";
117
- State[State["DECIMAL_CHARACTER_REFERENCE"] = 77] = "DECIMAL_CHARACTER_REFERENCE";
118
- State[State["NUMERIC_CHARACTER_REFERENCE_END"] = 78] = "NUMERIC_CHARACTER_REFERENCE_END";
82
+ State[State["AMBIGUOUS_AMPERSAND"] = 72] = "AMBIGUOUS_AMPERSAND";
119
83
  })(State || (State = {}));
120
84
  //Tokenizer initial states for different modes
121
85
  export const TokenizerMode = {
@@ -145,27 +109,33 @@ function isAsciiLetter(cp) {
145
109
  function isAsciiAlphaNumeric(cp) {
146
110
  return isAsciiLetter(cp) || isAsciiDigit(cp);
147
111
  }
148
- function isAsciiUpperHexDigit(cp) {
149
- return cp >= $.LATIN_CAPITAL_A && cp <= $.LATIN_CAPITAL_F;
150
- }
151
- function isAsciiLowerHexDigit(cp) {
152
- return cp >= $.LATIN_SMALL_A && cp <= $.LATIN_SMALL_F;
153
- }
154
- function isAsciiHexDigit(cp) {
155
- return isAsciiDigit(cp) || isAsciiUpperHexDigit(cp) || isAsciiLowerHexDigit(cp);
156
- }
157
112
  function toAsciiLower(cp) {
158
113
  return cp + 32;
159
114
  }
160
115
  function isWhitespace(cp) {
161
116
  return cp === $.SPACE || cp === $.LINE_FEED || cp === $.TABULATION || cp === $.FORM_FEED;
162
117
  }
163
- function isEntityInAttributeInvalidEnd(nextCp) {
164
- return nextCp === $.EQUALS_SIGN || isAsciiAlphaNumeric(nextCp);
165
- }
166
118
  function isScriptDataDoubleEscapeSequenceEnd(cp) {
167
119
  return isWhitespace(cp) || cp === $.SOLIDUS || cp === $.GREATER_THAN_SIGN;
168
120
  }
121
+ function getErrorForNumericCharacterReference(code) {
122
+ if (code === $.NULL) {
123
+ return ERR.nullCharacterReference;
124
+ }
125
+ else if (code > 1114111) {
126
+ return ERR.characterReferenceOutsideUnicodeRange;
127
+ }
128
+ else if (isSurrogate(code)) {
129
+ return ERR.surrogateCharacterReference;
130
+ }
131
+ else if (isUndefinedCodePoint(code)) {
132
+ return ERR.noncharacterCharacterReference;
133
+ }
134
+ else if (isControlCodePoint(code) || code === $.CARRIAGE_RETURN) {
135
+ return ERR.controlCharacterReference;
136
+ }
137
+ return null;
138
+ }
169
139
  //Tokenizer
170
140
  export class Tokenizer {
171
141
  constructor(options, handler) {
@@ -185,18 +155,38 @@ export class Tokenizer {
185
155
  this.active = false;
186
156
  this.state = State.DATA;
187
157
  this.returnState = State.DATA;
188
- this.charRefCode = -1;
158
+ this.entityStartPos = 0;
189
159
  this.consumedAfterSnapshot = -1;
190
160
  this.currentCharacterToken = null;
191
161
  this.currentToken = null;
192
162
  this.currentAttr = { name: '', value: '' };
193
163
  this.preprocessor = new Preprocessor(handler);
194
164
  this.currentLocation = this.getCurrentLocation(-1);
165
+ this.entityDecoder = new EntityDecoder(htmlDecodeTree, (cp, consumed) => {
166
+ // Note: Set `pos` _before_ flushing, as flushing might drop
167
+ // the current chunk and invalidate `entityStartPos`.
168
+ this.preprocessor.pos = this.entityStartPos + consumed - 1;
169
+ this._flushCodePointConsumedAsCharacterReference(cp);
170
+ }, handler.onParseError
171
+ ? {
172
+ missingSemicolonAfterCharacterReference: () => {
173
+ this._err(ERR.missingSemicolonAfterCharacterReference, 1);
174
+ },
175
+ absenceOfDigitsInNumericCharacterReference: (consumed) => {
176
+ this._err(ERR.absenceOfDigitsInNumericCharacterReference, this.entityStartPos - this.preprocessor.pos + consumed);
177
+ },
178
+ validateNumericCharacterReference: (code) => {
179
+ const error = getErrorForNumericCharacterReference(code);
180
+ if (error)
181
+ this._err(error, 1);
182
+ },
183
+ }
184
+ : undefined);
195
185
  }
196
186
  //Errors
197
- _err(code) {
187
+ _err(code, cpOffset = 0) {
198
188
  var _a, _b;
199
- (_b = (_a = this.handler).onParseError) === null || _b === void 0 ? void 0 : _b.call(_a, this.preprocessor.getError(code));
189
+ (_b = (_a = this.handler).onParseError) === null || _b === void 0 ? void 0 : _b.call(_a, this.preprocessor.getError(code, cpOffset));
200
190
  }
201
191
  // NOTE: `offset` may never run across line boundaries.
202
192
  getCurrentLocation(offset) {
@@ -258,7 +248,8 @@ export class Tokenizer {
258
248
  //Hibernation
259
249
  _ensureHibernation() {
260
250
  if (this.preprocessor.endOfChunkHit) {
261
- this._unconsume(this.consumedAfterSnapshot);
251
+ this.preprocessor.retreat(this.consumedAfterSnapshot);
252
+ this.consumedAfterSnapshot = 0;
262
253
  this.active = false;
263
254
  return true;
264
255
  }
@@ -269,14 +260,6 @@ export class Tokenizer {
269
260
  this.consumedAfterSnapshot++;
270
261
  return this.preprocessor.advance();
271
262
  }
272
- _unconsume(count) {
273
- this.consumedAfterSnapshot -= count;
274
- this.preprocessor.retreat(count);
275
- }
276
- _reconsumeInState(state, cp) {
277
- this.state = state;
278
- this._callState(cp);
279
- }
280
263
  _advanceBy(count) {
281
264
  this.consumedAfterSnapshot += count;
282
265
  for (let i = 0; i < count; i++) {
@@ -448,7 +431,7 @@ export class Tokenizer {
448
431
  this.active = false;
449
432
  }
450
433
  //Characters emission
451
- //OPTIMIZATION: specification uses only one type of character tokens (one token per character).
434
+ //OPTIMIZATION: The specification uses only one type of character token (one token per character).
452
435
  //This causes a huge memory overhead and a lot of unnecessary parser loops. parse5 uses 3 groups of characters.
453
436
  //If we have a sequence of characters that belong to the same group, the parser can process it
454
437
  //as a single solid character token.
@@ -458,15 +441,15 @@ export class Tokenizer {
458
441
  //3)TokenType.CHARACTER - any character sequence which don't belong to groups 1 and 2 (e.g. 'abcdef1234@@#$%^')
459
442
  _appendCharToCurrentCharacterToken(type, ch) {
460
443
  if (this.currentCharacterToken) {
461
- if (this.currentCharacterToken.type !== type) {
444
+ if (this.currentCharacterToken.type === type) {
445
+ this.currentCharacterToken.chars += ch;
446
+ return;
447
+ }
448
+ else {
462
449
  this.currentLocation = this.getCurrentLocation(0);
463
450
  this._emitCurrentCharacterToken(this.currentLocation);
464
451
  this.preprocessor.dropParsedChunk();
465
452
  }
466
- else {
467
- this.currentCharacterToken.chars += ch;
468
- return;
469
- }
470
453
  }
471
454
  this._createCharacterToken(type, ch);
472
455
  }
@@ -484,59 +467,11 @@ export class Tokenizer {
484
467
  this._appendCharToCurrentCharacterToken(TokenType.CHARACTER, ch);
485
468
  }
486
469
  // Character reference helpers
487
- _matchNamedCharacterReference(cp) {
488
- let result = null;
489
- let excess = 0;
490
- let withoutSemicolon = false;
491
- for (let i = 0, current = htmlDecodeTree[0]; i >= 0; cp = this._consume()) {
492
- i = determineBranch(htmlDecodeTree, current, i + 1, cp);
493
- if (i < 0)
494
- break;
495
- excess += 1;
496
- current = htmlDecodeTree[i];
497
- const masked = current & BinTrieFlags.VALUE_LENGTH;
498
- // If the branch is a value, store it and continue
499
- if (masked) {
500
- // The mask is the number of bytes of the value, including the current byte.
501
- const valueLength = (masked >> 14) - 1;
502
- // Attribute values that aren't terminated properly aren't parsed, and shouldn't lead to a parser error.
503
- // See the example in https://html.spec.whatwg.org/multipage/parsing.html#named-character-reference-state
504
- if (cp !== $.SEMICOLON &&
505
- this._isCharacterReferenceInAttribute() &&
506
- isEntityInAttributeInvalidEnd(this.preprocessor.peek(1))) {
507
- //NOTE: we don't flush all consumed code points here, and instead switch back to the original state after
508
- //emitting an ampersand. This is fine, as alphanumeric characters won't be parsed differently in attributes.
509
- result = [$.AMPERSAND];
510
- // Skip over the value.
511
- i += valueLength;
512
- }
513
- else {
514
- // If this is a surrogate pair, consume the next two bytes.
515
- result =
516
- valueLength === 0
517
- ? [htmlDecodeTree[i] & ~BinTrieFlags.VALUE_LENGTH]
518
- : valueLength === 1
519
- ? [htmlDecodeTree[++i]]
520
- : [htmlDecodeTree[++i], htmlDecodeTree[++i]];
521
- excess = 0;
522
- withoutSemicolon = cp !== $.SEMICOLON;
523
- }
524
- if (valueLength === 0) {
525
- // If the value is zero-length, we're done.
526
- this._consume();
527
- break;
528
- }
529
- }
530
- }
531
- this._unconsume(excess);
532
- if (withoutSemicolon && !this.preprocessor.endOfChunkHit) {
533
- this._err(ERR.missingSemicolonAfterCharacterReference);
534
- }
535
- // We want to emit the error above on the code point after the entity.
536
- // We always consume one code point too many in the loop, and we wait to
537
- // unconsume it until after the error is emitted.
538
- this._unconsume(1);
539
- return result;
470
+ _startCharacterReference() {
471
+ this.returnState = this.state;
472
+ this.state = State.CHARACTER_REFERENCE;
473
+ this.entityStartPos = this.preprocessor.pos;
474
+ this.entityDecoder.startEntity(this._isCharacterReferenceInAttribute() ? DecodingMode.Attribute : DecodingMode.Legacy);
540
475
  }
541
476
  _isCharacterReferenceInAttribute() {
542
477
  return (this.returnState === State.ATTRIBUTE_VALUE_DOUBLE_QUOTED ||
@@ -839,37 +774,13 @@ export class Tokenizer {
839
774
  break;
840
775
  }
841
776
  case State.CHARACTER_REFERENCE: {
842
- this._stateCharacterReference(cp);
843
- break;
844
- }
845
- case State.NAMED_CHARACTER_REFERENCE: {
846
- this._stateNamedCharacterReference(cp);
777
+ this._stateCharacterReference();
847
778
  break;
848
779
  }
849
780
  case State.AMBIGUOUS_AMPERSAND: {
850
781
  this._stateAmbiguousAmpersand(cp);
851
782
  break;
852
783
  }
853
- case State.NUMERIC_CHARACTER_REFERENCE: {
854
- this._stateNumericCharacterReference(cp);
855
- break;
856
- }
857
- case State.HEXADEMICAL_CHARACTER_REFERENCE_START: {
858
- this._stateHexademicalCharacterReferenceStart(cp);
859
- break;
860
- }
861
- case State.HEXADEMICAL_CHARACTER_REFERENCE: {
862
- this._stateHexademicalCharacterReference(cp);
863
- break;
864
- }
865
- case State.DECIMAL_CHARACTER_REFERENCE: {
866
- this._stateDecimalCharacterReference(cp);
867
- break;
868
- }
869
- case State.NUMERIC_CHARACTER_REFERENCE_END: {
870
- this._stateNumericCharacterReferenceEnd(cp);
871
- break;
872
- }
873
784
  default: {
874
785
  throw new Error('Unknown state');
875
786
  }
@@ -885,8 +796,7 @@ export class Tokenizer {
885
796
  break;
886
797
  }
887
798
  case $.AMPERSAND: {
888
- this.returnState = State.DATA;
889
- this.state = State.CHARACTER_REFERENCE;
799
+ this._startCharacterReference();
890
800
  break;
891
801
  }
892
802
  case $.NULL: {
@@ -908,8 +818,7 @@ export class Tokenizer {
908
818
  _stateRcdata(cp) {
909
819
  switch (cp) {
910
820
  case $.AMPERSAND: {
911
- this.returnState = State.RCDATA;
912
- this.state = State.CHARACTER_REFERENCE;
821
+ this._startCharacterReference();
913
822
  break;
914
823
  }
915
824
  case $.LESS_THAN_SIGN: {
@@ -1678,8 +1587,7 @@ export class Tokenizer {
1678
1587
  break;
1679
1588
  }
1680
1589
  case $.AMPERSAND: {
1681
- this.returnState = State.ATTRIBUTE_VALUE_DOUBLE_QUOTED;
1682
- this.state = State.CHARACTER_REFERENCE;
1590
+ this._startCharacterReference();
1683
1591
  break;
1684
1592
  }
1685
1593
  case $.NULL: {
@@ -1706,8 +1614,7 @@ export class Tokenizer {
1706
1614
  break;
1707
1615
  }
1708
1616
  case $.AMPERSAND: {
1709
- this.returnState = State.ATTRIBUTE_VALUE_SINGLE_QUOTED;
1710
- this.state = State.CHARACTER_REFERENCE;
1617
+ this._startCharacterReference();
1711
1618
  break;
1712
1619
  }
1713
1620
  case $.NULL: {
@@ -1738,8 +1645,7 @@ export class Tokenizer {
1738
1645
  break;
1739
1646
  }
1740
1647
  case $.AMPERSAND: {
1741
- this.returnState = State.ATTRIBUTE_VALUE_UNQUOTED;
1742
- this.state = State.CHARACTER_REFERENCE;
1648
+ this._startCharacterReference();
1743
1649
  break;
1744
1650
  }
1745
1651
  case $.GREATER_THAN_SIGN: {
@@ -2235,7 +2141,7 @@ export class Tokenizer {
2235
2141
  this._emitEOFToken();
2236
2142
  break;
2237
2143
  }
2238
- default:
2144
+ default: {
2239
2145
  if (this._consumeSequenceIfMatch($$.PUBLIC, false)) {
2240
2146
  this.state = State.AFTER_DOCTYPE_PUBLIC_KEYWORD;
2241
2147
  }
@@ -2250,6 +2156,7 @@ export class Tokenizer {
2250
2156
  this.state = State.BOGUS_DOCTYPE;
2251
2157
  this._stateBogusDoctype(cp);
2252
2158
  }
2159
+ }
2253
2160
  }
2254
2161
  }
2255
2162
  // After DOCTYPE public keyword state
@@ -2755,37 +2662,35 @@ export class Tokenizer {
2755
2662
  }
2756
2663
  // Character reference state
2757
2664
  //------------------------------------------------------------------
2758
- _stateCharacterReference(cp) {
2759
- if (cp === $.NUMBER_SIGN) {
2760
- this.state = State.NUMERIC_CHARACTER_REFERENCE;
2761
- }
2762
- else if (isAsciiAlphaNumeric(cp)) {
2763
- this.state = State.NAMED_CHARACTER_REFERENCE;
2764
- this._stateNamedCharacterReference(cp);
2665
+ _stateCharacterReference() {
2666
+ let length = this.entityDecoder.write(this.preprocessor.html, this.preprocessor.pos);
2667
+ if (length < 0) {
2668
+ if (this.preprocessor.lastChunkWritten) {
2669
+ length = this.entityDecoder.end();
2670
+ }
2671
+ else {
2672
+ // Wait for the rest of the entity.
2673
+ this.active = false;
2674
+ // Mark the entire buffer as read.
2675
+ this.preprocessor.pos = this.preprocessor.html.length - 1;
2676
+ this.consumedAfterSnapshot = 0;
2677
+ this.preprocessor.endOfChunkHit = true;
2678
+ return;
2679
+ }
2765
2680
  }
2766
- else {
2681
+ if (length === 0) {
2682
+ // This was not a valid entity. Go back to the beginning, and
2683
+ // figure out what to do.
2684
+ this.preprocessor.pos = this.entityStartPos;
2767
2685
  this._flushCodePointConsumedAsCharacterReference($.AMPERSAND);
2768
- this._reconsumeInState(this.returnState, cp);
2769
- }
2770
- }
2771
- // Named character reference state
2772
- //------------------------------------------------------------------
2773
- _stateNamedCharacterReference(cp) {
2774
- const matchResult = this._matchNamedCharacterReference(cp);
2775
- //NOTE: Matching can be abrupted by hibernation. In that case, match
2776
- //results are no longer valid and we will need to start over.
2777
- if (this._ensureHibernation()) {
2778
- // Stay in the state, try again.
2779
- }
2780
- else if (matchResult) {
2781
- for (let i = 0; i < matchResult.length; i++) {
2782
- this._flushCodePointConsumedAsCharacterReference(matchResult[i]);
2783
- }
2784
- this.state = this.returnState;
2686
+ this.state =
2687
+ !this._isCharacterReferenceInAttribute() && isAsciiAlphaNumeric(this.preprocessor.peek(1))
2688
+ ? State.AMBIGUOUS_AMPERSAND
2689
+ : this.returnState;
2785
2690
  }
2786
2691
  else {
2787
- this._flushCodePointConsumedAsCharacterReference($.AMPERSAND);
2788
- this.state = State.AMBIGUOUS_AMPERSAND;
2692
+ // We successfully parsed an entity. Switch to the return state.
2693
+ this.state = this.returnState;
2789
2694
  }
2790
2695
  }
2791
2696
  // Ambiguos ampersand state
@@ -2798,106 +2703,8 @@ export class Tokenizer {
2798
2703
  if (cp === $.SEMICOLON) {
2799
2704
  this._err(ERR.unknownNamedCharacterReference);
2800
2705
  }
2801
- this._reconsumeInState(this.returnState, cp);
2802
- }
2803
- }
2804
- // Numeric character reference state
2805
- //------------------------------------------------------------------
2806
- _stateNumericCharacterReference(cp) {
2807
- this.charRefCode = 0;
2808
- if (cp === $.LATIN_SMALL_X || cp === $.LATIN_CAPITAL_X) {
2809
- this.state = State.HEXADEMICAL_CHARACTER_REFERENCE_START;
2810
- }
2811
- // Inlined decimal character reference start state
2812
- else if (isAsciiDigit(cp)) {
2813
- this.state = State.DECIMAL_CHARACTER_REFERENCE;
2814
- this._stateDecimalCharacterReference(cp);
2815
- }
2816
- else {
2817
- this._err(ERR.absenceOfDigitsInNumericCharacterReference);
2818
- this._flushCodePointConsumedAsCharacterReference($.AMPERSAND);
2819
- this._flushCodePointConsumedAsCharacterReference($.NUMBER_SIGN);
2820
- this._reconsumeInState(this.returnState, cp);
2821
- }
2822
- }
2823
- // Hexademical character reference start state
2824
- //------------------------------------------------------------------
2825
- _stateHexademicalCharacterReferenceStart(cp) {
2826
- if (isAsciiHexDigit(cp)) {
2827
- this.state = State.HEXADEMICAL_CHARACTER_REFERENCE;
2828
- this._stateHexademicalCharacterReference(cp);
2829
- }
2830
- else {
2831
- this._err(ERR.absenceOfDigitsInNumericCharacterReference);
2832
- this._flushCodePointConsumedAsCharacterReference($.AMPERSAND);
2833
- this._flushCodePointConsumedAsCharacterReference($.NUMBER_SIGN);
2834
- this._unconsume(2);
2835
2706
  this.state = this.returnState;
2707
+ this._callState(cp);
2836
2708
  }
2837
2709
  }
2838
- // Hexademical character reference state
2839
- //------------------------------------------------------------------
2840
- _stateHexademicalCharacterReference(cp) {
2841
- if (isAsciiUpperHexDigit(cp)) {
2842
- this.charRefCode = this.charRefCode * 16 + cp - 0x37;
2843
- }
2844
- else if (isAsciiLowerHexDigit(cp)) {
2845
- this.charRefCode = this.charRefCode * 16 + cp - 0x57;
2846
- }
2847
- else if (isAsciiDigit(cp)) {
2848
- this.charRefCode = this.charRefCode * 16 + cp - 0x30;
2849
- }
2850
- else if (cp === $.SEMICOLON) {
2851
- this.state = State.NUMERIC_CHARACTER_REFERENCE_END;
2852
- }
2853
- else {
2854
- this._err(ERR.missingSemicolonAfterCharacterReference);
2855
- this.state = State.NUMERIC_CHARACTER_REFERENCE_END;
2856
- this._stateNumericCharacterReferenceEnd(cp);
2857
- }
2858
- }
2859
- // Decimal character reference state
2860
- //------------------------------------------------------------------
2861
- _stateDecimalCharacterReference(cp) {
2862
- if (isAsciiDigit(cp)) {
2863
- this.charRefCode = this.charRefCode * 10 + cp - 0x30;
2864
- }
2865
- else if (cp === $.SEMICOLON) {
2866
- this.state = State.NUMERIC_CHARACTER_REFERENCE_END;
2867
- }
2868
- else {
2869
- this._err(ERR.missingSemicolonAfterCharacterReference);
2870
- this.state = State.NUMERIC_CHARACTER_REFERENCE_END;
2871
- this._stateNumericCharacterReferenceEnd(cp);
2872
- }
2873
- }
2874
- // Numeric character reference end state
2875
- //------------------------------------------------------------------
2876
- _stateNumericCharacterReferenceEnd(cp) {
2877
- if (this.charRefCode === $.NULL) {
2878
- this._err(ERR.nullCharacterReference);
2879
- this.charRefCode = $.REPLACEMENT_CHARACTER;
2880
- }
2881
- else if (this.charRefCode > 1114111) {
2882
- this._err(ERR.characterReferenceOutsideUnicodeRange);
2883
- this.charRefCode = $.REPLACEMENT_CHARACTER;
2884
- }
2885
- else if (isSurrogate(this.charRefCode)) {
2886
- this._err(ERR.surrogateCharacterReference);
2887
- this.charRefCode = $.REPLACEMENT_CHARACTER;
2888
- }
2889
- else if (isUndefinedCodePoint(this.charRefCode)) {
2890
- this._err(ERR.noncharacterCharacterReference);
2891
- }
2892
- else if (isControlCodePoint(this.charRefCode) || this.charRefCode === $.CARRIAGE_RETURN) {
2893
- this._err(ERR.controlCharacterReference);
2894
- const replacement = C1_CONTROLS_REFERENCE_REPLACEMENTS.get(this.charRefCode);
2895
- if (replacement !== undefined) {
2896
- this.charRefCode = replacement;
2897
- }
2898
- }
2899
- this._flushCodePointConsumedAsCharacterReference(this.charRefCode);
2900
- this._reconsumeInState(this.returnState, cp);
2901
- }
2902
2710
  }
2903
- //# sourceMappingURL=index.js.map
@@ -2,11 +2,11 @@ import { ERR, type ParserError, type ParserErrorHandler } from '../common/error-
2
2
  export declare class Preprocessor {
3
3
  private handler;
4
4
  html: string;
5
- private pos;
5
+ pos: number;
6
6
  private lastGapPos;
7
7
  private gapStack;
8
8
  private skipNextNewLine;
9
- private lastChunkWritten;
9
+ lastChunkWritten: boolean;
10
10
  endOfChunkHit: boolean;
11
11
  bufferWaterline: number;
12
12
  private isEol;
@@ -19,7 +19,7 @@ export declare class Preprocessor {
19
19
  /** The column on the current line. If we just saw a gap (eg. a surrogate pair), return the index before. */
20
20
  get col(): number;
21
21
  get offset(): number;
22
- getError(code: ERR): ParserError;
22
+ getError(code: ERR, cpOffset: number): ParserError;
23
23
  private lastErrOffset;
24
24
  private _err;
25
25
  private _addGap;
@@ -34,4 +34,3 @@ export declare class Preprocessor {
34
34
  private _checkForProblematicCharacters;
35
35
  retreat(count: number): void;
36
36
  }
37
- //# sourceMappingURL=preprocessor.d.ts.map
@@ -31,22 +31,24 @@ export class Preprocessor {
31
31
  get offset() {
32
32
  return this.droppedBufferSize + this.pos;
33
33
  }
34
- getError(code) {
34
+ getError(code, cpOffset) {
35
35
  const { line, col, offset } = this;
36
+ const startCol = col + cpOffset;
37
+ const startOffset = offset + cpOffset;
36
38
  return {
37
39
  code,
38
40
  startLine: line,
39
41
  endLine: line,
40
- startCol: col,
41
- endCol: col,
42
- startOffset: offset,
43
- endOffset: offset,
42
+ startCol,
43
+ endCol: startCol,
44
+ startOffset,
45
+ endOffset: startOffset,
44
46
  };
45
47
  }
46
48
  _err(code) {
47
49
  if (this.handler.onParseError && this.lastErrOffset !== this.offset) {
48
50
  this.lastErrOffset = this.offset;
49
- this.handler.onParseError(this.getError(code));
51
+ this.handler.onParseError(this.getError(code, 0));
50
52
  }
51
53
  }
52
54
  _addGap() {
@@ -124,7 +126,8 @@ export class Preprocessor {
124
126
  this.endOfChunkHit = !this.lastChunkWritten;
125
127
  return $.EOF;
126
128
  }
127
- return this.html.charCodeAt(pos);
129
+ const code = this.html.charCodeAt(pos);
130
+ return code === $.CARRIAGE_RETURN ? $.LINE_FEED : code;
128
131
  }
129
132
  advance() {
130
133
  this.pos++;
@@ -191,4 +194,3 @@ export class Preprocessor {
191
194
  this.isEol = false;
192
195
  }
193
196
  }
194
- //# sourceMappingURL=preprocessor.js.map
@@ -77,9 +77,8 @@ export interface DocumentType {
77
77
  /** Comment source code location info. Available if location info is enabled. */
78
78
  sourceCodeLocation?: Location | null;
79
79
  }
80
- export declare type ParentNode = Document | DocumentFragment | Element | Template;
81
- export declare type ChildNode = Element | Template | CommentNode | TextNode | DocumentType;
82
- export declare type Node = ParentNode | ChildNode;
83
- export declare type DefaultTreeAdapterMap = TreeAdapterTypeMap<Node, ParentNode, ChildNode, Document, DocumentFragment, Element, CommentNode, TextNode, Template, DocumentType>;
80
+ export type ParentNode = Document | DocumentFragment | Element | Template;
81
+ export type ChildNode = Element | Template | CommentNode | TextNode | DocumentType;
82
+ export type Node = ParentNode | ChildNode;
83
+ export type DefaultTreeAdapterMap = TreeAdapterTypeMap<Node, ParentNode, ChildNode, Document, DocumentFragment, Element, CommentNode, TextNode, Template, DocumentType>;
84
84
  export declare const defaultTreeAdapter: TreeAdapter<DefaultTreeAdapterMap>;
85
- //# sourceMappingURL=default.d.ts.map
@@ -1,11 +1,4 @@
1
1
  import { DOCUMENT_MODE } from '../common/html.js';
2
- function createTextNode(value) {
3
- return {
4
- nodeName: '#text',
5
- value,
6
- parentNode: null,
7
- };
8
- }
9
2
  export const defaultTreeAdapter = {
10
3
  //Node construction
11
4
  createDocument() {
@@ -38,6 +31,13 @@ export const defaultTreeAdapter = {
38
31
  parentNode: null,
39
32
  };
40
33
  },
34
+ createTextNode(value) {
35
+ return {
36
+ nodeName: '#text',
37
+ value,
38
+ parentNode: null,
39
+ };
40
+ },
41
41
  //Tree mutation
42
42
  appendChild(parentNode, newNode) {
43
43
  parentNode.childNodes.push(newNode);
@@ -93,7 +93,7 @@ export const defaultTreeAdapter = {
93
93
  return;
94
94
  }
95
95
  }
96
- defaultTreeAdapter.appendChild(parentNode, createTextNode(text));
96
+ defaultTreeAdapter.appendChild(parentNode, defaultTreeAdapter.createTextNode(text));
97
97
  },
98
98
  insertTextBefore(parentNode, text, referenceNode) {
99
99
  const prevNode = parentNode.childNodes[parentNode.childNodes.indexOf(referenceNode) - 1];
@@ -101,7 +101,7 @@ export const defaultTreeAdapter = {
101
101
  prevNode.value += text;
102
102
  }
103
103
  else {
104
- defaultTreeAdapter.insertBefore(parentNode, createTextNode(text), referenceNode);
104
+ defaultTreeAdapter.insertBefore(parentNode, defaultTreeAdapter.createTextNode(text), referenceNode);
105
105
  }
106
106
  },
107
107
  adoptAttributes(recipient, attrs) {
@@ -171,4 +171,3 @@ export const defaultTreeAdapter = {
171
171
  node.sourceCodeLocation = { ...node.sourceCodeLocation, ...endLocation };
172
172
  },
173
173
  };
174
- //# sourceMappingURL=default.js.map