fix(memory-ui): escape < in <!-- user-edited literals to unblock vite dep-scan

Vite's dep pre-bundling runs esbuild's lite parser over .vue script blocks
to find imports. On esbuild 0.27.5 that parser interprets the
HTML-style sequence `<!--` inside a JS string/regex literal as the start
of a legacy line comment, which made it conflate two unrelated string
literals on lines 95 and 110 of MemoryBrowser.vue and report a fake
"Unterminated string literal" against a phantom line that doesn't exist
in the source.

Replacing the raw `<` with `\x3c` keeps the runtime behavior identical
(includes/regex match the same `<!-- user-edited` marker) but breaks the
HTML-comment heuristic so the scanner no longer chokes. The two call
sites — userEdited detection in parseSections and the strip regex in
stripMarker — both need the escape.

Repro: `pnpm dev` from a cold cache surfaces the error during dep scan,
runtime tests passed already because the actual JS parser handles the
strings fine.
This commit is contained in:
matevip 2026-05-29 06:16:19 +08:00
parent 51e1bd2582
commit 69bea272dd

View File

@ -92,7 +92,10 @@ function parseSections(content: string): MemorySectionData[] {
if (match) {
const heading = match[1].trim()
const rawBody = match[2].trim()
const userEdited = rawBody.includes('<!-- user-edited')
// `\x3c` escapes the `<` so Vite's esbuild dep-scan doesn't treat
// the embedded `<!-- ... -->` sequence as an HTML-like line comment
// and conflate this string literal with the one in stripMarker below.
const userEdited = rawBody.includes('\x3c!-- user-edited')
// Strip the hidden marker from the display body it is metadata, and
// since renderMarkdown escapes HTML it would otherwise show as raw text.
result.push({ heading, body: stripMarker(rawBody), userEdited })
@ -107,7 +110,8 @@ function parseSections(content: string): MemorySectionData[] {
// Strip the hidden user-edited marker so it never shows up as raw text in the
// editor (and never accumulates when a section is edited repeatedly).
function stripMarker(body: string): string {
return body.replace(/^[ \t]*<!-- user-edited:.*-->[ \t]*$/gm, '').trim()
// `\x3c` escape same reason as in parseSections above.
return body.replace(/^[ \t]*\x3c!-- user-edited:.*-->[ \t]*$/gm, '').trim()
}
/**