@mrhenry/twig-html-parser 0.1.0 → 0.1.2
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.
- package/CHANGELOG.md +46 -0
- package/package.json +2 -2
- package/src/html-tokenizer.js +114 -21
- package/src/parser.js +41 -11
- package/test/fixtures/wpt-html5lib-inputs.json +1 -0
- package/test/html-tokenizer.test.js +110 -0
- package/test/limits.test.js +68 -0
- package/test/twig-html-parser.test.js +25 -0
- package/test/wpt-html5lib.test.js +114 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.2 (2026-09-26)
|
|
4
|
+
|
|
5
|
+
* Bounded the hybrid parser against pathological nesting. `pairTree` now walks
|
|
6
|
+
the AST iteratively instead of by recursion, and both the element stack
|
|
7
|
+
(`buildTree`) and the twig-block stack (`pairTwigBlocks`) are capped at
|
|
8
|
+
`4096` open levels; past the cap an element or block is kept as a leaf. This
|
|
9
|
+
removes the stack-overflow denial of service a deeply nested untrusted
|
|
10
|
+
template could trigger.
|
|
11
|
+
* Lowered the `MAX_ELEMENT_DEPTH`/`MAX_BLOCK_DEPTH` caps from `4096` to `256`.
|
|
12
|
+
The caps bound the tree this package builds, but recursive consumers (the
|
|
13
|
+
Prettier printer overflows at roughly 1000 nested elements) could still be
|
|
14
|
+
overflowed by a tree the parser considered valid; `256` keeps a promised
|
|
15
|
+
tree safe to walk.
|
|
16
|
+
* Added `test/limits.test.js` covering 20k-deep element and block nesting.
|
|
17
|
+
|
|
18
|
+
* Added a tokenizer corpus test derived from the WPT html5lib suite
|
|
19
|
+
(`wpt/html/syntax/parsing/resources/*.dat`, ~1959 inputs, vendored under
|
|
20
|
+
`test/fixtures/wpt-html5lib-inputs.json`). Every input must tokenize to a
|
|
21
|
+
contiguous, source-ordered token list with exact offsets and without
|
|
22
|
+
hanging; a few cases assert tokenizer-level spec outcomes (including
|
|
23
|
+
unquoted attribute values such as `<div id=foo>`, where `>` ends the value
|
|
24
|
+
and a trailing `/` is part of it).
|
|
25
|
+
* The raw-text end tag is now consumed with the full tag machinery, honouring
|
|
26
|
+
quoted attribute values, so `</script foo=">" dd>` closes at its real `>`
|
|
27
|
+
instead of at the `>` inside the quoted value. An unterminated `</script`
|
|
28
|
+
before EOF stays raw text and leaves the element open, as the spec requires.
|
|
29
|
+
* HTML comments now also close on `--!>` (the spec's comment-end-bang state, a
|
|
30
|
+
parse error) in addition to `-->`, so `<!-- BAR --!>BAZ` no longer swallows
|
|
31
|
+
the trailing text.
|
|
32
|
+
* Fixed raw-text and RCDATA elements closing on an inappropriate end tag. The
|
|
33
|
+
tokenizer now follows the spec's "appropriate end tag" rule instead of a bare
|
|
34
|
+
prefix search, so `<script>var x = "</scripture>";</script>` keeps
|
|
35
|
+
`</scripture>` as script text and closes on the real `</script>`.
|
|
36
|
+
* `xmp`, `iframe`, `noembed` and `noframes` are now tokenized as raw text
|
|
37
|
+
(their content is not parsed as markup), matching the spec's RAWTEXT
|
|
38
|
+
elements. `noscript` and the obsolete `plaintext` stay parsed as markup.
|
|
39
|
+
* End tags with a tail no longer overwrite the tag name: `</div class=x>` is an
|
|
40
|
+
end tag for `div`, not for `class=x`, so it correctly closes an open `<div>`.
|
|
41
|
+
* Fixed two tokenizer bugs that produced overlapping or dropped tokens: a bogus
|
|
42
|
+
comment (`<!- x>`, `<?`) no longer also flushes a duplicate `text` token, and
|
|
43
|
+
`<?` at end of input now emits its comment instead of nothing.
|
|
44
|
+
* Fixed an infinite loop when an end tag carried an equals sign in its tail
|
|
45
|
+
(e.g. `</div class=x>`); the tokenizer now consumes the offending character
|
|
46
|
+
and terminates
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrhenry/twig-html-parser",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.js",
|
|
@@ -11,6 +11,6 @@
|
|
|
11
11
|
"test": "node --test test/*.test.js"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@mrhenry/twig-tokenizer": "0.1.
|
|
14
|
+
"@mrhenry/twig-tokenizer": "^0.1.2"
|
|
15
15
|
}
|
|
16
16
|
}
|
package/src/html-tokenizer.js
CHANGED
|
@@ -22,8 +22,13 @@
|
|
|
22
22
|
|
|
23
23
|
/** Whitespace characters inside HTML tags. */
|
|
24
24
|
const WS = ' \t\n\f\r';
|
|
25
|
-
/**
|
|
26
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Elements whose content is raw text (not parsed as markup). Mirrors the
|
|
27
|
+
* spec's RAWTEXT / script-data elements. `noscript` and the obsolete
|
|
28
|
+
* `plaintext` are intentionally excluded: `noscript` depends on the scripting
|
|
29
|
+
* flag and `plaintext` runs to EOF without an end tag.
|
|
30
|
+
*/
|
|
31
|
+
const RAWTEXT_ELEMENTS = new Set(['script', 'style', 'xmp', 'iframe', 'noembed', 'noframes']);
|
|
27
32
|
/** Elements whose content is RCDATA (treated as raw text here). */
|
|
28
33
|
const RCDATA_ELEMENTS = new Set(['textarea', 'title']);
|
|
29
34
|
|
|
@@ -350,7 +355,8 @@ export function tokenizeHtml(atoms, source) {
|
|
|
350
355
|
/**
|
|
351
356
|
* Consumes a `<!-- ... -->` comment across text and twig atoms. Returns the
|
|
352
357
|
* raw text consumed; when the comment is unterminated the rest of the input
|
|
353
|
-
* is consumed.
|
|
358
|
+
* is consumed. The spec's comment-end-bang state also closes on `--!>`
|
|
359
|
+
* (a parse error), so both terminators are recognised.
|
|
354
360
|
*
|
|
355
361
|
* @returns {{text: string, end: number}}
|
|
356
362
|
*/
|
|
@@ -369,8 +375,15 @@ export function tokenizeHtml(atoms, source) {
|
|
|
369
375
|
break;
|
|
370
376
|
}
|
|
371
377
|
const raw = a.raw;
|
|
372
|
-
const
|
|
373
|
-
const
|
|
378
|
+
const closeIdx = raw.indexOf('-->', cursor.pos);
|
|
379
|
+
const bangIdx = raw.indexOf('--!>', cursor.pos);
|
|
380
|
+
let idx = closeIdx;
|
|
381
|
+
let length = 3;
|
|
382
|
+
if (bangIdx !== -1 && (closeIdx === -1 || bangIdx < closeIdx)) {
|
|
383
|
+
idx = bangIdx;
|
|
384
|
+
length = 4;
|
|
385
|
+
}
|
|
386
|
+
const limit = idx === -1 ? raw.length : idx + length;
|
|
374
387
|
out += raw.slice(cursor.pos, limit);
|
|
375
388
|
cursor.pos = limit;
|
|
376
389
|
end = a.rawStart + limit;
|
|
@@ -382,13 +395,19 @@ export function tokenizeHtml(atoms, source) {
|
|
|
382
395
|
}
|
|
383
396
|
|
|
384
397
|
/**
|
|
385
|
-
* Scans raw text up to
|
|
398
|
+
* Scans raw text up to an *appropriate end tag* for `tagName` or a twig
|
|
399
|
+
* atom. The spec's RAWTEXT/RCDATA end-tag-open states only treat `</name`
|
|
400
|
+
* as an end tag when the name is complete, i.e. followed by whitespace, `/`
|
|
401
|
+
* or `>`; otherwise the `</name` run is ordinary raw text. A bare prefix
|
|
402
|
+
* such as `</scripture>` must not close a `<script>`.
|
|
386
403
|
*
|
|
387
404
|
* @param {string} tagName
|
|
388
405
|
* @returns {{text: string, textStart: number, textEnd: number, found: boolean, endTag: string, endTagStart: number, endTagEnd: number}}
|
|
389
406
|
*/
|
|
390
407
|
function scanRawText(tagName) {
|
|
391
408
|
const lowerTag = tagName.toLowerCase();
|
|
409
|
+
const marker = `</${lowerTag}`;
|
|
410
|
+
const markerLength = marker.length;
|
|
392
411
|
const start = cursor.offset();
|
|
393
412
|
let out = '';
|
|
394
413
|
let textEnd = start;
|
|
@@ -398,26 +417,98 @@ export function tokenizeHtml(atoms, source) {
|
|
|
398
417
|
break; // twig or end of input
|
|
399
418
|
}
|
|
400
419
|
const raw = a.raw;
|
|
401
|
-
const
|
|
420
|
+
const lower = raw.toLowerCase();
|
|
421
|
+
let searchFrom = cursor.pos;
|
|
422
|
+
let idx = -1;
|
|
423
|
+
for (;;) {
|
|
424
|
+
const candidate = lower.indexOf(marker, searchFrom);
|
|
425
|
+
if (candidate === -1) {
|
|
426
|
+
break;
|
|
427
|
+
}
|
|
428
|
+
const after = raw[candidate + markerLength];
|
|
429
|
+
// only whitespace, `/` or `>` makes this an appropriate end tag;
|
|
430
|
+
// anything else (or end of input) is raw text and the scan continues
|
|
431
|
+
if (after === undefined || after === ' ' || after === '\t' || after === '\n' || after === '\f' || after === '\r' || after === '/' || after === '>') {
|
|
432
|
+
idx = candidate;
|
|
433
|
+
break;
|
|
434
|
+
}
|
|
435
|
+
searchFrom = candidate + markerLength;
|
|
436
|
+
}
|
|
402
437
|
const limit = idx === -1 ? raw.length : idx;
|
|
403
438
|
out += raw.slice(cursor.pos, limit);
|
|
404
439
|
cursor.pos = limit;
|
|
405
440
|
textEnd = a.rawStart + limit;
|
|
406
441
|
if (idx !== -1) {
|
|
407
|
-
// consume
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
442
|
+
// consume the end tag through its closing `>`, honouring quoted
|
|
443
|
+
// attribute values so a `>` inside `</script foo=">">` does not
|
|
444
|
+
// terminate the tag early (spec: script data / RAWTEXT end tag
|
|
445
|
+
// name states reuse the ordinary tag machinery)
|
|
446
|
+
const endTagStart = a.rawStart + idx;
|
|
447
|
+
const consumed = consumeEndTag();
|
|
448
|
+
if (consumed === -1) {
|
|
449
|
+
// no `>` before EOF: the `</name` run is raw text (spec's
|
|
450
|
+
// eof-in-script-data behaviour), so keep it and stop
|
|
451
|
+
out += source.slice(endTagStart);
|
|
452
|
+
textEnd = source.length;
|
|
453
|
+
cursor.pos = raw.length;
|
|
454
|
+
break;
|
|
411
455
|
}
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
456
|
+
return {
|
|
457
|
+
text: out,
|
|
458
|
+
textStart: start,
|
|
459
|
+
textEnd,
|
|
460
|
+
found: true,
|
|
461
|
+
endTag: source.slice(endTagStart, consumed),
|
|
462
|
+
endTagStart,
|
|
463
|
+
endTagEnd: consumed,
|
|
464
|
+
};
|
|
416
465
|
}
|
|
417
466
|
}
|
|
418
467
|
return { text: out, textStart: start, textEnd, found: false, endTag: '', endTagStart: 0, endTagEnd: 0 };
|
|
419
468
|
}
|
|
420
469
|
|
|
470
|
+
/**
|
|
471
|
+
* Consumes an end tag from the current position (the `<` of `</name`) through
|
|
472
|
+
* its closing `>`, honouring double- and single-quoted attribute values so a
|
|
473
|
+
* `>` inside a quoted value does not end the tag. Twig atoms inside the tag
|
|
474
|
+
* are consumed whole. Returns the absolute offset just past the `>`, or `-1`
|
|
475
|
+
* when the tag is unterminated at end of input.
|
|
476
|
+
*
|
|
477
|
+
* @returns {number} Absolute end offset of the end tag, or -1 at EOF.
|
|
478
|
+
*/
|
|
479
|
+
function consumeEndTag() {
|
|
480
|
+
// starting quote state: null (outside), '"' or "'"
|
|
481
|
+
let quote = null;
|
|
482
|
+
for (;;) {
|
|
483
|
+
const a = cursor.textAtom();
|
|
484
|
+
if (!a) {
|
|
485
|
+
if (cursor.atTwig()) {
|
|
486
|
+
cursor.takeTwig();
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
return -1;
|
|
490
|
+
}
|
|
491
|
+
const raw = a.raw;
|
|
492
|
+
let i = cursor.pos;
|
|
493
|
+
for (; i < raw.length; i += 1) {
|
|
494
|
+
const ch = raw[i];
|
|
495
|
+
if (quote !== null) {
|
|
496
|
+
if (ch === quote) {
|
|
497
|
+
quote = null;
|
|
498
|
+
}
|
|
499
|
+
continue;
|
|
500
|
+
}
|
|
501
|
+
if (ch === '"' || ch === "'") {
|
|
502
|
+
quote = ch;
|
|
503
|
+
} else if (ch === '>') {
|
|
504
|
+
cursor.pos = i + 1;
|
|
505
|
+
return a.rawStart + i + 1;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
cursor.pos = i;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
421
512
|
/**
|
|
422
513
|
* Commits the current attribute (if any) to the tag's attribute list.
|
|
423
514
|
*/
|
|
@@ -583,7 +674,6 @@ export function tokenizeHtml(atoms, source) {
|
|
|
583
674
|
if (c === '?') {
|
|
584
675
|
cursor.next();
|
|
585
676
|
declStart = /** @type {TagState} */ (tag).rawStart;
|
|
586
|
-
tag = null;
|
|
587
677
|
state = 'bogusComment';
|
|
588
678
|
break;
|
|
589
679
|
}
|
|
@@ -661,11 +751,11 @@ export function tokenizeHtml(atoms, source) {
|
|
|
661
751
|
state = 'data';
|
|
662
752
|
break;
|
|
663
753
|
}
|
|
664
|
-
//
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
754
|
+
// The spec reuses the "before attribute name" states for end tags:
|
|
755
|
+
// an unexpected character is a parse error and the tag name is
|
|
756
|
+
// left untouched. `</div class=x>` is still an end tag for `div`,
|
|
757
|
+
// so keep scanning to `>` without overwriting the name.
|
|
758
|
+
cursor.next();
|
|
669
759
|
break;
|
|
670
760
|
}
|
|
671
761
|
|
|
@@ -1012,6 +1102,9 @@ export function tokenizeHtml(atoms, source) {
|
|
|
1012
1102
|
case 'bogusComment': {
|
|
1013
1103
|
const rest = readTagRest();
|
|
1014
1104
|
tokens.push(htmlToken('comment', source.slice(declStart, rest.end), declStart, rest.end));
|
|
1105
|
+
// clear the pending markup so the end-of-input flush cannot emit a
|
|
1106
|
+
// second, overlapping text token for the same span
|
|
1107
|
+
tag = null;
|
|
1015
1108
|
state = 'data';
|
|
1016
1109
|
break;
|
|
1017
1110
|
}
|
package/src/parser.js
CHANGED
|
@@ -183,7 +183,12 @@ export function buildTree(tokens) {
|
|
|
183
183
|
),
|
|
184
184
|
});
|
|
185
185
|
append(element);
|
|
186
|
-
|
|
186
|
+
// Cap the open-element stack so a pathological input (deeply nested
|
|
187
|
+
// tags) cannot build an unboundedly deep tree. Past the cap the
|
|
188
|
+
// element is treated as a leaf: its would-be children become its
|
|
189
|
+
// siblings, which keeps memory and every downstream traversal
|
|
190
|
+
// bounded while preserving the source text.
|
|
191
|
+
if (!token.selfClosing && !VOID_ELEMENTS.has(token.name ?? '') && stack.length <= MAX_ELEMENT_DEPTH) {
|
|
187
192
|
stack.push(element);
|
|
188
193
|
}
|
|
189
194
|
break;
|
|
@@ -238,6 +243,25 @@ export function buildTree(tokens) {
|
|
|
238
243
|
return root;
|
|
239
244
|
}
|
|
240
245
|
|
|
246
|
+
/**
|
|
247
|
+
* The deepest open-element stack the tree builder maintains. A source nested
|
|
248
|
+
* past this depth is flattened rather than allowed to grow without bound: the
|
|
249
|
+
* cap keeps `buildTree` linear in memory and prevents deep recursion in this
|
|
250
|
+
* package's own traversals and in consumers that walk the AST recursively.
|
|
251
|
+
*/
|
|
252
|
+
const MAX_ELEMENT_DEPTH = 256;
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* The deepest open-block stack {@link pairTwigBlocks} maintains. As with
|
|
256
|
+
* {@link MAX_ELEMENT_DEPTH}, nesting past the cap degrades to flat leaves
|
|
257
|
+
* rather than growing an unboundedly deep tree.
|
|
258
|
+
*
|
|
259
|
+
* The cap is kept well below the stack limit of recursive consumers (the
|
|
260
|
+
* Prettier printer overflows at roughly 1000 nested elements), so a tree this
|
|
261
|
+
* package promises to build can also be walked safely by its callers.
|
|
262
|
+
*/
|
|
263
|
+
const MAX_BLOCK_DEPTH = 256;
|
|
264
|
+
|
|
241
265
|
/** Void elements that never have an end tag. */
|
|
242
266
|
const VOID_ELEMENTS = new Set([
|
|
243
267
|
'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link',
|
|
@@ -251,24 +275,23 @@ const VOID_ELEMENTS = new Set([
|
|
|
251
275
|
* @param {AstNode} root
|
|
252
276
|
*/
|
|
253
277
|
function pairTree(root) {
|
|
254
|
-
|
|
255
|
-
|
|
278
|
+
// Iterative post-order-free walk: the tree can be arbitrarily deep (up to
|
|
279
|
+
// MAX_ELEMENT_DEPTH), so recursion here would risk a stack overflow on
|
|
280
|
+
// untrusted templates. Children are paired before being enqueued, matching
|
|
281
|
+
// the previous depth-first recursion order.
|
|
282
|
+
/** @type {AstNode[]} */
|
|
283
|
+
const stack = [root];
|
|
284
|
+
while (stack.length > 0) {
|
|
285
|
+
const n = /** @type {AstNode} */ (stack.pop());
|
|
256
286
|
if (Array.isArray(n.children)) {
|
|
257
287
|
n.children = /** @type {AstNode[]} */ (pairTwigBlocks(n.children));
|
|
258
288
|
for (const child of n.children) {
|
|
259
|
-
|
|
289
|
+
stack.push(child);
|
|
260
290
|
}
|
|
261
291
|
}
|
|
262
292
|
if (n.type === 'element' && Array.isArray(n.attrs)) {
|
|
263
293
|
n.attrs = pairTwigBlocks(n.attrs);
|
|
264
294
|
}
|
|
265
|
-
};
|
|
266
|
-
const children = root.children;
|
|
267
|
-
if (Array.isArray(children)) {
|
|
268
|
-
root.children = /** @type {AstNode[]} */ (pairTwigBlocks(children));
|
|
269
|
-
for (const child of root.children) {
|
|
270
|
-
walk(child);
|
|
271
|
-
}
|
|
272
295
|
}
|
|
273
296
|
}
|
|
274
297
|
|
|
@@ -290,6 +313,13 @@ export function pairTwigBlocks(items) {
|
|
|
290
313
|
const twig = /** @type {AstNode} */ (item);
|
|
291
314
|
const atom = /** @type {Atom} */ (twig.atom);
|
|
292
315
|
if (isBlockOpen(atom)) {
|
|
316
|
+
if (stack.length >= MAX_BLOCK_DEPTH) {
|
|
317
|
+
// Past the cap a block-open is kept as a leaf, so nesting cannot
|
|
318
|
+
// grow without bound. Its matching close will not pair and stays
|
|
319
|
+
// a leaf too; the source text is preserved either way.
|
|
320
|
+
out.push(twig);
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
293
323
|
stack.push({ open: twig, sections: [{ head: null, body: [] }] });
|
|
294
324
|
continue;
|
|
295
325
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"adoption01.dat":["<a><p></a></p>","<a>1<p>2</a>3</p>","<a>1<button>2</a>3</button>","<a>1<b>2</a>3</b>","<a>1<div>2<div>3</a>4</div>5</div>","<table><a>1<p>2</a>3</p>","<b><b><a><p></a>","<b><a><b><p></a>","<a><b><b><p></a>","<p>1<s id=\"A\">2<b id=\"B\">3</p>4</s>5</b>","<table><a>1<td>2</td>3</table>","<table>A<td>B</td>C</table>","<a><svg><tr><input></a>","<div><a><b><div><div><div><div><div><div><div><div><div><div></a>","<div><a><b><u><i><code><div></a>","<b><b><b><b>x</b></b></b></b>y","<p><b><b><b><b><p>x","<b><em><foo><foob><fooc><aside></b></em>"],"adoption02.dat":["<b>1<i>2<p>3</b>4","<a><div><style></style><address><a>","<nobr><table><marquee></table><nobr>","<a><table><marquee></table><a>"],"blocks.dat":["<!doctype html><p>foo<address>bar<p>baz","<!doctype html><address><p>foo</address>bar","<!doctype html><p>foo<article>bar<p>baz","<!doctype html><article><p>foo</article>bar","<!doctype html><p>foo<aside>bar<p>baz","<!doctype html><aside><p>foo</aside>bar","<!doctype html><p>foo<blockquote>bar<p>baz","<!doctype html><blockquote><p>foo</blockquote>bar","<!doctype html><p>foo<center>bar<p>baz","<!doctype html><center><p>foo</center>bar","<!doctype html><p>foo<details>bar<p>baz","<!doctype html><details><p>foo</details>bar","<!doctype html><p>foo<dialog>bar<p>baz","<!doctype html><dialog><p>foo</dialog>bar","<!doctype html><p>foo<dir>bar<p>baz","<!doctype html><dir><p>foo</dir>bar","<!doctype html><p>foo<div>bar<p>baz","<!doctype html><div><p>foo</div>bar","<!doctype html><p>foo<dl>bar<p>baz","<!doctype html><dl><p>foo</dl>bar","<!doctype html><p>foo<fieldset>bar<p>baz","<!doctype html><fieldset><p>foo</fieldset>bar","<!doctype html><p>foo<figcaption>bar<p>baz","<!doctype html><figcaption><p>foo</figcaption>bar","<!doctype html><p>foo<figure>bar<p>baz","<!doctype html><figure><p>foo</figure>bar","<!doctype html><p>foo<footer>bar<p>baz","<!doctype html><footer><p>foo</footer>bar","<!doctype html><p>foo<header>bar<p>baz","<!doctype html><header><p>foo</header>bar","<!doctype html><p>foo<hgroup>bar<p>baz","<!doctype html><hgroup><p>foo</hgroup>bar","<!doctype html><p>foo<listing>bar<p>baz","<!doctype html><listing><p>foo</listing>bar","<!doctype html><p>foo<menu>bar<p>baz","<!doctype html><menu><p>foo</menu>bar","<!doctype html><p>foo<nav>bar<p>baz","<!doctype html><nav><p>foo</nav>bar","<!doctype html><p>foo<ol>bar<p>baz","<!doctype html><ol><p>foo</ol>bar","<!doctype html><p>foo<pre>bar<p>baz","<!doctype html><pre><p>foo</pre>bar","<!doctype html><p>foo<section>bar<p>baz","<!doctype html><section><p>foo</section>bar","<!doctype html><p>foo<summary>bar<p>baz","<!doctype html><summary><p>foo</summary>bar","<!doctype html><p>foo<ul>bar<p>baz","<!doctype html><ul><p>foo</ul>bar"],"comments01.dat":["FOO<!-- BAR -->BAZ","FOO<!-- BAR --!>BAZ","FOO<!-- BAR --! >BAZ","FOO<!-- BAR --!\n>BAZ","FOO<!-- BAR -- >BAZ","FOO<!-- BAR -- <QUX> -- MUX -->BAZ","FOO<!-- BAR -- <QUX> -- MUX --!>BAZ","FOO<!-- BAR -- <QUX> -- MUX -- >BAZ","FOO<!---->BAZ","FOO<!--->BAZ","FOO<!-->BAZ","<?xml version=\"1.0\">Hi","<?xml version=\"1.0\">","<?xml version","FOO<!----->BAZ","<html><!-- comment --><title>Comment before head</title>"],"doctype01.dat":["<!DOCTYPE html>Hello","<!dOctYpE HtMl>Hello","<!DOCTYPEhtml>Hello","<!DOCTYPE>Hello","<!DOCTYPE >Hello","<!DOCTYPE potato>Hello","<!DOCTYPE potato >Hello","<!DOCTYPE potato taco>Hello","<!DOCTYPE potato taco \"ddd>Hello","<!DOCTYPE potato sYstEM>Hello","<!DOCTYPE potato sYstEM >Hello","<!DOCTYPE potato sYstEM ggg>Hello","<!DOCTYPE potato SYSTEM taco >Hello","<!DOCTYPE potato SYSTEM 'taco\"'>Hello","<!DOCTYPE potato SYSTEM \"taco\">Hello","<!DOCTYPE potato SYSTEM \"tai'co\">Hello","<!DOCTYPE potato SYSTEMtaco \"ddd\">Hello","<!DOCTYPE potato grass SYSTEM taco>Hello","<!DOCTYPE potato pUbLIc>Hello","<!DOCTYPE potato pUbLIc >Hello","<!DOCTYPE potato pUbLIcgoof>Hello","<!DOCTYPE potato PUBLIC goof>Hello","<!DOCTYPE potato PUBLIC \"go'of\">Hello","<!DOCTYPE potato PUBLIC 'go'of'>Hello","<!DOCTYPE potato PUBLIC 'go:hh of' >Hello","<!DOCTYPE potato PUBLIC \"W3C-//dfdf\" SYSTEM ggg>Hello","<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\n \"http://www.w3.org/TR/html4/strict.dtd\">Hello","<!DOCTYPE ...>Hello","<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\n\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">","<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Frameset//EN\"\n\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\">","<!DOCTYPE root-element [SYSTEM OR PUBLIC FPI] \"uri\" [ \n<!-- internal declarations -->\n]>","<!DOCTYPE html PUBLIC\n \"-//WAPFORUM//DTD XHTML Mobile 1.0//EN\"\n \"http://www.wapforum.org/DTD/xhtml-mobile10.dtd\">","<!DOCTYPE HTML SYSTEM \"http://www.w3.org/DTD/HTML4-strict.dtd\"><body><b>Mine!</b></body>","<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"\"http://www.w3.org/TR/html4/strict.dtd\">","<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\"'http://www.w3.org/TR/html4/strict.dtd'>","<!DOCTYPE HTML PUBLIC\"-//W3C//DTD HTML 4.01//EN\"'http://www.w3.org/TR/html4/strict.dtd'>","<!DOCTYPE HTML PUBLIC'-//W3C//DTD HTML 4.01//EN''http://www.w3.org/TR/html4/strict.dtd'>"],"domjs-unsafe.dat":["<svg><![CDATA[foo\nbar]]>","<svg><![CDATA[foo\rbar]]>","<svg><![CDATA[foo\r\nbar]]>","<script>a='\u0000'</script>","<script type=\"data\"><!--\u0000</script>","<script type=\"data\"><!--foo\u0000</script>","<script type=\"data\"><!-- foo-\u0000</script>","<script type=\"data\"><!-- foo--\u0000</script>","<script type=\"data\"><!-- foo-","<script type=\"data\"><!-- foo-<</script>","<script type=\"data\"><!-- foo-<S","<script type=\"data\"><!-- foo-</SCRIPT>","<script type=\"data\"><!--<p></script>","<script type=\"data\"><!--<script></script></script>","<script type=\"data\"><!--<script>\u0000</script></script>","<script type=\"data\"><!--<script>-\u0000</script></script>","<script type=\"data\"><!--<script>--\u0000</script></script>","<script type=\"data\"><!--<script>---</script></script>","<script type=\"data\"><!--<script></scrip></SCRIPT></script>","<script type=\"data\"><!--<script></scrip </SCRIPT></script>","<script type=\"data\"><!--<script></scrip/</SCRIPT></script>","<script type=\"data\"></scrip/></script>","<script type=\"data\"></scrip ></script>","<script type=\"data\"><!--</scrip></script>","<script type=\"data\"><!--</scrip </script>","<script type=\"data\"><!--</scrip/</script>","<!DOCTYPE html><!DOCTYPE html>","<html><!DOCTYPE html>","<html><head><!DOCTYPE html></head>","<html><head></head><!DOCTYPE html>","<body></body><!DOCTYPE html>","<table><!DOCTYPE html></table>","<select><!DOCTYPE html></select>","<table><colgroup><!DOCTYPE html></colgroup></table>","<table><colgroup><!--test--></colgroup></table>","<table><colgroup><html></colgroup></table>","<table><colgroup> foo</colgroup></table>","<select><!--test--></select>","<select><html></select>","<frameset><html></frameset>","<frameset></frameset><html>","<frameset></frameset><!DOCTYPE html>","<html><body></body></html><!DOCTYPE html>","<svg><!DOCTYPE html></svg>","<svg><font></font></svg>","<svg><font id=foo></font></svg>","<svg><font size=4></font></svg>","<svg><font color=red></font></svg>","<svg><font font=sans></font></svg>"],"entities01.dat":["FOO>BAR","FOO>BAR","FOO> BAR","FOO>;;BAR","I'm ¬it; I tell you","I'm ∉ I tell you","&ammmp;","&ammmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmp;","FOO& BAR","FOO&<BAR>","FOO&&&>BAR","FOO)BAR","FOOABAR","FOOABAR","FOO&#BAR","FOO&#ZOO","FOOºR","FOO&#xZOO","FOO&#XZOO","FOO)BAR","FOO䆺R","FOOAZOO","FOO�ZOO","FOOxZOO","FOOyZOO","FOO€ZOO","FOOZOO","FOO‚ZOO","FOOƒZOO","FOO„ZOO","FOO…ZOO","FOO†ZOO","FOO‡ZOO","FOOˆZOO","FOO‰ZOO","FOOŠZOO","FOO‹ZOO","FOOŒZOO","FOOZOO","FOOŽZOO","FOOZOO","FOOZOO","FOO‘ZOO","FOO’ZOO","FOO“ZOO","FOO”ZOO","FOO•ZOO","FOO–ZOO","FOO—ZOO","FOO˜ZOO","FOO™ZOO","FOOšZOO","FOO›ZOO","FOOœZOO","FOOZOO","FOOžZOO","FOOŸZOO","FOO ZOO","FOO퟿ZOO","FOO�ZOO","FOO�ZOO","FOO�ZOO","FOO�ZOO","FOOZOO","FOOZOO","FOO􈟔ZOO","FOOZOO","FOO�ZOO","FOO�ZOO","FOO�","FOO�","FOO�","FOO�ZOO","FOO�ZOO","FOO�ZOO"],"entities02.dat":["<div bar=\"ZZ>YY\"></div>","<div bar=\"ZZ&\"></div>","<div bar='ZZ&'></div>","<div bar=ZZ&></div>","<div bar=\"ZZ>=YY\"></div>","<div bar=\"ZZ>0YY\"></div>","<div bar=\"ZZ>9YY\"></div>","<div bar=\"ZZ>aYY\"></div>","<div bar=\"ZZ>ZYY\"></div>","<div bar=\"ZZ> YY\"></div>","<div bar=\"ZZ>\"></div>","<div bar='ZZ>'></div>","<div bar=ZZ>></div>","<div bar=\"ZZ£_id=23\"></div>","<div bar=\"ZZ&prod_id=23\"></div>","<div bar=\"ZZ£_id=23\"></div>","<div bar=\"ZZ∏_id=23\"></div>","<div bar=\"ZZ£=23\"></div>","<div bar=\"ZZ&prod=23\"></div>","<div>ZZ£_id=23</div>","<div>ZZ&prod_id=23</div>","<div>ZZ£_id=23</div>","<div>ZZ∏_id=23</div>","<div>ZZ£=23</div>","<div>ZZ&prod=23</div>","<div>ZZÆ=</div>"],"foreign-fragment.dat":["<nobr>X","<font color></font>X","<font></font>X","<g></path>X","</path>X","</foreignObject>X","</desc>X","</title>X","</svg>X","</mfenced>X","</malignmark>X","</math>X","</annotation-xml>X","</mtext>X","</mi>X","</mo>X","</mn>X","</ms>X","<b></b><mglyph/><i></i><malignmark/><u></u><ms/>X","<malignmark></malignmark>","<div></div>","<figure></figure>","<b></b><mglyph/><i></i><malignmark/><u></u><mn/>X","<malignmark></malignmark>","<div></div>","<figure></figure>","<b></b><mglyph/><i></i><malignmark/><u></u><mo/>X","<malignmark></malignmark>","<div></div>","<figure></figure>","<b></b><mglyph/><i></i><malignmark/><u></u><mi/>X","<malignmark></malignmark>","<div></div>","<figure></figure>","<b></b><mglyph/><i></i><malignmark/><u></u><mtext/>X","<malignmark></malignmark>","<div></div>","<figure></figure>","<div></div>","<figure></figure>","<div></div>","<figure></figure>","<div></div>","<figure></figure>","<div></div>","<figure></figure>","<figure></figure>","<div><h1>X</h1></div>","<div></div>","<div></div>","<plaintext><foo>","<frameset>X","<head>X","<body>X","<html>X","<html class=\"foo\">X","<body class=\"foo\">X","<svg><p>","<p>","<svg></p><foo>","<svg></br><foo>","</p><foo>","</br><foo>","<body><foo>","<p><foo>","<p></p><foo>"],"html5test-com.dat":["<div<div>","<div foo<bar=''>","<div foo=`bar`>","<div \\\"foo=''>","<a href='\\nbar'></a>","<!DOCTYPE html>","⟨⟩","'","ⅈ","𝕂","∉","<?import namespace=\"foo\" implementation=\"#bar\">","<!--foo--bar-->","<svg><title><![CDATA[x]]>","<svg><foreignobject><![CDATA[x]]>","<svg><foreignobject><p><![CDATA[x]]>","<math><![CDATA[x]]>","<math><mtext><![CDATA[x]]>","<math><mtext><i><![CDATA[x]]>","<![CDATA[x]]>","<textarea><!--</textarea>--></textarea>","<textarea><!--</textarea>-->","<style><!--</style>--></style>","<style><!--</style>-->","<ul><li>A </li> <li>B</li></ul>","<table><form><input type=hidden><input></form><div></div></table>","<i>A<b>B<p></i>C</b>D","<div></div>","<svg></svg>","<math></math>"],"inbody01.dat":["<button>1</foo>","<foo>1<p>2</foo>","<dd>1</foo>","<foo>1<dd>2</foo>"],"isindex.dat":["<isindex>","<isindex name=\"A\" action=\"B\" prompt=\"C\" foo=\"D\">","<form><isindex>","<!doctype html><isindex>x</isindex>x"],"main-element.dat":["<!doctype html><p>foo<main>bar<p>baz","<!doctype html><main><p>foo</main>bar","<!DOCTYPE html>xxx<svg><x><g><a><main><b>"],"math.dat":["<math><tr><td><mo><tr>","<math><tr><td><mo><tr>","<math><thead><mo><tbody>","<math><tfoot><mo><tbody>","<math><tbody><mo><tfoot>","<math><tbody><mo></table>","<math><thead><mo></table>","<math><tfoot><mo></table>"],"menuitem-element.dat":["<menuitem>","</menuitem>","<!DOCTYPE html><body><menuitem>A","<!DOCTYPE html><body><menuitem>A<menuitem>B","<!DOCTYPE html><body><menuitem>A<menu>B</menu>","<!DOCTYPE html><body><menuitem>A<hr>B","<!DOCTYPE html><li><menuitem><li>","<!DOCTYPE html><menuitem><p></menuitem>x","<!DOCTYPE html><p><b></p><menuitem>","<!DOCTYPE html><menuitem><asdf></menuitem>x","<!DOCTYPE html></menuitem>","<!DOCTYPE html><html></menuitem>","<!DOCTYPE html><head></menuitem>","<!DOCTYPE html><select><menuitem></select>","<!DOCTYPE html><option><menuitem>","<!DOCTYPE html><menuitem><option>","<!DOCTYPE html><menuitem></body>","<!DOCTYPE html><menuitem></html>","<!DOCTYPE html><menuitem><p>","<!DOCTYPE html><menuitem><li>"],"namespace-sensitivity.dat":["<body><table><tr><td><svg><td><foreignObject><span></td>Foo"],"noscript01.dat":["<head><noscript><!doctype html><!--foo--></noscript>","<head><noscript><html class=\"foo\"><!--foo--></noscript>","<head><noscript></noscript>","<head><noscript> </noscript>","<head><noscript><!--foo--></noscript>","<head><noscript><basefont><!--foo--></noscript>","<head><noscript><bgsound><!--foo--></noscript>","<head><noscript><link><!--foo--></noscript>","<head><noscript><meta><!--foo--></noscript>","<head><noscript><noframes>XXX</noscript></noframes></noscript>","<head><noscript><style>XXX</style></noscript>","<head><noscript></br><!--foo--></noscript>","<head><noscript><head class=\"foo\"><!--foo--></noscript>","<head><noscript><noscript class=\"foo\"><!--foo--></noscript>","<head><noscript></p><!--foo--></noscript>","<head><noscript><p><!--foo--></noscript>","<head><noscript>XXX<!--foo--></noscript></head>","<head><noscript>"],"pending-spec-changes-plain-text-unsafe.dat":["<body><table>\u0000filler\u0000text\u0000"],"pending-spec-changes.dat":["<input type=\"hidden\"><frameset>","<!DOCTYPE html><table><caption><svg>foo</table>bar","<table><tr><td><svg><desc><td></desc><circle>"],"plain-text-unsafe.dat":["FOO
ZOO","<html>\u0000<frameset></frameset>","<html> \u0000 <frameset></frameset>","<html>a\u0000a<frameset></frameset>","<html>\u0000\u0000<frameset></frameset>","<html>\u0000\n<frameset></frameset>","<html><select>\u0000","\u0000","<body>\u0000","<plaintext>\u0000filler\u0000text\u0000","<svg><![CDATA[\u0000filler\u0000text\u0000]]>","<body><!\u0000>","<body><!\u0000filler\u0000text>","<body><svg><foreignObject>\u0000filler\u0000text","<svg>\u0000filler\u0000text","<svg>\u0000<frameset>","<svg>\u0000 <frameset>","<svg>\u0000a<frameset>","<svg>\u0000</svg><frameset>","<svg>\u0000 </svg><frameset>","<svg>\u0000a</svg><frameset>","<svg><path></path></svg><frameset>","<svg><p><frameset>","<!DOCTYPE html><pre>\r\n\r\nA</pre>","<!DOCTYPE html><pre>\r\rA</pre>","<!DOCTYPE html><pre>\rA</pre>","<!DOCTYPE html><table><tr><td><math><mtext>\u0000a","<!DOCTYPE html><table><tr><td><svg><foreignObject>\u0000a","<!DOCTYPE html><math><mi>a\u0000b","<!DOCTYPE html><math><mo>a\u0000b","<!DOCTYPE html><math><mn>a\u0000b","<!DOCTYPE html><math><ms>a\u0000b","<!DOCTYPE html><math><mtext>a\u0000b","<math>\u0000filler\u0000text","<math><![CDATA[\u0000filler\u0000text\u0000]]>","<math><annotation-xml>\u0000x","<math><annotation-xml encoding=\"text/html\">\u0000x","\u0000filler\u0000text","\u0000filler\u0000text","\u0000filler\u0000text","\u0000x","\u0000filler\u0000text","\u0000filler\u0000text","\u0000filler\u0000text","\u0000filler\u0000text","\u0000filler\u0000text","\u0000filler\u0000text","\u0000filler\u0000text"],"processing-instructions.dat":["<body><?something>","<body><?something><span>","<body><?something good>","<body><?something else is good>","<body><?one><?two>","<body><?a$><?b$><?good?>","<body><?hey there?>","<body><?hey there?>","<body><?hey?there>","<body><?hey\tthere=1?>","<body><?hey\nthere=1?>","<body><?hey\rthere=1?>","<body><?hey\fthere=1?>","<body><?something ? >","<body><?something x >","<body><?something ?\\t ??>","<body><?t d > ?>","<body><?module-handler>","<body><?module-handler data>","<body><?view-port>","<body><?view-port data>","<body><?config-v2>","<body><?config-v2 data>","<body><?x>","<body><?x data>","<body><?zz2op>","<body><?zz2op data>","<body><?xla->","<body><?xla- data>","<body><?a-b-c>","<body><?a-b-c data>","<body><?v-123>","<body><?v-123 data>","<body><?a0-b1-c2>","<body><?a0-b1-c2 data>","<body><?page-404>","<body><?page-404 data>","<body><?r2-d2>","<body><?r2-d2 data>","<body><?level-99>","<body><?level-99 data>","<body><?UPPERCASE>","<body><?UPPERCASE data>","<body><?all-KINDS-of-CaSeS>","<body><?all-KINDS-of-CaSeS data>","<body><?user_name>","<body><?user_name data>","<body><?S_S-S_S>","<body><?S_S-S_S data>","<body><?b_>","<body><?b_ data>","<body><?_prefix>","<body><?_prefix data>","<body><?_x132>","<body><?_x132 data>","<body><?_-_>","<body><?_-_ data>","<body><?_>","<body><?_ data>","<body><?A---------------->","<body><?A---------------- data>","<body><?z0123456789>","<body><?z0123456789 data>","<body><?m-0>","<body><?m-0 data>","<body><?xml>","<body><?xml-stylesheet>","<body><?XML>","<body><?XML-stylesheet>","<body><?xML>","<body><?xml-STYLesheet>","<body><?1st-place>","<body><?2-factor>","<body><?99-problems>","<body><?٥-star>","<body><?-prefix>","<body><?--internal>","<body><?-data->","<body><?-100>","<body><?·middle-dot>","<body><?͵greek-numeral>","<body><?́accent-start>","<body><?price$value>","<body><?user@domain>","<body><?tag#id>","<body><?a+b>","<body><?100%>","<body><?data.v1>","<body><?namespace:tag>","<body><?error!code>","<body><?x=y>","<body><?a<b>","<body><?true&false>","<body><?not|or>","<body><?lit$123456789>","<body><?lit$$4x>","<body><?🚀-launch>","<body><?error-⚠️>","<body><?fire-🔥>","<body><?v1-✅>","<body><?start","<body><?start?","<body><?start ","<body><?start data","<body><?start ? ?","<body><?","<body><? ","<div><?something></div>","<div><?something good></div>","<table><?something></table>","<table><tr><?something></tr></table>","<script><?something></script>","<style><?something></style>","<?something>","<head><?something>","<html><?something><head>","<html><head></head><?something><body>","<html><body></body><?something>","<html><body></body></html><?something>","<body><template><?something></template>","<body><textarea><?something></textarea>","<body><title><?something></title>","<noscript><?pi>","<template><?pi>"],"quirks01.dat":["<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Frameset//EN\"\n\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd\"><p><table>","<!DOCTYPE html SYSTEM \"http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd\"><p><table>","<!DOCTYPE html PUBLIC \"html\"><p><table>","<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2//EN\"\n \"http://www.w3.org/TR/html4/strict.dtd\"><p><table>"],"ruby.dat":["<html><ruby>a<rb>b<rb></ruby></html>","<html><ruby>a<rb>b<rt></ruby></html>","<html><ruby>a<rb>b<rtc></ruby></html>","<html><ruby>a<rb>b<rp></ruby></html>","<html><ruby>a<rb>b<span></ruby></html>","<html><ruby>a<rt>b<rb></ruby></html>","<html><ruby>a<rt>b<rt></ruby></html>","<html><ruby>a<rt>b<rtc></ruby></html>","<html><ruby>a<rt>b<rp></ruby></html>","<html><ruby>a<rt>b<span></ruby></html>","<html><ruby>a<rtc>b<rb></ruby></html>","<html><ruby>a<rtc>b<rt>c<rt>d</ruby></html>","<html><ruby>a<rtc>b<rtc></ruby></html>","<html><ruby>a<rtc>b<rp></ruby></html>","<html><ruby>a<rtc>b<span></ruby></html>","<html><ruby>a<rp>b<rb></ruby></html>","<html><ruby>a<rp>b<rt></ruby></html>","<html><ruby>a<rp>b<rtc></ruby></html>","<html><ruby>a<rp>b<rp></ruby></html>","<html><ruby>a<rp>b<span></ruby></html>","<html><ruby><rtc><ruby>a<rb>b<rt></ruby></ruby></html>"],"scriptdata01.dat":["FOO<script>'Hello'</script>BAR","FOO<script></script>BAR","FOO<script></script >BAR","FOO<script></script/>BAR","FOO<script></script/ >BAR","FOO<script type=\"text/plain\"></scriptx>BAR","FOO<script></script foo=\">\" dd>BAR","FOO<script>'<'</script>BAR","FOO<script>'<!'</script>BAR","FOO<script>'<!-'</script>BAR","FOO<script>'<!--'</script>BAR","FOO<script>'<!---'</script>BAR","FOO<script>'<!-->'</script>BAR","FOO<script>'<!-- potato'</script>BAR","FOO<script>'<!-- <sCrIpt'</script>BAR","FOO<script type=\"text/plain\">'<!-- <sCrIpt>'</script>BAR","FOO<script type=\"text/plain\">'<!-- <sCrIpt> -'</script>BAR","FOO<script type=\"text/plain\">'<!-- <sCrIpt> --'</script>BAR","FOO<script>'<!-- <sCrIpt> -->'</script>BAR","FOO<script type=\"text/plain\">'<!-- <sCrIpt> --!>'</script>BAR","FOO<script type=\"text/plain\">'<!-- <sCrIpt> -- >'</script>BAR","FOO<script type=\"text/plain\">'<!-- <sCrIpt '</script>BAR","FOO<script type=\"text/plain\">'<!-- <sCrIpt/'</script>BAR","FOO<script type=\"text/plain\">'<!-- <sCrIpt\\'</script>BAR","FOO<script type=\"text/plain\">'<!-- <sCrIpt/'</script>BAR</script>QUX","FOO<script><!--<script>-></script>--></script>QUX"],"scripted_adoption01.dat":["<p><b id=\"A\"><script>document.getElementById(\"A\").id = \"B\"</script></p>TEXT</b>"],"scripted_ark.dat":["<p><font size=4><font size=4><font size=4><script>document.getElementsByTagName(\"font\")[2].setAttribute(\"size\", \"5\");</script><font size=4><p>X"],"scripted_foster01.dat":["<table><tr><script>var t=document.querySelector('table');document.documentElement.remove();document.appendChild(t)</script><b>","<table><tr><script>var t=document.querySelector('table');document.documentElement.remove();document.appendChild(t)</script>FOSTERTEXT"],"scripted_webkit01.dat":["1<script>document.write(\"2\")</script>3","1<script>document.write(\"<script>document.write('2')</scr\"+ \"ipt><script>document.write('3')</scr\" + \"ipt>\")</script>4"],"search-element.dat":["<!doctype html><p>foo<search>bar<p>baz","<!doctype html><search><p>foo</search>bar","<!DOCTYPE html>xxx<svg><x><g><a><search><b>"],"svg.dat":["<svg><tr><td><title><tr>","<svg><tr><td><title><tr>","<svg><thead><title><tbody>","<svg><tfoot><title><tbody>","<svg><tbody><title><tfoot>","<svg><tbody><title></table>","<svg><thead><title></table>","<svg><tfoot><title></table>"],"tables01.dat":["<table><th>","<table><td>","<table><col foo='bar'>","<table><colgroup></html>foo","<table></table><p>foo","<table></body></caption></col></colgroup></html></tbody></td></tfoot></th></thead></tr><td>","<table><select><option>3</select></table>","<table><select><table></table></select></table>","<table><select></table>","<table><select><option>A<tr><td>B</td></tr></table>","<table><td></body></caption></col></colgroup></html>foo","<table><td>A</table>B","<table><tr><caption>","<table><tr></body></caption></col></colgroup></html></td></th><td>foo","<table><td><tr>","<table><td><button><td>","<table><tr><td><svg><desc><td>","<div><table><svg><foreignObject><select><table><s>","<table>a<!doctype html>"],"template.dat":["<body><template>Hello</template>","<template>Hello</template>","<template></template><div></div>","<html><template>Hello</template>","<head><template><div></div></template></head>","<div><template><div><span></template><b>","<div><template></div>Hello","<div></template></div>","<table><template></template></table>","<table><template></template></div>","<table><div><template></template></div>","<table><template></template><div></div>","<table> <template></template></table>","<table><tbody><template></template></tbody>","<table><tbody><template></tbody></template>","<table><tbody><template></template></tbody></table>","<table><thead><template></template></thead>","<table><tfoot><template></template></tfoot>","<select><template></template></select>","<select><template><option></option></template></select>","<template><option></option></select><option></option></template>","<select><template></template><option></select>","<select><option><template></template></select>","<select><template>","<select><option></option><template>","<select><option></option><template><option>","<table><thead><template><td></template></table>","<table><template><thead></template></table>","<body><table><template><td></tr><div></template></table>","<table><template><thead></template></thead></table>","<table><thead><template><tr></template></table>","<table><template><tr></template></table>","<table><tr><template><td>","<table><template><tr><template><td></template></tr></template></table>","<table><template><tr><template><td></td></template></tr></template></table>","<table><template><td></template>","<body><template><td></td></template>","<body><template><template><tr></tr></template><td></td></template>","<table><colgroup><template><col>","<frameset><template><frame></frame></template></frameset>","<template><frame></frame></frameset><frame></frame></template>","<template><div><frameset><span></span></div><span></span></template>","<body><template><div><frameset><span></span></div><span></span></template></body>","<head><template></template></head><p><frameset>","<template>x</template><p><frameset>","<head></head><template></template><p><frameset>","<p><template></template><frameset>","<p><template><frameset></template>","<template></template>x<frameset>","<body><template><script>var i = 1;</script><td></td></template>","<body><template><tr><div></div></tr></template>","<table><template><tr><div></div></tr></template>","<body><template><tr></tr><td></td></template>","<body><template><td></td></tr><td></td></template>","<body><template><td></td><tbody><td></td></template>","<body><template><td></td><caption></caption><td></td></template>","<body><template><td></td><colgroup></caption><td></td></template>","<body><template><td></td></table><td></td></template>","<body><template><tr></tr><tbody><tr></tr></template>","<body><template><tr></tr><caption><tr></tr></template>","<body><template><tr></tr></table><tr></tr></template>","<body><template><thead></thead><caption></caption><tbody></tbody></template>","<body><template><thead></thead></table><tbody></tbody></template></body>","<body><template><div><tr></tr></div></template>","<body><template><em>Hello</em></template>","<body><template><!--comment--></template>","<body><template><style></style><td></td></template>","<body><template><meta><td></td></template>","<body><template><link><td></td></template>","<body><table><colgroup><template><col></col></template></colgroup></table></body>","<body a=b><template><div></div><body c=d><div></div></body></template></body>","<html a=b><template><div><html b=c><span></template>","<html a=b><template><col></col><html b=c><col></col></template>","<html a=b><template><frame></frame><html b=c><frame></frame></template>","<body><template><tr></tr><template></template><td></td></template>","<body><template><thead></thead><template><tr></tr></template><tr></tr><tfoot></tfoot></template>","<body><template><template><b><template></template></template>text</template>","<body><template><col><colgroup>","<body><template><col></colgroup>","<body><template><col><colgroup></template></body>","<body><template><col><div>","<body><template><col></div>","<body><template><col>Hello","<body><template><i><menu>Foo</i>","<body><template></div><div>Foo</div><template></template><tr></tr>","<body><div><template></div><tr><td>Foo</td></tr></template>","<template></figcaption><sub><table></table>","<template><template>","<template><div>","<template><template><div>","<template><template><table>","<template><template><tbody>","<template><template><tr>","<template><template><td>","<template><template><caption>","<template><template><colgroup>","<template><template><col>","<template><template><tbody><select>","<template><template><table>Foo","<template><template><frame>","<template><template><script>var i","<template><template><style>var i","<template><table></template><body><span>Foo","<template><td></template><body><span>Foo","<template><object></template><body><span>Foo","<template><svg><template>","<template><svg><foo><template><foreignObject><div></template><div>","<dummy><template><span></dummy>","<body><table><tr><td><select><template>Foo</template><caption>A</table>","<body></body><template>","<head></head><template>","<head></head><template>Foo</template>","<html><head></head><template></template><head>","<!DOCTYPE HTML><dummy><table><template><table><template><table><script>","<template><a><table><a>","<template><form><input name=\"q\"></form><div>second</div></template>","<template><table><form></table></template>","<table><form></table>","<template><form><form><input></template>","<form><form>","<template><form><template></template><form></template>","<template><template><form></template><form></template>","<form><template><form></template><form>","<br>BC<form>D<div>E</form>F</div>G","<!DOCTYPE HTML><template><tr><td>cell</td></tr></template>","<!DOCTYPE HTML><template> <tr> <td>cell</td> </tr> </template>","<!DOCTYPE HTML><template><tr><td>cell</td></tr>a</template>"],"tests1.dat":["Test","<p>One<p>Two","Line1<br>Line2<br>Line3<br>Line4","<html>","<head>","<body>","<html><head>","<html><head></head>","<html><head></head><body>","<html><head></head><body></body>","<html><head><body></body></html>","<html><head></body></html>","<html><head><body></html>","<html><body></html>","<body></html>","<head></html>","</head>","</body>","</html>","<b><table><td><i></table>","<b><table><td></b><i></table>X","<h1>Hello<h2>World","<a><p>X<a>Y</a>Z</p></a>","<b><button>foo</b>bar","<!DOCTYPE html><span><button>foo</span>bar","<p><b><div><marquee></p></b></div>X","<script><div></script></div><title><p></title><p><p>","<!--><div>--<!-->","<p><hr></p>","<select><b><option><select><option></b></select>X","<a><table><td><a><table></table><a></tr><a></table><b>X</b>C<a>Y","<a X>0<b>1<a Y>2","<!-----><font><div>hello<table>excite!<b>me!<th><i>please!</tr><!--X-->","<!DOCTYPE html><li>hello<li>world<ul>how<li>do</ul>you</body><!--do-->","<!DOCTYPE html>A<option>B<optgroup>C<select>D</option>E","<","<#","</","</#","<?","<?#","<!","<!#","<?COMMENT?>","<!COMMENT>","</ COMMENT >","<?COM--MENT?>","<!COM--MENT>","</ COM--MENT >","<!DOCTYPE html><style> EOF","<!DOCTYPE html><script> <!-- </script> --> </script> EOF","<b><p></b>TEST","<p id=a><b><p id=b></b>TEST","<b id=a><p><b id=b></p></b>TEST","<!DOCTYPE html><title>U-test</title><body><div><p>Test<u></p></div></body>","<!DOCTYPE html><font><table></font></table></font>","<font><p>hello<b>cruel</font>world","<b>Test</i>Test","<b>A<cite>B<div>C","<b>A<cite>B<div>C</cite>D","<b>A<cite>B<div>C</b>D","","<DIV>","<DIV> abc","<DIV> abc <B>","<DIV> abc <B> def","<DIV> abc <B> def <I>","<DIV> abc <B> def <I> ghi","<DIV> abc <B> def <I> ghi <P>","<DIV> abc <B> def <I> ghi <P> jkl","<DIV> abc <B> def <I> ghi <P> jkl </B>","<DIV> abc <B> def <I> ghi <P> jkl </B> mno","<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I>","<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr","<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr </P>","<DIV> abc <B> def <I> ghi <P> jkl </B> mno </I> pqr </P> stu","<test attribute---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->","<a href=\"blah\">aba<table><a href=\"foo\">br<tr><td></td></tr>x</table>aoe","<a href=\"blah\">aba<table><tr><td><a href=\"foo\">br</td></tr>x</table>aoe","<table><a href=\"blah\">aba<tr><td><a href=\"foo\">br</td></tr>x</table>aoe","<a href=a>aa<marquee>aa<a href=b>bb</marquee>aa","<wbr><strike><code></strike><code><strike></code>","<!DOCTYPE html><spacer>foo","<title><meta></title><link><title><meta></title>","<style><!--</style><meta><script>--><link></script>","<head><meta></head><link>","<table><tr><tr><td><td><span><th><span>X</table>","<body><body><base><link><meta><title><p></title><body><p></body>","<textarea><p></textarea>","<p><image></p>","<a><table><a></table><p><a><div><a>","<head></p><meta><p>","<head></html><meta><p>","<b><table><td></b><i></table>","<h1><h2>","<a><p><a></a></p></a>","<b><button></b></button></b>","<p><b><div><marquee></p></b></div>","<script></script></div><title></title><p><p>","<select><b><option><select><option></b></select>","<html><head><title></title><body></body></html>","<a><table><td><a><table></table><a></tr><a></table><a>","<ul><li></li><div><li></div><li><li><div><li><address><li><b><em></b><li></ul>","<ul><li><ul></li><li>a</li></ul></li></ul>","<frameset><frame><frameset><frame></frameset><noframes></noframes></frameset>","<h1><table><td><h3></table><h3></h1>","<table><colgroup><col><colgroup><col><col><col><colgroup><col><col><thead><tr><td></table>","<table><col><tbody><col><tr><col><td><col></table><col>","<table><colgroup><tbody><colgroup><tr><colgroup><td><colgroup></table><colgroup>","</strong></b></em></i></u></strike></s></blink></tt></pre></big></small></font></select></h1></h2></h3></h4></h5></h6></body></br></a></img></title></span></style></script></table></th></td></tr></frame></area></link></param></hr></input></col></base></meta></basefont></bgsound></embed></spacer></p></dd></dt></caption></colgroup></tbody></tfoot></thead></address></blockquote></center></dir></div></dl></fieldset></listing></menu></ol></ul></li></nobr></wbr></form></button></marquee></object></html></frameset></head></iframe></image></isindex></noembed></noframes></noscript></optgroup></option></plaintext></textarea>","<table><tr></strong></b></em></i></u></strike></s></blink></tt></pre></big></small></font></select></h1></h2></h3></h4></h5></h6></body></br></a></img></title></span></style></script></table></th></td></tr></frame></area></link></param></hr></input></col></base></meta></basefont></bgsound></embed></spacer></p></dd></dt></caption></colgroup></tbody></tfoot></thead></address></blockquote></center></dir></div></dl></fieldset></listing></menu></ol></ul></li></nobr></wbr></form></button></marquee></object></html></frameset></head></iframe></image></isindex></noembed></noframes></noscript></optgroup></option></plaintext></textarea>","<frameset>"],"tests10.dat":["<!DOCTYPE html><svg></svg>","<!DOCTYPE html><svg></svg><![CDATA[a]]>","<!DOCTYPE html><body><svg></svg>","<!DOCTYPE html><body><select><svg></svg></select>","<!DOCTYPE html><body><select><option><svg></svg></option></select>","<!DOCTYPE html><body><table><svg></svg></table>","<!DOCTYPE html><body><table><svg><g>foo</g></svg></table>","<!DOCTYPE html><body><table><svg><g>foo</g><g>bar</g></svg></table>","<!DOCTYPE html><body><table><tbody><svg><g>foo</g><g>bar</g></svg></tbody></table>","<!DOCTYPE html><body><table><tbody><tr><svg><g>foo</g><g>bar</g></svg></tr></tbody></table>","<!DOCTYPE html><body><table><tbody><tr><td><svg><g>foo</g><g>bar</g></svg></td></tr></tbody></table>","<!DOCTYPE html><body><table><tbody><tr><td><svg><g>foo</g><g>bar</g></svg><p>baz</td></tr></tbody></table>","<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g></svg><p>baz</caption></table>","<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g><p>baz</table><p>quux","<!DOCTYPE html><body><table><caption><svg><g>foo</g><g>bar</g>baz</table><p>quux","<!DOCTYPE html><body><table><colgroup><svg><g>foo</g><g>bar</g><p>baz</table><p>quux","<!DOCTYPE html><body><table><tr><td><select><svg><g>foo</g><g>bar</g><p>baz</table><p>quux","<!DOCTYPE html><body><table><select><svg><g>foo</g><g>bar</g><p>baz</table><p>quux","<!DOCTYPE html><body></body></html><svg><g>foo</g><g>bar</g><p>baz","<!DOCTYPE html><body></body><svg><g>foo</g><g>bar</g><p>baz","<!DOCTYPE html><frameset><svg><g></g><g></g><p><span>","<!DOCTYPE html><frameset></frameset><svg><g></g><g></g><p><span>","<!DOCTYPE html><body xlink:href=foo><svg xlink:href=foo></svg>","<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo></g></svg>","<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo /></svg>","<!DOCTYPE html><body xlink:href=foo xml:lang=en><svg><g xml:lang=en xlink:href=foo />bar</svg>","<svg></path>","<div><svg></div>a","<div><svg><path></div>a","<div><svg><path></svg><path>","<div><svg><path><foreignObject><math></div>a","<div><svg><path><foreignObject><p></div>a","<!DOCTYPE html><svg><desc><div><svg><ul>a","<!DOCTYPE html><svg><desc><svg><ul>a","<!DOCTYPE html><p><svg><desc><p>","<!DOCTYPE html><p><svg><title><p>","<div><svg><path><foreignObject><p></foreignObject><p>","<math><mi><div><object><div><span></span></div></object></div></mi><mi>","<math><mi><svg><foreignObject><div><div></div></div></foreignObject></svg></mi><mi>","<svg><script></script><path>","<table><svg></svg><tr>","<math><mi><mglyph>","<math><mi><malignmark>","<math><mo><mglyph>","<math><mo><malignmark>","<math><mn><mglyph>","<math><mn><malignmark>","<math><ms><mglyph>","<math><ms><malignmark>","<math><mtext><mglyph>","<math><mtext><malignmark>","<math><annotation-xml><svg></svg></annotation-xml><mi>","<math><annotation-xml><svg><foreignObject><div><math><mi></mi></math><span></span></div></foreignObject><path></path></svg></annotation-xml><mi>","<math><annotation-xml><svg><foreignObject><math><mi><svg></svg></mi><mo></mo></math><span></span></foreignObject><path></path></svg></annotation-xml><mi>"],"tests11.dat":["<!DOCTYPE html><body><svg attributeName='' attributeType='' baseFrequency='' baseProfile='' calcMode='' clipPathUnits='' diffuseConstant='' edgeMode='' filterUnits='' glyphRef='' gradientTransform='' gradientUnits='' kernelMatrix='' kernelUnitLength='' keyPoints='' keySplines='' keyTimes='' lengthAdjust='' limitingConeAngle='' markerHeight='' markerUnits='' markerWidth='' maskContentUnits='' maskUnits='' numOctaves='' pathLength='' patternContentUnits='' patternTransform='' patternUnits='' pointsAtX='' pointsAtY='' pointsAtZ='' preserveAlpha='' preserveAspectRatio='' primitiveUnits='' refX='' refY='' repeatCount='' repeatDur='' requiredExtensions='' requiredFeatures='' specularConstant='' specularExponent='' spreadMethod='' startOffset='' stdDeviation='' stitchTiles='' surfaceScale='' systemLanguage='' tableValues='' targetX='' targetY='' textLength='' viewBox='' viewTarget='' xChannelSelector='' yChannelSelector='' zoomAndPan=''></svg>","<!DOCTYPE html><BODY><SVG ATTRIBUTENAME='' ATTRIBUTETYPE='' BASEFREQUENCY='' BASEPROFILE='' CALCMODE='' CLIPPATHUNITS='' DIFFUSECONSTANT='' EDGEMODE='' FILTERUNITS='' GLYPHREF='' GRADIENTTRANSFORM='' GRADIENTUNITS='' KERNELMATRIX='' KERNELUNITLENGTH='' KEYPOINTS='' KEYSPLINES='' KEYTIMES='' LENGTHADJUST='' LIMITINGCONEANGLE='' MARKERHEIGHT='' MARKERUNITS='' MARKERWIDTH='' MASKCONTENTUNITS='' MASKUNITS='' NUMOCTAVES='' PATHLENGTH='' PATTERNCONTENTUNITS='' PATTERNTRANSFORM='' PATTERNUNITS='' POINTSATX='' POINTSATY='' POINTSATZ='' PRESERVEALPHA='' PRESERVEASPECTRATIO='' PRIMITIVEUNITS='' REFX='' REFY='' REPEATCOUNT='' REPEATDUR='' REQUIREDEXTENSIONS='' REQUIREDFEATURES='' SPECULARCONSTANT='' SPECULAREXPONENT='' SPREADMETHOD='' STARTOFFSET='' STDDEVIATION='' STITCHTILES='' SURFACESCALE='' SYSTEMLANGUAGE='' TABLEVALUES='' TARGETX='' TARGETY='' TEXTLENGTH='' VIEWBOX='' VIEWTARGET='' XCHANNELSELECTOR='' YCHANNELSELECTOR='' ZOOMANDPAN=''></SVG>","<!DOCTYPE html><body><svg attributename='' attributetype='' basefrequency='' baseprofile='' calcmode='' clippathunits='' diffuseconstant='' edgemode='' filterunits='' filterres='' glyphref='' gradienttransform='' gradientunits='' kernelmatrix='' kernelunitlength='' keypoints='' keysplines='' keytimes='' lengthadjust='' limitingconeangle='' markerheight='' markerunits='' markerwidth='' maskcontentunits='' maskunits='' numoctaves='' pathlength='' patterncontentunits='' patterntransform='' patternunits='' pointsatx='' pointsaty='' pointsatz='' preservealpha='' preserveaspectratio='' primitiveunits='' refx='' refy='' repeatcount='' repeatdur='' requiredextensions='' requiredfeatures='' specularconstant='' specularexponent='' spreadmethod='' startoffset='' stddeviation='' stitchtiles='' surfacescale='' systemlanguage='' tablevalues='' targetx='' targety='' textlength='' viewbox='' viewtarget='' xchannelselector='' ychannelselector='' zoomandpan=''></svg>","<!DOCTYPE html><body><math attributeName='' attributeType='' baseFrequency='' baseProfile='' calcMode='' clipPathUnits='' diffuseConstant='' edgeMode='' filterUnits='' glyphRef='' gradientTransform='' gradientUnits='' kernelMatrix='' kernelUnitLength='' keyPoints='' keySplines='' keyTimes='' lengthAdjust='' limitingConeAngle='' markerHeight='' markerUnits='' markerWidth='' maskContentUnits='' maskUnits='' numOctaves='' pathLength='' patternContentUnits='' patternTransform='' patternUnits='' pointsAtX='' pointsAtY='' pointsAtZ='' preserveAlpha='' preserveAspectRatio='' primitiveUnits='' refX='' refY='' repeatCount='' repeatDur='' requiredExtensions='' requiredFeatures='' specularConstant='' specularExponent='' spreadMethod='' startOffset='' stdDeviation='' stitchTiles='' surfaceScale='' systemLanguage='' tableValues='' targetX='' targetY='' textLength='' viewBox='' viewTarget='' xChannelSelector='' yChannelSelector='' zoomAndPan=''></math>","<!DOCTYPE html><body><svg contentScriptType='' contentStyleType='' externalResourcesRequired='' filterRes=''></svg>","<!DOCTYPE html><body><svg CONTENTSCRIPTTYPE='' CONTENTSTYLETYPE='' EXTERNALRESOURCESREQUIRED='' FILTERRES=''></svg>","<!DOCTYPE html><body><svg contentscripttype='' contentstyletype='' externalresourcesrequired='' filterres=''></svg>","<!DOCTYPE html><body><math contentScriptType='' contentStyleType='' externalResourcesRequired='' filterRes=''></math>","<!DOCTYPE html><body><svg><altGlyph /><altGlyphDef /><altGlyphItem /><animateColor /><animateMotion /><animateTransform /><clipPath /><feBlend /><feColorMatrix /><feComponentTransfer /><feComposite /><feConvolveMatrix /><feDiffuseLighting /><feDisplacementMap /><feDistantLight /><feFlood /><feFuncA /><feFuncB /><feFuncG /><feFuncR /><feGaussianBlur /><feImage /><feMerge /><feMergeNode /><feMorphology /><feOffset /><fePointLight /><feSpecularLighting /><feSpotLight /><feTile /><feTurbulence /><foreignObject /><glyphRef /><linearGradient /><radialGradient /><textPath /></svg>","<!DOCTYPE html><body><svg><altglyph /><altglyphdef /><altglyphitem /><animatecolor /><animatemotion /><animatetransform /><clippath /><feblend /><fecolormatrix /><fecomponenttransfer /><fecomposite /><feconvolvematrix /><fediffuselighting /><fedisplacementmap /><fedistantlight /><feflood /><fefunca /><fefuncb /><fefuncg /><fefuncr /><fegaussianblur /><feimage /><femerge /><femergenode /><femorphology /><feoffset /><fepointlight /><fespecularlighting /><fespotlight /><fetile /><feturbulence /><foreignobject /><glyphref /><lineargradient /><radialgradient /><textpath /></svg>","<!DOCTYPE html><BODY><SVG><ALTGLYPH /><ALTGLYPHDEF /><ALTGLYPHITEM /><ANIMATECOLOR /><ANIMATEMOTION /><ANIMATETRANSFORM /><CLIPPATH /><FEBLEND /><FECOLORMATRIX /><FECOMPONENTTRANSFER /><FECOMPOSITE /><FECONVOLVEMATRIX /><FEDIFFUSELIGHTING /><FEDISPLACEMENTMAP /><FEDISTANTLIGHT /><FEFLOOD /><FEFUNCA /><FEFUNCB /><FEFUNCG /><FEFUNCR /><FEGAUSSIANBLUR /><FEIMAGE /><FEMERGE /><FEMERGENODE /><FEMORPHOLOGY /><FEOFFSET /><FEPOINTLIGHT /><FESPECULARLIGHTING /><FESPOTLIGHT /><FETILE /><FETURBULENCE /><FOREIGNOBJECT /><GLYPHREF /><LINEARGRADIENT /><RADIALGRADIENT /><TEXTPATH /></SVG>","<!DOCTYPE html><body><math><altGlyph /><altGlyphDef /><altGlyphItem /><animateColor /><animateMotion /><animateTransform /><clipPath /><feBlend /><feColorMatrix /><feComponentTransfer /><feComposite /><feConvolveMatrix /><feDiffuseLighting /><feDisplacementMap /><feDistantLight /><feFlood /><feFuncA /><feFuncB /><feFuncG /><feFuncR /><feGaussianBlur /><feImage /><feMerge /><feMergeNode /><feMorphology /><feOffset /><fePointLight /><feSpecularLighting /><feSpotLight /><feTile /><feTurbulence /><foreignObject /><glyphRef /><linearGradient /><radialGradient /><textPath /></math>","<!DOCTYPE html><body><svg><solidColor /></svg>"],"tests12.dat":["<!DOCTYPE html><body><p>foo<math><mtext><i>baz</i></mtext><annotation-xml><svg><desc><b>eggs</b></desc><g><foreignObject><P>spam<TABLE><tr><td><img></td></table></foreignObject></g><g>quux</g></svg></annotation-xml></math>bar","<!DOCTYPE html><body>foo<math><mtext><i>baz</i></mtext><annotation-xml><svg><desc><b>eggs</b></desc><g><foreignObject><P>spam<TABLE><tr><td><img></td></table></foreignObject></g><g>quux</g></svg></annotation-xml></math>bar"],"tests14.dat":["<!DOCTYPE html><html><body><xyz:abc></xyz:abc>","<!DOCTYPE html><html><body><xyz:abc></xyz:abc><span></span>","<!DOCTYPE html><html><html abc:def=gh><xyz:abc></xyz:abc>","<!DOCTYPE html><html xml:lang=bar><html xml:lang=foo>","<!DOCTYPE html><html 123=456>","<!DOCTYPE html><html 123=456><html 789=012>","<!DOCTYPE html><html><body 789=012>"],"tests15.dat":["<!DOCTYPE html><p><b><i><u></p> <p>X","<p><b><i><u></p>\n<p>X","<!doctype html></html> <head>","<!doctype html></body><meta>","<html></html><!-- foo -->","<!doctype html></body><title>X</title>","<!doctype html><table> X<meta></table>","<!doctype html><table> x</table>","<!doctype html><table> x </table>","<!doctype html><table><tr> x</table>","<!doctype html><table>X<style> <tr>x </style> </table>","<!doctype html><div><table><a>foo</a> <tr><td>bar</td> </tr></table></div>","<frame></frame></frame><frameset><frame><frameset><frame></frameset><noframes></frameset><noframes>","<!DOCTYPE html><object></html>"],"tests16.dat":["<!doctype html><script>","<!doctype html><script>a","<!doctype html><script><","<!doctype html><script></","<!doctype html><script></S","<!doctype html><script></SC","<!doctype html><script></SCR","<!doctype html><script></SCRI","<!doctype html><script></SCRIP","<!doctype html><script></SCRIPT","<!doctype html><script></SCRIPT ","<!doctype html><script></s","<!doctype html><script></sc","<!doctype html><script></scr","<!doctype html><script></scri","<!doctype html><script></scrip","<!doctype html><script></script","<!doctype html><script></script ","<!doctype html><script><!","<!doctype html><script><!a","<!doctype html><script><!-","<!doctype html><script><!-a","<!doctype html><script><!--","<!doctype html><script><!--a","<!doctype html><script><!--<","<!doctype html><script><!--<a","<!doctype html><script><!--</","<!doctype html><script><!--</script","<!doctype html><script><!--</script ","<!doctype html><script><!--<s","<!doctype html><script><!--<script","<!doctype html><script><!--<script ","<!doctype html><script><!--<script <","<!doctype html><script><!--<script <a","<!doctype html><script><!--<script </","<!doctype html><script><!--<script </s","<!doctype html><script><!--<script </script","<!doctype html><script><!--<script </scripta","<!doctype html><script><!--<script </script ","<!doctype html><script><!--<script </script>","<!doctype html><script><!--<script </script/","<!doctype html><script><!--<script </script <","<!doctype html><script><!--<script </script <a","<!doctype html><script><!--<script </script </","<!doctype html><script><!--<script </script </script","<!doctype html><script><!--<script </script </script ","<!doctype html><script><!--<script </script </script/","<!doctype html><script><!--<script </script </script>","<!doctype html><script><!--<script -","<!doctype html><script><!--<script -a","<!doctype html><script><!--<script -<","<!doctype html><script><!--<script --","<!doctype html><script><!--<script --a","<!doctype html><script><!--<script --<","<!doctype html><script><!--<script -->","<!doctype html><script><!--<script --><","<!doctype html><script><!--<script --></","<!doctype html><script><!--<script --></script","<!doctype html><script><!--<script --></script ","<!doctype html><script><!--<script --></script/","<!doctype html><script><!--<script --></script>","<!doctype html><script><!--<script><\\/script>--></script>","<!doctype html><script><!--<script></scr'+'ipt>--></script>","<!doctype html><script><!--<script></script><script></script></script>","<!doctype html><script><!--<script></script><script></script>--><!--</script>","<!doctype html><script><!--<script></script><script></script>-- ></script>","<!doctype html><script><!--<script></script><script></script>- -></script>","<!doctype html><script><!--<script></script><script></script>- - ></script>","<!doctype html><script><!--<script></script><script></script>-></script>","<!doctype html><script><!--<script>--!></script>X","<!doctype html><script><!--<scr'+'ipt></script>--></script>","<!doctype html><script><!--<script></scr'+'ipt></script>X","<!doctype html><style><!--<style></style>--></style>","<!doctype html><style><!--</style>X","<!doctype html><style><!--...</style>...--></style>","<!doctype html><style><!--<br><html xmlns:v=\"urn:schemas-microsoft-com:vml\"><!--[if !mso]><style></style>X","<!doctype html><style><!--...<style><!--...--!></style>--></style>","<!doctype html><style><!--...</style><!-- --><style>@import ...</style>","<!doctype html><style>...<style><!--...</style><!-- --></style>","<!doctype html><style>...<!--[if IE]><style>...</style>X","<!doctype html><title><!--<title></title>--></title>","<!doctype html><title></title></title>","<!doctype html><title>foo/title><link></head><body>X","<!doctype html><noscript><!--<noscript></noscript>--></noscript>","<!doctype html><noscript><!--<noscript></noscript>--></noscript>","<!doctype html><noscript><!--</noscript>X<noscript>--></noscript>","<!doctype html><noscript><!--</noscript>X<noscript>--></noscript>","<!doctype html><noscript><iframe></noscript>X","<!doctype html><noscript><iframe></noscript>X","<!doctype html><noframes><!--<noframes></noframes>--></noframes>","<!doctype html><noframes><body><script><!--...</script></body></noframes></html>","<!doctype html><textarea><!--<textarea></textarea>--></textarea>","<!doctype html><textarea></textarea></textarea>","<!doctype html><textarea><</textarea>","<!doctype html><textarea>a<b</textarea>","<!doctype html><iframe><!--<iframe></iframe>--></iframe>","<!doctype html><iframe>...<!--X->...<!--/X->...</iframe>","<!doctype html><xmp><!--<xmp></xmp>--></xmp>","<!doctype html><noembed><!--<noembed></noembed>--></noembed>","<script>","<script>a","<script><","<script></","<script></S","<script></SC","<script></SCR","<script></SCRI","<script></SCRIP","<script></SCRIPT","<script></SCRIPT ","<script></s","<script></sc","<script></scr","<script></scri","<script></scrip","<script></script","<script></script ","<script><!","<script><!a","<script><!-","<script><!-a","<script><!--","<script><!--a","<script><!--<","<script><!--<a","<script><!--</","<script><!--</script","<script><!--</script ","<script><!--<s","<script><!--<script","<script><!--<script ","<script><!--<script <","<script><!--<script <a","<script><!--<script </","<script><!--<script </s","<script><!--<script </script","<script><!--<script </scripta","<script><!--<script </script ","<script><!--<script </script>","<script><!--<script </script/","<script><!--<script </script <","<script><!--<script </script <a","<script><!--<script </script </","<script><!--<script </script </script","<script><!--<script </script </script ","<script><!--<script </script </script/","<script><!--<script </script </script>","<script><!--<script -","<script><!--<script -a","<script><!--<script --","<script><!--<script --a","<script><!--<script -->","<script><!--<script --><","<script><!--<script --></","<script><!--<script --></script","<script><!--<script --></script ","<script><!--<script --></script/","<script><!--<script --></script>","<script><!--<script><\\/script>--></script>","<script><!--<script></scr'+'ipt>--></script>","<script><!--<script></script><script></script></script>","<script><!--<script></script><script></script>--><!--</script>","<script><!--<script></script><script></script>-- ></script>","<script><!--<script></script><script></script>- -></script>","<script><!--<script></script><script></script>- - ></script>","<script><!--<script></script><script></script>-></script>","<script><!--<script>--!></script>X","<script><!--<scr'+'ipt></script>--></script>","<script><!--<script></scr'+'ipt></script>X","<style><!--<style></style>--></style>","<style><!--</style>X","<style><!--...</style>...--></style>","<style><!--<br><html xmlns:v=\"urn:schemas-microsoft-com:vml\"><!--[if !mso]><style></style>X","<style><!--...<style><!--...--!></style>--></style>","<style><!--...</style><!-- --><style>@import ...</style>","<style>...<style><!--...</style><!-- --></style>","<style>...<!--[if IE]><style>...</style>X","<title><!--<title></title>--></title>","<title></title></title>","<title>foo/title><link></head><body>X","<noscript><!--<noscript></noscript>--></noscript>","<noscript><!--<noscript></noscript>--></noscript>","<noscript><!--</noscript>X<noscript>--></noscript>","<noscript><!--</noscript>X<noscript>--></noscript>","<noscript><iframe></noscript>X","<noscript><iframe></noscript>X","<noframes><!--<noframes></noframes>--></noframes>","<noframes><body><script><!--...</script></body></noframes></html>","<textarea><!--<textarea></textarea>--></textarea>","<textarea></textarea></textarea>","<iframe><!--<iframe></iframe>--></iframe>","<iframe>...<!--X->...<!--/X->...</iframe>","<xmp><!--<xmp></xmp>--></xmp>","<noembed><!--<noembed></noembed>--></noembed>","<!doctype html><table>\n","<!doctype html><table><td><span><font></span><span>","<!doctype html><form><table></form><form></table></form>"],"tests17.dat":["<!doctype html><table><tbody><select><tr>","<!doctype html><table><tr><select><td>","<!doctype html><table><tr><td><select><td>","<!doctype html><table><tr><th><select><td>","<!doctype html><table><caption><select><tr>","<!doctype html><select><tr>","<!doctype html><select><td>","<!doctype html><select><th>","<!doctype html><select><tbody>","<!doctype html><select><thead>","<!doctype html><select><tfoot>","<!doctype html><select><caption>","<!doctype html><table><tr></table>a"],"tests18.dat":["<plaintext></plaintext>","<!doctype html><plaintext></plaintext>","<!doctype html><html><plaintext></plaintext>","<!doctype html><head><plaintext></plaintext>","<!doctype html><html><noscript><plaintext></plaintext>","<!doctype html></head><plaintext></plaintext>","<!doctype html><body><plaintext></plaintext>","<!doctype html><table><plaintext></plaintext>","<!doctype html><table><tbody><plaintext></plaintext>","<!doctype html><table><tbody><tr><plaintext></plaintext>","<!doctype html><table><td><plaintext></plaintext>","<!doctype html><table><caption><plaintext></plaintext>","<!doctype html><table><colgroup><plaintext></plaintext>","<!doctype html><select><plaintext></plaintext>X","<!doctype html><table><select><plaintext>a<caption>b","<!doctype html><template><plaintext>a</template>b","<!doctype html><body></body><plaintext></plaintext>","<!doctype html><frameset><plaintext></plaintext>","<!doctype html><frameset></frameset><plaintext></plaintext>","<!doctype html><body></body></html><plaintext></plaintext>","<!doctype html><frameset></frameset></html><plaintext></plaintext>","<!doctype html><svg><plaintext>a</plaintext>b","<!doctype html><svg><title><plaintext>a</plaintext>b","<!doctype html><table><tr><style></script></style>abc","<!doctype html><table><tr><script></style></script>abc","<!doctype html><table><caption><style></script></style>abc","<!doctype html><table><td><style></script></style>abc","<!doctype html><select><script></style></script>abc","<!doctype html><table><select><script></style></script>abc","<!doctype html><table><tr><select><script></style></script>abc","<!doctype html><frameset></frameset><noframes>abc","<!doctype html><frameset></frameset><noframes>abc</noframes><!--abc-->","<!doctype html><frameset></frameset></html><noframes>abc","<!doctype html><frameset></frameset></html><noframes>abc</noframes><!--abc-->","<!doctype html><table><tr></tbody><tfoot>","<!doctype html><table><td><svg></svg>abc<td>"],"tests19.dat":["<!doctype html><math><mn DefinitionUrl=\"foo\">","<!doctype html><html></p><!--foo-->","<!doctype html><head></head></p><!--foo-->","<!doctype html><body><p><pre>","<!doctype html><body><p><listing>","<!doctype html><p><plaintext>","<!doctype html><p><h1>","<!doctype html><isindex type=\"hidden\">","<!doctype html><ruby><p><rp>","<!doctype html><ruby><div><span><rp>","<!doctype html><ruby><div><p><rp>","<!doctype html><ruby><p><rt>","<!doctype html><ruby><div><span><rt>","<!doctype html><ruby><div><p><rt>","<html><ruby>a<rb>b<rt></ruby></html>","<html><ruby>a<rp>b<rt></ruby></html>","<html><ruby>a<rt>b<rt></ruby></html>","<html><ruby>a<rtc>b<rt>c<rb>d</ruby></html>","<!doctype html><math/><foo>","<!doctype html><svg/><foo>","<!doctype html><div></body><!--foo-->","<!doctype html><h1><div><h3><span></h1>foo","<!doctype html><p></h3>foo","<!doctype html><h3><li>abc</h2>foo","<!doctype html><table>abc<!--foo-->","<!doctype html><table> <!--foo-->","<!doctype html><table> b <!--foo-->","<!doctype html><select><option><option>","<!doctype html><select><option></optgroup>","<!doctype html><dd><optgroup><dd>","<!doctype html><p><math><mi><p><h1>","<!doctype html><p><math><mo><p><h1>","<!doctype html><p><math><mn><p><h1>","<!doctype html><p><math><ms><p><h1>","<!doctype html><p><math><mtext><p><h1>","<!doctype html><frameset></noframes>","<!doctype html><html c=d><body></html><html a=b>","<!doctype html><html c=d><frameset></frameset></html><html a=b>","<!doctype html><html><frameset></frameset></html><!--foo-->","<!doctype html><html><frameset></frameset></html> ","<!doctype html><html><frameset></frameset></html>abc","<!doctype html><html><frameset></frameset></html><p>","<!doctype html><html><frameset></frameset></html></p>","<html><frameset></frameset></html><!doctype html>","<!doctype html><body><frameset>","<!doctype html><p><frameset><frame>","<!doctype html><p>a<frameset>","<!doctype html><p> <frameset><frame>","<!doctype html><pre><frameset>","<!doctype html><listing><frameset>","<!doctype html><li><frameset>","<!doctype html><dd><frameset>","<!doctype html><dt><frameset>","<!doctype html><button><frameset>","<!doctype html><applet><frameset>","<!doctype html><marquee><frameset>","<!doctype html><object><frameset>","<!doctype html><table><frameset>","<!doctype html><area><frameset>","<!doctype html><basefont><frameset>","<!doctype html><bgsound><frameset>","<!doctype html><br><frameset>","<!doctype html><embed><frameset>","<!doctype html><img><frameset>","<!doctype html><input><frameset>","<!doctype html><keygen><frameset>","<!doctype html><wbr><frameset>","<!doctype html><hr><frameset>","<!doctype html><textarea></textarea><frameset>","<!doctype html><xmp></xmp><frameset>","<!doctype html><iframe></iframe><frameset>","<!doctype html><select></select><frameset>","<!doctype html><svg></svg><frameset><frame>","<!doctype html><math></math><frameset><frame>","<!doctype html><svg><foreignObject><div> <frameset><frame>","<!doctype html><svg>a</svg><frameset><frame>","<!doctype html><svg> </svg><frameset><frame>","<html>aaa<frameset></frameset>","<html> a <frameset></frameset>","<!doctype html><div><frameset>","<!doctype html><div><body><frameset>","<!doctype html><p><math></p>a","<!doctype html><p><math><mn><span></p>a","<!doctype html><math></html>","<!doctype html><meta charset=\"ascii\">","<!doctype html><meta http-equiv=\"content-type\" content=\"text/html;charset=ascii\">","<!doctype html><head><!--aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa--><meta charset=\"utf8\">","<!doctype html><html a=b><head></head><html c=d>","<!doctype html><image/>","<!doctype html>a<i>b<table>c<b>d</i>e</b>f","<!doctype html><table><i>a<b>b<div>c<a>d</i>e</b>f","<!doctype html><i>a<b>b<div>c<a>d</i>e</b>f","<!doctype html><table><i>a<b>b<div>c</i>","<!doctype html><table><i>a<div>b<tr>c<b>d</i>e","<!doctype html><table><td><table><i>a<div>b<b>c</i>d","<!doctype html><body><bgsound>","<!doctype html><body><basefont>","<!doctype html><a><b></a><basefont>","<!doctype html><a><b></a><bgsound>","<!doctype html><figcaption><article></figcaption>a","<!doctype html><summary><article></summary>a","<!doctype html><p><a><plaintext>b","<!DOCTYPE html><div>a<a></div>b<p>c</p>d"],"tests2.dat":["<!DOCTYPE html>Test","<textarea>test</div>test","<table><td>","<table><td>test</tbody></table>","<frame>test","<!DOCTYPE html><frameset>test","<!DOCTYPE html><frameset> te st","<!DOCTYPE html><frameset></frameset> te st","<!DOCTYPE html><frameset><!DOCTYPE html>","<!DOCTYPE html><font><p><b>test</font>","<!DOCTYPE html><dt><div><dd>","<script></x","<table><plaintext><td>","<plaintext></plaintext>","<!DOCTYPE html><table><tr>TEST","<!DOCTYPE html><body t1=1><body t2=2><body t3=3 t4=4>","</b test","<!DOCTYPE html></b test<b &=&>X","<!doctypehtml><scrIPt type=text/x-foobar;baz>X</SCRipt","&","&#","&#X","&#x","-","&x-test","<!doctypehtml><p><li>","<!doctypehtml><p><dt>","<!doctypehtml><p><dd>","<!doctypehtml><p><form>","<!DOCTYPE html><p></P>X","&","&AMp;","<!DOCTYPE html><html><head></head><body><thisISasillyTESTelementNameToMakeSureCrazyTagNamesArePARSEDcorrectLY>","<!DOCTYPE html>X</body>X","<!DOCTYPE html><!-- X","<!DOCTYPE html><table><caption>test TEST</caption><td>test","<!DOCTYPE html><select><option><optgroup>","<!DOCTYPE html><select><optgroup><option></optgroup><option><select><option>","<!DOCTYPE html><select><optgroup><option><optgroup>","<!DOCTYPE html><datalist><option>foo</datalist>bar","<!DOCTYPE html><font><input><input></font>","<!DOCTYPE html><!-- XXX - XXX -->","<!DOCTYPE html><!-- XXX - XXX","<!DOCTYPE html><!-- XXX - XXX - XXX -->","<!DOCTYPE html> <!DOCTYPE html>","test\ntest","<!DOCTYPE html><body><title>test</body></title>","<!DOCTYPE html><body><title>X</title><meta name=z><link rel=foo><style>\nx { content:\"</style\" } </style>","<!DOCTYPE html><select><optgroup></optgroup></select>"," \n ","<!DOCTYPE html> <html>","<!DOCTYPE html><script>\n</script> <title>x</title> </head>","<!DOCTYPE html><html><body><html id=x>","<!DOCTYPE html>X</body><html id=\"x\">","<!DOCTYPE html><head><html id=x>","<!DOCTYPE html>X</html>X","<!DOCTYPE html>X</html> ","<!DOCTYPE html>X</html><p>X","<!DOCTYPE html>X<p/x/y/z>","<!DOCTYPE html><!--x--","<!DOCTYPE html><table><tr><td></p></table>","<!DOCTYPE <!DOCTYPE HTML>><!--<!--x-->-->","<!doctype html><div><form></form><div></div></div>"],"tests20.dat":["<!doctype html><p><button><button>","<!doctype html><p><button><address>","<!doctype html><p><button><article>","<!doctype html><p><button><aside>","<!doctype html><p><button><blockquote>","<!doctype html><p><button><center>","<!doctype html><p><button><details>","<!doctype html><p><button><dialog>","<!doctype html><p><button><dir>","<!doctype html><p><button><div>","<!doctype html><p><button><dl>","<!doctype html><p><button><fieldset>","<!doctype html><p><button><figcaption>","<!doctype html><p><button><figure>","<!doctype html><p><button><footer>","<!doctype html><p><button><header>","<!doctype html><p><button><hgroup>","<!doctype html><p><button><main>","<!doctype html><p><button><menu>","<!doctype html><p><button><nav>","<!doctype html><p><button><ol>","<!doctype html><p><button><p>","<!doctype html><p><button><search>","<!doctype html><p><button><section>","<!doctype html><p><button><summary>","<!doctype html><p><button><ul>","<!doctype html><p><button><h1>","<!doctype html><p><button><h6>","<!doctype html><p><button><listing>","<!doctype html><p><button><pre>","<!doctype html><p><button><form>","<!doctype html><p><button><li>","<!doctype html><p><button><dd>","<!doctype html><p><button><dt>","<!doctype html><p><button><plaintext>","<!doctype html><p><button><table>","<!doctype html><p><button><hr>","<!doctype html><p><button><xmp>","<!doctype html><p><button></p>","<!doctype html><button><p></button>x","<!doctype html><address><button></address>a","<p><table></p>","<!doctype html><svg>","<!doctype html><p><figcaption>","<!doctype html><p><summary>","<!doctype html><form><table><form>","<!doctype html><table><form><form>","<!doctype html><table><form></table><form>","<!doctype html><svg><foreignObject><p>","<!doctype html><svg><title>abc","<option><span><option>","<option><option>","<math><annotation-xml><div>","<math><annotation-xml encoding=\"application/svg+xml\"><div>","<math><annotation-xml encoding=\"application/xhtml+xml\"><div>","<math><annotation-xml encoding=\"aPPlication/xhtmL+xMl\"><div>","<math><annotation-xml encoding=\"text/html\"><div>","<math><annotation-xml encoding=\"Text/htmL\"><div>","<math><annotation-xml encoding=\" text/html \"><div>","<math><annotation-xml> </annotation-xml>","<math><annotation-xml>c</annotation-xml>","<math><annotation-xml><!--foo-->","<math><annotation-xml></svg>x","<math><annotation-xml><svg>x"],"tests21.dat":["<svg><![CDATA[foo]]>","<math><![CDATA[foo]]>","<div><![CDATA[foo]]>","<svg><![CDATA[foo","<svg><![CDATA[","<svg><![CDATA[]]>","<svg><![CDATA[]] >]]>","<svg><![CDATA[]]","<svg><![CDATA[]","<svg><![CDATA[]>a","<!DOCTYPE html><svg><![CDATA[foo]]]>","<!DOCTYPE html><svg><![CDATA[foo]]]]>","<!DOCTYPE html><svg><![CDATA[foo]]]]]>","<svg><foreignObject><div><![CDATA[foo]]>","<svg><![CDATA[<svg>]]>","<svg><![CDATA[</svg>a]]>","<svg><![CDATA[<svg>a","<svg><![CDATA[</svg>a","<svg><![CDATA[<svg>]]><path>","<svg><![CDATA[<svg>]]></path>","<svg><![CDATA[<svg>]]><!--path-->","<svg><![CDATA[<svg>]]>path","<svg><![CDATA[<!--svg-->]]>"],"tests22.dat":["<a><b><big><em><strong><div>X</a>","<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8>A</a>","<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8><div id=9>A</a>","<a><b><div id=1><div id=2><div id=3><div id=4><div id=5><div id=6><div id=7><div id=8><div id=9><div id=10>A</a>","<cite><b><cite><i><cite><i><cite><i><div>X</b>TEST"],"tests23.dat":["<p><font size=4><font color=red><font size=4><font size=4><font size=4><font size=4><font size=4><font color=red><p>X","<p><font size=4><font size=4><font size=4><font size=4><p>X","<p><font size=4><font size=4><font size=4><font size=\"5\"><font size=4><p>X","<p><font size=4 id=a><font size=4 id=b><font size=4><font size=4><p>X","<p><b id=a><b id=a><b id=a><b><object><b id=a><b id=a>X</object><p>Y"],"tests24.dat":["<!DOCTYPE html>≂̸","<!DOCTYPE html>≂̸A","<!DOCTYPE html>  ","<!DOCTYPE html>  A","<!DOCTYPE html>⊂⃒","<!DOCTYPE html>⊂⃒A","<!DOCTYPE html>𝔾","<!DOCTYPE html>𝔾A"],"tests25.dat":["<!DOCTYPE html><body><foo>A","<!DOCTYPE html><body><area>A","<!DOCTYPE html><body><base>A","<!DOCTYPE html><body><basefont>A","<!DOCTYPE html><body><bgsound>A","<!DOCTYPE html><body><br>A","<!DOCTYPE html><body><col>A","<!DOCTYPE html><body><command>A","<!DOCTYPE html><body><embed>A","<!DOCTYPE html><body><frame>A","<!DOCTYPE html><body><hr>A","<!DOCTYPE html><body><img>A","<!DOCTYPE html><body><input>A","<!DOCTYPE html><body><keygen>A","<!DOCTYPE html><keygen>A</keygen>B","</keygen>A","<!DOCTYPE html></keygen>A","<!DOCTYPE html><head></keygen>A","<!DOCTYPE html><head></head></keygen>A","<!DOCTYPE html><body></keygen>A","<!DOCTYPE html><body><link>A","<!DOCTYPE html><body><meta>A","<!DOCTYPE html><body><param>A","<!DOCTYPE html><body><source>A","<!DOCTYPE html><body><track>A","<!DOCTYPE html><body><wbr>A"],"tests26.dat":["<!DOCTYPE html><body><a href='#1'><nobr>1<nobr></a><br><a href='#2'><nobr>2<nobr></a><br><a href='#3'><nobr>3<nobr></a>","<!DOCTYPE html><body><b><nobr>1<nobr></b><i><nobr>2<nobr></i>3","<!DOCTYPE html><body><b><nobr>1<table><nobr></b><i><nobr>2<nobr></i>3","<!DOCTYPE html><body><b><nobr>1<table><tr><td><nobr></b><i><nobr>2<nobr></i>3","<!DOCTYPE html><body><b><nobr>1<div><nobr></b><i><nobr>2<nobr></i>3","<!DOCTYPE html><body><b><nobr>1<nobr></b><div><i><nobr>2<nobr></i>3","<!DOCTYPE html><body><b><nobr>1<nobr><ins></b><i><nobr>","<!DOCTYPE html><body><b><nobr>1<ins><nobr></b><i>2","<!DOCTYPE html><body><b>1<nobr></b><i><nobr>2</i>","<p><code x</code></p>\n","<!DOCTYPE html><svg><foreignObject><p><i></p>a","<!DOCTYPE html><table><tr><td><svg><foreignObject><p><i></p>a","<!DOCTYPE html><math><mtext><p><i></p>a","<!DOCTYPE html><table><tr><td><math><mtext><p><i></p>a","<!DOCTYPE html><body><div><!/div>a","<button><p><button>","<svg></p><foo>","<svg></br><foo>","<math></p><foo>","<math></br><foo>"],"tests3.dat":["<head></head><style></style>","<head></head><script></script>","<head></head><!-- --><style></style><!-- --><script></script>","<head></head><!-- -->x<style></style><!-- --><script></script>","<!DOCTYPE html><html><head></head><body><pre>\n</pre></body></html>","<!DOCTYPE html><html><head></head><body><pre>\nfoo</pre></body></html>","<!DOCTYPE html><html><head></head><body><pre>\n\nfoo</pre></body></html>","<!DOCTYPE html><html><head></head><body><pre>\nfoo\n</pre></body></html>","<!DOCTYPE html><html><head></head><body><pre>x</pre><span>\n</span></body></html>","<!DOCTYPE html><html><head></head><body><pre>x\ny</pre></body></html>","<!DOCTYPE html><html><head></head><body><pre>x<div>\ny</pre></body></html>","<!DOCTYPE html><pre>

A</pre>","<!DOCTYPE html><HTML><META><HEAD></HEAD></HTML>","<!DOCTYPE html><HTML><HEAD><head></HEAD></HTML>","<textarea>foo<span>bar</span><i>baz","<title>foo<span>bar</em><i>baz","<!DOCTYPE html><textarea>\n</textarea>","<!DOCTYPE html><textarea>\nfoo</textarea>","<!DOCTYPE html><textarea>\n\nfoo</textarea>","<!DOCTYPE html><html><head></head><body><ul><li><div><p><li></ul></body></html>","<!doctype html><nobr><nobr><nobr>","<!doctype html><nobr><nobr></nobr><nobr>","<!doctype html><html><body><p><table></table></body></html>","<p><table></table>"],"tests4.dat":["direct div content","direct textarea content","textarea content with <em>pseudo</em> <foo>markup","this is CDATA inside a <style> element","</plaintext>","setting html's innerHTML","<title>setting head's innerHTML</title>","direct <title> content","<!-- inside </script> -->"],"tests5.dat":["<style> <!-- </style>x","<style> <!-- </style> --> </style>x","<style> <!--> </style>x","<style> <!---> </style>x","<iframe> <!---> </iframe>x","<iframe> <!--- </iframe>->x</iframe> --> </iframe>x","<script> <!-- </script> --> </script>x","<title> <!-- </title> --> </title>x","<textarea> <!--- </textarea>->x</textarea> --> </textarea>x","<style> <!</-- </style>x","<p><xmp></xmp>","<xmp> <!-- > --> </xmp>","<title>&</title>","<title><!--&--></title>","<title><!--</title>","<noscript><!--</noscript>--></noscript>","<noscript><!--</noscript>--></noscript>"],"tests6.dat":["<!doctype html></head> <head>","<!doctype html><form><div></form><div>","<!doctype html><title>&</title>","<!doctype html><title><!--&--></title>","<!doctype>","<!---x","<body>\n<div>","<frameset></frameset>\nfoo","<frameset></frameset>\n<noframes>","<frameset></frameset>\n<div>","<frameset></frameset>\n</html>","<frameset></frameset>\n</div>","<form><form>","<button><button>","<table><tr><td></th>","<table><caption><td>","<table><caption><div>","</caption><div>","<table><caption><div></caption>","<table><caption></table>","</table><div>","<table><caption></body></col></colgroup></html></tbody></td></tfoot></th></thead></tr>","<table><caption><div></div>","<table><tr><td></body></caption></col></colgroup></html>","</table></tbody></tfoot></thead></tr><div>","<table><colgroup>foo","foo<col>","<table><colgroup></col>","<frameset><div>","</frameset><frame>","<frameset></div>","</body><div>","<table><tr><div>","</tr><td>","</tbody></tfoot></thead><td>","<table><tr><div><td>","<caption><col><colgroup><tbody><tfoot><thead><tr>","<table><tbody></thead>","</table><tr>","<table><tbody></body></caption></col></colgroup></html></td></th></tr>","<table><tbody></div>","<table><table>","<table></body></caption></col></colgroup></html></tbody></td></tfoot></th></thead></tr>","</table><tr>","<body></body></html>","<html><frameset></frameset></html> ","<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\"><html></html>","<param><frameset></frameset>","<source><frameset></frameset>","<track><frameset></frameset>","</html><frameset></frameset>","</body><frameset></frameset>"],"tests7.dat":["<!doctype html><body><title>X</title>","<!doctype html><table><title>X</title></table>","<!doctype html><head></head><title>X</title>","<!doctype html></head><title>X</title>","<!doctype html></head><base>X","<!doctype html></head><basefont>X","<!doctype html></head><bgsound>X","<!doctype html><table><meta></table>","<!doctype html><table>X<tr><td><table> <meta></table></table>","<!doctype html><html> <head>","<!doctype html> <head>","<!doctype html><table><style> <tr>x </style> </table>","<!doctype html><table><TBODY><script> <tr>x </script> </table>","<!doctype html><p><applet><p>X</p></applet>","<!doctype html><p><object type=\"application/x-non-existant-plugin\"><p>X</p></object>","<!doctype html><listing>\nX</listing>","<!doctype html><select><input>X","<!doctype html><select><select>X","<!doctype html><table><input type=hidDEN></table>","<!doctype html><table>X<input type=hidDEN></table>","<!doctype html><table> <input type=hidDEN></table>","<!doctype html><table> <input type='hidDEN'></table>","<!doctype html><table><input type=\" hidden\"><input type=hidDEN></table>","<!doctype html><table><select>X<tr>","<!doctype html><select>X</select>","<!DOCTYPE hTmL><html></html>","<!DOCTYPE HTML><html></html>","<body>X</body></body>","<div><p>a</x> b","<table><tr><td><code></code> </table>","<table><b><tr><td>aaa</td></tr>bbb</table>ccc","A<table><tr> B</tr> B</table>","A<table><tr> B</tr> </em>C</table>","<select><keygen>"],"tests8.dat":["<div>\n<div></div>\n</span>x","<div>x<div></div>\n</span>x","<div>x<div></div>x</span>x","<div>x<div></div>y</span>z","<table><div>x<div></div>x</span>x","<table><li><li></table>","x<table>x","x<table><table>x","<b>a<div></div><div></b>y","<a><div><p></a>"],"tests9.dat":["<!DOCTYPE html><math></math>","<!DOCTYPE html><body><math></math>","<!DOCTYPE html><math><mi>","<!DOCTYPE html><math><annotation-xml><svg><u>","<!DOCTYPE html><body><select><math></math></select>","<!DOCTYPE html><body><select><option><math></math></option></select>","<!DOCTYPE html><body><table><math></math></table>","<!DOCTYPE html><body><table><math><mi>foo</mi></math></table>","<!DOCTYPE html><body><table><math><mi>foo</mi><mi>bar</mi></math></table>","<!DOCTYPE html><body><table><tbody><math><mi>foo</mi><mi>bar</mi></math></tbody></table>","<!DOCTYPE html><body><table><tbody><tr><math><mi>foo</mi><mi>bar</mi></math></tr></tbody></table>","<!DOCTYPE html><body><table><tbody><tr><td><math><mi>foo</mi><mi>bar</mi></math></td></tr></tbody></table>","<!DOCTYPE html><body><table><tbody><tr><td><math><mi>foo</mi><mi>bar</mi></math><p>baz</td></tr></tbody></table>","<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi></math><p>baz</caption></table>","<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux","<!DOCTYPE html><body><table><caption><math><mi>foo</mi><mi>bar</mi>baz</table><p>quux","<!DOCTYPE html><body><table><colgroup><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux","<!DOCTYPE html><body><table><tr><td><select><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux","<!DOCTYPE html><body><table><select><math><mi>foo</mi><mi>bar</mi><p>baz</table><p>quux","<!DOCTYPE html><body></body></html><math><mi>foo</mi><mi>bar</mi><p>baz","<!DOCTYPE html><body></body><math><mi>foo</mi><mi>bar</mi><p>baz","<!DOCTYPE html><frameset><math><mi></mi><mi></mi><p><span>","<!DOCTYPE html><frameset></frameset><math><mi></mi><mi></mi><p><span>","<!DOCTYPE html><body xlink:href=foo><math xlink:href=foo></math>","<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo></mi></math>","<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo /></math>","<!DOCTYPE html><body xlink:href=foo xml:lang=en><math><mi xml:lang=en xlink:href=foo />bar</math>"],"tests_innerHTML_1.dat":["<body><span>","<span><body>","<span><body>","<body><span>","<frameset><span>","<span><frameset>","<span><frameset>","<frameset><span>","<table><tr>","</table><tr>","<a>","<a><caption>a","<a><colgroup><col>","<a><tbody><tr>","<a><tfoot><tr>","<a><thead><tr>","<a><tr>","<a><th>","<a><td>","<table></table><tbody>","</table><span>","<span></table>","</caption><span>","<span></caption><span>","<span><caption><span>","<span><col><span>","<span><colgroup><span>","<span><html><span>","<span><tbody><span>","<span><td><span>","<span><tfoot><span>","<span><thead><span>","<span><th><span>","<span><tr><span>","<span></table><span>","</colgroup><col>","<a><col>","<caption><a>","<col><a>","<colgroup><a>","<tbody><a>","<tfoot><a>","<thead><a>","</table><a>","<a><tr>","<a><td>","<td><table><tbody><a><tr>","</tr><td>","<td><table><a><tr></tr><tr>","<caption><td>","<col><td>","<colgroup><td>","<tbody><td>","<tfoot><td>","<thead><td>","<tr><td>","</table><td>","<td><table></table><td>","<caption><a>","<col><a>","<colgroup><a>","<tbody><a>","<tfoot><a>","<th><a>","<thead><a>","<tr><a>","</table><a>","</tbody><a>","</td><a>","</tfoot><a>","</thead><a>","</th><a>","</tr><a>","<table><td><td>","</select><option>","<input><option>","<keygen><option>","<textarea><option>","</html><!--abc-->","</frameset><frame>",""],"tricky01.dat":["<b><p>Bold </b> Not bold</p>\nAlso not bold.","<html>\n<font color=red><i>Italic and Red<p>Italic and Red </font> Just italic.</p> Italic only.</i> Plain\n<p>I should not be red. <font color=red>Red. <i>Italic and red.</p>\n<p>Italic and red. </i> Red.</font> I should not be red.</p>\n<b>Bold <i>Bold and italic</b> Only Italic </i> Plain","<html><body>\n<p><font size=\"7\">First paragraph.</p>\n<p>Second paragraph.</p></font>\n<b><p><i>Bold and Italic</b> Italic</p>","<html>\n<dl>\n<dt><b>Boo\n<dd>Goo?\n</dl>\n</html>","<html><body>\n<label><a><div>Hello<div>World</div></a></label> \n</body></html>","<table><center> <font>a</center> <img> <tr><td> </td> </tr> </table>","<table><tr><p><a><p>You should see this text.","<TABLE>\n<TR>\n<CENTER><CENTER><TD></TD></TR><TR>\n<FONT>\n<TABLE><tr></tr></TABLE>\n</P>\n<a></font><font></a>\nThis page contains an insanely badly-nested tag sequence.","<html>\n<body>\n<b><nobr><div>This text is in a div inside a nobr</nobr>More text that should not be in the nobr, i.e., the\nnobr should have closed the div inside it implicitly. </b><pre>A pre tag outside everything else.</pre>\n</body>\n</html>"],"void-in-phrasing.dat":["<!DOCTYPE html><body><p><br></p>","<!DOCTYPE html><body><p><br>text</p>","<!DOCTYPE html><body><p>before<br>after</p>","<!DOCTYPE html><body><p><br><br></p>","<!DOCTYPE html><body><p>a<br>b<br>c</p>","<!DOCTYPE html><body><h1><br></h1>","<!DOCTYPE html><body><p><input></p>","<!DOCTYPE html><body><p><img></p>","<!DOCTYPE html><body><p><wbr></p>","<!DOCTYPE html><body><p><embed></p>","<!DOCTYPE html><body><h2><input></h2>","<!DOCTYPE html><body><em><br></em>","<!DOCTYPE html><body><strong><br>text</strong>"],"webkit01.dat":["Test","<div></div>","<div>Test</div>","<di","<div>Hello</div>\n<script>\nconsole.log(\"PASS\");\n</script>\n<div>Bye</div>","<div foo=\"bar\">Hello</div>","<div>Hello</div>\n<script>\nconsole.log(\"FOO<span>BAR</span>BAZ\");\n</script>\n<div>Bye</div>","<foo bar=\"baz\"></foo><potato quack=\"duck\"></potato>","<foo bar=\"baz\"><potato quack=\"duck\"></potato></foo>","<foo></foo bar=\"baz\"><potato></potato quack=\"duck\">","</ tttt>","<div FOO ><img><img></div>","<p>Test</p<p>Test2</p>","<rdar://problem/6869687>","<A>test< /A>","<","<body foo='bar'><body foo='baz' yo='mama'>","<body></br foo=\"bar\"></body>","<bdy><br foo=\"bar\"></body>","<body></body></br foo=\"bar\">","<bdy></body><br foo=\"bar\">","<html><body></body></html><!-- Hi there -->","<html><body></body></html><!-- Comment A --><!-- Comment B --><!-- Comment C --><!-- Comment D --><!-- Comment E -->","<html><body></body></html>x<!-- Hi there -->","<html><body></body></html>x<!-- Hi there --></html><!-- Again -->","<html><body></body></html>x<!-- Hi there --></body></html><!-- Again -->","<html><body></body>\n <!-- Hi there --></html>","<html><body></body></html>\n <!-- Hi there -->","<html><body><ruby><div><rp>xx</rp></div></ruby></body></html>","<html><body><ruby><div><rt>xx</rt></div></ruby></body></html>","<html><frameset><!--1--><noframes>A</noframes><!--2--></frameset><!--3--><noframes>B</noframes><!--4--></html><!--5--><noframes>C</noframes><!--6-->","<select><option>A<select><option>B<select><option>C<select><option>D<select><option>E<select><option>F<select><option>G<select>","<dd><dd><dt><dt><dd><li><li>","<div><b></div><div><nobr>a<nobr>","<head></head>\n<body></body>","<head></head> <style></style>ddd","<kbd><table></kbd><col><select><tr>","<kbd><table></kbd><col><select><tr></table><div>","<a><li><style></style><title></title></a>","<font></p><p><meta><title></title></font>","<a><center><title></title><a>","<svg><title><div>","<svg><title><rect><div>","<svg><title><svg><div>","<img <=\"\" FAIL>","<ul><li><div id='foo'/>A</li><li>B<div>C</div></li></ul>","<svg><em><desc></em>","<table><tr><td><svg><desc><td></desc><circle>","<svg><tfoot></mi><td>","<math><mrow><mrow><mn>1</mn></mrow><mi>a</mi></mrow></math>","<!doctype html><input type=\"hidden\"><frameset>","<!doctype html><input type=\"button\"><frameset>"],"webkit02.dat":["<foo bar=qux/>","<p id=\"status\"><noscript><strong>A</strong></noscript><span>B</span></p>","<p id=\"status\"><noscript><strong>A</strong></noscript><span>B</span></p>","<div><sarcasm><div></div></sarcasm></div>","<html><body><img src=\"\" border=\"0\" alt=\"><div>A</div></body></html>","<table><td></tbody>A","<table><td></thead>A","<table><td></tfoot>A","<table><thead><td></tbody>A","<legend>test</legend>","<table><input>","<b><em><dcell><postfield><postfield><postfield><postfield><missing_glyph><missing_glyph><missing_glyph><missing_glyph><hkern><aside></b></em>","<b><em><foo><foo><aside></b>","<b><em><foo><foo><aside></b></em>","<b><em><foo><foo><foo><aside></b>","<b><em><foo><foo><foo><aside></b></em>","<b><em><foo><foo><foo><foo><foo><foo><foo><foo><foo><foo><aside></b></em>","<b><em><foo><foob><foob><foob><foob><fooc><fooc><fooc><fooc><food><aside></b></em>","<option><XH<optgroup></optgroup>","<svg><foreignObject><div>foo</div><plaintext></foreignObject></svg><div>bar</div>","<svg><foreignObject></foreignObject><title></svg>foo","</foreignObject><plaintext><div>foo</div>","<svg xml:base xml:lang xml:space xml:baaah definitionurl>","<math definitionurl xlink:title xlink:show>","<math DEFINITIONURL>","<select><hr>","<select><option><hr>","<select><optgroup><option><hr>","<select><optgroup><hr>","<select><option><optgroup><hr>","<table><tr><td><select><hr>","<table><tr><td><select><option><hr>","<table><tr><td><select><optgroup><option><hr>","<table><tr><td><select><optgroup><hr>","<table><tr><td><select><option><optgroup><hr>","<select><div><i></div><option>option","<div><i></div><option>option","<select><div>div 1</div><button>button</button><div>div 2</div><datalist><option>option</option></datalist><div>div 3</div></select>","<select><button>button</select>","<select><datalist>datalist</select>","<select><button><select></select></button></select>","<select><button><div><select></select>","<select><div><option><img>option</option></div></select>","<select><input>","<select><button><selectedcontent></button><option>X","<select><button><selectedcontent></button><option>x<i>i<b>ib</i>b","<select><button><selectedcontent></button><option>X<option>Y","<select><button><selectedcontent></button><option>X<option selected>Y","<font><select><option>a</option></font></select>"]}
|
|
@@ -95,6 +95,41 @@ test('tokenizes a twig print in an attribute value', () => {
|
|
|
95
95
|
assert.equal(/** @type {any} */ (attr.valueChunks[0]).atom.raw, '{{ url }}');
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
+
test('tokenizes unquoted attribute values', () => {
|
|
99
|
+
const source = '<div id=target class=row data-note=1></div>';
|
|
100
|
+
const tokens = html(source);
|
|
101
|
+
assert.deepEqual(types(tokens), ['startTag', 'endTag']);
|
|
102
|
+
const tag = /** @type {any} */ (tokens[0]);
|
|
103
|
+
assert.equal(tag.raw, '<div id=target class=row data-note=1>');
|
|
104
|
+
assert.deepEqual(
|
|
105
|
+
tag.attrs.map((/** @type {any} */ a) => a.nameRaw),
|
|
106
|
+
['id', 'class', 'data-note'],
|
|
107
|
+
);
|
|
108
|
+
assert.deepEqual(
|
|
109
|
+
tag.attrs.map((/** @type {any} */ a) => a.quote),
|
|
110
|
+
[null, null, null],
|
|
111
|
+
);
|
|
112
|
+
assert.deepEqual(
|
|
113
|
+
tag.attrs.map((/** @type {any} */ a) => a.valueChunks[0].text),
|
|
114
|
+
['target', 'row', '1'],
|
|
115
|
+
);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test('keeps a slash inside an unquoted attribute value', () => {
|
|
119
|
+
const tokens = html('<div id=target/>');
|
|
120
|
+
const tag = /** @type {any} */ (tokens[0]);
|
|
121
|
+
assert.equal(tag.attrs[0].valueChunks[0].text, 'target/');
|
|
122
|
+
assert.equal(tag.selfClosing, false);
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
test('tokenizes twig inside an unquoted attribute value', () => {
|
|
126
|
+
const tokens = html('<div class={{ foo }}></div>');
|
|
127
|
+
const tag = /** @type {any} */ (tokens[0]);
|
|
128
|
+
const chunk = tag.attrs[0].valueChunks[0];
|
|
129
|
+
assert.equal(chunk.type, 'twig');
|
|
130
|
+
assert.equal(chunk.atom.raw, '{{ foo }}');
|
|
131
|
+
});
|
|
132
|
+
|
|
98
133
|
test('tokenizes conditional attributes via twig between attributes', () => {
|
|
99
134
|
const source = '<div class="row" {% if x %} id="y" {% endif %} data-x>';
|
|
100
135
|
const tokens = html(source);
|
|
@@ -145,6 +180,81 @@ test('preserves self-closing tags', () => {
|
|
|
145
180
|
assert.equal(tokens[0].raw, '<link rel="x" />');
|
|
146
181
|
});
|
|
147
182
|
|
|
183
|
+
test('does not hang on an end tag with an equals sign in its tail', () => {
|
|
184
|
+
const source = '</div class=x>tail';
|
|
185
|
+
const tokens = html(source);
|
|
186
|
+
assert.deepEqual(types(tokens), ['endTag', 'text']);
|
|
187
|
+
assert.equal(tokens[0].raw, '</div class=x>');
|
|
188
|
+
assert.equal(tokens[1].raw, 'tail');
|
|
189
|
+
assertContiguous(source, tokens);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test('keeps the written tag name on an end tag with attributes', () => {
|
|
193
|
+
// the spec reuses the before-attribute-name states for end tags; the tag
|
|
194
|
+
// name is never overwritten by the attribute text
|
|
195
|
+
for (const source of ['</div a>', '</div class=x>', '</div =1>', '</div a=b c=d>']) {
|
|
196
|
+
const tokens = html(source);
|
|
197
|
+
assert.equal(tokens[0].type, 'endTag', source);
|
|
198
|
+
assert.equal(tokens[0].name, 'div', source);
|
|
199
|
+
assert.equal(tokens[0].raw, source);
|
|
200
|
+
assertContiguous(source, tokens);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
|
|
204
|
+
test('an appropriate end tag closes raw text; a name prefix does not', () => {
|
|
205
|
+
const tokens = html('<script>var x = "</scripture>";</script>');
|
|
206
|
+
assert.deepEqual(types(tokens), ['startTag', 'text', 'endTag']);
|
|
207
|
+
assert.equal(tokens[1].raw, 'var x = "</scripture>";');
|
|
208
|
+
assert.equal(tokens[2].raw, '</script>');
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test('closes raw text on a trimmed appropriate end tag', () => {
|
|
212
|
+
// whitespace and `/` after the name still make it an appropriate end tag
|
|
213
|
+
for (const source of ['<style>a</style >', '<script>x</script/>', '<script>x</script >']) {
|
|
214
|
+
const tokens = html(source);
|
|
215
|
+
assert.equal(tokens[0].type, 'startTag', source);
|
|
216
|
+
assert.equal(tokens[1].raw, source.startsWith('<style>') ? 'a' : 'x', source);
|
|
217
|
+
assert.equal(tokens[2].type, 'endTag', source);
|
|
218
|
+
assertContiguous(source, tokens);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
test('treats every RAWTEXT element as opaque content', () => {
|
|
223
|
+
for (const name of ['script', 'style', 'xmp', 'iframe', 'noembed', 'noframes']) {
|
|
224
|
+
const source = `<${ name }><b x=y>{{ v }}</b></${ name }>`;
|
|
225
|
+
const tokens = html(source);
|
|
226
|
+
assert.deepEqual(types(tokens), ['startTag', 'text', 'twig', 'text', 'endTag'], name);
|
|
227
|
+
assert.equal(tokens[0].name, name);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
test('keeps an unterminated raw-text end tag as text', () => {
|
|
232
|
+
// EOF before `>`: the `</name` run is raw text and the element stays open
|
|
233
|
+
for (const name of ['script', 'style', 'xmp', 'iframe']) {
|
|
234
|
+
const source = `<${ name }>x</${ name }`;
|
|
235
|
+
const tokens = html(source);
|
|
236
|
+
assert.deepEqual(types(tokens), ['startTag', 'text'], name);
|
|
237
|
+
assert.equal(tokens[1].raw, `x</${ name }`, name);
|
|
238
|
+
assertContiguous(source, tokens);
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
test('does not treat noscript as raw text', () => {
|
|
243
|
+
const tokens = html('<noscript><b>x</b></noscript>');
|
|
244
|
+
assert.deepEqual(types(tokens), ['startTag', 'startTag', 'text', 'endTag', 'endTag']);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test('does not emit overlapping tokens for a bogus comment', () => {
|
|
248
|
+
for (const source of ['<!- x>', '<!-a', '<?']) {
|
|
249
|
+
const tokens = html(source);
|
|
250
|
+
assertContiguous(source, tokens);
|
|
251
|
+
assert.ok(tokens.every((t) => t.type === 'comment' || t.type === 'text'), source);
|
|
252
|
+
}
|
|
253
|
+
assert.deepEqual(types(html('<!- x>')), ['comment']);
|
|
254
|
+
assert.deepEqual(types(html('<?')), ['text']);
|
|
255
|
+
assert.deepEqual(types(html('<?x>')), ['comment']);
|
|
256
|
+
});
|
|
257
|
+
|
|
148
258
|
test('treats a stray < followed by twig as text', () => {
|
|
149
259
|
const source = '< {{ x }}';
|
|
150
260
|
const tokens = html(source);
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* Resource-bound tests for the hybrid parser.
|
|
4
|
+
*
|
|
5
|
+
* Untrusted template source must never be able to exhaust the stack or build an
|
|
6
|
+
* unboundedly deep tree. These cases nest far past any realistic document and
|
|
7
|
+
* assert that parsing stays flat and does not throw.
|
|
8
|
+
*
|
|
9
|
+
* @module test
|
|
10
|
+
*/
|
|
11
|
+
import { test } from 'node:test';
|
|
12
|
+
import assert from 'node:assert/strict';
|
|
13
|
+
import { parse } from '@mrhenry/twig-html-parser';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The deepest element nesting, measured iteratively so the assertion itself
|
|
17
|
+
* cannot overflow the stack.
|
|
18
|
+
*
|
|
19
|
+
* @param {ReturnType<typeof parse>} root
|
|
20
|
+
* @returns {number}
|
|
21
|
+
*/
|
|
22
|
+
function maxDepth(root) {
|
|
23
|
+
let max = 0;
|
|
24
|
+
const stack = [{ node: root, depth: 0 }];
|
|
25
|
+
|
|
26
|
+
for (;;) {
|
|
27
|
+
const entry = stack.pop();
|
|
28
|
+
if (!entry) {
|
|
29
|
+
break;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const { node, depth } = entry;
|
|
33
|
+
if (depth > max) {
|
|
34
|
+
max = depth;
|
|
35
|
+
}
|
|
36
|
+
if (Array.isArray(node.children)) {
|
|
37
|
+
for (const child of node.children) {
|
|
38
|
+
stack.push({ node: child, depth: depth + 1 });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return max;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
test('deeply nested elements are depth-capped instead of overflowing the stack', () => {
|
|
47
|
+
const depth = 20000;
|
|
48
|
+
const source = `${'<div>'.repeat(depth)}x${'</div>'.repeat(depth)}`;
|
|
49
|
+
|
|
50
|
+
const tree = parse(source);
|
|
51
|
+
|
|
52
|
+
assert.ok(maxDepth(tree) <= 257, 'element depth stays bounded');
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('deeply nested twig blocks do not overflow the stack', () => {
|
|
56
|
+
const depth = 20000;
|
|
57
|
+
const source = `${'{% if x %}'.repeat(depth)}x${'{% endif %}'.repeat(depth)}`;
|
|
58
|
+
|
|
59
|
+
const tree = parse(source);
|
|
60
|
+
|
|
61
|
+
assert.ok(maxDepth(tree) <= 257, 'block depth stays bounded');
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test('a single element beyond the cap is still represented as text', () => {
|
|
65
|
+
const tree = parse('<div class="a">x</div>');
|
|
66
|
+
|
|
67
|
+
assert.ok(maxDepth(tree) >= 1);
|
|
68
|
+
});
|
|
@@ -171,6 +171,31 @@ test('twig block indentation spans are contiguous with source', () => {
|
|
|
171
171
|
assertOffsetsInSource(root, source);
|
|
172
172
|
});
|
|
173
173
|
|
|
174
|
+
test('an end tag with attributes still closes the element', () => {
|
|
175
|
+
// the tag name is `div` even though the end tag carries a tail
|
|
176
|
+
const source = '<div>a</div class=x>b';
|
|
177
|
+
const root = ast(source);
|
|
178
|
+
const div = root.children[0];
|
|
179
|
+
assert.equal(div.type, 'element');
|
|
180
|
+
assert.equal(div.name, 'div');
|
|
181
|
+
assert.equal(div.endTagRaw, '</div class=x>');
|
|
182
|
+
assert.equal(root.children[1].raw, 'b');
|
|
183
|
+
assertOffsetsInSource(root, source);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
test('raw text with an inappropriate end tag stays a single element', () => {
|
|
187
|
+
const source = '<script>var x = "</scripture>";</script>';
|
|
188
|
+
const root = ast(source);
|
|
189
|
+
assert.equal(root.children.length, 1);
|
|
190
|
+
const script = root.children[0];
|
|
191
|
+
assert.equal(script.name, 'script');
|
|
192
|
+
assert.equal(script.children.length, 1);
|
|
193
|
+
assert.equal(script.children[0].type, 'text');
|
|
194
|
+
assert.equal(script.children[0].raw, 'var x = "</scripture>";');
|
|
195
|
+
assert.equal(script.endTagRaw, '</script>');
|
|
196
|
+
assertOffsetsInSource(root, source);
|
|
197
|
+
});
|
|
198
|
+
|
|
174
199
|
test('parser summary', () => {
|
|
175
200
|
assert.ok(true);
|
|
176
201
|
});
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// @ts-check
|
|
2
|
+
/**
|
|
3
|
+
* WPT html5lib tokenizer corpus tests.
|
|
4
|
+
*
|
|
5
|
+
* `fixtures/wpt-html5lib-inputs.json` holds the `#data` sections of the
|
|
6
|
+
* upstream html5lib suite (`wpt/html/syntax/parsing/resources/*.dat`). They are
|
|
7
|
+
* a broad corpus of real and malformed HTML inputs (script data, comments,
|
|
8
|
+
* doctypes, attributes, foreign content, …). Our tokenizer does not implement
|
|
9
|
+
* tree construction, so the expected DOM trees do not apply; instead every
|
|
10
|
+
* input must tokenize to a contiguous, source-ordered list with exact offsets,
|
|
11
|
+
* without hanging.
|
|
12
|
+
*
|
|
13
|
+
* A few cases also assert the tokenizer-level outcome the spec defines (an
|
|
14
|
+
* inappropriate end tag that stays raw text, an end tag carrying attributes).
|
|
15
|
+
*
|
|
16
|
+
* @module test
|
|
17
|
+
*/
|
|
18
|
+
import { test } from 'node:test';
|
|
19
|
+
import assert from 'node:assert/strict';
|
|
20
|
+
import { readFileSync } from 'node:fs';
|
|
21
|
+
import { Lexer, Source } from '@mrhenry/twig-tokenizer';
|
|
22
|
+
import { extractAtoms, tokenizeHtml } from '@mrhenry/twig-html-parser';
|
|
23
|
+
|
|
24
|
+
/** @type {Record<string, string[]>} */
|
|
25
|
+
const corpus = JSON.parse(
|
|
26
|
+
readFileSync( new URL( './fixtures/wpt-html5lib-inputs.json', import.meta.url ), 'utf8' ),
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* @param {string} source
|
|
31
|
+
* @returns {ReturnType<typeof tokenizeHtml>}
|
|
32
|
+
*/
|
|
33
|
+
function html( source ) {
|
|
34
|
+
const tokens = new Lexer().tokenize( new Source( source, 'index.twig' ) ).getTokens();
|
|
35
|
+
return tokenizeHtml( extractAtoms( source, tokens ), source );
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Asserts the token list covers the source contiguously and in order.
|
|
40
|
+
*
|
|
41
|
+
* @param {string} source
|
|
42
|
+
* @param {ReturnType<typeof tokenizeHtml>} tokens
|
|
43
|
+
*/
|
|
44
|
+
function assertContiguous( source, tokens ) {
|
|
45
|
+
let prev = 0;
|
|
46
|
+
for ( const token of tokens ) {
|
|
47
|
+
assert.ok( token.rawStart >= prev, `token out of order at ${ token.rawStart } (prev ${ prev })` );
|
|
48
|
+
assert.ok( token.rawStart === prev, `gap at ${ token.rawStart } (prev ${ prev })` );
|
|
49
|
+
assert.ok( token.rawEnd >= token.rawStart, `negative span at ${ token.rawStart }` );
|
|
50
|
+
prev = token.rawEnd;
|
|
51
|
+
}
|
|
52
|
+
assert.equal( prev, source.length, `trailing gap (covered ${ prev }/${ source.length })` );
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
for ( const [ file, inputs ] of Object.entries( corpus ) ) {
|
|
56
|
+
test( `WPT html5lib tokenizer corpus: ${ file } (${ inputs.length } inputs)`, () => {
|
|
57
|
+
for ( const source of inputs ) {
|
|
58
|
+
assertContiguous( source, html( source ) );
|
|
59
|
+
}
|
|
60
|
+
} );
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
test( 'WPT: an inappropriate end tag stays inside script data', () => {
|
|
64
|
+
const source = 'FOO<script type="text/plain"></scriptx>BAR';
|
|
65
|
+
const tokens = html( source );
|
|
66
|
+
assert.deepEqual( tokens.map( ( token ) => token.type ), [ 'text', 'startTag', 'text' ] );
|
|
67
|
+
assert.equal( tokens[ 2 ].raw, '</scriptx>BAR' );
|
|
68
|
+
} );
|
|
69
|
+
|
|
70
|
+
test( 'WPT: an end tag with attributes closes at the correct `>`', () => {
|
|
71
|
+
const source = 'FOO<script></script foo=">" dd>BAR';
|
|
72
|
+
const tokens = html( source );
|
|
73
|
+
assert.deepEqual( tokens.map( ( token ) => token.type ), [ 'text', 'startTag', 'endTag', 'text' ] );
|
|
74
|
+
assert.equal( tokens[ 2 ].name, 'script' );
|
|
75
|
+
assert.equal( tokens[ 2 ].raw, '</script foo=">" dd>' );
|
|
76
|
+
assert.equal( tokens[ 3 ].raw, 'BAR' );
|
|
77
|
+
} );
|
|
78
|
+
|
|
79
|
+
test( 'WPT: comment end bang and abrupt comment closings', () => {
|
|
80
|
+
for ( const [ source, types ] of /** @type {Array<[string, string[]]>} */ ( [
|
|
81
|
+
[ 'FOO<!-- BAR --!>BAZ', [ 'text', 'comment', 'text' ] ],
|
|
82
|
+
[ '<!---->BAZ', [ 'comment', 'text' ] ],
|
|
83
|
+
[ '<!-- BAR -- >BAZ', [ 'comment' ] ],
|
|
84
|
+
] ) ) {
|
|
85
|
+
assert.deepEqual( html( source ).map( ( token ) => token.type ), types, source );
|
|
86
|
+
}
|
|
87
|
+
} );
|
|
88
|
+
|
|
89
|
+
test( 'WPT: unquoted attribute values', () => {
|
|
90
|
+
// tests22.dat: `<div id=1>` — the value runs to whitespace or `>`
|
|
91
|
+
const tokens = html( '<div id=1><div id=2>A' );
|
|
92
|
+
const first = /** @type {any} */ ( tokens[ 0 ] );
|
|
93
|
+
assert.equal( first.type, 'startTag' );
|
|
94
|
+
assert.equal( first.attrs[ 0 ].nameRaw, 'id' );
|
|
95
|
+
assert.equal( first.attrs[ 0 ].quote, null );
|
|
96
|
+
assert.deepEqual( first.attrs[ 0 ].valueChunks.map( ( /** @type {any} */ c ) => c.text ), [ '1' ] );
|
|
97
|
+
|
|
98
|
+
// `>` terminates an unquoted value, so the tag closes
|
|
99
|
+
assert.deepEqual( html( '<div id=foo>' ).map( ( token ) => token.type ), [ 'startTag' ] );
|
|
100
|
+
|
|
101
|
+
// a `/` is part of an unquoted value, not a self-closing marker
|
|
102
|
+
const trailing = /** @type {any} */ ( html( '<div id=foo/>' )[ 0 ] );
|
|
103
|
+
assert.equal( trailing.selfClosing, false );
|
|
104
|
+
assert.deepEqual( trailing.attrs[ 0 ].valueChunks.map( ( /** @type {any} */ c ) => c.text ), [ 'foo/' ] );
|
|
105
|
+
} );
|
|
106
|
+
|
|
107
|
+
test( 'WPT: an unterminated raw-text end tag stays text', () => {
|
|
108
|
+
// scriptdata01.dat covers eof-in-script; a `</script` without `>` is data
|
|
109
|
+
const tokens = html( '<script>x</script' );
|
|
110
|
+
assert.deepEqual( tokens.map( ( token ) => token.type ), [ 'startTag', 'text' ] );
|
|
111
|
+
assert.equal( tokens[ 1 ].raw, 'x</script' );
|
|
112
|
+
|
|
113
|
+
assert.deepEqual( html( '<style>x</style' ).map( ( token ) => token.type ), [ 'startTag', 'text' ] );
|
|
114
|
+
} );
|