99 lines
2.3 KiB
JavaScript
99 lines
2.3 KiB
JavaScript
let mermaidPromise;
|
|
|
|
async function getMermaid() {
|
|
if (!mermaidPromise) {
|
|
mermaidPromise = import("https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs").then(
|
|
(module) => {
|
|
const mermaid = module.default ?? module;
|
|
mermaid.initialize({ startOnLoad: false });
|
|
return mermaid;
|
|
},
|
|
);
|
|
}
|
|
|
|
return mermaidPromise;
|
|
}
|
|
|
|
function readDiagramSource(block) {
|
|
const code = block.querySelector("code");
|
|
return (code?.textContent ?? block.textContent ?? "").trim();
|
|
}
|
|
|
|
async function renderBlock(block) {
|
|
if (block.dataset.mermaidOverrideState) {
|
|
return;
|
|
}
|
|
|
|
const source = readDiagramSource(block);
|
|
if (!source) {
|
|
block.dataset.mermaidOverrideState = "empty";
|
|
return;
|
|
}
|
|
|
|
block.dataset.mermaidOverrideState = "pending";
|
|
|
|
try {
|
|
const mermaid = await getMermaid();
|
|
const replacement = document.createElement("div");
|
|
replacement.className = "mermaid";
|
|
replacement.textContent = source;
|
|
replacement.dataset.mermaidOverrideState = "rendered";
|
|
block.replaceWith(replacement);
|
|
await mermaid.run({ nodes: [replacement] });
|
|
} catch (error) {
|
|
block.dataset.mermaidOverrideState = "failed";
|
|
console.warn("Mermaid override failed", error);
|
|
}
|
|
}
|
|
|
|
function findBlocks(root = document) {
|
|
const blocks = [];
|
|
|
|
if (root instanceof Element && root.matches("pre.mermaid")) {
|
|
blocks.push(root);
|
|
}
|
|
|
|
if (root instanceof Document || root instanceof Element) {
|
|
blocks.push(...root.querySelectorAll("pre.mermaid"));
|
|
}
|
|
|
|
return blocks;
|
|
}
|
|
|
|
function renderAll(root = document) {
|
|
for (const block of findBlocks(root)) {
|
|
void renderBlock(block);
|
|
}
|
|
}
|
|
|
|
function installObserver() {
|
|
if (!(document.body instanceof HTMLBodyElement)) {
|
|
return;
|
|
}
|
|
|
|
const observer = new MutationObserver((mutations) => {
|
|
for (const mutation of mutations) {
|
|
for (const node of mutation.addedNodes) {
|
|
if (node instanceof Element) {
|
|
renderAll(node);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
observer.observe(document.body, { childList: true, subtree: true });
|
|
}
|
|
|
|
if (document.readyState === "loading") {
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
renderAll();
|
|
installObserver();
|
|
});
|
|
} else {
|
|
renderAll();
|
|
installObserver();
|
|
}
|
|
|
|
window.addEventListener("pageshow", () => renderAll());
|
|
window.addEventListener("popstate", () => renderAll());
|