From adbc049eed4ef8a7464d5d38e44d32b6f08eae10 Mon Sep 17 00:00:00 2001 From: Yash Dogra Date: Mon, 9 Nov 2026 13:54:03 +0530 Subject: [PATCH 1/2] fix(tokenizer): drop unfinished tags after a closing tag name or slash at EOF --- src/Tokenizer.spec.ts | 9 +++++++++ src/Tokenizer.ts | 4 +++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Tokenizer.spec.ts b/src/Tokenizer.spec.ts index e596b976..3a31efd1 100644 --- a/src/Tokenizer.spec.ts +++ b/src/Tokenizer.spec.ts @@ -222,6 +222,15 @@ describe("Tokenizer", () => { expect(tokenize("")).toMatchSnapshot(); }); + it.each(["a { + expect( + tokenize(input).filter(([event]) => event === "ontext"), + ).toEqual([["ontext", 0, 1]]); + }, + ); + it("should treat as a declaration", () => { expect(tokenize("")).toMatchSnapshot(); }); diff --git a/src/Tokenizer.ts b/src/Tokenizer.ts index 6f983e1b..20ecb76c 100644 --- a/src/Tokenizer.ts +++ b/src/Tokenizer.ts @@ -1114,7 +1114,9 @@ export default class Tokenizer { case State.InAttributeValueSq: case State.InAttributeValueDq: case State.InAttributeValueNq: - case State.InClosingTagName: { + case State.InSelfClosingTag: + case State.InClosingTagName: + case State.AfterClosingTagName: { /* * If we are currently in an opening or closing tag, us not calling the * respective callback signals that the tag should be ignored. From db1230d85d988d74b286a973458aaf0c10361a6e Mon Sep 17 00:00:00 2001 From: yxshee <84263676+yxshee@users.noreply.github.com> Date: Mon, 9 Nov 2026 14:28:26 +0530 Subject: [PATCH 2/2] test(tokenizer): check every chunk split for unfinished tags at EOF --- src/Tokenizer.spec.ts | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Tokenizer.spec.ts b/src/Tokenizer.spec.ts index 3a31efd1..68cc1c7e 100644 --- a/src/Tokenizer.spec.ts +++ b/src/Tokenizer.spec.ts @@ -225,9 +225,15 @@ describe("Tokenizer", () => { it.each(["a { - expect( - tokenize(input).filter(([event]) => event === "ontext"), - ).toEqual([["ontext", 0, 1]]); + for (let split = 0; split <= input.length; split++) { + expect( + tokenize((tokenizer) => { + tokenizer.write(input.slice(0, split)); + tokenizer.write(input.slice(split)); + tokenizer.end(); + }).filter(([event]) => event === "ontext"), + ).toEqual([["ontext", 0, 1]]); + } }, );