diff --git a/README.md b/README.md index feec446..1bd0a4f 100644 --- a/README.md +++ b/README.md @@ -227,6 +227,13 @@ deno task test deno task build ``` +Manual UI regression check for scan/clean results rendering: + +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 - `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(\`\`);