Pure `nix fmt` output from the commit before this one — no hand edits. 203 files: 52 md, 42 tsx, 32 js, 32 css, 21 ts, 13 html, 8 json, 3 mjs. Reproduce with `nix develop -c nix fmt` on the parent commit; the result should be byte-identical to this tree. None of the 13 `.prettierignore` entries appears here — verified by intersecting the changed-file list against the ignore file, with a control proving the intersection finds a match when one exists.
30 lines
1.1 KiB
TypeScript
30 lines
1.1 KiB
TypeScript
// Markdown → sanitized HTML, ported from app.js's `mdNode`. Message
|
|
// bodies rendered into the live stream (assistant text, send/recv
|
|
// payloads) are untrusted (peer-agent / matrix-relayed content,
|
|
// agent-authored files) — `marked` itself no longer sanitizes (v5+
|
|
// dropped the built-in sanitizer), so every parse is run through
|
|
// DOMPurify before it's ever handed to `dangerouslySetInnerHTML`.
|
|
import { marked } from "marked";
|
|
import DOMPurify from "dompurify";
|
|
|
|
marked.setOptions({ breaks: true, gfm: true });
|
|
|
|
const ESCAPE_RE = /[&<>"]/g;
|
|
const ESCAPE_MAP: Record<string, string> = {
|
|
"&": "&",
|
|
"<": "<",
|
|
">": ">",
|
|
'"': """,
|
|
};
|
|
|
|
/** Render `text` as sanitized markdown HTML. Falls back to escaped plain
|
|
* text if `marked` throws (mirrors app.js's try/catch fallback). */
|
|
export function renderMarkdown(text: string | null | undefined): string {
|
|
const src = String(text ?? "");
|
|
try {
|
|
return DOMPurify.sanitize(marked.parse(src) as string);
|
|
} catch (err) {
|
|
console.warn("marked failed", err);
|
|
return src.replace(ESCAPE_RE, (c) => ESCAPE_MAP[c] ?? c);
|
|
}
|
|
}
|