* 创建 Mermaid 预览
(content: string)
| 1475 | * 创建 Mermaid 预览 |
| 1476 | */ |
| 1477 | private async createMermaidPreview(content: string): Promise<void> { |
| 1478 | if (!this.mermaidPreview) { |
| 1479 | this.mermaidPreview = document.createElement("div"); |
| 1480 | this.mermaidPreview.className = "milkup-mermaid-preview"; |
| 1481 | this.dom.appendChild(this.mermaidPreview); |
| 1482 | } |
| 1483 | |
| 1484 | const preview = this.mermaidPreview; |
| 1485 | |
| 1486 | // 排队执行,避免多个 mermaid 块同时 render 互相干扰 |
| 1487 | mermaidRenderQueue = mermaidRenderQueue.then(async () => { |
| 1488 | // renderId 需要在 try 外声明,以便 catch 中清理 mermaid 遗留的临时元素 |
| 1489 | const renderId = `mermaid-${++mermaidIdCounter}`; |
| 1490 | try { |
| 1491 | const mermaid = await import("mermaid"); |
| 1492 | const isDark = detectDarkTheme(); |
| 1493 | |
| 1494 | mermaid.default.initialize({ |
| 1495 | startOnLoad: false, |
| 1496 | darkMode: isDark, |
| 1497 | theme: "base", |
| 1498 | themeVariables: getMermaidThemeVariables(), |
| 1499 | }); |
| 1500 | |
| 1501 | const { svg } = await mermaid.default.render(renderId, content); |
| 1502 | preview.innerHTML = svg; |
| 1503 | padMermaidSvgBounds(preview); |
| 1504 | // 根据实际背景色修正文本颜色 |
| 1505 | fixMermaidTextContrast(preview); |
| 1506 | } catch (error) { |
| 1507 | // mermaid.render() 语法错误时会在 removeTempElements() 之前抛出异常, |
| 1508 | // 导致临时 DOM 元素(<div id="d..."> / <svg> / <iframe>)遗留在 document.body 中。 |
| 1509 | // 这些孤儿元素不断累积会干扰页面布局,导致 tab 栏等 UI 元素显示异常。 |
| 1510 | document.getElementById(`d${renderId}`)?.remove(); |
| 1511 | document.getElementById(renderId)?.remove(); |
| 1512 | document.getElementById(`i${renderId}`)?.remove(); |
| 1513 | preview.innerHTML = `<div class="milkup-mermaid-error">Mermaid 渲染错误</div>`; |
| 1514 | } |
| 1515 | }); |
| 1516 | |
| 1517 | await mermaidRenderQueue; |
| 1518 | this.updateMermaidDisplay(); |
| 1519 | } |
| 1520 | |
| 1521 | /** |
| 1522 | * CodeMirror 更新回调 |
no test coverage detected