From 5e5d0cc9a13102459485ceb1b21158063c05fb50 Mon Sep 17 00:00:00 2001 From: Yang Jun Date: Mon, 11 May 2026 23:36:31 +0800 Subject: [PATCH] refactor(strip_html): treat '<...>' as a catch-all block kind Adding ['<', '>'] as the lowest-priority entry of `blocks` lets the inner loop subsume the generic-tag fallback: the `end` sentinel and its `< 0` / `<= 0` follow-up checks disappear, the "no terminator" exit becomes a single `i === lt` test, and Set<[string, string]> collapses to Map. Co-authored-by: Cursor --- src/filters/html.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/filters/html.ts b/src/filters/html.ts index e59adfd58..21cb8c4a9 100644 --- a/src/filters/html.ts +++ b/src/filters/html.ts @@ -42,29 +42,25 @@ export function newline_to_br (this: FilterImpl, v: string) { return str.replace(/\r?\n/gm, '
\n') } -// Raw-text blocks (HTML5): a regex equivalent is O(n^2) in V8 on unclosed openers. +// Raw-text blocks (HTML5) plus '<...>' as the catch-all kind; a regex +// equivalent is O(n^2) in V8 on unclosed openers. export function strip_html (this: FilterImpl, v: string) { const str = stringify(v) this.context.memoryLimit.use(str.length) - const blocks = new Set<[string, string]>([[''], [''], ['']]) + const blocks = new Map([[''], [''], [''], ['<', '>']]) let out = '' let i = 0 while (i < str.length) { const lt = str.indexOf('<', i) if (lt < 0) return out + str.slice(i) out += str.slice(i, lt) - let end = -1 - for (const block of blocks) { - const [opener, closer] = block + for (const [opener, closer] of blocks) { if (!str.startsWith(opener, lt)) continue const e = str.indexOf(closer, lt + opener.length) - if (e < 0) blocks.delete(block) - else end = e + closer.length - break + if (e >= 0) { i = e + closer.length; break } + blocks.delete(opener) } - if (end < 0) end = str.indexOf('>', lt + 1) + 1 - if (end <= 0) return out + str.slice(lt) - i = end + if (i === lt) return out + str.slice(lt) } return out }