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