parse5 6.0.1 → 7.0.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 (86) hide show
  1. package/README.md +2 -2
  2. package/dist/cjs/common/doctype.d.ts +5 -0
  3. package/dist/cjs/common/doctype.js +120 -0
  4. package/dist/cjs/common/error-codes.d.ts +68 -0
  5. package/dist/cjs/common/error-codes.js +67 -0
  6. package/dist/cjs/common/foreign-content.d.ts +10 -0
  7. package/dist/cjs/common/foreign-content.js +239 -0
  8. package/dist/cjs/common/html.d.ts +288 -0
  9. package/dist/cjs/common/html.js +529 -0
  10. package/dist/cjs/common/token.d.ts +85 -0
  11. package/dist/cjs/common/token.js +25 -0
  12. package/dist/cjs/common/unicode.d.ts +49 -0
  13. package/dist/cjs/common/unicode.js +77 -0
  14. package/dist/cjs/index.d.ts +60 -0
  15. package/dist/cjs/index.js +55 -0
  16. package/dist/cjs/package.json +1 -0
  17. package/dist/cjs/parser/formatting-element-list.d.ts +32 -0
  18. package/dist/cjs/parser/formatting-element-list.js +110 -0
  19. package/dist/cjs/parser/index.d.ts +157 -0
  20. package/dist/cjs/parser/index.js +3049 -0
  21. package/dist/cjs/parser/open-element-stack.d.ts +53 -0
  22. package/dist/cjs/parser/open-element-stack.js +316 -0
  23. package/dist/cjs/serializer/index.d.ts +61 -0
  24. package/dist/cjs/serializer/index.js +173 -0
  25. package/dist/cjs/tokenizer/index.d.ts +250 -0
  26. package/dist/cjs/tokenizer/index.js +2921 -0
  27. package/dist/cjs/tokenizer/preprocessor.d.ts +37 -0
  28. package/dist/cjs/tokenizer/preprocessor.js +198 -0
  29. package/dist/cjs/tree-adapters/default.d.ts +92 -0
  30. package/dist/cjs/tree-adapters/default.js +185 -0
  31. package/dist/cjs/tree-adapters/interface.d.ts +250 -0
  32. package/dist/cjs/tree-adapters/interface.js +3 -0
  33. package/dist/common/doctype.d.ts +5 -0
  34. package/{lib → dist}/common/doctype.js +25 -72
  35. package/dist/common/error-codes.d.ts +68 -0
  36. package/dist/common/error-codes.js +64 -0
  37. package/dist/common/foreign-content.d.ts +10 -0
  38. package/dist/common/foreign-content.js +230 -0
  39. package/dist/common/html.d.ts +288 -0
  40. package/dist/common/html.js +523 -0
  41. package/dist/common/token.d.ts +85 -0
  42. package/dist/common/token.js +21 -0
  43. package/dist/common/unicode.d.ts +49 -0
  44. package/dist/common/unicode.js +69 -0
  45. package/dist/index.d.ts +60 -0
  46. package/dist/index.js +44 -0
  47. package/dist/parser/formatting-element-list.d.ts +32 -0
  48. package/dist/parser/formatting-element-list.js +106 -0
  49. package/dist/parser/index.d.ts +157 -0
  50. package/dist/parser/index.js +3054 -0
  51. package/dist/parser/open-element-stack.d.ts +53 -0
  52. package/dist/parser/open-element-stack.js +312 -0
  53. package/dist/serializer/index.d.ts +61 -0
  54. package/dist/serializer/index.js +168 -0
  55. package/dist/tokenizer/index.d.ts +250 -0
  56. package/dist/tokenizer/index.js +2917 -0
  57. package/dist/tokenizer/preprocessor.d.ts +37 -0
  58. package/dist/tokenizer/preprocessor.js +194 -0
  59. package/dist/tree-adapters/default.d.ts +92 -0
  60. package/dist/tree-adapters/default.js +182 -0
  61. package/dist/tree-adapters/interface.d.ts +250 -0
  62. package/dist/tree-adapters/interface.js +2 -0
  63. package/package.json +19 -5
  64. package/lib/common/error-codes.js +0 -65
  65. package/lib/common/foreign-content.js +0 -265
  66. package/lib/common/html.js +0 -272
  67. package/lib/common/unicode.js +0 -109
  68. package/lib/extensions/error-reporting/mixin-base.js +0 -43
  69. package/lib/extensions/error-reporting/parser-mixin.js +0 -52
  70. package/lib/extensions/error-reporting/preprocessor-mixin.js +0 -24
  71. package/lib/extensions/error-reporting/tokenizer-mixin.js +0 -17
  72. package/lib/extensions/location-info/open-element-stack-mixin.js +0 -35
  73. package/lib/extensions/location-info/parser-mixin.js +0 -223
  74. package/lib/extensions/location-info/tokenizer-mixin.js +0 -146
  75. package/lib/extensions/position-tracking/preprocessor-mixin.js +0 -64
  76. package/lib/index.js +0 -29
  77. package/lib/parser/formatting-element-list.js +0 -181
  78. package/lib/parser/index.js +0 -2956
  79. package/lib/parser/open-element-stack.js +0 -482
  80. package/lib/serializer/index.js +0 -176
  81. package/lib/tokenizer/index.js +0 -2196
  82. package/lib/tokenizer/named-entity-data.js +0 -5
  83. package/lib/tokenizer/preprocessor.js +0 -159
  84. package/lib/tree-adapters/default.js +0 -221
  85. package/lib/utils/merge-options.js +0 -13
  86. package/lib/utils/mixin.js +0 -39
