import {addScript} from "../util/addScript"; import {Constants} from "../../constants"; import {hasClosestByAttribute, hasClosestByClassName} from "../util/hasClosest"; import {genIconHTML} from "./util"; export const mermaidRender = (element: Element, cdn = Constants.PROTYLE_CDN) => { let mermaidElements: Element[] = []; if (element.getAttribute("data-subtype") === "mermaid") { // 编辑器内代码块编辑渲染 mermaidElements = [element]; } else { mermaidElements = Array.from(element.querySelectorAll('[data-subtype="mermaid"]')); } if (mermaidElements.length === 0) { return; } addScript(`${cdn}/js/mermaid/mermaid.min.js?v=11.6.0`, "protyleMermaidScript").then(() => { const config: any = { securityLevel: "loose", // 升级后无 https://github.com/siyuan-note/siyuan/issues/3587,可使用该选项 altFontFamily: "sans-serif", fontFamily: "sans-serif", startOnLoad: false, flowchart: { htmlLabels: true, useMaxWidth: !0 }, sequence: { useMaxWidth: true, diagramMarginX: 8, diagramMarginY: 8, boxMargin: 8, showSequenceNumbers: true // Mermaid 时序图增加序号 https://github.com/siyuan-note/siyuan/pull/6992 https://mermaid.js.org/syntax/sequenceDiagram.html#sequencenumbers }, gantt: { leftPadding: 75, rightPadding: 20 } }; if (window.siyuan.config.appearance.mode === 1) { config.theme = "dark"; } window.mermaid.initialize(config); if (mermaidElements[0].firstElementChild.clientWidth === 0) { const observer = new MutationObserver(() => { initMermaid(mermaidElements); observer.disconnect(); }); const hideElement = hasClosestByAttribute(mermaidElements[0], "fold", "1"); if (hideElement) { observer.observe(hideElement, {attributeFilter: ["fold"]}); } else { const cardElement = hasClosestByClassName(mermaidElements[0], "card__block", true); if (cardElement) { observer.observe(cardElement, {attributeFilter: ["class"]}); } } } else { initMermaid(mermaidElements); } }); }; const initMermaid = (mermaidElements: Element[]) => { const wysiswgElement = hasClosestByClassName(mermaidElements[0], "protyle-wysiwyg", true); mermaidElements.forEach(async (item: HTMLElement) => { if (item.getAttribute("data-render") === "true") { return; } if (!item.firstElementChild.classList.contains("protyle-icons")) { item.insertAdjacentHTML("afterbegin", genIconHTML(wysiswgElement)); } const renderElement = item.firstElementChild.nextElementSibling as HTMLElement; if (!item.getAttribute("data-content")) { renderElement.innerHTML = `${Constants.ZWSP}`; return; } const id = "mermaid" + Lute.NewNodeID(); try { renderElement.innerHTML = `${Constants.ZWSP}
`; const mermaidData = await window.mermaid.render(id, Lute.UnEscapeHTMLStr(item.getAttribute("data-content"))); renderElement.lastElementChild.innerHTML = mermaidData.svg; } catch (e) { const errorElement = document.querySelector("#" + id); renderElement.lastElementChild.innerHTML = `${errorElement.outerHTML}
${e.message.replace(/\n/, "
")}
`; errorElement.parentElement.remove(); } item.setAttribute("data-render", "true"); }); };