diff --git a/package-lock.json b/package-lock.json index 47d4ca25..a4a6570a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@fingerprintjs/fingerprintjs": "^5.0.1", "date-fns": "^4.1.0", + "dompurify": "^3.4.11", "highlight.js": "^11.11.1", "katex": "^0.16.45", "md-editor-v3": "^6.5.0", diff --git a/package.json b/package.json index afa16128..2de6fa5f 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "dependencies": { "@fingerprintjs/fingerprintjs": "^5.0.1", "date-fns": "^4.1.0", + "dompurify": "^3.4.11", "highlight.js": "^11.11.1", "katex": "^0.16.45", "md-editor-v3": "^6.5.0", diff --git a/src/services/pltxt2htm/advancedParser.ts b/src/services/pltxt2htm/advancedParser.ts index 06f1ad61..e18ecf8b 100644 --- a/src/services/pltxt2htm/advancedParser.ts +++ b/src/services/pltxt2htm/advancedParser.ts @@ -2,6 +2,7 @@ import { getWasmInstance } from './wasmLoader' import { getDeallocator } from './deallocator' import hljs from 'highlight.js' import mermaid from 'mermaid' +import DOMPurify from 'dompurify' import renderMathInElement from 'katex/contrib/auto-render/auto-render.js' import 'katex/dist/katex.min.css' import storageManager from '@storage/index' @@ -27,6 +28,13 @@ function ensureMermaidInitialized() { mermaidInitialized = true } +function createMermaidDiagram(svg: string): Node | null { + const diagram = DOMPurify.sanitize(svg, { + USE_PROFILES: { svg: true, svgFilters: true }, + RETURN_DOM: true, + }) + return diagram instanceof SVGSVGElement ? diagram : null +} async function renderMermaidDiagrams(container: HTMLElement) { ensureMermaidInitialized() @@ -42,11 +50,14 @@ async function renderMermaidDiagrams(container: HTMLElement) { try { const renderId = `mermaid-${Date.now()}-${index}`; - const { svg } = await mermaid.render(renderId, source); - const wrapper = document.createElement("div"); - wrapper.className = "mermaid-diagram"; - wrapper.innerHTML = svg; - pre.replaceWith(wrapper); + const { svg } = await mermaid.render(renderId, source) + const diagram = createMermaidDiagram(svg) + if (!diagram) return + + const wrapper = document.createElement('div') + wrapper.className = 'mermaid-diagram' + wrapper.replaceChildren(diagram) + pre.replaceWith(wrapper) } catch (e) { console.warn("mermaid render failed:", e); } @@ -101,7 +112,9 @@ async function parse(source: string, context: ParseContext = {}) { if (!rawHtml) return '' const tempDiv = document.createElement('div') - tempDiv.innerHTML = rawHtml + tempDiv.innerHTML = DOMPurify.sanitize(rawHtml, { + USE_PROFILES: { html: true, svg: true, svgFilters: true, mathMl: true }, + }) if (typeof renderMathInElement === 'function') { renderMathInElement(tempDiv, {