@@ -1,2956 +0,0 @@
1
- 'use strict';
2
-
3
- const Tokenizer = require('../tokenizer');
4
- const OpenElementStack = require('./open-element-stack');
5
- const FormattingElementList = require('./formatting-element-list');
6
- const LocationInfoParserMixin = require('../extensions/location-info/parser-mixin');
7
- const ErrorReportingParserMixin = require('../extensions/error-reporting/parser-mixin');
8
- const Mixin = require('../utils/mixin');
9
- const defaultTreeAdapter = require('../tree-adapters/default');
10
- const mergeOptions = require('../utils/merge-options');
11
- const doctype = require('../common/doctype');
12
- const foreignContent = require('../common/foreign-content');
13
- const ERR = require('../common/error-codes');
14
- const unicode = require('../common/unicode');
15
- const HTML = require('../common/html');
16
-
17
- //Aliases
18
- const $ = HTML.TAG_NAMES;
19
- const NS = HTML.NAMESPACES;
20
- const ATTRS = HTML.ATTRS;
21
-
22
- const DEFAULT_OPTIONS = {
23
- scriptingEnabled: true,
24
- sourceCodeLocationInfo: false,
25
- onParseError: null,
26
- treeAdapter: defaultTreeAdapter
27
- };
28
-
29
- //Misc constants
30
- const HIDDEN_INPUT_TYPE = 'hidden';
31
-
32
- //Adoption agency loops iteration count
33
- const AA_OUTER_LOOP_ITER = 8;
34
- const AA_INNER_LOOP_ITER = 3;
35
-
36
- //Insertion modes
37
- const INITIAL_MODE = 'INITIAL_MODE';
38
- const BEFORE_HTML_MODE = 'BEFORE_HTML_MODE';
39
- const BEFORE_HEAD_MODE = 'BEFORE_HEAD_MODE';
40
- const IN_HEAD_MODE = 'IN_HEAD_MODE';
41
- const IN_HEAD_NO_SCRIPT_MODE = 'IN_HEAD_NO_SCRIPT_MODE';
42
- const AFTER_HEAD_MODE = 'AFTER_HEAD_MODE';
43
- const IN_BODY_MODE = 'IN_BODY_MODE';
44
- const TEXT_MODE = 'TEXT_MODE';
45
- const IN_TABLE_MODE = 'IN_TABLE_MODE';
46
- const IN_TABLE_TEXT_MODE = 'IN_TABLE_TEXT_MODE';
47
- const IN_CAPTION_MODE = 'IN_CAPTION_MODE';
48
- const IN_COLUMN_GROUP_MODE = 'IN_COLUMN_GROUP_MODE';
49
- const IN_TABLE_BODY_MODE = 'IN_TABLE_BODY_MODE';
50
- const IN_ROW_MODE = 'IN_ROW_MODE';
51
- const IN_CELL_MODE = 'IN_CELL_MODE';
52
- const IN_SELECT_MODE = 'IN_SELECT_MODE';
53
- const IN_SELECT_IN_TABLE_MODE = 'IN_SELECT_IN_TABLE_MODE';
54
- const IN_TEMPLATE_MODE = 'IN_TEMPLATE_MODE';
55
- const AFTER_BODY_MODE = 'AFTER_BODY_MODE';
56
- const IN_FRAMESET_MODE = 'IN_FRAMESET_MODE';
57
- const AFTER_FRAMESET_MODE = 'AFTER_FRAMESET_MODE';
58
- const AFTER_AFTER_BODY_MODE = 'AFTER_AFTER_BODY_MODE';
59
- const AFTER_AFTER_FRAMESET_MODE = 'AFTER_AFTER_FRAMESET_MODE';
60
-
61
- //Insertion mode reset map
62
- const INSERTION_MODE_RESET_MAP = {
63
- [$.TR]: IN_ROW_MODE,
64
- [$.TBODY]: IN_TABLE_BODY_MODE,
65
- [$.THEAD]: IN_TABLE_BODY_MODE,
66
- [$.TFOOT]: IN_TABLE_BODY_MODE,
67
- [$.CAPTION]: IN_CAPTION_MODE,
68
- [$.COLGROUP]: IN_COLUMN_GROUP_MODE,
69
- [$.TABLE]: IN_TABLE_MODE,
70
- [$.BODY]: IN_BODY_MODE,
71
- [$.FRAMESET]: IN_FRAMESET_MODE
72
- };
73
-
74
- //Template insertion mode switch map
75
- const TEMPLATE_INSERTION_MODE_SWITCH_MAP = {
76
- [$.CAPTION]: IN_TABLE_MODE,
77
- [$.COLGROUP]: IN_TABLE_MODE,
78
- [$.TBODY]: IN_TABLE_MODE,
79
- [$.TFOOT]: IN_TABLE_MODE,
80
- [$.THEAD]: IN_TABLE_MODE,
81
- [$.COL]: IN_COLUMN_GROUP_MODE,
82
- [$.TR]: IN_TABLE_BODY_MODE,
83
- [$.TD]: IN_ROW_MODE,
84
- [$.TH]: IN_ROW_MODE
85
- };
86
-
87
- //Token handlers map for insertion modes
88
- const TOKEN_HANDLERS = {
89
- [INITIAL_MODE]: {
90
- [Tokenizer.CHARACTER_TOKEN]: tokenInInitialMode,
91
- [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInInitialMode,
92
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken,
93
- [Tokenizer.COMMENT_TOKEN]: appendComment,
94
- [Tokenizer.DOCTYPE_TOKEN]: doctypeInInitialMode,
95
- [Tokenizer.START_TAG_TOKEN]: tokenInInitialMode,
96
- [Tokenizer.END_TAG_TOKEN]: tokenInInitialMode,
97
- [Tokenizer.EOF_TOKEN]: tokenInInitialMode
98
- },
99
- [BEFORE_HTML_MODE]: {
100
- [Tokenizer.CHARACTER_TOKEN]: tokenBeforeHtml,
101
- [Tokenizer.NULL_CHARACTER_TOKEN]: tokenBeforeHtml,
102
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken,
103
- [Tokenizer.COMMENT_TOKEN]: appendComment,
104
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
105
- [Tokenizer.START_TAG_TOKEN]: startTagBeforeHtml,
106
- [Tokenizer.END_TAG_TOKEN]: endTagBeforeHtml,
107
- [Tokenizer.EOF_TOKEN]: tokenBeforeHtml
108
- },
109
- [BEFORE_HEAD_MODE]: {
110
- [Tokenizer.CHARACTER_TOKEN]: tokenBeforeHead,
111
- [Tokenizer.NULL_CHARACTER_TOKEN]: tokenBeforeHead,
112
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: ignoreToken,
113
- [Tokenizer.COMMENT_TOKEN]: appendComment,
114
- [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype,
115
- [Tokenizer.START_TAG_TOKEN]: startTagBeforeHead,
116
- [Tokenizer.END_TAG_TOKEN]: endTagBeforeHead,
117
- [Tokenizer.EOF_TOKEN]: tokenBeforeHead
118
- },
119
- [IN_HEAD_MODE]: {
120
- [Tokenizer.CHARACTER_TOKEN]: tokenInHead,
121
- [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInHead,
122
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
123
- [Tokenizer.COMMENT_TOKEN]: appendComment,
124
- [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype,
125
- [Tokenizer.START_TAG_TOKEN]: startTagInHead,
126
- [Tokenizer.END_TAG_TOKEN]: endTagInHead,
127
- [Tokenizer.EOF_TOKEN]: tokenInHead
128
- },
129
- [IN_HEAD_NO_SCRIPT_MODE]: {
130
- [Tokenizer.CHARACTER_TOKEN]: tokenInHeadNoScript,
131
- [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInHeadNoScript,
132
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
133
- [Tokenizer.COMMENT_TOKEN]: appendComment,
134
- [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype,
135
- [Tokenizer.START_TAG_TOKEN]: startTagInHeadNoScript,
136
- [Tokenizer.END_TAG_TOKEN]: endTagInHeadNoScript,
137
- [Tokenizer.EOF_TOKEN]: tokenInHeadNoScript
138
- },
139
- [AFTER_HEAD_MODE]: {
140
- [Tokenizer.CHARACTER_TOKEN]: tokenAfterHead,
141
- [Tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterHead,
142
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
143
- [Tokenizer.COMMENT_TOKEN]: appendComment,
144
- [Tokenizer.DOCTYPE_TOKEN]: misplacedDoctype,
145
- [Tokenizer.START_TAG_TOKEN]: startTagAfterHead,
146
- [Tokenizer.END_TAG_TOKEN]: endTagAfterHead,
147
- [Tokenizer.EOF_TOKEN]: tokenAfterHead
148
- },
149
- [IN_BODY_MODE]: {
150
- [Tokenizer.CHARACTER_TOKEN]: characterInBody,
151
- [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
152
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,
153
- [Tokenizer.COMMENT_TOKEN]: appendComment,
154
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
155
- [Tokenizer.START_TAG_TOKEN]: startTagInBody,
156
- [Tokenizer.END_TAG_TOKEN]: endTagInBody,
157
- [Tokenizer.EOF_TOKEN]: eofInBody
158
- },
159
- [TEXT_MODE]: {
160
- [Tokenizer.CHARACTER_TOKEN]: insertCharacters,
161
- [Tokenizer.NULL_CHARACTER_TOKEN]: insertCharacters,
162
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
163
- [Tokenizer.COMMENT_TOKEN]: ignoreToken,
164
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
165
- [Tokenizer.START_TAG_TOKEN]: ignoreToken,
166
- [Tokenizer.END_TAG_TOKEN]: endTagInText,
167
- [Tokenizer.EOF_TOKEN]: eofInText
168
- },
169
- [IN_TABLE_MODE]: {
170
- [Tokenizer.CHARACTER_TOKEN]: characterInTable,
171
- [Tokenizer.NULL_CHARACTER_TOKEN]: characterInTable,
172
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable,
173
- [Tokenizer.COMMENT_TOKEN]: appendComment,
174
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
175
- [Tokenizer.START_TAG_TOKEN]: startTagInTable,
176
- [Tokenizer.END_TAG_TOKEN]: endTagInTable,
177
- [Tokenizer.EOF_TOKEN]: eofInBody
178
- },
179
- [IN_TABLE_TEXT_MODE]: {
180
- [Tokenizer.CHARACTER_TOKEN]: characterInTableText,
181
- [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
182
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInTableText,
183
- [Tokenizer.COMMENT_TOKEN]: tokenInTableText,
184
- [Tokenizer.DOCTYPE_TOKEN]: tokenInTableText,
185
- [Tokenizer.START_TAG_TOKEN]: tokenInTableText,
186
- [Tokenizer.END_TAG_TOKEN]: tokenInTableText,
187
- [Tokenizer.EOF_TOKEN]: tokenInTableText
188
- },
189
- [IN_CAPTION_MODE]: {
190
- [Tokenizer.CHARACTER_TOKEN]: characterInBody,
191
- [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
192
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,
193
- [Tokenizer.COMMENT_TOKEN]: appendComment,
194
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
195
- [Tokenizer.START_TAG_TOKEN]: startTagInCaption,
196
- [Tokenizer.END_TAG_TOKEN]: endTagInCaption,
197
- [Tokenizer.EOF_TOKEN]: eofInBody
198
- },
199
- [IN_COLUMN_GROUP_MODE]: {
200
- [Tokenizer.CHARACTER_TOKEN]: tokenInColumnGroup,
201
- [Tokenizer.NULL_CHARACTER_TOKEN]: tokenInColumnGroup,
202
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
203
- [Tokenizer.COMMENT_TOKEN]: appendComment,
204
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
205
- [Tokenizer.START_TAG_TOKEN]: startTagInColumnGroup,
206
- [Tokenizer.END_TAG_TOKEN]: endTagInColumnGroup,
207
- [Tokenizer.EOF_TOKEN]: eofInBody
208
- },
209
- [IN_TABLE_BODY_MODE]: {
210
- [Tokenizer.CHARACTER_TOKEN]: characterInTable,
211
- [Tokenizer.NULL_CHARACTER_TOKEN]: characterInTable,
212
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable,
213
- [Tokenizer.COMMENT_TOKEN]: appendComment,
214
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
215
- [Tokenizer.START_TAG_TOKEN]: startTagInTableBody,
216
- [Tokenizer.END_TAG_TOKEN]: endTagInTableBody,
217
- [Tokenizer.EOF_TOKEN]: eofInBody
218
- },
219
- [IN_ROW_MODE]: {
220
- [Tokenizer.CHARACTER_TOKEN]: characterInTable,
221
- [Tokenizer.NULL_CHARACTER_TOKEN]: characterInTable,
222
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: characterInTable,
223
- [Tokenizer.COMMENT_TOKEN]: appendComment,
224
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
225
- [Tokenizer.START_TAG_TOKEN]: startTagInRow,
226
- [Tokenizer.END_TAG_TOKEN]: endTagInRow,
227
- [Tokenizer.EOF_TOKEN]: eofInBody
228
- },
229
- [IN_CELL_MODE]: {
230
- [Tokenizer.CHARACTER_TOKEN]: characterInBody,
231
- [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
232
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,
233
- [Tokenizer.COMMENT_TOKEN]: appendComment,
234
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
235
- [Tokenizer.START_TAG_TOKEN]: startTagInCell,
236
- [Tokenizer.END_TAG_TOKEN]: endTagInCell,
237
- [Tokenizer.EOF_TOKEN]: eofInBody
238
- },
239
- [IN_SELECT_MODE]: {
240
- [Tokenizer.CHARACTER_TOKEN]: insertCharacters,
241
- [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
242
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
243
- [Tokenizer.COMMENT_TOKEN]: appendComment,
244
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
245
- [Tokenizer.START_TAG_TOKEN]: startTagInSelect,
246
- [Tokenizer.END_TAG_TOKEN]: endTagInSelect,
247
- [Tokenizer.EOF_TOKEN]: eofInBody
248
- },
249
- [IN_SELECT_IN_TABLE_MODE]: {
250
- [Tokenizer.CHARACTER_TOKEN]: insertCharacters,
251
- [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
252
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
253
- [Tokenizer.COMMENT_TOKEN]: appendComment,
254
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
255
- [Tokenizer.START_TAG_TOKEN]: startTagInSelectInTable,
256
- [Tokenizer.END_TAG_TOKEN]: endTagInSelectInTable,
257
- [Tokenizer.EOF_TOKEN]: eofInBody
258
- },
259
- [IN_TEMPLATE_MODE]: {
260
- [Tokenizer.CHARACTER_TOKEN]: characterInBody,
261
- [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
262
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,
263
- [Tokenizer.COMMENT_TOKEN]: appendComment,
264
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
265
- [Tokenizer.START_TAG_TOKEN]: startTagInTemplate,
266
- [Tokenizer.END_TAG_TOKEN]: endTagInTemplate,
267
- [Tokenizer.EOF_TOKEN]: eofInTemplate
268
- },
269
- [AFTER_BODY_MODE]: {
270
- [Tokenizer.CHARACTER_TOKEN]: tokenAfterBody,
271
- [Tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterBody,
272
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,
273
- [Tokenizer.COMMENT_TOKEN]: appendCommentToRootHtmlElement,
274
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
275
- [Tokenizer.START_TAG_TOKEN]: startTagAfterBody,
276
- [Tokenizer.END_TAG_TOKEN]: endTagAfterBody,
277
- [Tokenizer.EOF_TOKEN]: stopParsing
278
- },
279
- [IN_FRAMESET_MODE]: {
280
- [Tokenizer.CHARACTER_TOKEN]: ignoreToken,
281
- [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
282
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
283
- [Tokenizer.COMMENT_TOKEN]: appendComment,
284
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
285
- [Tokenizer.START_TAG_TOKEN]: startTagInFrameset,
286
- [Tokenizer.END_TAG_TOKEN]: endTagInFrameset,
287
- [Tokenizer.EOF_TOKEN]: stopParsing
288
- },
289
- [AFTER_FRAMESET_MODE]: {
290
- [Tokenizer.CHARACTER_TOKEN]: ignoreToken,
291
- [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
292
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: insertCharacters,
293
- [Tokenizer.COMMENT_TOKEN]: appendComment,
294
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
295
- [Tokenizer.START_TAG_TOKEN]: startTagAfterFrameset,
296
- [Tokenizer.END_TAG_TOKEN]: endTagAfterFrameset,
297
- [Tokenizer.EOF_TOKEN]: stopParsing
298
- },
299
- [AFTER_AFTER_BODY_MODE]: {
300
- [Tokenizer.CHARACTER_TOKEN]: tokenAfterAfterBody,
301
- [Tokenizer.NULL_CHARACTER_TOKEN]: tokenAfterAfterBody,
302
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,
303
- [Tokenizer.COMMENT_TOKEN]: appendCommentToDocument,
304
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
305
- [Tokenizer.START_TAG_TOKEN]: startTagAfterAfterBody,
306
- [Tokenizer.END_TAG_TOKEN]: tokenAfterAfterBody,
307
- [Tokenizer.EOF_TOKEN]: stopParsing
308
- },
309
- [AFTER_AFTER_FRAMESET_MODE]: {
310
- [Tokenizer.CHARACTER_TOKEN]: ignoreToken,
311
- [Tokenizer.NULL_CHARACTER_TOKEN]: ignoreToken,
312
- [Tokenizer.WHITESPACE_CHARACTER_TOKEN]: whitespaceCharacterInBody,
313
- [Tokenizer.COMMENT_TOKEN]: appendCommentToDocument,
314
- [Tokenizer.DOCTYPE_TOKEN]: ignoreToken,
315
- [Tokenizer.START_TAG_TOKEN]: startTagAfterAfterFrameset,
316
- [Tokenizer.END_TAG_TOKEN]: ignoreToken,
317
- [Tokenizer.EOF_TOKEN]: stopParsing
318
- }
319
- };
320
-
321
- //Parser
322
- class Parser {
323
- constructor(options) {
324
- this.options = mergeOptions(DEFAULT_OPTIONS, options);
325
-
326
- this.treeAdapter = this.options.treeAdapter;
327
- this.pendingScript = null;
328
-
329
- if (this.options.sourceCodeLocationInfo) {
330
- Mixin.install(this, LocationInfoParserMixin);
331
- }
332
-
333
- if (this.options.onParseError) {
334
- Mixin.install(this, ErrorReportingParserMixin, { onParseError: this.options.onParseError });
335
- }
336
- }
337
-
338
- // API
339
- parse(html) {
340
- const document = this.treeAdapter.createDocument();
341
-
342
- this._bootstrap(document, null);
343
- this.tokenizer.write(html, true);
344
- this._runParsingLoop(null);
345
-
346
- return document;
347
- }
348
-
349
- parseFragment(html, fragmentContext) {
350
- //NOTE: use <template> element as a fragment context if context element was not provided,
351
- //so we will parse in "forgiving" manner
352
- if (!fragmentContext) {
353
- fragmentContext = this.treeAdapter.createElement($.TEMPLATE, NS.HTML, []);
354
- }
355
-
356
- //NOTE: create fake element which will be used as 'document' for fragment parsing.
357
- //This is important for jsdom there 'document' can't be recreated, therefore
358
- //fragment parsing causes messing of the main `document`.
359
- const documentMock = this.treeAdapter.createElement('documentmock', NS.HTML, []);
360
-
361
- this._bootstrap(documentMock, fragmentContext);
362
-
363
- if (this.treeAdapter.getTagName(fragmentContext) === $.TEMPLATE) {
364
- this._pushTmplInsertionMode(IN_TEMPLATE_MODE);
365
- }
366
-
367
- this._initTokenizerForFragmentParsing();
368
- this._insertFakeRootElement();
369
- this._resetInsertionMode();
370
- this._findFormInFragmentContext();
371
- this.tokenizer.write(html, true);
372
- this._runParsingLoop(null);
373
-
374
- const rootElement = this.treeAdapter.getFirstChild(documentMock);
375
- const fragment = this.treeAdapter.createDocumentFragment();
376
-
377
- this._adoptNodes(rootElement, fragment);
378
-
379
- return fragment;
380
- }
381
-
382
- //Bootstrap parser
383
- _bootstrap(document, fragmentContext) {
384
- this.tokenizer = new Tokenizer(this.options);
385
-
386
- this.stopped = false;
387
-
388
- this.insertionMode = INITIAL_MODE;
389
- this.originalInsertionMode = '';
390
-
391
- this.document = document;
392
- this.fragmentContext = fragmentContext;
393
-
394
- this.headElement = null;
395
- this.formElement = null;
396
-
397
- this.openElements = new OpenElementStack(this.document, this.treeAdapter);
398
- this.activeFormattingElements = new FormattingElementList(this.treeAdapter);
399
-
400
- this.tmplInsertionModeStack = [];
401
- this.tmplInsertionModeStackTop = -1;
402
- this.currentTmplInsertionMode = null;
403
-
404
- this.pendingCharacterTokens = [];
405
- this.hasNonWhitespacePendingCharacterToken = false;
406
-
407
- this.framesetOk = true;
408
- this.skipNextNewLine = false;
409
- this.fosterParentingEnabled = false;
410
- }
411
-
412
- //Errors
413
- _err() {
414
- // NOTE: err reporting is noop by default. Enabled by mixin.
415
- }
416
-
417
- //Parsing loop
418
- _runParsingLoop(scriptHandler) {
419
- while (!this.stopped) {
420
- this._setupTokenizerCDATAMode();
421
-
422
- const token = this.tokenizer.getNextToken();
423
-
424
- if (token.type === Tokenizer.HIBERNATION_TOKEN) {
425
- break;
426
- }
427
-
428
- if (this.skipNextNewLine) {
429
- this.skipNextNewLine = false;
430
-
431
- if (token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN && token.chars[0] === '\n') {
432
- if (token.chars.length === 1) {
433
- continue;
434
- }
435
-
436
- token.chars = token.chars.substr(1);
437
- }
438
- }
439
-
440
- this._processInputToken(token);
441
-
442
- if (scriptHandler && this.pendingScript) {
443
- break;
444
- }
445
- }
446
- }
447
-
448
- runParsingLoopForCurrentChunk(writeCallback, scriptHandler) {
449
- this._runParsingLoop(scriptHandler);
450
-
451
- if (scriptHandler && this.pendingScript) {
452
- const script = this.pendingScript;
453
-
454
- this.pendingScript = null;
455
-
456
- scriptHandler(script);
457
-
458
- return;
459
- }
460
-
461
- if (writeCallback) {
462
- writeCallback();
463
- }
464
- }
465
-
466
- //Text parsing
467
- _setupTokenizerCDATAMode() {
468
- const current = this._getAdjustedCurrentElement();
469
-
470
- this.tokenizer.allowCDATA =
471
- current &&
472
- current !== this.document &&
473
- this.treeAdapter.getNamespaceURI(current) !== NS.HTML &&
474
- !this._isIntegrationPoint(current);
475
- }
476
-
477
- _switchToTextParsing(currentToken, nextTokenizerState) {
478
- this._insertElement(currentToken, NS.HTML);
479
- this.tokenizer.state = nextTokenizerState;
480
- this.originalInsertionMode = this.insertionMode;
481
- this.insertionMode = TEXT_MODE;
482
- }
483
-
484
- switchToPlaintextParsing() {
485
- this.insertionMode = TEXT_MODE;
486
- this.originalInsertionMode = IN_BODY_MODE;
487
- this.tokenizer.state = Tokenizer.MODE.PLAINTEXT;
488
- }
489
-
490
- //Fragment parsing
491
- _getAdjustedCurrentElement() {
492
- return this.openElements.stackTop === 0 && this.fragmentContext
493
- ? this.fragmentContext
494
- : this.openElements.current;
495
- }
496
-
497
- _findFormInFragmentContext() {
498
- let node = this.fragmentContext;
499
-
500
- do {
501
- if (this.treeAdapter.getTagName(node) === $.FORM) {
502
- this.formElement = node;
503
- break;
504
- }
505
-
506
- node = this.treeAdapter.getParentNode(node);
507
- } while (node);
508
- }
509
-
510
- _initTokenizerForFragmentParsing() {
511
- if (this.treeAdapter.getNamespaceURI(this.fragmentContext) === NS.HTML) {
512
- const tn = this.treeAdapter.getTagName(this.fragmentContext);
513
-
514
- if (tn === $.TITLE || tn === $.TEXTAREA) {
515
- this.tokenizer.state = Tokenizer.MODE.RCDATA;
516
- } else if (
517
- tn === $.STYLE ||
518
- tn === $.XMP ||
519
- tn === $.IFRAME ||
520
- tn === $.NOEMBED ||
521
- tn === $.NOFRAMES ||
522
- tn === $.NOSCRIPT
523
- ) {
524
- this.tokenizer.state = Tokenizer.MODE.RAWTEXT;
525
- } else if (tn === $.SCRIPT) {
526
- this.tokenizer.state = Tokenizer.MODE.SCRIPT_DATA;
527
- } else if (tn === $.PLAINTEXT) {
528
- this.tokenizer.state = Tokenizer.MODE.PLAINTEXT;
529
- }
530
- }
531
- }
532
-
533
- //Tree mutation
534
- _setDocumentType(token) {
535
- const name = token.name || '';
536
- const publicId = token.publicId || '';
537
- const systemId = token.systemId || '';
538
-
539
- this.treeAdapter.setDocumentType(this.document, name, publicId, systemId);
540
- }
541
-
542
- _attachElementToTree(element) {
543
- if (this._shouldFosterParentOnInsertion()) {
544
- this._fosterParentElement(element);
545
- } else {
546
- const parent = this.openElements.currentTmplContent || this.openElements.current;
547
-
548
- this.treeAdapter.appendChild(parent, element);
549
- }
550
- }
551
-
552
- _appendElement(token, namespaceURI) {
553
- const element = this.treeAdapter.createElement(token.tagName, namespaceURI, token.attrs);
554
-
555
- this._attachElementToTree(element);
556
- }
557
-
558
- _insertElement(token, namespaceURI) {
559
- const element = this.treeAdapter.createElement(token.tagName, namespaceURI, token.attrs);
560
-
561
- this._attachElementToTree(element);
562
- this.openElements.push(element);
563
- }
564
-
565
- _insertFakeElement(tagName) {
566
- const element = this.treeAdapter.createElement(tagName, NS.HTML, []);
567
-
568
- this._attachElementToTree(element);
569
- this.openElements.push(element);
570
- }
571
-
572
- _insertTemplate(token) {
573
- const tmpl = this.treeAdapter.createElement(token.tagName, NS.HTML, token.attrs);
574
- const content = this.treeAdapter.createDocumentFragment();
575
-
576
- this.treeAdapter.setTemplateContent(tmpl, content);
577
- this._attachElementToTree(tmpl);
578
- this.openElements.push(tmpl);
579
- }
580
-
581
- _insertFakeRootElement() {
582
- const element = this.treeAdapter.createElement($.HTML, NS.HTML, []);
583
-
584
- this.treeAdapter.appendChild(this.openElements.current, element);
585
- this.openElements.push(element);
586
- }
587
-
588
- _appendCommentNode(token, parent) {
589
- const commentNode = this.treeAdapter.createCommentNode(token.data);
590
-
591
- this.treeAdapter.appendChild(parent, commentNode);
592
- }
593
-
594
- _insertCharacters(token) {
595
- if (this._shouldFosterParentOnInsertion()) {
596
- this._fosterParentText(token.chars);
597
- } else {
598
- const parent = this.openElements.currentTmplContent || this.openElements.current;
599
-
600
- this.treeAdapter.insertText(parent, token.chars);
601
- }
602
- }
603
-
604
- _adoptNodes(donor, recipient) {
605
- for (let child = this.treeAdapter.getFirstChild(donor); child; child = this.treeAdapter.getFirstChild(donor)) {
606
- this.treeAdapter.detachNode(child);
607
- this.treeAdapter.appendChild(recipient, child);
608
- }
609
- }
610
-
611
- //Token processing
612
- _shouldProcessTokenInForeignContent(token) {
613
- const current = this._getAdjustedCurrentElement();
614
-
615
- if (!current || current === this.document) {
616
- return false;
617
- }
618
-
619
- const ns = this.treeAdapter.getNamespaceURI(current);
620
-
621
- if (ns === NS.HTML) {
622
- return false;
623
- }
624
-
625
- if (
626
- this.treeAdapter.getTagName(current) === $.ANNOTATION_XML &&
627
- ns === NS.MATHML &&
628
- token.type === Tokenizer.START_TAG_TOKEN &&
629
- token.tagName === $.SVG
630
- ) {
631
- return false;
632
- }
633
-
634
- const isCharacterToken =
635
- token.type === Tokenizer.CHARACTER_TOKEN ||
636
- token.type === Tokenizer.NULL_CHARACTER_TOKEN ||
637
- token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN;
638
-
639
- const isMathMLTextStartTag =
640
- token.type === Tokenizer.START_TAG_TOKEN && token.tagName !== $.MGLYPH && token.tagName !== $.MALIGNMARK;
641
-
642
- if ((isMathMLTextStartTag || isCharacterToken) && this._isIntegrationPoint(current, NS.MATHML)) {
643
- return false;
644
- }
645
-
646
- if (
647
- (token.type === Tokenizer.START_TAG_TOKEN || isCharacterToken) &&
648
- this._isIntegrationPoint(current, NS.HTML)
649
- ) {
650
- return false;
651
- }
652
-
653
- return token.type !== Tokenizer.EOF_TOKEN;
654
- }
655
-
656
- _processToken(token) {
657
- TOKEN_HANDLERS[this.insertionMode][token.type](this, token);
658
- }
659
-
660
- _processTokenInBodyMode(token) {
661
- TOKEN_HANDLERS[IN_BODY_MODE][token.type](this, token);
662
- }
663
-
664
- _processTokenInForeignContent(token) {
665
- if (token.type === Tokenizer.CHARACTER_TOKEN) {
666
- characterInForeignContent(this, token);
667
- } else if (token.type === Tokenizer.NULL_CHARACTER_TOKEN) {
668
- nullCharacterInForeignContent(this, token);
669
- } else if (token.type === Tokenizer.WHITESPACE_CHARACTER_TOKEN) {
670
- insertCharacters(this, token);
671
- } else if (token.type === Tokenizer.COMMENT_TOKEN) {
672
- appendComment(this, token);
673
- } else if (token.type === Tokenizer.START_TAG_TOKEN) {
674
- startTagInForeignContent(this, token);
675
- } else if (token.type === Tokenizer.END_TAG_TOKEN) {
676
- endTagInForeignContent(this, token);
677
- }
678
- }
679
-
680
- _processInputToken(token) {
681
- if (this._shouldProcessTokenInForeignContent(token)) {
682
- this._processTokenInForeignContent(token);
683
- } else {
684
- this._processToken(token);
685
- }
686
-
687
- if (token.type === Tokenizer.START_TAG_TOKEN && token.selfClosing && !token.ackSelfClosing) {
688
- this._err(ERR.nonVoidHtmlElementStartTagWithTrailingSolidus);
689
- }
690
- }
691
-
692
- //Integration points
693
- _isIntegrationPoint(element, foreignNS) {
694
- const tn = this.treeAdapter.getTagName(element);
695
- const ns = this.treeAdapter.getNamespaceURI(element);
696
- const attrs = this.treeAdapter.getAttrList(element);
697
-
698
- return foreignContent.isIntegrationPoint(tn, ns, attrs, foreignNS);
699
- }
700
-
701
- //Active formatting elements reconstruction
702
- _reconstructActiveFormattingElements() {
703
- const listLength = this.activeFormattingElements.length;
704
-
705
- if (listLength) {
706
- let unopenIdx = listLength;
707
- let entry = null;
708
-
709
- do {
710
- unopenIdx--;
711
- entry = this.activeFormattingElements.entries[unopenIdx];
712
-
713
- if (entry.type === FormattingElementList.MARKER_ENTRY || this.openElements.contains(entry.element)) {
714
- unopenIdx++;
715
- break;
716
- }
717
- } while (unopenIdx > 0);
718
-
719
- for (let i = unopenIdx; i < listLength; i++) {
720
- entry = this.activeFormattingElements.entries[i];
721
- this._insertElement(entry.token, this.treeAdapter.getNamespaceURI(entry.element));
722
- entry.element = this.openElements.current;
723
- }
724
- }
725
- }
726
-
727
- //Close elements
728
- _closeTableCell() {
729
- this.openElements.generateImpliedEndTags();
730
- this.openElements.popUntilTableCellPopped();
731
- this.activeFormattingElements.clearToLastMarker();
732
- this.insertionMode = IN_ROW_MODE;
733
- }
734
-
735
- _closePElement() {
736
- this.openElements.generateImpliedEndTagsWithExclusion($.P);
737
- this.openElements.popUntilTagNamePopped($.P);
738
- }
739
-
740
- //Insertion modes
741
- _resetInsertionMode() {
742
- for (let i = this.openElements.stackTop, last = false; i >= 0; i--) {
743
- let element = this.openElements.items[i];
744
-
745
- if (i === 0) {
746
- last = true;
747
-
748
- if (this.fragmentContext) {
749
- element = this.fragmentContext;
750
- }
751
- }
752
-
753
- const tn = this.treeAdapter.getTagName(element);
754
- const newInsertionMode = INSERTION_MODE_RESET_MAP[tn];
755
-
756
- if (newInsertionMode) {
757
- this.insertionMode = newInsertionMode;
758
- break;
759
- } else if (!last && (tn === $.TD || tn === $.TH)) {
760
- this.insertionMode = IN_CELL_MODE;
761
- break;
762
- } else if (!last && tn === $.HEAD) {
763
- this.insertionMode = IN_HEAD_MODE;
764
- break;
765
- } else if (tn === $.SELECT) {
766
- this._resetInsertionModeForSelect(i);
767
- break;
768
- } else if (tn === $.TEMPLATE) {
769
- this.insertionMode = this.currentTmplInsertionMode;
770
- break;
771
- } else if (tn === $.HTML) {
772
- this.insertionMode = this.headElement ? AFTER_HEAD_MODE : BEFORE_HEAD_MODE;
773
- break;
774
- } else if (last) {
775
- this.insertionMode = IN_BODY_MODE;
776
- break;
777
- }
778
- }
779
- }
780
-
781
- _resetInsertionModeForSelect(selectIdx) {
782
- if (selectIdx > 0) {
783
- for (let i = selectIdx - 1; i > 0; i--) {
784
- const ancestor = this.openElements.items[i];
785
- const tn = this.treeAdapter.getTagName(ancestor);
786
-
787
- if (tn === $.TEMPLATE) {
788
- break;
789
- } else if (tn === $.TABLE) {
790
- this.insertionMode = IN_SELECT_IN_TABLE_MODE;
791
- return;
792
- }
793
- }
794
- }
795
-
796
- this.insertionMode = IN_SELECT_MODE;
797
- }
798
-
799
- _pushTmplInsertionMode(mode) {
800
- this.tmplInsertionModeStack.push(mode);
801
- this.tmplInsertionModeStackTop++;
802
- this.currentTmplInsertionMode = mode;
803
- }
804
-
805
- _popTmplInsertionMode() {
806
- this.tmplInsertionModeStack.pop();
807
- this.tmplInsertionModeStackTop--;
808
- this.currentTmplInsertionMode = this.tmplInsertionModeStack[this.tmplInsertionModeStackTop];
809
- }
810
-
811
- //Foster parenting
812
- _isElementCausesFosterParenting(element) {
813
- const tn = this.treeAdapter.getTagName(element);
814
-
815
- return tn === $.TABLE || tn === $.TBODY || tn === $.TFOOT || tn === $.THEAD || tn === $.TR;
816
- }
817
-
818
- _shouldFosterParentOnInsertion() {
819
- return this.fosterParentingEnabled && this._isElementCausesFosterParenting(this.openElements.current);
820
- }
821
-
822
- _findFosterParentingLocation() {
823
- const location = {
824
- parent: null,
825
- beforeElement: null
826
- };
827
-
828
- for (let i = this.openElements.stackTop; i >= 0; i--) {
829
- const openElement = this.openElements.items[i];
830
- const tn = this.treeAdapter.getTagName(openElement);
831
- const ns = this.treeAdapter.getNamespaceURI(openElement);
832
-
833
- if (tn === $.TEMPLATE && ns === NS.HTML) {
834
- location.parent = this.treeAdapter.getTemplateContent(openElement);
835
- break;
836
- } else if (tn === $.TABLE) {
837
- location.parent = this.treeAdapter.getParentNode(openElement);
838
-
839
- if (location.parent) {
840
- location.beforeElement = openElement;
841
- } else {
842
- location.parent = this.openElements.items[i - 1];
843
- }
844
-
845
- break;
846
- }
847
- }
848
-
849
- if (!location.parent) {
850
- location.parent = this.openElements.items[0];
851
- }
852
-
853
- return location;
854
- }
855
-
856
- _fosterParentElement(element) {
857
- const location = this._findFosterParentingLocation();
858
-
859
- if (location.beforeElement) {
860
- this.treeAdapter.insertBefore(location.parent, element, location.beforeElement);
861
- } else {
862
- this.treeAdapter.appendChild(location.parent, element);
863
- }
864
- }
865
-
866
- _fosterParentText(chars) {
867
- const location = this._findFosterParentingLocation();
868
-
869
- if (location.beforeElement) {
870
- this.treeAdapter.insertTextBefore(location.parent, chars, location.beforeElement);
871
- } else {
872
- this.treeAdapter.insertText(location.parent, chars);
873
- }
874
- }
875
-
876
- //Special elements
877
- _isSpecialElement(element) {
878
- const tn = this.treeAdapter.getTagName(element);
879
- const ns = this.treeAdapter.getNamespaceURI(element);
880
-
881
- return HTML.SPECIAL_ELEMENTS[ns][tn];
882
- }
883
- }
884
-
885
- module.exports = Parser;
886
-
887
- //Adoption agency algorithm
888
- //(see: http://www.whatwg.org/specs/web-apps/current-work/multipage/tree-construction.html#adoptionAgency)
889
- //------------------------------------------------------------------
890
-
891
- //Steps 5-8 of the algorithm
892
- function aaObtainFormattingElementEntry(p, token) {
893
- let formattingElementEntry = p.activeFormattingElements.getElementEntryInScopeWithTagName(token.tagName);
894
-
895
- if (formattingElementEntry) {
896
- if (!p.openElements.contains(formattingElementEntry.element)) {
897
- p.activeFormattingElements.removeEntry(formattingElementEntry);
898
- formattingElementEntry = null;
899
- } else if (!p.openElements.hasInScope(token.tagName)) {
900
- formattingElementEntry = null;
901
- }
902
- } else {
903
- genericEndTagInBody(p, token);
904
- }
905
-
906
- return formattingElementEntry;
907
- }
908
-
909
- //Steps 9 and 10 of the algorithm
910
- function aaObtainFurthestBlock(p, formattingElementEntry) {
911
- let furthestBlock = null;
912
-
913
- for (let i = p.openElements.stackTop; i >= 0; i--) {
914
- const element = p.openElements.items[i];
915
-
916
- if (element === formattingElementEntry.element) {
917
- break;
918
- }
919
-
920
- if (p._isSpecialElement(element)) {
921
- furthestBlock = element;
922
- }
923
- }
924
-
925
- if (!furthestBlock) {
926
- p.openElements.popUntilElementPopped(formattingElementEntry.element);
927
- p.activeFormattingElements.removeEntry(formattingElementEntry);
928
- }
929
-
930
- return furthestBlock;
931
- }
932
-
933
- //Step 13 of the algorithm
934
- function aaInnerLoop(p, furthestBlock, formattingElement) {
935
- let lastElement = furthestBlock;
936
- let nextElement = p.openElements.getCommonAncestor(furthestBlock);
937
-
938
- for (let i = 0, element = nextElement; element !== formattingElement; i++, element = nextElement) {
939
- //NOTE: store next element for the next loop iteration (it may be deleted from the stack by step 9.5)
940
- nextElement = p.openElements.getCommonAncestor(element);
941
-
942
- const elementEntry = p.activeFormattingElements.getElementEntry(element);
943
- const counterOverflow = elementEntry && i >= AA_INNER_LOOP_ITER;
944
- const shouldRemoveFromOpenElements = !elementEntry || counterOverflow;
945
-
946
- if (shouldRemoveFromOpenElements) {
947
- if (counterOverflow) {
948
- p.activeFormattingElements.removeEntry(elementEntry);
949
- }
950
-
951
- p.openElements.remove(element);
952
- } else {
953
- element = aaRecreateElementFromEntry(p, elementEntry);
954
-
955
- if (lastElement === furthestBlock) {
956
- p.activeFormattingElements.bookmark = elementEntry;
957
- }
958
-
959
- p.treeAdapter.detachNode(lastElement);
960
- p.treeAdapter.appendChild(element, lastElement);
961
- lastElement = element;
962
- }
963
- }
964
-
965
- return lastElement;
966
- }
967
-
968
- //Step 13.7 of the algorithm
969
- function aaRecreateElementFromEntry(p, elementEntry) {
970
- const ns = p.treeAdapter.getNamespaceURI(elementEntry.element);
971
- const newElement = p.treeAdapter.createElement(elementEntry.token.tagName, ns, elementEntry.token.attrs);
972
-
973
- p.openElements.replace(elementEntry.element, newElement);
974
- elementEntry.element = newElement;
975
-
976
- return newElement;
977
- }
978
-
979
- //Step 14 of the algorithm
980
- function aaInsertLastNodeInCommonAncestor(p, commonAncestor, lastElement) {
981
- if (p._isElementCausesFosterParenting(commonAncestor)) {
982
- p._fosterParentElement(lastElement);
983
- } else {
984
- const tn = p.treeAdapter.getTagName(commonAncestor);
985
- const ns = p.treeAdapter.getNamespaceURI(commonAncestor);
986
-
987
- if (tn === $.TEMPLATE && ns === NS.HTML) {
988
- commonAncestor = p.treeAdapter.getTemplateContent(commonAncestor);
989
- }
990
-
991
- p.treeAdapter.appendChild(commonAncestor, lastElement);
992
- }
993
- }
994
-
995
- //Steps 15-19 of the algorithm
996
- function aaReplaceFormattingElement(p, furthestBlock, formattingElementEntry) {
997
- const ns = p.treeAdapter.getNamespaceURI(formattingElementEntry.element);
998
- const token = formattingElementEntry.token;
999
- const newElement = p.treeAdapter.createElement(token.tagName, ns, token.attrs);
1000
-
1001
- p._adoptNodes(furthestBlock, newElement);
1002
- p.treeAdapter.appendChild(furthestBlock, newElement);
1003
-
1004
- p.activeFormattingElements.insertElementAfterBookmark(newElement, formattingElementEntry.token);
1005
- p.activeFormattingElements.removeEntry(formattingElementEntry);
1006
-
1007
- p.openElements.remove(formattingElementEntry.element);
1008
- p.openElements.insertAfter(furthestBlock, newElement);
1009
- }
1010
-
1011
- //Algorithm entry point
1012
- function callAdoptionAgency(p, token) {
1013
- let formattingElementEntry;
1014
-
1015
- for (let i = 0; i < AA_OUTER_LOOP_ITER; i++) {
1016
- formattingElementEntry = aaObtainFormattingElementEntry(p, token, formattingElementEntry);
1017
-
1018
- if (!formattingElementEntry) {
1019
- break;
1020
- }
1021
-
1022
- const furthestBlock = aaObtainFurthestBlock(p, formattingElementEntry);
1023
-
1024
- if (!furthestBlock) {
1025
- break;
1026
- }
1027
-
1028
- p.activeFormattingElements.bookmark = formattingElementEntry;
1029
-
1030
- const lastElement = aaInnerLoop(p, furthestBlock, formattingElementEntry.element);
1031
- const commonAncestor = p.openElements.getCommonAncestor(formattingElementEntry.element);
1032
-
1033
- p.treeAdapter.detachNode(lastElement);
1034
- aaInsertLastNodeInCommonAncestor(p, commonAncestor, lastElement);
1035
- aaReplaceFormattingElement(p, furthestBlock, formattingElementEntry);
1036
- }
1037
- }
1038
-
1039
- //Generic token handlers
1040
- //------------------------------------------------------------------
1041
- function ignoreToken() {
1042
- //NOTE: do nothing =)
1043
- }
1044
-
1045
- function misplacedDoctype(p) {
1046
- p._err(ERR.misplacedDoctype);
1047
- }
1048
-
1049
- function appendComment(p, token) {
1050
- p._appendCommentNode(token, p.openElements.currentTmplContent || p.openElements.current);
1051
- }
1052
-
1053
- function appendCommentToRootHtmlElement(p, token) {
1054
- p._appendCommentNode(token, p.openElements.items[0]);
1055
- }
1056
-
1057
- function appendCommentToDocument(p, token) {
1058
- p._appendCommentNode(token, p.document);
1059
- }
1060
-
1061
- function insertCharacters(p, token) {
1062
- p._insertCharacters(token);
1063
- }
1064
-
1065
- function stopParsing(p) {
1066
- p.stopped = true;
1067
- }
1068
-
1069
- // The "initial" insertion mode
1070
- //------------------------------------------------------------------
1071
- function doctypeInInitialMode(p, token) {
1072
- p._setDocumentType(token);
1073
-
1074
- const mode = token.forceQuirks ? HTML.DOCUMENT_MODE.QUIRKS : doctype.getDocumentMode(token);
1075
-
1076
- if (!doctype.isConforming(token)) {
1077
- p._err(ERR.nonConformingDoctype);
1078
- }
1079
-
1080
- p.treeAdapter.setDocumentMode(p.document, mode);
1081
-
1082
- p.insertionMode = BEFORE_HTML_MODE;
1083
- }
1084
-
1085
- function tokenInInitialMode(p, token) {
1086
- p._err(ERR.missingDoctype, { beforeToken: true });
1087
- p.treeAdapter.setDocumentMode(p.document, HTML.DOCUMENT_MODE.QUIRKS);
1088
- p.insertionMode = BEFORE_HTML_MODE;
1089
- p._processToken(token);
1090
- }
1091
-
1092
- // The "before html" insertion mode
1093
- //------------------------------------------------------------------
1094
- function startTagBeforeHtml(p, token) {
1095
- if (token.tagName === $.HTML) {
1096
- p._insertElement(token, NS.HTML);
1097
- p.insertionMode = BEFORE_HEAD_MODE;
1098
- } else {
1099
- tokenBeforeHtml(p, token);
1100
- }
1101
- }
1102
-
1103
- function endTagBeforeHtml(p, token) {
1104
- const tn = token.tagName;
1105
-
1106
- if (tn === $.HTML || tn === $.HEAD || tn === $.BODY || tn === $.BR) {
1107
- tokenBeforeHtml(p, token);
1108
- }
1109
- }
1110
-
1111
- function tokenBeforeHtml(p, token) {
1112
- p._insertFakeRootElement();
1113
- p.insertionMode = BEFORE_HEAD_MODE;
1114
- p._processToken(token);
1115
- }
1116
-
1117
- // The "before head" insertion mode
1118
- //------------------------------------------------------------------
1119
- function startTagBeforeHead(p, token) {
1120
- const tn = token.tagName;
1121
-
1122
- if (tn === $.HTML) {
1123
- startTagInBody(p, token);
1124
- } else if (tn === $.HEAD) {
1125
- p._insertElement(token, NS.HTML);
1126
- p.headElement = p.openElements.current;
1127
- p.insertionMode = IN_HEAD_MODE;
1128
- } else {
1129
- tokenBeforeHead(p, token);
1130
- }
1131
- }
1132
-
1133
- function endTagBeforeHead(p, token) {
1134
- const tn = token.tagName;
1135
-
1136
- if (tn === $.HEAD || tn === $.BODY || tn === $.HTML || tn === $.BR) {
1137
- tokenBeforeHead(p, token);
1138
- } else {
1139
- p._err(ERR.endTagWithoutMatchingOpenElement);
1140
- }
1141
- }
1142
-
1143
- function tokenBeforeHead(p, token) {
1144
- p._insertFakeElement($.HEAD);
1145
- p.headElement = p.openElements.current;
1146
- p.insertionMode = IN_HEAD_MODE;
1147
- p._processToken(token);
1148
- }
1149
-
1150
- // The "in head" insertion mode
1151
- //------------------------------------------------------------------
1152
- function startTagInHead(p, token) {
1153
- const tn = token.tagName;
1154
-
1155
- if (tn === $.HTML) {
1156
- startTagInBody(p, token);
1157
- } else if (tn === $.BASE || tn === $.BASEFONT || tn === $.BGSOUND || tn === $.LINK || tn === $.META) {
1158
- p._appendElement(token, NS.HTML);
1159
- token.ackSelfClosing = true;
1160
- } else if (tn === $.TITLE) {
1161
- p._switchToTextParsing(token, Tokenizer.MODE.RCDATA);
1162
- } else if (tn === $.NOSCRIPT) {
1163
- if (p.options.scriptingEnabled) {
1164
- p._switchToTextParsing(token, Tokenizer.MODE.RAWTEXT);
1165
- } else {
1166
- p._insertElement(token, NS.HTML);
1167
- p.insertionMode = IN_HEAD_NO_SCRIPT_MODE;
1168
- }
1169
- } else if (tn === $.NOFRAMES || tn === $.STYLE) {
1170
- p._switchToTextParsing(token, Tokenizer.MODE.RAWTEXT);
1171
- } else if (tn === $.SCRIPT) {
1172
- p._switchToTextParsing(token, Tokenizer.MODE.SCRIPT_DATA);
1173
- } else if (tn === $.TEMPLATE) {
1174
- p._insertTemplate(token, NS.HTML);
1175
- p.activeFormattingElements.insertMarker();
1176
- p.framesetOk = false;
1177
- p.insertionMode = IN_TEMPLATE_MODE;
1178
- p._pushTmplInsertionMode(IN_TEMPLATE_MODE);
1179
- } else if (tn === $.HEAD) {
1180
- p._err(ERR.misplacedStartTagForHeadElement);
1181
- } else {
1182
- tokenInHead(p, token);
1183
- }
1184
- }
1185
-
1186
- function endTagInHead(p, token) {
1187
- const tn = token.tagName;
1188
-
1189
- if (tn === $.HEAD) {
1190
- p.openElements.pop();
1191
- p.insertionMode = AFTER_HEAD_MODE;
1192
- } else if (tn === $.BODY || tn === $.BR || tn === $.HTML) {
1193
- tokenInHead(p, token);
1194
- } else if (tn === $.TEMPLATE) {
1195
- if (p.openElements.tmplCount > 0) {
1196
- p.openElements.generateImpliedEndTagsThoroughly();
1197
-
1198
- if (p.openElements.currentTagName !== $.TEMPLATE) {
1199
- p._err(ERR.closingOfElementWithOpenChildElements);
1200
- }
1201
-
1202
- p.openElements.popUntilTagNamePopped($.TEMPLATE);
1203
- p.activeFormattingElements.clearToLastMarker();
1204
- p._popTmplInsertionMode();
1205
- p._resetInsertionMode();
1206
- } else {
1207
- p._err(ERR.endTagWithoutMatchingOpenElement);
1208
- }
1209
- } else {
1210
- p._err(ERR.endTagWithoutMatchingOpenElement);
1211
- }
1212
- }
1213
-
1214
- function tokenInHead(p, token) {
1215
- p.openElements.pop();
1216
- p.insertionMode = AFTER_HEAD_MODE;
1217
- p._processToken(token);
1218
- }
1219
-
1220
- // The "in head no script" insertion mode
1221
- //------------------------------------------------------------------
1222
- function startTagInHeadNoScript(p, token) {
1223
- const tn = token.tagName;
1224
-
1225
- if (tn === $.HTML) {
1226
- startTagInBody(p, token);
1227
- } else if (
1228
- tn === $.BASEFONT ||
1229
- tn === $.BGSOUND ||
1230
- tn === $.HEAD ||
1231
- tn === $.LINK ||
1232
- tn === $.META ||
1233
- tn === $.NOFRAMES ||
1234
- tn === $.STYLE
1235
- ) {
1236
- startTagInHead(p, token);
1237
- } else if (tn === $.NOSCRIPT) {
1238
- p._err(ERR.nestedNoscriptInHead);
1239
- } else {
1240
- tokenInHeadNoScript(p, token);
1241
- }
1242
- }
1243
-
1244
- function endTagInHeadNoScript(p, token) {
1245
- const tn = token.tagName;
1246
-
1247
- if (tn === $.NOSCRIPT) {
1248
- p.openElements.pop();
1249
- p.insertionMode = IN_HEAD_MODE;
1250
- } else if (tn === $.BR) {
1251
- tokenInHeadNoScript(p, token);
1252
- } else {
1253
- p._err(ERR.endTagWithoutMatchingOpenElement);
1254
- }
1255
- }
1256
-
1257
- function tokenInHeadNoScript(p, token) {
1258
- const errCode =
1259
- token.type === Tokenizer.EOF_TOKEN ? ERR.openElementsLeftAfterEof : ERR.disallowedContentInNoscriptInHead;
1260
-
1261
- p._err(errCode);
1262
- p.openElements.pop();
1263
- p.insertionMode = IN_HEAD_MODE;
1264
- p._processToken(token);
1265
- }
1266
-
1267
- // The "after head" insertion mode
1268
- //------------------------------------------------------------------
1269
- function startTagAfterHead(p, token) {
1270
- const tn = token.tagName;
1271
-
1272
- if (tn === $.HTML) {
1273
- startTagInBody(p, token);
1274
- } else if (tn === $.BODY) {
1275
- p._insertElement(token, NS.HTML);
1276
- p.framesetOk = false;
1277
- p.insertionMode = IN_BODY_MODE;
1278
- } else if (tn === $.FRAMESET) {
1279
- p._insertElement(token, NS.HTML);
1280
- p.insertionMode = IN_FRAMESET_MODE;
1281
- } else if (
1282
- tn === $.BASE ||
1283
- tn === $.BASEFONT ||
1284
- tn === $.BGSOUND ||
1285
- tn === $.LINK ||
1286
- tn === $.META ||
1287
- tn === $.NOFRAMES ||
1288
- tn === $.SCRIPT ||
1289
- tn === $.STYLE ||
1290
- tn === $.TEMPLATE ||
1291
- tn === $.TITLE
1292
- ) {
1293
- p._err(ERR.abandonedHeadElementChild);
1294
- p.openElements.push(p.headElement);
1295
- startTagInHead(p, token);
1296
- p.openElements.remove(p.headElement);
1297
- } else if (tn === $.HEAD) {
1298
- p._err(ERR.misplacedStartTagForHeadElement);
1299
- } else {
1300
- tokenAfterHead(p, token);
1301
- }
1302
- }
1303
-
1304
- function endTagAfterHead(p, token) {
1305
- const tn = token.tagName;
1306
-
1307
- if (tn === $.BODY || tn === $.HTML || tn === $.BR) {
1308
- tokenAfterHead(p, token);
1309
- } else if (tn === $.TEMPLATE) {
1310
- endTagInHead(p, token);
1311
- } else {
1312
- p._err(ERR.endTagWithoutMatchingOpenElement);
1313
- }
1314
- }
1315
-
1316
- function tokenAfterHead(p, token) {
1317
- p._insertFakeElement($.BODY);
1318
- p.insertionMode = IN_BODY_MODE;
1319
- p._processToken(token);
1320
- }
1321
-
1322
- // The "in body" insertion mode
1323
- //------------------------------------------------------------------
1324
- function whitespaceCharacterInBody(p, token) {
1325
- p._reconstructActiveFormattingElements();
1326
- p._insertCharacters(token);
1327
- }
1328
-
1329
- function characterInBody(p, token) {
1330
- p._reconstructActiveFormattingElements();
1331
- p._insertCharacters(token);
1332
- p.framesetOk = false;
1333
- }
1334
-
1335
- function htmlStartTagInBody(p, token) {
1336
- if (p.openElements.tmplCount === 0) {
1337
- p.treeAdapter.adoptAttributes(p.openElements.items[0], token.attrs);
1338
- }
1339
- }
1340
-
1341
- function bodyStartTagInBody(p, token) {
1342
- const bodyElement = p.openElements.tryPeekProperlyNestedBodyElement();
1343
-
1344
- if (bodyElement && p.openElements.tmplCount === 0) {
1345
- p.framesetOk = false;
1346
- p.treeAdapter.adoptAttributes(bodyElement, token.attrs);
1347
- }
1348
- }
1349
-
1350
- function framesetStartTagInBody(p, token) {
1351
- const bodyElement = p.openElements.tryPeekProperlyNestedBodyElement();
1352
-
1353
- if (p.framesetOk && bodyElement) {
1354
- p.treeAdapter.detachNode(bodyElement);
1355
- p.openElements.popAllUpToHtmlElement();
1356
- p._insertElement(token, NS.HTML);
1357
- p.insertionMode = IN_FRAMESET_MODE;
1358
- }
1359
- }
1360
-
1361
- function addressStartTagInBody(p, token) {
1362
- if (p.openElements.hasInButtonScope($.P)) {
1363
- p._closePElement();
1364
- }
1365
-
1366
- p._insertElement(token, NS.HTML);
1367
- }
1368
-
1369
- function numberedHeaderStartTagInBody(p, token) {
1370
- if (p.openElements.hasInButtonScope($.P)) {
1371
- p._closePElement();
1372
- }
1373
-
1374
- const tn = p.openElements.currentTagName;
1375
-
1376
- if (tn === $.H1 || tn === $.H2 || tn === $.H3 || tn === $.H4 || tn === $.H5 || tn === $.H6) {
1377
- p.openElements.pop();
1378
- }
1379
-
1380
- p._insertElement(token, NS.HTML);
1381
- }
1382
-
1383
- function preStartTagInBody(p, token) {
1384
- if (p.openElements.hasInButtonScope($.P)) {
1385
- p._closePElement();
1386
- }
1387
-
1388
- p._insertElement(token, NS.HTML);
1389
- //NOTE: If the next token is a U+000A LINE FEED (LF) character token, then ignore that token and move
1390
- //on to the next one. (Newlines at the start of pre blocks are ignored as an authoring convenience.)
1391
- p.skipNextNewLine = true;
1392
- p.framesetOk = false;
1393
- }
1394
-
1395
- function formStartTagInBody(p, token) {
1396
- const inTemplate = p.openElements.tmplCount > 0;
1397
-
1398
- if (!p.formElement || inTemplate) {
1399
- if (p.openElements.hasInButtonScope($.P)) {
1400
- p._closePElement();
1401
- }
1402
-
1403
- p._insertElement(token, NS.HTML);
1404
-
1405
- if (!inTemplate) {
1406
- p.formElement = p.openElements.current;
1407
- }
1408
- }
1409
- }
1410
-
1411
- function listItemStartTagInBody(p, token) {
1412
- p.framesetOk = false;
1413
-
1414
- const tn = token.tagName;
1415
-
1416
- for (let i = p.openElements.stackTop; i >= 0; i--) {
1417
- const element = p.openElements.items[i];
1418
- const elementTn = p.treeAdapter.getTagName(element);
1419
- let closeTn = null;
1420
-
1421
- if (tn === $.LI && elementTn === $.LI) {
1422
- closeTn = $.LI;
1423
- } else if ((tn === $.DD || tn === $.DT) && (elementTn === $.DD || elementTn === $.DT)) {
1424
- closeTn = elementTn;
1425
- }
1426
-
1427
- if (closeTn) {
1428
- p.openElements.generateImpliedEndTagsWithExclusion(closeTn);
1429
- p.openElements.popUntilTagNamePopped(closeTn);
1430
- break;
1431
- }
1432
-
1433
- if (elementTn !== $.ADDRESS && elementTn !== $.DIV && elementTn !== $.P && p._isSpecialElement(element)) {
1434
- break;
1435
- }
1436
- }
1437
-
1438
- if (p.openElements.hasInButtonScope($.P)) {
1439
- p._closePElement();
1440
- }
1441
-
1442
- p._insertElement(token, NS.HTML);
1443
- }
1444
-
1445
- function plaintextStartTagInBody(p, token) {
1446
- if (p.openElements.hasInButtonScope($.P)) {
1447
- p._closePElement();
1448
- }
1449
-
1450
- p._insertElement(token, NS.HTML);
1451
- p.tokenizer.state = Tokenizer.MODE.PLAINTEXT;
1452
- }
1453
-
1454
- function buttonStartTagInBody(p, token) {
1455
- if (p.openElements.hasInScope($.BUTTON)) {
1456
- p.openElements.generateImpliedEndTags();
1457
- p.openElements.popUntilTagNamePopped($.BUTTON);
1458
- }
1459
-
1460
- p._reconstructActiveFormattingElements();
1461
- p._insertElement(token, NS.HTML);
1462
- p.framesetOk = false;
1463
- }
1464
-
1465
- function aStartTagInBody(p, token) {
1466
- const activeElementEntry = p.activeFormattingElements.getElementEntryInScopeWithTagName($.A);
1467
-
1468
- if (activeElementEntry) {
1469
- callAdoptionAgency(p, token);
1470
- p.openElements.remove(activeElementEntry.element);
1471
- p.activeFormattingElements.removeEntry(activeElementEntry);
1472
- }
1473
-
1474
- p._reconstructActiveFormattingElements();
1475
- p._insertElement(token, NS.HTML);
1476
- p.activeFormattingElements.pushElement(p.openElements.current, token);
1477
- }
1478
-
1479
- function bStartTagInBody(p, token) {
1480
- p._reconstructActiveFormattingElements();
1481
- p._insertElement(token, NS.HTML);
1482
- p.activeFormattingElements.pushElement(p.openElements.current, token);
1483
- }
1484
-
1485
- function nobrStartTagInBody(p, token) {
1486
- p._reconstructActiveFormattingElements();
1487
-
1488
- if (p.openElements.hasInScope($.NOBR)) {
1489
- callAdoptionAgency(p, token);
1490
- p._reconstructActiveFormattingElements();
1491
- }
1492
-
1493
- p._insertElement(token, NS.HTML);
1494
- p.activeFormattingElements.pushElement(p.openElements.current, token);
1495
- }
1496
-
1497
- function appletStartTagInBody(p, token) {
1498
- p._reconstructActiveFormattingElements();
1499
- p._insertElement(token, NS.HTML);
1500
- p.activeFormattingElements.insertMarker();
1501
- p.framesetOk = false;
1502
- }
1503
-
1504
- function tableStartTagInBody(p, token) {
1505
- if (
1506
- p.treeAdapter.getDocumentMode(p.document) !== HTML.DOCUMENT_MODE.QUIRKS &&
1507
- p.openElements.hasInButtonScope($.P)
1508
- ) {
1509
- p._closePElement();
1510
- }
1511
-
1512
- p._insertElement(token, NS.HTML);
1513
- p.framesetOk = false;
1514
- p.insertionMode = IN_TABLE_MODE;
1515
- }
1516
-
1517
- function areaStartTagInBody(p, token) {
1518
- p._reconstructActiveFormattingElements();
1519
- p._appendElement(token, NS.HTML);
1520
- p.framesetOk = false;
1521
- token.ackSelfClosing = true;
1522
- }
1523
-
1524
- function inputStartTagInBody(p, token) {
1525
- p._reconstructActiveFormattingElements();
1526
- p._appendElement(token, NS.HTML);
1527
-
1528
- const inputType = Tokenizer.getTokenAttr(token, ATTRS.TYPE);
1529
-
1530
- if (!inputType || inputType.toLowerCase() !== HIDDEN_INPUT_TYPE) {
1531
- p.framesetOk = false;
1532
- }
1533
-
1534
- token.ackSelfClosing = true;
1535
- }
1536
-
1537
- function paramStartTagInBody(p, token) {
1538
- p._appendElement(token, NS.HTML);
1539
- token.ackSelfClosing = true;
1540
- }
1541
-
1542
- function hrStartTagInBody(p, token) {
1543
- if (p.openElements.hasInButtonScope($.P)) {
1544
- p._closePElement();
1545
- }
1546
-
1547
- p._appendElement(token, NS.HTML);
1548
- p.framesetOk = false;
1549
- token.ackSelfClosing = true;
1550
- }
1551
-
1552
- function imageStartTagInBody(p, token) {
1553
- token.tagName = $.IMG;
1554
- areaStartTagInBody(p, token);
1555
- }
1556
-
1557
- function textareaStartTagInBody(p, token) {
1558
- p._insertElement(token, NS.HTML);
1559
- //NOTE: If the next token is a U+000A LINE FEED (LF) character token, then ignore that token and move
1560
- //on to the next one. (Newlines at the start of textarea elements are ignored as an authoring convenience.)
1561
- p.skipNextNewLine = true;
1562
- p.tokenizer.state = Tokenizer.MODE.RCDATA;
1563
- p.originalInsertionMode = p.insertionMode;
1564
- p.framesetOk = false;
1565
- p.insertionMode = TEXT_MODE;
1566
- }
1567
-
1568
- function xmpStartTagInBody(p, token) {
1569
- if (p.openElements.hasInButtonScope($.P)) {
1570
- p._closePElement();
1571
- }
1572
-
1573
- p._reconstructActiveFormattingElements();
1574
- p.framesetOk = false;
1575
- p._switchToTextParsing(token, Tokenizer.MODE.RAWTEXT);
1576
- }
1577
-
1578
- function iframeStartTagInBody(p, token) {
1579
- p.framesetOk = false;
1580
- p._switchToTextParsing(token, Tokenizer.MODE.RAWTEXT);
1581
- }
1582
-
1583
- //NOTE: here we assume that we always act as an user agent with enabled plugins, so we parse
1584
- //<noembed> as a rawtext.
1585
- function noembedStartTagInBody(p, token) {
1586
- p._switchToTextParsing(token, Tokenizer.MODE.RAWTEXT);
1587
- }
1588
-
1589
- function selectStartTagInBody(p, token) {
1590
- p._reconstructActiveFormattingElements();
1591
- p._insertElement(token, NS.HTML);
1592
- p.framesetOk = false;
1593
-
1594
- if (
1595
- p.insertionMode === IN_TABLE_MODE ||
1596
- p.insertionMode === IN_CAPTION_MODE ||
1597
- p.insertionMode === IN_TABLE_BODY_MODE ||
1598
- p.insertionMode === IN_ROW_MODE ||
1599
- p.insertionMode === IN_CELL_MODE
1600
- ) {
1601
- p.insertionMode = IN_SELECT_IN_TABLE_MODE;
1602
- } else {
1603
- p.insertionMode = IN_SELECT_MODE;
1604
- }
1605
- }
1606
-
1607
- function optgroupStartTagInBody(p, token) {
1608
- if (p.openElements.currentTagName === $.OPTION) {
1609
- p.openElements.pop();
1610
- }
1611
-
1612
- p._reconstructActiveFormattingElements();
1613
- p._insertElement(token, NS.HTML);
1614
- }
1615
-
1616
- function rbStartTagInBody(p, token) {
1617
- if (p.openElements.hasInScope($.RUBY)) {
1618
- p.openElements.generateImpliedEndTags();
1619
- }
1620
-
1621
- p._insertElement(token, NS.HTML);
1622
- }
1623
-
1624
- function rtStartTagInBody(p, token) {
1625
- if (p.openElements.hasInScope($.RUBY)) {
1626
- p.openElements.generateImpliedEndTagsWithExclusion($.RTC);
1627
- }
1628
-
1629
- p._insertElement(token, NS.HTML);
1630
- }
1631
-
1632
- function menuStartTagInBody(p, token) {
1633
- if (p.openElements.hasInButtonScope($.P)) {
1634
- p._closePElement();
1635
- }
1636
-
1637
- p._insertElement(token, NS.HTML);
1638
- }
1639
-
1640
- function mathStartTagInBody(p, token) {
1641
- p._reconstructActiveFormattingElements();
1642
-
1643
- foreignContent.adjustTokenMathMLAttrs(token);
1644
- foreignContent.adjustTokenXMLAttrs(token);
1645
-
1646
- if (token.selfClosing) {
1647
- p._appendElement(token, NS.MATHML);
1648
- } else {
1649
- p._insertElement(token, NS.MATHML);
1650
- }
1651
-
1652
- token.ackSelfClosing = true;
1653
- }
1654
-
1655
- function svgStartTagInBody(p, token) {
1656
- p._reconstructActiveFormattingElements();
1657
-
1658
- foreignContent.adjustTokenSVGAttrs(token);
1659
- foreignContent.adjustTokenXMLAttrs(token);
1660
-
1661
- if (token.selfClosing) {
1662
- p._appendElement(token, NS.SVG);
1663
- } else {
1664
- p._insertElement(token, NS.SVG);
1665
- }
1666
-
1667
- token.ackSelfClosing = true;
1668
- }
1669
-
1670
- function genericStartTagInBody(p, token) {
1671
- p._reconstructActiveFormattingElements();
1672
- p._insertElement(token, NS.HTML);
1673
- }
1674
-
1675
- //OPTIMIZATION: Integer comparisons are low-cost, so we can use very fast tag name length filters here.
1676
- //It's faster than using dictionary.
1677
- function startTagInBody(p, token) {
1678
- const tn = token.tagName;
1679
-
1680
- switch (tn.length) {
1681
- case 1:
1682
- if (tn === $.I || tn === $.S || tn === $.B || tn === $.U) {
1683
- bStartTagInBody(p, token);
1684
- } else if (tn === $.P) {
1685
- addressStartTagInBody(p, token);
1686
- } else if (tn === $.A) {
1687
- aStartTagInBody(p, token);
1688
- } else {
1689
- genericStartTagInBody(p, token);
1690
- }
1691
-
1692
- break;
1693
-
1694
- case 2:
1695
- if (tn === $.DL || tn === $.OL || tn === $.UL) {
1696
- addressStartTagInBody(p, token);
1697
- } else if (tn === $.H1 || tn === $.H2 || tn === $.H3 || tn === $.H4 || tn === $.H5 || tn === $.H6) {
1698
- numberedHeaderStartTagInBody(p, token);
1699
- } else if (tn === $.LI || tn === $.DD || tn === $.DT) {
1700
- listItemStartTagInBody(p, token);
1701
- } else if (tn === $.EM || tn === $.TT) {
1702
- bStartTagInBody(p, token);
1703
- } else if (tn === $.BR) {
1704
- areaStartTagInBody(p, token);
1705
- } else if (tn === $.HR) {
1706
- hrStartTagInBody(p, token);
1707
- } else if (tn === $.RB) {
1708
- rbStartTagInBody(p, token);
1709
- } else if (tn === $.RT || tn === $.RP) {
1710
- rtStartTagInBody(p, token);
1711
- } else if (tn !== $.TH && tn !== $.TD && tn !== $.TR) {
1712
- genericStartTagInBody(p, token);
1713
- }
1714
-
1715
- break;
1716
-
1717
- case 3:
1718
- if (tn === $.DIV || tn === $.DIR || tn === $.NAV) {
1719
- addressStartTagInBody(p, token);
1720
- } else if (tn === $.PRE) {
1721
- preStartTagInBody(p, token);
1722
- } else if (tn === $.BIG) {
1723
- bStartTagInBody(p, token);
1724
- } else if (tn === $.IMG || tn === $.WBR) {
1725
- areaStartTagInBody(p, token);
1726
- } else if (tn === $.XMP) {
1727
- xmpStartTagInBody(p, token);
1728
- } else if (tn === $.SVG) {
1729
- svgStartTagInBody(p, token);
1730
- } else if (tn === $.RTC) {
1731
- rbStartTagInBody(p, token);
1732
- } else if (tn !== $.COL) {
1733
- genericStartTagInBody(p, token);
1734
- }
1735
-
1736
- break;
1737
-
1738
- case 4:
1739
- if (tn === $.HTML) {
1740
- htmlStartTagInBody(p, token);
1741
- } else if (tn === $.BASE || tn === $.LINK || tn === $.META) {
1742
- startTagInHead(p, token);
1743
- } else if (tn === $.BODY) {
1744
- bodyStartTagInBody(p, token);
1745
- } else if (tn === $.MAIN || tn === $.MENU) {
1746
- addressStartTagInBody(p, token);
1747
- } else if (tn === $.FORM) {
1748
- formStartTagInBody(p, token);
1749
- } else if (tn === $.CODE || tn === $.FONT) {
1750
- bStartTagInBody(p, token);
1751
- } else if (tn === $.NOBR) {
1752
- nobrStartTagInBody(p, token);
1753
- } else if (tn === $.AREA) {
1754
- areaStartTagInBody(p, token);
1755
- } else if (tn === $.MATH) {
1756
- mathStartTagInBody(p, token);
1757
- } else if (tn === $.MENU) {
1758
- menuStartTagInBody(p, token);
1759
- } else if (tn !== $.HEAD) {
1760
- genericStartTagInBody(p, token);
1761
- }
1762
-
1763
- break;
1764
-
1765
- case 5:
1766
- if (tn === $.STYLE || tn === $.TITLE) {
1767
- startTagInHead(p, token);
1768
- } else if (tn === $.ASIDE) {
1769
- addressStartTagInBody(p, token);
1770
- } else if (tn === $.SMALL) {
1771
- bStartTagInBody(p, token);
1772
- } else if (tn === $.TABLE) {
1773
- tableStartTagInBody(p, token);
1774
- } else if (tn === $.EMBED) {
1775
- areaStartTagInBody(p, token);
1776
- } else if (tn === $.INPUT) {
1777
- inputStartTagInBody(p, token);
1778
- } else if (tn === $.PARAM || tn === $.TRACK) {
1779
- paramStartTagInBody(p, token);
1780
- } else if (tn === $.IMAGE) {
1781
- imageStartTagInBody(p, token);
1782
- } else if (tn !== $.FRAME && tn !== $.TBODY && tn !== $.TFOOT && tn !== $.THEAD) {
1783
- genericStartTagInBody(p, token);
1784
- }
1785
-
1786
- break;
1787
-
1788
- case 6:
1789
- if (tn === $.SCRIPT) {
1790
- startTagInHead(p, token);
1791
- } else if (
1792
- tn === $.CENTER ||
1793
- tn === $.FIGURE ||
1794
- tn === $.FOOTER ||
1795
- tn === $.HEADER ||
1796
- tn === $.HGROUP ||
1797
- tn === $.DIALOG
1798
- ) {
1799
- addressStartTagInBody(p, token);
1800
- } else if (tn === $.BUTTON) {
1801
- buttonStartTagInBody(p, token);
1802
- } else if (tn === $.STRIKE || tn === $.STRONG) {
1803
- bStartTagInBody(p, token);
1804
- } else if (tn === $.APPLET || tn === $.OBJECT) {
1805
- appletStartTagInBody(p, token);
1806
- } else if (tn === $.KEYGEN) {
1807
- areaStartTagInBody(p, token);
1808
- } else if (tn === $.SOURCE) {
1809
- paramStartTagInBody(p, token);
1810
- } else if (tn === $.IFRAME) {
1811
- iframeStartTagInBody(p, token);
1812
- } else if (tn === $.SELECT) {
1813
- selectStartTagInBody(p, token);
1814
- } else if (tn === $.OPTION) {
1815
- optgroupStartTagInBody(p, token);
1816
- } else {
1817
- genericStartTagInBody(p, token);
1818
- }
1819
-
1820
- break;
1821
-
1822
- case 7:
1823
- if (tn === $.BGSOUND) {
1824
- startTagInHead(p, token);
1825
- } else if (
1826
- tn === $.DETAILS ||
1827
- tn === $.ADDRESS ||
1828
- tn === $.ARTICLE ||
1829
- tn === $.SECTION ||
1830
- tn === $.SUMMARY
1831
- ) {
1832
- addressStartTagInBody(p, token);
1833
- } else if (tn === $.LISTING) {
1834
- preStartTagInBody(p, token);
1835
- } else if (tn === $.MARQUEE) {
1836
- appletStartTagInBody(p, token);
1837
- } else if (tn === $.NOEMBED) {
1838
- noembedStartTagInBody(p, token);
1839
- } else if (tn !== $.CAPTION) {
1840
- genericStartTagInBody(p, token);
1841
- }
1842
-
1843
- break;
1844
-
1845
- case 8:
1846
- if (tn === $.BASEFONT) {
1847
- startTagInHead(p, token);
1848
- } else if (tn === $.FRAMESET) {
1849
- framesetStartTagInBody(p, token);
1850
- } else if (tn === $.FIELDSET) {
1851
- addressStartTagInBody(p, token);
1852
- } else if (tn === $.TEXTAREA) {
1853
- textareaStartTagInBody(p, token);
1854
- } else if (tn === $.TEMPLATE) {
1855
- startTagInHead(p, token);
1856
- } else if (tn === $.NOSCRIPT) {
1857
- if (p.options.scriptingEnabled) {
1858
- noembedStartTagInBody(p, token);
1859
- } else {
1860
- genericStartTagInBody(p, token);
1861
- }
1862
- } else if (tn === $.OPTGROUP) {
1863
- optgroupStartTagInBody(p, token);
1864
- } else if (tn !== $.COLGROUP) {
1865
- genericStartTagInBody(p, token);
1866
- }
1867
-
1868
- break;
1869
-
1870
- case 9:
1871
- if (tn === $.PLAINTEXT) {
1872
- plaintextStartTagInBody(p, token);
1873
- } else {
1874
- genericStartTagInBody(p, token);
1875
- }
1876
-
1877
- break;
1878
-
1879
- case 10:
1880
- if (tn === $.BLOCKQUOTE || tn === $.FIGCAPTION) {
1881
- addressStartTagInBody(p, token);
1882
- } else {
1883
- genericStartTagInBody(p, token);
1884
- }
1885
-
1886
- break;
1887
-
1888
- default:
1889
- genericStartTagInBody(p, token);
1890
- }
1891
- }
1892
-
1893
- function bodyEndTagInBody(p) {
1894
- if (p.openElements.hasInScope($.BODY)) {
1895
- p.insertionMode = AFTER_BODY_MODE;
1896
- }
1897
- }
1898
-
1899
- function htmlEndTagInBody(p, token) {
1900
- if (p.openElements.hasInScope($.BODY)) {
1901
- p.insertionMode = AFTER_BODY_MODE;
1902
- p._processToken(token);
1903
- }
1904
- }
1905
-
1906
- function addressEndTagInBody(p, token) {
1907
- const tn = token.tagName;
1908
-
1909
- if (p.openElements.hasInScope(tn)) {
1910
- p.openElements.generateImpliedEndTags();
1911
- p.openElements.popUntilTagNamePopped(tn);
1912
- }
1913
- }
1914
-
1915
- function formEndTagInBody(p) {
1916
- const inTemplate = p.openElements.tmplCount > 0;
1917
- const formElement = p.formElement;
1918
-
1919
- if (!inTemplate) {
1920
- p.formElement = null;
1921
- }
1922
-
1923
- if ((formElement || inTemplate) && p.openElements.hasInScope($.FORM)) {
1924
- p.openElements.generateImpliedEndTags();
1925
-
1926
- if (inTemplate) {
1927
- p.openElements.popUntilTagNamePopped($.FORM);
1928
- } else {
1929
- p.openElements.remove(formElement);
1930
- }
1931
- }
1932
- }
1933
-
1934
- function pEndTagInBody(p) {
1935
- if (!p.openElements.hasInButtonScope($.P)) {
1936
- p._insertFakeElement($.P);
1937
- }
1938
-
1939
- p._closePElement();
1940
- }
1941
-
1942
- function liEndTagInBody(p) {
1943
- if (p.openElements.hasInListItemScope($.LI)) {
1944
- p.openElements.generateImpliedEndTagsWithExclusion($.LI);
1945
- p.openElements.popUntilTagNamePopped($.LI);
1946
- }
1947
- }
1948
-
1949
- function ddEndTagInBody(p, token) {
1950
- const tn = token.tagName;
1951
-
1952
- if (p.openElements.hasInScope(tn)) {
1953
- p.openElements.generateImpliedEndTagsWithExclusion(tn);
1954
- p.openElements.popUntilTagNamePopped(tn);
1955
- }
1956
- }
1957
-
1958
- function numberedHeaderEndTagInBody(p) {
1959
- if (p.openElements.hasNumberedHeaderInScope()) {
1960
- p.openElements.generateImpliedEndTags();
1961
- p.openElements.popUntilNumberedHeaderPopped();
1962
- }
1963
- }
1964
-
1965
- function appletEndTagInBody(p, token) {
1966
- const tn = token.tagName;
1967
-
1968
- if (p.openElements.hasInScope(tn)) {
1969
- p.openElements.generateImpliedEndTags();
1970
- p.openElements.popUntilTagNamePopped(tn);
1971
- p.activeFormattingElements.clearToLastMarker();
1972
- }
1973
- }
1974
-
1975
- function brEndTagInBody(p) {
1976
- p._reconstructActiveFormattingElements();
1977
- p._insertFakeElement($.BR);
1978
- p.openElements.pop();
1979
- p.framesetOk = false;
1980
- }
1981
-
1982
- function genericEndTagInBody(p, token) {
1983
- const tn = token.tagName;
1984
-
1985
- for (let i = p.openElements.stackTop; i > 0; i--) {
1986
- const element = p.openElements.items[i];
1987
-
1988
- if (p.treeAdapter.getTagName(element) === tn) {
1989
- p.openElements.generateImpliedEndTagsWithExclusion(tn);
1990
- p.openElements.popUntilElementPopped(element);
1991
- break;
1992
- }
1993
-
1994
- if (p._isSpecialElement(element)) {
1995
- break;
1996
- }
1997
- }
1998
- }
1999
-
2000
- //OPTIMIZATION: Integer comparisons are low-cost, so we can use very fast tag name length filters here.
2001
- //It's faster than using dictionary.
2002
- function endTagInBody(p, token) {
2003
- const tn = token.tagName;
2004
-
2005
- switch (tn.length) {
2006
- case 1:
2007
- if (tn === $.A || tn === $.B || tn === $.I || tn === $.S || tn === $.U) {
2008
- callAdoptionAgency(p, token);
2009
- } else if (tn === $.P) {
2010
- pEndTagInBody(p, token);
2011
- } else {
2012
- genericEndTagInBody(p, token);
2013
- }
2014
-
2015
- break;
2016
-
2017
- case 2:
2018
- if (tn === $.DL || tn === $.UL || tn === $.OL) {
2019
- addressEndTagInBody(p, token);
2020
- } else if (tn === $.LI) {
2021
- liEndTagInBody(p, token);
2022
- } else if (tn === $.DD || tn === $.DT) {
2023
- ddEndTagInBody(p, token);
2024
- } else if (tn === $.H1 || tn === $.H2 || tn === $.H3 || tn === $.H4 || tn === $.H5 || tn === $.H6) {
2025
- numberedHeaderEndTagInBody(p, token);
2026
- } else if (tn === $.BR) {
2027
- brEndTagInBody(p, token);
2028
- } else if (tn === $.EM || tn === $.TT) {
2029
- callAdoptionAgency(p, token);
2030
- } else {
2031
- genericEndTagInBody(p, token);
2032
- }
2033
-
2034
- break;
2035
-
2036
- case 3:
2037
- if (tn === $.BIG) {
2038
- callAdoptionAgency(p, token);
2039
- } else if (tn === $.DIR || tn === $.DIV || tn === $.NAV || tn === $.PRE) {
2040
- addressEndTagInBody(p, token);
2041
- } else {
2042
- genericEndTagInBody(p, token);
2043
- }
2044
-
2045
- break;
2046
-
2047
- case 4:
2048
- if (tn === $.BODY) {
2049
- bodyEndTagInBody(p, token);
2050
- } else if (tn === $.HTML) {
2051
- htmlEndTagInBody(p, token);
2052
- } else if (tn === $.FORM) {
2053
- formEndTagInBody(p, token);
2054
- } else if (tn === $.CODE || tn === $.FONT || tn === $.NOBR) {
2055
- callAdoptionAgency(p, token);
2056
- } else if (tn === $.MAIN || tn === $.MENU) {
2057
- addressEndTagInBody(p, token);
2058
- } else {
2059
- genericEndTagInBody(p, token);
2060
- }
2061
-
2062
- break;
2063
-
2064
- case 5:
2065
- if (tn === $.ASIDE) {
2066
- addressEndTagInBody(p, token);
2067
- } else if (tn === $.SMALL) {
2068
- callAdoptionAgency(p, token);
2069
- } else {
2070
- genericEndTagInBody(p, token);
2071
- }
2072
-
2073
- break;
2074
-
2075
- case 6:
2076
- if (
2077
- tn === $.CENTER ||
2078
- tn === $.FIGURE ||
2079
- tn === $.FOOTER ||
2080
- tn === $.HEADER ||
2081
- tn === $.HGROUP ||
2082
- tn === $.DIALOG
2083
- ) {
2084
- addressEndTagInBody(p, token);
2085
- } else if (tn === $.APPLET || tn === $.OBJECT) {
2086
- appletEndTagInBody(p, token);
2087
- } else if (tn === $.STRIKE || tn === $.STRONG) {
2088
- callAdoptionAgency(p, token);
2089
- } else {
2090
- genericEndTagInBody(p, token);
2091
- }
2092
-
2093
- break;
2094
-
2095
- case 7:
2096
- if (
2097
- tn === $.ADDRESS ||
2098
- tn === $.ARTICLE ||
2099
- tn === $.DETAILS ||
2100
- tn === $.SECTION ||
2101
- tn === $.SUMMARY ||
2102
- tn === $.LISTING
2103
- ) {
2104
- addressEndTagInBody(p, token);
2105
- } else if (tn === $.MARQUEE) {
2106
- appletEndTagInBody(p, token);
2107
- } else {
2108
- genericEndTagInBody(p, token);
2109
- }
2110
-
2111
- break;
2112
-
2113
- case 8:
2114
- if (tn === $.FIELDSET) {
2115
- addressEndTagInBody(p, token);
2116
- } else if (tn === $.TEMPLATE) {
2117
- endTagInHead(p, token);
2118
- } else {
2119
- genericEndTagInBody(p, token);
2120
- }
2121
-
2122
- break;
2123
-
2124
- case 10:
2125
- if (tn === $.BLOCKQUOTE || tn === $.FIGCAPTION) {
2126
- addressEndTagInBody(p, token);
2127
- } else {
2128
- genericEndTagInBody(p, token);
2129
- }
2130
-
2131
- break;
2132
-
2133
- default:
2134
- genericEndTagInBody(p, token);
2135
- }
2136
- }
2137
-
2138
- function eofInBody(p, token) {
2139
- if (p.tmplInsertionModeStackTop > -1) {
2140
- eofInTemplate(p, token);
2141
- } else {
2142
- p.stopped = true;
2143
- }
2144
- }
2145
-
2146
- // The "text" insertion mode
2147
- //------------------------------------------------------------------
2148
- function endTagInText(p, token) {
2149
- if (token.tagName === $.SCRIPT) {
2150
- p.pendingScript = p.openElements.current;
2151
- }
2152
-
2153
- p.openElements.pop();
2154
- p.insertionMode = p.originalInsertionMode;
2155
- }
2156
-
2157
- function eofInText(p, token) {
2158
- p._err(ERR.eofInElementThatCanContainOnlyText);
2159
- p.openElements.pop();
2160
- p.insertionMode = p.originalInsertionMode;
2161
- p._processToken(token);
2162
- }
2163
-
2164
- // The "in table" insertion mode
2165
- //------------------------------------------------------------------
2166
- function characterInTable(p, token) {
2167
- const curTn = p.openElements.currentTagName;
2168
-
2169
- if (curTn === $.TABLE || curTn === $.TBODY || curTn === $.TFOOT || curTn === $.THEAD || curTn === $.TR) {
2170
- p.pendingCharacterTokens = [];
2171
- p.hasNonWhitespacePendingCharacterToken = false;
2172
- p.originalInsertionMode = p.insertionMode;
2173
- p.insertionMode = IN_TABLE_TEXT_MODE;
2174
- p._processToken(token);
2175
- } else {
2176
- tokenInTable(p, token);
2177
- }
2178
- }
2179
-
2180
- function captionStartTagInTable(p, token) {
2181
- p.openElements.clearBackToTableContext();
2182
- p.activeFormattingElements.insertMarker();
2183
- p._insertElement(token, NS.HTML);
2184
- p.insertionMode = IN_CAPTION_MODE;
2185
- }
2186
-
2187
- function colgroupStartTagInTable(p, token) {
2188
- p.openElements.clearBackToTableContext();
2189
- p._insertElement(token, NS.HTML);
2190
- p.insertionMode = IN_COLUMN_GROUP_MODE;
2191
- }
2192
-
2193
- function colStartTagInTable(p, token) {
2194
- p.openElements.clearBackToTableContext();
2195
- p._insertFakeElement($.COLGROUP);
2196
- p.insertionMode = IN_COLUMN_GROUP_MODE;
2197
- p._processToken(token);
2198
- }
2199
-
2200
- function tbodyStartTagInTable(p, token) {
2201
- p.openElements.clearBackToTableContext();
2202
- p._insertElement(token, NS.HTML);
2203
- p.insertionMode = IN_TABLE_BODY_MODE;
2204
- }
2205
-
2206
- function tdStartTagInTable(p, token) {
2207
- p.openElements.clearBackToTableContext();
2208
- p._insertFakeElement($.TBODY);
2209
- p.insertionMode = IN_TABLE_BODY_MODE;
2210
- p._processToken(token);
2211
- }
2212
-
2213
- function tableStartTagInTable(p, token) {
2214
- if (p.openElements.hasInTableScope($.TABLE)) {
2215
- p.openElements.popUntilTagNamePopped($.TABLE);
2216
- p._resetInsertionMode();
2217
- p._processToken(token);
2218
- }
2219
- }
2220
-
2221
- function inputStartTagInTable(p, token) {
2222
- const inputType = Tokenizer.getTokenAttr(token, ATTRS.TYPE);
2223
-
2224
- if (inputType && inputType.toLowerCase() === HIDDEN_INPUT_TYPE) {
2225
- p._appendElement(token, NS.HTML);
2226
- } else {
2227
- tokenInTable(p, token);
2228
- }
2229
-
2230
- token.ackSelfClosing = true;
2231
- }
2232
-
2233
- function formStartTagInTable(p, token) {
2234
- if (!p.formElement && p.openElements.tmplCount === 0) {
2235
- p._insertElement(token, NS.HTML);
2236
- p.formElement = p.openElements.current;
2237
- p.openElements.pop();
2238
- }
2239
- }
2240
-
2241
- function startTagInTable(p, token) {
2242
- const tn = token.tagName;
2243
-
2244
- switch (tn.length) {
2245
- case 2:
2246
- if (tn === $.TD || tn === $.TH || tn === $.TR) {
2247
- tdStartTagInTable(p, token);
2248
- } else {
2249
- tokenInTable(p, token);
2250
- }
2251
-
2252
- break;
2253
-
2254
- case 3:
2255
- if (tn === $.COL) {
2256
- colStartTagInTable(p, token);
2257
- } else {
2258
- tokenInTable(p, token);
2259
- }
2260
-
2261
- break;
2262
-
2263
- case 4:
2264
- if (tn === $.FORM) {
2265
- formStartTagInTable(p, token);
2266
- } else {
2267
- tokenInTable(p, token);
2268
- }
2269
-
2270
- break;
2271
-
2272
- case 5:
2273
- if (tn === $.TABLE) {
2274
- tableStartTagInTable(p, token);
2275
- } else if (tn === $.STYLE) {
2276
- startTagInHead(p, token);
2277
- } else if (tn === $.TBODY || tn === $.TFOOT || tn === $.THEAD) {
2278
- tbodyStartTagInTable(p, token);
2279
- } else if (tn === $.INPUT) {
2280
- inputStartTagInTable(p, token);
2281
- } else {
2282
- tokenInTable(p, token);
2283
- }
2284
-
2285
- break;
2286
-
2287
- case 6:
2288
- if (tn === $.SCRIPT) {
2289
- startTagInHead(p, token);
2290
- } else {
2291
- tokenInTable(p, token);
2292
- }
2293
-
2294
- break;
2295
-
2296
- case 7:
2297
- if (tn === $.CAPTION) {
2298
- captionStartTagInTable(p, token);
2299
- } else {
2300
- tokenInTable(p, token);
2301
- }
2302
-
2303
- break;
2304
-
2305
- case 8:
2306
- if (tn === $.COLGROUP) {
2307
- colgroupStartTagInTable(p, token);
2308
- } else if (tn === $.TEMPLATE) {
2309
- startTagInHead(p, token);
2310
- } else {
2311
- tokenInTable(p, token);
2312
- }
2313
-
2314
- break;
2315
-
2316
- default:
2317
- tokenInTable(p, token);
2318
- }
2319
- }
2320
-
2321
- function endTagInTable(p, token) {
2322
- const tn = token.tagName;
2323
-
2324
- if (tn === $.TABLE) {
2325
- if (p.openElements.hasInTableScope($.TABLE)) {
2326
- p.openElements.popUntilTagNamePopped($.TABLE);
2327
- p._resetInsertionMode();
2328
- }
2329
- } else if (tn === $.TEMPLATE) {
2330
- endTagInHead(p, token);
2331
- } else if (
2332
- tn !== $.BODY &&
2333
- tn !== $.CAPTION &&
2334
- tn !== $.COL &&
2335
- tn !== $.COLGROUP &&
2336
- tn !== $.HTML &&
2337
- tn !== $.TBODY &&
2338
- tn !== $.TD &&
2339
- tn !== $.TFOOT &&
2340
- tn !== $.TH &&
2341
- tn !== $.THEAD &&
2342
- tn !== $.TR
2343
- ) {
2344
- tokenInTable(p, token);
2345
- }
2346
- }
2347
-
2348
- function tokenInTable(p, token) {
2349
- const savedFosterParentingState = p.fosterParentingEnabled;
2350
-
2351
- p.fosterParentingEnabled = true;
2352
- p._processTokenInBodyMode(token);
2353
- p.fosterParentingEnabled = savedFosterParentingState;
2354
- }
2355
-
2356
- // The "in table text" insertion mode
2357
- //------------------------------------------------------------------
2358
- function whitespaceCharacterInTableText(p, token) {
2359
- p.pendingCharacterTokens.push(token);
2360
- }
2361
-
2362
- function characterInTableText(p, token) {
2363
- p.pendingCharacterTokens.push(token);
2364
- p.hasNonWhitespacePendingCharacterToken = true;
2365
- }
2366
-
2367
- function tokenInTableText(p, token) {
2368
- let i = 0;
2369
-
2370
- if (p.hasNonWhitespacePendingCharacterToken) {
2371
- for (; i < p.pendingCharacterTokens.length; i++) {
2372
- tokenInTable(p, p.pendingCharacterTokens[i]);
2373
- }
2374
- } else {
2375
- for (; i < p.pendingCharacterTokens.length; i++) {
2376
- p._insertCharacters(p.pendingCharacterTokens[i]);
2377
- }
2378
- }
2379
-
2380
- p.insertionMode = p.originalInsertionMode;
2381
- p._processToken(token);
2382
- }
2383
-
2384
- // The "in caption" insertion mode
2385
- //------------------------------------------------------------------
2386
- function startTagInCaption(p, token) {
2387
- const tn = token.tagName;
2388
-
2389
- if (
2390
- tn === $.CAPTION ||
2391
- tn === $.COL ||
2392
- tn === $.COLGROUP ||
2393
- tn === $.TBODY ||
2394
- tn === $.TD ||
2395
- tn === $.TFOOT ||
2396
- tn === $.TH ||
2397
- tn === $.THEAD ||
2398
- tn === $.TR
2399
- ) {
2400
- if (p.openElements.hasInTableScope($.CAPTION)) {
2401
- p.openElements.generateImpliedEndTags();
2402
- p.openElements.popUntilTagNamePopped($.CAPTION);
2403
- p.activeFormattingElements.clearToLastMarker();
2404
- p.insertionMode = IN_TABLE_MODE;
2405
- p._processToken(token);
2406
- }
2407
- } else {
2408
- startTagInBody(p, token);
2409
- }
2410
- }
2411
-
2412
- function endTagInCaption(p, token) {
2413
- const tn = token.tagName;
2414
-
2415
- if (tn === $.CAPTION || tn === $.TABLE) {
2416
- if (p.openElements.hasInTableScope($.CAPTION)) {
2417
- p.openElements.generateImpliedEndTags();
2418
- p.openElements.popUntilTagNamePopped($.CAPTION);
2419
- p.activeFormattingElements.clearToLastMarker();
2420
- p.insertionMode = IN_TABLE_MODE;
2421
-
2422
- if (tn === $.TABLE) {
2423
- p._processToken(token);
2424
- }
2425
- }
2426
- } else if (
2427
- tn !== $.BODY &&
2428
- tn !== $.COL &&
2429
- tn !== $.COLGROUP &&
2430
- tn !== $.HTML &&
2431
- tn !== $.TBODY &&
2432
- tn !== $.TD &&
2433
- tn !== $.TFOOT &&
2434
- tn !== $.TH &&
2435
- tn !== $.THEAD &&
2436
- tn !== $.TR
2437
- ) {
2438
- endTagInBody(p, token);
2439
- }
2440
- }
2441
-
2442
- // The "in column group" insertion mode
2443
- //------------------------------------------------------------------
2444
- function startTagInColumnGroup(p, token) {
2445
- const tn = token.tagName;
2446
-
2447
- if (tn === $.HTML) {
2448
- startTagInBody(p, token);
2449
- } else if (tn === $.COL) {
2450
- p._appendElement(token, NS.HTML);
2451
- token.ackSelfClosing = true;
2452
- } else if (tn === $.TEMPLATE) {
2453
- startTagInHead(p, token);
2454
- } else {
2455
- tokenInColumnGroup(p, token);
2456
- }
2457
- }
2458
-
2459
- function endTagInColumnGroup(p, token) {
2460
- const tn = token.tagName;
2461
-
2462
- if (tn === $.COLGROUP) {
2463
- if (p.openElements.currentTagName === $.COLGROUP) {
2464
- p.openElements.pop();
2465
- p.insertionMode = IN_TABLE_MODE;
2466
- }
2467
- } else if (tn === $.TEMPLATE) {
2468
- endTagInHead(p, token);
2469
- } else if (tn !== $.COL) {
2470
- tokenInColumnGroup(p, token);
2471
- }
2472
- }
2473
-
2474
- function tokenInColumnGroup(p, token) {
2475
- if (p.openElements.currentTagName === $.COLGROUP) {
2476
- p.openElements.pop();
2477
- p.insertionMode = IN_TABLE_MODE;
2478
- p._processToken(token);
2479
- }
2480
- }
2481
-
2482
- // The "in table body" insertion mode
2483
- //------------------------------------------------------------------
2484
- function startTagInTableBody(p, token) {
2485
- const tn = token.tagName;
2486
-
2487
- if (tn === $.TR) {
2488
- p.openElements.clearBackToTableBodyContext();
2489
- p._insertElement(token, NS.HTML);
2490
- p.insertionMode = IN_ROW_MODE;
2491
- } else if (tn === $.TH || tn === $.TD) {
2492
- p.openElements.clearBackToTableBodyContext();
2493
- p._insertFakeElement($.TR);
2494
- p.insertionMode = IN_ROW_MODE;
2495
- p._processToken(token);
2496
- } else if (
2497
- tn === $.CAPTION ||
2498
- tn === $.COL ||
2499
- tn === $.COLGROUP ||
2500
- tn === $.TBODY ||
2501
- tn === $.TFOOT ||
2502
- tn === $.THEAD
2503
- ) {
2504
- if (p.openElements.hasTableBodyContextInTableScope()) {
2505
- p.openElements.clearBackToTableBodyContext();
2506
- p.openElements.pop();
2507
- p.insertionMode = IN_TABLE_MODE;
2508
- p._processToken(token);
2509
- }
2510
- } else {
2511
- startTagInTable(p, token);
2512
- }
2513
- }
2514
-
2515
- function endTagInTableBody(p, token) {
2516
- const tn = token.tagName;
2517
-
2518
- if (tn === $.TBODY || tn === $.TFOOT || tn === $.THEAD) {
2519
- if (p.openElements.hasInTableScope(tn)) {
2520
- p.openElements.clearBackToTableBodyContext();
2521
- p.openElements.pop();
2522
- p.insertionMode = IN_TABLE_MODE;
2523
- }
2524
- } else if (tn === $.TABLE) {
2525
- if (p.openElements.hasTableBodyContextInTableScope()) {
2526
- p.openElements.clearBackToTableBodyContext();
2527
- p.openElements.pop();
2528
- p.insertionMode = IN_TABLE_MODE;
2529
- p._processToken(token);
2530
- }
2531
- } else if (
2532
- (tn !== $.BODY && tn !== $.CAPTION && tn !== $.COL && tn !== $.COLGROUP) ||
2533
- (tn !== $.HTML && tn !== $.TD && tn !== $.TH && tn !== $.TR)
2534
- ) {
2535
- endTagInTable(p, token);
2536
- }
2537
- }
2538
-
2539
- // The "in row" insertion mode
2540
- //------------------------------------------------------------------
2541
- function startTagInRow(p, token) {
2542
- const tn = token.tagName;
2543
-
2544
- if (tn === $.TH || tn === $.TD) {
2545
- p.openElements.clearBackToTableRowContext();
2546
- p._insertElement(token, NS.HTML);
2547
- p.insertionMode = IN_CELL_MODE;
2548
- p.activeFormattingElements.insertMarker();
2549
- } else if (
2550
- tn === $.CAPTION ||
2551
- tn === $.COL ||
2552
- tn === $.COLGROUP ||
2553
- tn === $.TBODY ||
2554
- tn === $.TFOOT ||
2555
- tn === $.THEAD ||
2556
- tn === $.TR
2557
- ) {
2558
- if (p.openElements.hasInTableScope($.TR)) {
2559
- p.openElements.clearBackToTableRowContext();
2560
- p.openElements.pop();
2561
- p.insertionMode = IN_TABLE_BODY_MODE;
2562
- p._processToken(token);
2563
- }
2564
- } else {
2565
- startTagInTable(p, token);
2566
- }
2567
- }
2568
-
2569
- function endTagInRow(p, token) {
2570
- const tn = token.tagName;
2571
-
2572
- if (tn === $.TR) {
2573
- if (p.openElements.hasInTableScope($.TR)) {
2574
- p.openElements.clearBackToTableRowContext();
2575
- p.openElements.pop();
2576
- p.insertionMode = IN_TABLE_BODY_MODE;
2577
- }
2578
- } else if (tn === $.TABLE) {
2579
- if (p.openElements.hasInTableScope($.TR)) {
2580
- p.openElements.clearBackToTableRowContext();
2581
- p.openElements.pop();
2582
- p.insertionMode = IN_TABLE_BODY_MODE;
2583
- p._processToken(token);
2584
- }
2585
- } else if (tn === $.TBODY || tn === $.TFOOT || tn === $.THEAD) {
2586
- if (p.openElements.hasInTableScope(tn) || p.openElements.hasInTableScope($.TR)) {
2587
- p.openElements.clearBackToTableRowContext();
2588
- p.openElements.pop();
2589
- p.insertionMode = IN_TABLE_BODY_MODE;
2590
- p._processToken(token);
2591
- }
2592
- } else if (
2593
- (tn !== $.BODY && tn !== $.CAPTION && tn !== $.COL && tn !== $.COLGROUP) ||
2594
- (tn !== $.HTML && tn !== $.TD && tn !== $.TH)
2595
- ) {
2596
- endTagInTable(p, token);
2597
- }
2598
- }
2599
-
2600
- // The "in cell" insertion mode
2601
- //------------------------------------------------------------------
2602
- function startTagInCell(p, token) {
2603
- const tn = token.tagName;
2604
-
2605
- if (
2606
- tn === $.CAPTION ||
2607
- tn === $.COL ||
2608
- tn === $.COLGROUP ||
2609
- tn === $.TBODY ||
2610
- tn === $.TD ||
2611
- tn === $.TFOOT ||
2612
- tn === $.TH ||
2613
- tn === $.THEAD ||
2614
- tn === $.TR
2615
- ) {
2616
- if (p.openElements.hasInTableScope($.TD) || p.openElements.hasInTableScope($.TH)) {
2617
- p._closeTableCell();
2618
- p._processToken(token);
2619
- }
2620
- } else {
2621
- startTagInBody(p, token);
2622
- }
2623
- }
2624
-
2625
- function endTagInCell(p, token) {
2626
- const tn = token.tagName;
2627
-
2628
- if (tn === $.TD || tn === $.TH) {
2629
- if (p.openElements.hasInTableScope(tn)) {
2630
- p.openElements.generateImpliedEndTags();
2631
- p.openElements.popUntilTagNamePopped(tn);
2632
- p.activeFormattingElements.clearToLastMarker();
2633
- p.insertionMode = IN_ROW_MODE;
2634
- }
2635
- } else if (tn === $.TABLE || tn === $.TBODY || tn === $.TFOOT || tn === $.THEAD || tn === $.TR) {
2636
- if (p.openElements.hasInTableScope(tn)) {
2637
- p._closeTableCell();
2638
- p._processToken(token);
2639
- }
2640
- } else if (tn !== $.BODY && tn !== $.CAPTION && tn !== $.COL && tn !== $.COLGROUP && tn !== $.HTML) {
2641
- endTagInBody(p, token);
2642
- }
2643
- }
2644
-
2645
- // The "in select" insertion mode
2646
- //------------------------------------------------------------------
2647
- function startTagInSelect(p, token) {
2648
- const tn = token.tagName;
2649
-
2650
- if (tn === $.HTML) {
2651
- startTagInBody(p, token);
2652
- } else if (tn === $.OPTION) {
2653
- if (p.openElements.currentTagName === $.OPTION) {
2654
- p.openElements.pop();
2655
- }
2656
-
2657
- p._insertElement(token, NS.HTML);
2658
- } else if (tn === $.OPTGROUP) {
2659
- if (p.openElements.currentTagName === $.OPTION) {
2660
- p.openElements.pop();
2661
- }
2662
-
2663
- if (p.openElements.currentTagName === $.OPTGROUP) {
2664
- p.openElements.pop();
2665
- }
2666
-
2667
- p._insertElement(token, NS.HTML);
2668
- } else if (tn === $.INPUT || tn === $.KEYGEN || tn === $.TEXTAREA || tn === $.SELECT) {
2669
- if (p.openElements.hasInSelectScope($.SELECT)) {
2670
- p.openElements.popUntilTagNamePopped($.SELECT);
2671
- p._resetInsertionMode();
2672
-
2673
- if (tn !== $.SELECT) {
2674
- p._processToken(token);
2675
- }
2676
- }
2677
- } else if (tn === $.SCRIPT || tn === $.TEMPLATE) {
2678
- startTagInHead(p, token);
2679
- }
2680
- }
2681
-
2682
- function endTagInSelect(p, token) {
2683
- const tn = token.tagName;
2684
-
2685
- if (tn === $.OPTGROUP) {
2686
- const prevOpenElement = p.openElements.items[p.openElements.stackTop - 1];
2687
- const prevOpenElementTn = prevOpenElement && p.treeAdapter.getTagName(prevOpenElement);
2688
-
2689
- if (p.openElements.currentTagName === $.OPTION && prevOpenElementTn === $.OPTGROUP) {
2690
- p.openElements.pop();
2691
- }
2692
-
2693
- if (p.openElements.currentTagName === $.OPTGROUP) {
2694
- p.openElements.pop();
2695
- }
2696
- } else if (tn === $.OPTION) {
2697
- if (p.openElements.currentTagName === $.OPTION) {
2698
- p.openElements.pop();
2699
- }
2700
- } else if (tn === $.SELECT && p.openElements.hasInSelectScope($.SELECT)) {
2701
- p.openElements.popUntilTagNamePopped($.SELECT);
2702
- p._resetInsertionMode();
2703
- } else if (tn === $.TEMPLATE) {
2704
- endTagInHead(p, token);
2705
- }
2706
- }
2707
-
2708
- //12.2.5.4.17 The "in select in table" insertion mode
2709
- //------------------------------------------------------------------
2710
- function startTagInSelectInTable(p, token) {
2711
- const tn = token.tagName;
2712
-
2713
- if (
2714
- tn === $.CAPTION ||
2715
- tn === $.TABLE ||
2716
- tn === $.TBODY ||
2717
- tn === $.TFOOT ||
2718
- tn === $.THEAD ||
2719
- tn === $.TR ||
2720
- tn === $.TD ||
2721
- tn === $.TH
2722
- ) {
2723
- p.openElements.popUntilTagNamePopped($.SELECT);
2724
- p._resetInsertionMode();
2725
- p._processToken(token);
2726
- } else {
2727
- startTagInSelect(p, token);
2728
- }
2729
- }
2730
-
2731
- function endTagInSelectInTable(p, token) {
2732
- const tn = token.tagName;
2733
-
2734
- if (
2735
- tn === $.CAPTION ||
2736
- tn === $.TABLE ||
2737
- tn === $.TBODY ||
2738
- tn === $.TFOOT ||
2739
- tn === $.THEAD ||
2740
- tn === $.TR ||
2741
- tn === $.TD ||
2742
- tn === $.TH
2743
- ) {
2744
- if (p.openElements.hasInTableScope(tn)) {
2745
- p.openElements.popUntilTagNamePopped($.SELECT);
2746
- p._resetInsertionMode();
2747
- p._processToken(token);
2748
- }
2749
- } else {
2750
- endTagInSelect(p, token);
2751
- }
2752
- }
2753
-
2754
- // The "in template" insertion mode
2755
- //------------------------------------------------------------------
2756
- function startTagInTemplate(p, token) {
2757
- const tn = token.tagName;
2758
-
2759
- if (
2760
- tn === $.BASE ||
2761
- tn === $.BASEFONT ||
2762
- tn === $.BGSOUND ||
2763
- tn === $.LINK ||
2764
- tn === $.META ||
2765
- tn === $.NOFRAMES ||
2766
- tn === $.SCRIPT ||
2767
- tn === $.STYLE ||
2768
- tn === $.TEMPLATE ||
2769
- tn === $.TITLE
2770
- ) {
2771
- startTagInHead(p, token);
2772
- } else {
2773
- const newInsertionMode = TEMPLATE_INSERTION_MODE_SWITCH_MAP[tn] || IN_BODY_MODE;
2774
-
2775
- p._popTmplInsertionMode();
2776
- p._pushTmplInsertionMode(newInsertionMode);
2777
- p.insertionMode = newInsertionMode;
2778
- p._processToken(token);
2779
- }
2780
- }
2781
-
2782
- function endTagInTemplate(p, token) {
2783
- if (token.tagName === $.TEMPLATE) {
2784
- endTagInHead(p, token);
2785
- }
2786
- }
2787
-
2788
- function eofInTemplate(p, token) {
2789
- if (p.openElements.tmplCount > 0) {
2790
- p.openElements.popUntilTagNamePopped($.TEMPLATE);
2791
- p.activeFormattingElements.clearToLastMarker();
2792
- p._popTmplInsertionMode();
2793
- p._resetInsertionMode();
2794
- p._processToken(token);
2795
- } else {
2796
- p.stopped = true;
2797
- }
2798
- }
2799
-
2800
- // The "after body" insertion mode
2801
- //------------------------------------------------------------------
2802
- function startTagAfterBody(p, token) {
2803
- if (token.tagName === $.HTML) {
2804
- startTagInBody(p, token);
2805
- } else {
2806
- tokenAfterBody(p, token);
2807
- }
2808
- }
2809
-
2810
- function endTagAfterBody(p, token) {
2811
- if (token.tagName === $.HTML) {
2812
- if (!p.fragmentContext) {
2813
- p.insertionMode = AFTER_AFTER_BODY_MODE;
2814
- }
2815
- } else {
2816
- tokenAfterBody(p, token);
2817
- }
2818
- }
2819
-
2820
- function tokenAfterBody(p, token) {
2821
- p.insertionMode = IN_BODY_MODE;
2822
- p._processToken(token);
2823
- }
2824
-
2825
- // The "in frameset" insertion mode
2826
- //------------------------------------------------------------------
2827
- function startTagInFrameset(p, token) {
2828
- const tn = token.tagName;
2829
-
2830
- if (tn === $.HTML) {
2831
- startTagInBody(p, token);
2832
- } else if (tn === $.FRAMESET) {
2833
- p._insertElement(token, NS.HTML);
2834
- } else if (tn === $.FRAME) {
2835
- p._appendElement(token, NS.HTML);
2836
- token.ackSelfClosing = true;
2837
- } else if (tn === $.NOFRAMES) {
2838
- startTagInHead(p, token);
2839
- }
2840
- }
2841
-
2842
- function endTagInFrameset(p, token) {
2843
- if (token.tagName === $.FRAMESET && !p.openElements.isRootHtmlElementCurrent()) {
2844
- p.openElements.pop();
2845
-
2846
- if (!p.fragmentContext && p.openElements.currentTagName !== $.FRAMESET) {
2847
- p.insertionMode = AFTER_FRAMESET_MODE;
2848
- }
2849
- }
2850
- }
2851
-
2852
- // The "after frameset" insertion mode
2853
- //------------------------------------------------------------------
2854
- function startTagAfterFrameset(p, token) {
2855
- const tn = token.tagName;
2856
-
2857
- if (tn === $.HTML) {
2858
- startTagInBody(p, token);
2859
- } else if (tn === $.NOFRAMES) {
2860
- startTagInHead(p, token);
2861
- }
2862
- }
2863
-
2864
- function endTagAfterFrameset(p, token) {
2865
- if (token.tagName === $.HTML) {
2866
- p.insertionMode = AFTER_AFTER_FRAMESET_MODE;
2867
- }
2868
- }
2869
-
2870
- // The "after after body" insertion mode
2871
- //------------------------------------------------------------------
2872
- function startTagAfterAfterBody(p, token) {
2873
- if (token.tagName === $.HTML) {
2874
- startTagInBody(p, token);
2875
- } else {
2876
- tokenAfterAfterBody(p, token);
2877
- }
2878
- }
2879
-
2880
- function tokenAfterAfterBody(p, token) {
2881
- p.insertionMode = IN_BODY_MODE;
2882
- p._processToken(token);
2883
- }
2884
-
2885
- // The "after after frameset" insertion mode
2886
- //------------------------------------------------------------------
2887
- function startTagAfterAfterFrameset(p, token) {
2888
- const tn = token.tagName;
2889
-
2890
- if (tn === $.HTML) {
2891
- startTagInBody(p, token);
2892
- } else if (tn === $.NOFRAMES) {
2893
- startTagInHead(p, token);
2894
- }
2895
- }
2896
-
2897
- // The rules for parsing tokens in foreign content
2898
- //------------------------------------------------------------------
2899
- function nullCharacterInForeignContent(p, token) {
2900
- token.chars = unicode.REPLACEMENT_CHARACTER;
2901
- p._insertCharacters(token);
2902
- }
2903
-
2904
- function characterInForeignContent(p, token) {
2905
- p._insertCharacters(token);
2906
- p.framesetOk = false;
2907
- }
2908
-
2909
- function startTagInForeignContent(p, token) {
2910
- if (foreignContent.causesExit(token) && !p.fragmentContext) {
2911
- while (
2912
- p.treeAdapter.getNamespaceURI(p.openElements.current) !== NS.HTML &&
2913
- !p._isIntegrationPoint(p.openElements.current)
2914
- ) {
2915
- p.openElements.pop();
2916
- }
2917
-
2918
- p._processToken(token);
2919
- } else {
2920
- const current = p._getAdjustedCurrentElement();
2921
- const currentNs = p.treeAdapter.getNamespaceURI(current);
2922
-
2923
- if (currentNs === NS.MATHML) {
2924
- foreignContent.adjustTokenMathMLAttrs(token);
2925
- } else if (currentNs === NS.SVG) {
2926
- foreignContent.adjustTokenSVGTagName(token);
2927
- foreignContent.adjustTokenSVGAttrs(token);
2928
- }
2929
-
2930
- foreignContent.adjustTokenXMLAttrs(token);
2931
-
2932
- if (token.selfClosing) {
2933
- p._appendElement(token, currentNs);
2934
- } else {
2935
- p._insertElement(token, currentNs);
2936
- }
2937
-
2938
- token.ackSelfClosing = true;
2939
- }
2940
- }
2941
-
2942
- function endTagInForeignContent(p, token) {
2943
- for (let i = p.openElements.stackTop; i > 0; i--) {
2944
- const element = p.openElements.items[i];
2945
-
2946
- if (p.treeAdapter.getNamespaceURI(element) === NS.HTML) {
2947
- p._processToken(token);
2948
- break;
2949
- }
2950
-
2951
- if (p.treeAdapter.getTagName(element).toLowerCase() === token.tagName) {
2952
- p.openElements.popUntilElementPopped(element);
2953
- break;
2954
- }
2955
- }
2956
- }