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