Skip to content

Commit 3effe59

Browse files
alexander-akaitclaude
authored andcommitted
fix(html): make flushText idempotent to avoid duplicate text emit at EOF
Copilot review follow-up on commit 132a4cd. Real bug verified by `walkHtmlTokens("a<div", 0, { text: ... })` — the `"a"` text span was emitted twice: 1) `STATE_TAG_OPEN`'s alpha branch flushed pending text on tag entry, 2) the EOF mid-tag handler called `flushText(tagStart)` again, re-emitting the same span because `flushText` never advanced `textStart`. Fix: `flushText` now advances `textStart = endPos` after emitting, so repeated `flushText` calls for the same span are no-ops. `emitOpenTag` / `emitCloseTag` overwrite `textStart` with their own `nextPos` after the tag emits, so the new advance doesn't shift any subsequent ranges. 238/238 tests pass, 100% coverage on `walkHtmlTokens.js`, `yarn lint` clean. https://claude.ai/code/session_01N4rd8xuv5oRaHWFL8dFpwh
1 parent 132a4cd commit 3effe59

1 file changed

Lines changed: 10 additions & 2 deletions

File tree

lib/html/walkHtmlTokens.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -302,8 +302,16 @@ const walkHtmlTokens = (input, pos = 0, callbacks = {}) => {
302302
* @param {number} endPos end position
303303
*/
304304
const flushText = (endPos) => {
305-
if (textStart < endPos && callbacks.text !== undefined) {
306-
callbacks.text(input, textStart, endPos);
305+
if (textStart < endPos) {
306+
if (callbacks.text !== undefined) {
307+
callbacks.text(input, textStart, endPos);
308+
}
309+
// Advance `textStart` so a second `flushText` for the same span
310+
// (e.g. from the EOF handler after a tag-open transition already
311+
// flushed the pending text) is a no-op rather than a duplicate
312+
// emit. emitOpenTag / emitCloseTag overwrite `textStart` with
313+
// their own `nextPos` anyway, so this doesn't shift their start.
314+
textStart = endPos;
307315
}
308316
};
309317

0 commit comments

Comments
 (0)