Spaces:
Paused
Paused
| const uml = async className => { | |
| // Custom element to encapsulate Mermaid content. | |
| class MermaidDiv extends HTMLElement { | |
| /** | |
| * Creates a special Mermaid div shadow DOM. | |
| * Works around issues of shared IDs. | |
| * @return {void} | |
| */ | |
| constructor() { | |
| super() | |
| // Create the Shadow DOM and attach style | |
| const shadow = this.attachShadow({ mode: "open" }) | |
| const style = document.createElement("style") | |
| style.textContent = ` | |
| :host { | |
| display: block; | |
| line-height: initial; | |
| font-size: 16px; | |
| } | |
| div.diagram { | |
| margin: 0; | |
| overflow: visible; | |
| }` | |
| shadow.appendChild(style) | |
| } | |
| } | |
| if (typeof customElements.get("diagram-div") === "undefined") { | |
| customElements.define("diagram-div", MermaidDiv) | |
| } | |
| const getFromCode = parent => { | |
| // Handles <pre><code> text extraction. | |
| let text = "" | |
| for (let j = 0; j < parent.childNodes.length; j++) { | |
| const subEl = parent.childNodes[j] | |
| if (subEl.tagName.toLowerCase() === "code") { | |
| for (let k = 0; k < subEl.childNodes.length; k++) { | |
| const child = subEl.childNodes[k] | |
| const whitespace = /^\s*$/ | |
| if (child.nodeName === "#text" && !(whitespace.test(child.nodeValue))) { | |
| text = child.nodeValue | |
| break | |
| } | |
| } | |
| } | |
| } | |
| return text | |
| } | |
| function createOrUpdateHyperlink(parentElement, linkText, linkHref) { | |
| // Search for an existing anchor element within the parentElement | |
| let existingAnchor = parentElement.querySelector("a"); | |
| // Check if an anchor element already exists | |
| if (existingAnchor) { | |
| // Update the hyperlink reference if it's different from the current one | |
| if (existingAnchor.href !== linkHref) { | |
| existingAnchor.href = linkHref; | |
| } | |
| // Update the target attribute to ensure it opens in a new tab | |
| existingAnchor.target = '_blank'; | |
| // If the text must be dynamic, uncomment and use the following line: | |
| // existingAnchor.textContent = linkText; | |
| } else { | |
| // If no anchor exists, create one and append it to the parentElement | |
| let anchorElement = document.createElement("a"); | |
| anchorElement.href = linkHref; // Set hyperlink reference | |
| anchorElement.textContent = linkText; // Set text displayed | |
| anchorElement.target = '_blank'; // Ensure it opens in a new tab | |
| parentElement.appendChild(anchorElement); // Append the new anchor element to the parent | |
| } | |
| } | |
| function removeLastLine(str) { | |
| // 将字符串按换行符分割成数组 | |
| var lines = str.split('\n'); | |
| lines.pop(); | |
| // 将数组重新连接成字符串,并按换行符连接 | |
| var result = lines.join('\n'); | |
| return result; | |
| } | |
| // 给出配置 Provide a default config in case one is not specified | |
| const defaultConfig = { | |
| startOnLoad: false, | |
| theme: "default", | |
| flowchart: { | |
| htmlLabels: false | |
| }, | |
| er: { | |
| useMaxWidth: false | |
| }, | |
| sequence: { | |
| useMaxWidth: false, | |
| noteFontWeight: "14px", | |
| actorFontSize: "14px", | |
| messageFontSize: "16px" | |
| } | |
| } | |
| if (document.body.classList.contains("dark")) { | |
| defaultConfig.theme = "dark" | |
| } | |
| const Module = await import('./file=themes/mermaid_editor.js'); | |
| function do_render(block, code, codeContent, cnt) { | |
| var rendered_content = mermaid.render(`_diagram_${cnt}`, code); | |
| ////////////////////////////// 记录有哪些代码已经被渲染了 /////////////////////////////////// | |
| let codeFinishRenderElement = block.querySelector("code_finish_render"); // 如果block下已存在code_already_rendered元素,则获取它 | |
| if (codeFinishRenderElement) { // 如果block下已存在code_already_rendered元素 | |
| codeFinishRenderElement.style.display = "none"; | |
| } else { | |
| // 如果不存在code_finish_render元素,则将code元素中的内容添加到新创建的code_finish_render元素中 | |
| let codeFinishRenderElementNew = document.createElement("code_finish_render"); // 创建一个新的code_already_rendered元素 | |
| codeFinishRenderElementNew.style.display = "none"; | |
| codeFinishRenderElementNew.textContent = ""; | |
| block.appendChild(codeFinishRenderElementNew); // 将新创建的code_already_rendered元素添加到block中 | |
| codeFinishRenderElement = codeFinishRenderElementNew; | |
| } | |
| ////////////////////////////// 创建一个用于渲染的容器 /////////////////////////////////// | |
| let mermaidRender = block.querySelector(".mermaid_render"); // 尝试获取已存在的<div class='mermaid_render'> | |
| if (!mermaidRender) { | |
| mermaidRender = document.createElement("div"); // 不存在,创建新的<div class='mermaid_render'> | |
| mermaidRender.classList.add("mermaid_render"); | |
| block.appendChild(mermaidRender); // 将新创建的元素附加到block | |
| } | |
| mermaidRender.innerHTML = rendered_content | |
| codeFinishRenderElement.textContent = code // 标记已经渲染的部分 | |
| ////////////////////////////// 创建一个“点击这里编辑脑图” /////////////////////////////// | |
| let pako_encode = Module.serializeState({ | |
| "code": codeContent, | |
| "mermaid": "{\n \"theme\": \"default\"\n}", | |
| "autoSync": true, | |
| "updateDiagram": false | |
| }); | |
| createOrUpdateHyperlink(block, "点击这里编辑脑图", "https://mermaid.live/edit#" + pako_encode) | |
| } | |
| // 加载配置 Load up the config | |
| mermaid.mermaidAPI.globalReset() // 全局复位 | |
| const config = (typeof mermaidConfig === "undefined") ? defaultConfig : mermaidConfig | |
| mermaid.initialize(config) | |
| // 查找需要渲染的元素 Find all of our Mermaid sources and render them. | |
| const blocks = document.querySelectorAll(`pre.mermaid`); | |
| for (let i = 0; i < blocks.length; i++) { | |
| var block = blocks[i] | |
| ////////////////////////////// 如果代码没有发生变化,就不渲染了 /////////////////////////////////// | |
| var code = getFromCode(block); | |
| let codeContent = block.querySelector("code").textContent; // 获取code元素中的文本内容 | |
| let codePendingRenderElement = block.querySelector("code_pending_render"); // 如果block下已存在code_already_rendered元素,则获取它 | |
| if (codePendingRenderElement) { // 如果block下已存在code_pending_render元素 | |
| codePendingRenderElement.style.display = "none"; | |
| if (codePendingRenderElement.textContent !== codeContent) { | |
| codePendingRenderElement.textContent = codeContent; // 如果现有的code_pending_render元素中的内容与code元素中的内容不同,更新code_pending_render元素中的内容 | |
| } | |
| else { | |
| continue; // 如果相同,就不处理了 | |
| } | |
| } else { // 如果不存在code_pending_render元素,则将code元素中的内容添加到新创建的code_pending_render元素中 | |
| let codePendingRenderElementNew = document.createElement("code_pending_render"); // 创建一个新的code_already_rendered元素 | |
| codePendingRenderElementNew.style.display = "none"; | |
| codePendingRenderElementNew.textContent = codeContent; | |
| block.appendChild(codePendingRenderElementNew); // 将新创建的code_pending_render元素添加到block中 | |
| codePendingRenderElement = codePendingRenderElementNew; | |
| } | |
| ////////////////////////////// 在这里才真正开始渲染 /////////////////////////////////// | |
| try { | |
| do_render(block, code, codeContent, i); | |
| // console.log("渲染", codeContent); | |
| } catch (err) { | |
| try { | |
| var lines = code.split('\n'); if (lines.length < 2) { continue; } | |
| do_render(block, removeLastLine(code), codeContent, i); | |
| // console.log("渲染", codeContent); | |
| } catch (err) { | |
| console.log("以下代码不能渲染", code, removeLastLine(code), err); | |
| } | |
| } | |
| } | |
| } | |