From b06a7ac42193cbf96699d8a164b5a189e54e8c9f Mon Sep 17 00:00:00 2001 From: hj Date: Thu, 21 May 2026 19:47:09 +0900 Subject: [PATCH 1/2] fix: avoid quadratic html-tag scan in ignoreHtmlTag --- packages/text-vide/src/useCheckIsHtmlTag.ts | 41 +++++++++++++++++++-- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/packages/text-vide/src/useCheckIsHtmlTag.ts b/packages/text-vide/src/useCheckIsHtmlTag.ts index c8af6f7..2692d73 100644 --- a/packages/text-vide/src/useCheckIsHtmlTag.ts +++ b/packages/text-vide/src/useCheckIsHtmlTag.ts @@ -1,10 +1,43 @@ -import { extractMatchRangeList } from './utils'; +import { MatchRange } from './utils'; -const HTML_TAG_REGEX = /|<[^>]+>/g; +const getHtmlTagRangeList = (text: string): MatchRange[] => { + const htmlTagRangeList: MatchRange[] = []; + let cursor = 0; + + while (cursor < text.length) { + const openIndex = text.indexOf('<', cursor); + if (openIndex === -1) { + break; + } + + if (text.startsWith('', openIndex + 4); + if (closeIndex === -1) { + break; + } + + htmlTagRangeList.push([openIndex, closeIndex + 2]); + cursor = closeIndex + 3; + continue; + } + + const closeIndex = text.indexOf('>', openIndex + 1); + if (closeIndex === -1) { + break; + } + + if (closeIndex > openIndex + 1) { + htmlTagRangeList.push([openIndex, closeIndex]); + } + + cursor = closeIndex + 1; + } + + return htmlTagRangeList; +}; export const useCheckIsHtmlTag = (text: string) => { - const htmlTagMatchList = text.matchAll(HTML_TAG_REGEX); - const htmlTagRangeList = extractMatchRangeList(htmlTagMatchList); + const htmlTagRangeList = getHtmlTagRangeList(text); const reversedHtmlTagRangeList = htmlTagRangeList.reverse(); return (match: RegExpMatchArray) => { From 9a9146546b9db2fbb4fb7e4a141d371d70606823 Mon Sep 17 00:00:00 2001 From: shj Date: Thu, 28 May 2026 18:31:15 +0900 Subject: [PATCH 2/2] fix: preserve tag recognition after unterminated HTML comments - Export MatchRange from utils so useCheckIsHtmlTag's import resolves (fixes TS2305 during vite-plugin-dts declaration emit). - Fall through to normal <...> scan when instead of aborting the loop, restoring the original regex behavior. - Add regression tests for unterminated comments, lone ', openIndex + 4); - if (closeIndex === -1) { - break; + const commentCloseIndex = text.indexOf('-->', openIndex + 4); + if (commentCloseIndex !== -1) { + htmlTagRangeList.push([openIndex, commentCloseIndex + 2]); + cursor = commentCloseIndex + 3; + continue; } - - htmlTagRangeList.push([openIndex, closeIndex + 2]); - cursor = closeIndex + 3; - continue; + // Unterminated `|<[^>]+>/g` regex). } const closeIndex = text.indexOf('>', openIndex + 1); diff --git a/packages/text-vide/src/utils.ts b/packages/text-vide/src/utils.ts index f74e9b1..1db0e6d 100644 --- a/packages/text-vide/src/utils.ts +++ b/packages/text-vide/src/utils.ts @@ -1,6 +1,8 @@ +export type MatchRange = [number, number]; + export const extractMatchRangeList = ( matchList: IterableIterator, -) => +): MatchRange[] => Array.from(matchList).map(match => { const startIndex = match.index!; const [matchedWord] = match;