This commit is contained in:
@@ -238,64 +238,101 @@ document.addEventListener("DOMContentLoaded", () => {
|
||||
});
|
||||
|
||||
|
||||
// Make Mermaid diagrams zoomable
|
||||
window.addEventListener('load', function() {
|
||||
// Initialize Mermaid (if not already)
|
||||
mermaid.initialize({ startOnLoad: false, theme: 'neutral' });
|
||||
// Make Mermaid diagrams use the active site theme and zoom controls.
|
||||
(function () {
|
||||
function cssVar(name, fallback) {
|
||||
const value = getComputedStyle(document.documentElement).getPropertyValue(name).trim();
|
||||
return value || fallback;
|
||||
}
|
||||
|
||||
// Find all Mermaid divs
|
||||
document.querySelectorAll('.mermaid').forEach(el => {
|
||||
// Decode HTML entities
|
||||
el.innerHTML = el.innerHTML
|
||||
.replace(/>/g, '>')
|
||||
.replace(/</g, '<')
|
||||
.replace(/&/g, '&');
|
||||
function mermaidConfig() {
|
||||
return {
|
||||
startOnLoad: false,
|
||||
theme: "base",
|
||||
themeVariables: {
|
||||
background: cssVar("--bg", "#faf9f6"),
|
||||
mainBkg: cssVar("--surface", "#ffffff"),
|
||||
primaryColor: cssVar("--surface", "#ffffff"),
|
||||
primaryTextColor: cssVar("--fg", "#000000"),
|
||||
primaryBorderColor: cssVar("--accent", "#2563eb"),
|
||||
secondaryColor: cssVar("--surface-soft", "#f3f1eb"),
|
||||
tertiaryColor: cssVar("--bg", "#faf9f6"),
|
||||
clusterBkg: cssVar("--surface-soft", "#f3f1eb"),
|
||||
clusterBorder: cssVar("--border", "#d7d7d7"),
|
||||
lineColor: cssVar("--border", "#d7d7d7"),
|
||||
textColor: cssVar("--fg", "#000000"),
|
||||
edgeLabelBackground: cssVar("--surface", "#ffffff"),
|
||||
fontFamily: cssVar("--font-body", "Noto, system-ui, sans-serif")
|
||||
},
|
||||
flowchart: {
|
||||
htmlLabels: true,
|
||||
curve: "basis"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Wrap in container if not already wrapped
|
||||
if (!el.parentElement.classList.contains('mermaid-container')) {
|
||||
const container = document.createElement('div');
|
||||
container.classList.add('mermaid-container');
|
||||
function decodeMermaidSource(source) {
|
||||
const textarea = document.createElement("textarea");
|
||||
textarea.innerHTML = source;
|
||||
return textarea.value.trim();
|
||||
}
|
||||
|
||||
// Add zoom controls
|
||||
const controls = document.createElement('div');
|
||||
controls.classList.add('mermaid-zoom-controls');
|
||||
async function renderMermaid() {
|
||||
if (!window.mermaid) return;
|
||||
const diagrams = document.querySelectorAll(".mermaid");
|
||||
if (!diagrams.length) return;
|
||||
|
||||
diagrams.forEach((el) => {
|
||||
if (!el.dataset.source) {
|
||||
el.dataset.source = decodeMermaidSource(el.textContent || el.innerHTML);
|
||||
}
|
||||
el.removeAttribute("data-processed");
|
||||
el.innerHTML = el.dataset.source;
|
||||
});
|
||||
|
||||
mermaid.initialize(mermaidConfig());
|
||||
await mermaid.run({ querySelector: ".mermaid" });
|
||||
wrapMermaidDiagrams();
|
||||
}
|
||||
|
||||
function wrapMermaidDiagrams() {
|
||||
document.querySelectorAll(".mermaid").forEach((el) => {
|
||||
if (el.closest(".mermaid-container")) return;
|
||||
|
||||
const container = document.createElement("div");
|
||||
container.className = "mermaid-container";
|
||||
const controls = document.createElement("div");
|
||||
controls.className = "mermaid-zoom-controls";
|
||||
controls.innerHTML = `
|
||||
<button class="zoom-in">+</button>
|
||||
<button class="zoom-out">-</button>
|
||||
<button class="zoom-in" type="button" aria-label="Zoom in">+</button>
|
||||
<button class="zoom-out" type="button" aria-label="Zoom out">-</button>
|
||||
`;
|
||||
container.appendChild(controls);
|
||||
|
||||
// Move the mermaid diagram into container
|
||||
container.appendChild(el.cloneNode(true));
|
||||
el.replaceWith(container);
|
||||
container.appendChild(controls);
|
||||
container.appendChild(el);
|
||||
|
||||
// Select the SVG inside
|
||||
const svg = container.querySelector('.mermaid svg');
|
||||
let scale = 1;
|
||||
|
||||
// Zoom functions
|
||||
controls.querySelector('.zoom-in').addEventListener('click', () => {
|
||||
scale += 0.1;
|
||||
const setScale = (next) => {
|
||||
const svg = container.querySelector(".mermaid svg");
|
||||
if (!svg) return;
|
||||
scale = Math.max(0.2, Math.min(3, next));
|
||||
svg.style.transform = `scale(${scale})`;
|
||||
});
|
||||
};
|
||||
|
||||
controls.querySelector('.zoom-out').addEventListener('click', () => {
|
||||
scale = Math.max(0.1, scale - 0.1);
|
||||
svg.style.transform = `scale(${scale})`;
|
||||
controls.querySelector(".zoom-in").addEventListener("click", () => setScale(scale + 0.1));
|
||||
controls.querySelector(".zoom-out").addEventListener("click", () => setScale(scale - 0.1));
|
||||
container.addEventListener("wheel", (e) => {
|
||||
if (!e.ctrlKey) return;
|
||||
e.preventDefault();
|
||||
setScale(scale + (e.deltaY < 0 ? 0.05 : -0.05));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Optional: scroll wheel zoom
|
||||
container.addEventListener('wheel', (e) => {
|
||||
if (e.ctrlKey) { // zoom only with ctrl+wheel
|
||||
e.preventDefault();
|
||||
if (e.deltaY < 0) scale += 0.05;
|
||||
else scale = Math.max(0.1, scale - 0.05);
|
||||
svg.style.transform = `scale(${scale})`;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Finally, render Mermaid diagrams
|
||||
mermaid.run({ querySelector: '.mermaid' });
|
||||
});
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", renderMermaid);
|
||||
} else {
|
||||
renderMermaid();
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -799,11 +799,14 @@ body.no-sidenotes {
|
||||
|
||||
/* Mermaid container for zooming and panning */
|
||||
.mermaid-container {
|
||||
overflow: auto; /* allow scrolling */
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
max-height: 800px; /* adjust to your page */
|
||||
border: 1px solid #ccc; /* optional, visual boundary */
|
||||
max-height: 800px;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 8px;
|
||||
background: color-mix(in oklab, var(--surface) 88%, var(--bg) 12%);
|
||||
position: relative;
|
||||
margin: 1.5rem 0;
|
||||
}
|
||||
|
||||
/* Make SVG scale properly */
|
||||
@@ -825,13 +828,14 @@ body.no-sidenotes {
|
||||
.mermaid-zoom-controls button {
|
||||
padding: 5px 10px;
|
||||
margin-left: 5px;
|
||||
background: #007bff;
|
||||
color: white;
|
||||
border: none;
|
||||
background: var(--surface);
|
||||
color: var(--fg);
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.mermaid-zoom-controls button:hover {
|
||||
background: #0056b3;
|
||||
background: var(--accent);
|
||||
color: var(--surface);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user