From bac24fb3cec30855474f65d6b7cc063bf47523e8 Mon Sep 17 00:00:00 2001 From: Theros Date: Sun, 1 Mar 2026 14:42:22 +0000 Subject: [PATCH 1/2] Escape scan result rows before rendering --- README.md | 6 ++++++ main.ts | 12 ++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index feec446..83ce071 100644 --- a/README.md +++ b/README.md @@ -227,6 +227,12 @@ deno task test deno task build ``` +Manual UI regression check for scan/clean results rendering: + +1. Create a test file whose name includes `<` and `>` in the target game folder. +2. Run `Scan` so the file appears under `Files To Remove`. +3. Confirm the results list renders the filename literally (including angle brackets) instead of interpreting it as HTML. + ## Project Structure - `main.ts` - desktop UI and command orchestration diff --git a/main.ts b/main.ts index 9ebc5f9..b197965 100644 --- a/main.ts +++ b/main.ts @@ -578,6 +578,14 @@ function setCleanReady(isReady) { function markScanDirty() { setCleanReady(false); } +function escapeHtml(value) { + return String(value) + .replaceAll("&", "&") + .replaceAll("<", "<") + .replaceAll(">", ">") + .replaceAll('"', """) + .replaceAll("'", "'"); +} function setResults(data) { const el = document.getElementById("fileList"); const rows = []; @@ -591,7 +599,7 @@ function setResults(data) { if (renames.length === 0) { rows.push(\`
No renames planned
\`); } else { - rows.push(...renames.map((rename) => \`
\${rename.from} -> \${rename.to}
\`)); + rows.push(...renames.map((rename) => \`
\${escapeHtml(rename.from)} -> \${escapeHtml(rename.to)}
\`)); } rows.push(\`\`); @@ -601,7 +609,7 @@ function setResults(data) { if (removals.length === 0) { rows.push(\`
No files to remove
\`); } else { - rows.push(...removals.map((file) => \`
\${file}
\`)); + rows.push(...removals.map((file) => \`
\${escapeHtml(file)}
\`)); } rows.push(\`\`); From a0ce4094fbf0f7c931c2bfddf43cf968bf74ca3a Mon Sep 17 00:00:00 2001 From: Theros Date: Sun, 1 Mar 2026 14:58:44 +0000 Subject: [PATCH 2/2] Adjust README UI regression steps for Windows --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 83ce071..1bd0a4f 100644 --- a/README.md +++ b/README.md @@ -229,9 +229,10 @@ deno task build Manual UI regression check for scan/clean results rendering: -1. Create a test file whose name includes `<` and `>` in the target game folder. -2. Run `Scan` so the file appears under `Files To Remove`. -3. Confirm the results list renders the filename literally (including angle brackets) instead of interpreting it as HTML. +1. Create a removable test file whose name includes `&` in the target game folder. +2. Add a `!rename` directive to `#keeplist.txt` whose `from` or `to` includes `` text, for example `!rename folder/source.txt -> folder/.txt`. +3. Run `Scan` so the file appears under `Files To Remove` and the directive appears under `Planned Renames`. +4. Confirm both sections render the special characters literally instead of interpreting them as HTML. ## Project Structure