fix: SVG regex prefers </svg> terminator, add self-closing children test

Use greedy <svg>...</svg> match preferring closing tag over inner />
to prevent truncation at first self-closing child element.
Self-closing root <svg .../> handled as separate alternative.
Added test with <path/> + <circle/> children asserting well-formed output.
This commit is contained in:
Thomas Camlong committed 2026-08-07 21:00:55 +02:00
1 parent 67ac2bbc7c
commit b3b2d5a022
2 files changed
+11 -1

No files matched your search

@@ -66,4 +66,14 @@ describe("SVG sanitization", () => {
const clean = sanitizeSvg(dirty);
expect(clean).not.toContain("onbegin");
});
it("preserves well-formed SVG with self-closing children", () => {
const icon = '<svg viewBox="0 0 24 24"><path d="M12 2L2 22h20Z" fill="currentColor"/><circle cx="12" cy="8" r="2"/></svg>';
const clean = sanitizeSvg(icon);
expect(clean).toContain("<path");
expect(clean).toContain("<circle");
expect(clean).toContain("</svg>");
expect(clean).not.toContain("<html");
expect(clean).not.toContain("<body");
});
});
@@ -86,7 +86,7 @@ export const sanitizeSvg = (svgText: string) => {
// linkedom's DOMParser omits html/body for fragment-only SVG; DOMPurify needs a body root.
const wrapped = `<html><body>${svgText}</body></html>`;
const sanitized = purify.sanitize(wrapped, svgSanitizeOptions);
const svgMatch = sanitized.match(/<svg[\s\S]*?(?:<\/svg>|\/>)/i);
const svgMatch = sanitized.match(/<svg[^>]*\/>|<svg[\s\S]*<\/svg>/i);
return svgMatch ? svgMatch[0] : "";
};