// The sanitizer is the whole reason the diagram can be inlined at all: the // site's CSP has no 'unsafe-inline' and a bare `style-src 'self'`, so anything // Mermaid emits as CSS is dead on arrival in production and would take the // picture with it. These cover the shapes Mermaid actually produces. import assert from "node:assert/strict"; import { readFileSync } from "node:fs"; import { join } from "node:path"; import { fileURLToPath } from "node:url"; import { describe, it } from "node:test"; import { sanitize } from "./render-diagram.mjs"; const webRoot = join(fileURLToPath(import.meta.url), "../.."); const svgPath = join(webRoot, "src/diagrams/architecture.svg"); const wrap = (inner, attrs = 'viewBox="0 0 10 10"') => `${inner}`; describe("sanitize", () => { it("drops the stylesheet Mermaid inlines", () => { const out = sanitize(wrap(""), "t"); assert.ok(!out.includes("")); }); it("drops style attributes but keeps font-style and other presentation attributes", () => { const out = sanitize( wrap('x'), "t", ); assert.ok(!/(^|[\s"'])style\s*=/.test(out)); assert.ok(out.includes('font-style="normal"')); assert.ok(out.includes('fill="red"')); }); it("drops the fixed pixel size so CSS can scale the figure", () => { const out = sanitize(wrap("", 'width="900" height="500" viewBox="0 0 900 500"'), "t"); assert.ok(!/]*\swidth=/.test(out)); assert.ok(!/]*\sheight=/.test(out)); assert.ok(out.includes('viewBox="0 0 900 500"')); }); it("refuses an SVG with no viewBox, which would have nothing to scale by", () => { assert.throws(() => sanitize('', "t"), /viewBox/); }); it("refuses a script, whatever a future Mermaid decides to emit", () => { assert.throws(() => sanitize(wrap(""), "t"), /script/); }); }); describe("the committed architecture.svg", () => { const svg = readFileSync(svgPath, "utf8"); it("carries nothing the site CSP would drop", () => { assert.ok(!/]/i.test(svg)); assert.ok(!/(^|[\s"'])style\s*=/i.test(svg)); assert.ok(!/