Skip to content

Commit ecdb071

Browse files
feat: Support xmp tag parsing (#1790)
1 parent 278e39b commit ecdb071

File tree

3 files changed

+128
-8
lines changed

3 files changed

+128
-8
lines changed

src/Tokenizer.spec.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ describe("Tokenizer", () => {
3737
it("for self-closing textarea tag", () => {
3838
expect(tokenize("<textarea /><div></div>")).toMatchSnapshot();
3939
});
40+
it("for self-closing xmp tag", () => {
41+
expect(tokenize("<xmp /><div></div>")).toMatchSnapshot();
42+
});
4043
});
4144

4245
describe("should support standard special tags", () => {
@@ -54,6 +57,9 @@ describe("Tokenizer", () => {
5457
tokenize("<textarea></textarea><div></div>"),
5558
).toMatchSnapshot();
5659
});
60+
it("for normal xmp tag", () => {
61+
expect(tokenize("<xmp></xmp><div></div>")).toMatchSnapshot();
62+
});
5763
});
5864

5965
describe("should treat html inside special tags as text", () => {
@@ -71,6 +77,9 @@ describe("Tokenizer", () => {
7177
tokenize("<textarea><div></div></textarea>"),
7278
).toMatchSnapshot();
7379
});
80+
it("for div inside xmp tag", () => {
81+
expect(tokenize("<xmp><div></div></xmp>")).toMatchSnapshot();
82+
});
7483
});
7584

7685
describe("should correctly mark attributes", () => {

src/Tokenizer.ts

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ const Sequences = {
138138
TextareaEnd: new Uint8Array([
139139
0x3c, 0x2f, 0x74, 0x65, 0x78, 0x74, 0x61, 0x72, 0x65, 0x61,
140140
]), // `</textarea`
141+
XmpEnd: new Uint8Array([0x3c, 0x2f, 0x78, 0x6d, 0x70]), // `</xmp`
141142
};
142143

143144
export default class Tokenizer {
@@ -391,7 +392,10 @@ export default class Tokenizer {
391392
this.state = State.InTagName;
392393
} else if (lower === Sequences.ScriptEnd[2]) {
393394
this.state = State.BeforeSpecialS;
394-
} else if (lower === Sequences.TitleEnd[2]) {
395+
} else if (
396+
lower === Sequences.TitleEnd[2] ||
397+
lower === Sequences.XmpEnd[2]
398+
) {
395399
this.state = State.BeforeSpecialT;
396400
} else {
397401
this.state = State.InTagName;
@@ -593,13 +597,26 @@ export default class Tokenizer {
593597

594598
private stateBeforeSpecialT(c: number): void {
595599
const lower = c | 0x20;
596-
if (lower === Sequences.TitleEnd[3]) {
597-
this.startSpecial(Sequences.TitleEnd, 4);
598-
} else if (lower === Sequences.TextareaEnd[3]) {
599-
this.startSpecial(Sequences.TextareaEnd, 4);
600-
} else {
601-
this.state = State.InTagName;
602-
this.stateInTagName(c); // Consume the token again
600+
switch (lower) {
601+
case Sequences.TitleEnd[3]: {
602+
this.startSpecial(Sequences.TitleEnd, 4);
603+
604+
break;
605+
}
606+
case Sequences.TextareaEnd[3]: {
607+
this.startSpecial(Sequences.TextareaEnd, 4);
608+
609+
break;
610+
}
611+
case Sequences.XmpEnd[3]: {
612+
this.startSpecial(Sequences.XmpEnd, 4);
613+
614+
break;
615+
}
616+
default: {
617+
this.state = State.InTagName;
618+
this.stateInTagName(c); // Consume the token again
619+
}
603620
}
604621
}
605622

src/__snapshots__/Tokenizer.spec.ts.snap

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,6 +487,37 @@ exports[`Tokenizer > should support self-closing special tags > for self-closing
487487
]
488488
`;
489489

490+
exports[`Tokenizer > should support self-closing special tags > for self-closing xmp tag 1`] = `
491+
[
492+
[
493+
"onopentagname",
494+
1,
495+
4,
496+
],
497+
[
498+
"onselfclosingtag",
499+
6,
500+
],
501+
[
502+
"onopentagname",
503+
8,
504+
11,
505+
],
506+
[
507+
"onopentagend",
508+
11,
509+
],
510+
[
511+
"onclosetag",
512+
14,
513+
17,
514+
],
515+
[
516+
"onend",
517+
],
518+
]
519+
`;
520+
490521
exports[`Tokenizer > should support standard special tags > for normal script tag 1`] = `
491522
[
492523
[
@@ -631,6 +662,42 @@ exports[`Tokenizer > should support standard special tags > for normal textarea
631662
]
632663
`;
633664

665+
exports[`Tokenizer > should support standard special tags > for normal xmp tag 1`] = `
666+
[
667+
[
668+
"onopentagname",
669+
1,
670+
4,
671+
],
672+
[
673+
"onopentagend",
674+
4,
675+
],
676+
[
677+
"onclosetag",
678+
7,
679+
10,
680+
],
681+
[
682+
"onopentagname",
683+
12,
684+
15,
685+
],
686+
[
687+
"onopentagend",
688+
15,
689+
],
690+
[
691+
"onclosetag",
692+
18,
693+
21,
694+
],
695+
[
696+
"onend",
697+
],
698+
]
699+
`;
700+
634701
exports[`Tokenizer > should treat html inside special tags as text > for div inside script tag 1`] = `
635702
[
636703
[
@@ -738,3 +805,30 @@ exports[`Tokenizer > should treat html inside special tags as text > for div ins
738805
],
739806
]
740807
`;
808+
809+
exports[`Tokenizer > should treat html inside special tags as text > for div inside xmp tag 1`] = `
810+
[
811+
[
812+
"onopentagname",
813+
1,
814+
4,
815+
],
816+
[
817+
"onopentagend",
818+
4,
819+
],
820+
[
821+
"ontext",
822+
5,
823+
16,
824+
],
825+
[
826+
"onclosetag",
827+
18,
828+
21,
829+
],
830+
[
831+
"onend",
832+
],
833+
]
834+
`;

0 commit comments

Comments
 (0)