From 5e6e2904ff06a24913702a0e72b2dfe7ee8f92f9 Mon Sep 17 00:00:00 2001 From: Cell <1024@lruihao.cn> Date: Thu, 30 Apr 2026 11:58:57 +0800 Subject: [PATCH] perf(mermaid): improve error handling and optimize rendering for mobile --- assets/js/lib/mermaid.js | 24 +++++++++++++------ .../pages/single/shortcodes/_mermaid.scss | 11 +++++---- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/assets/js/lib/mermaid.js b/assets/js/lib/mermaid.js index d53b4d47..dd8f8ddc 100644 --- a/assets/js/lib/mermaid.js +++ b/assets/js/lib/mermaid.js @@ -248,12 +248,20 @@ async function renderMermaidElement(el, { theme, darkMode } = {}) { el.setAttribute('data-processed', '') const svgId = svgEl?.id || id if (svgId) { - const group = svgEl ? getMermaidPanzoomGroup(svgEl) : null - if (svgEl && group?.transform) applyPanzoomTransformToSvg(svgEl, group.transform) + {{- if $wrapped }} + const group = getMermaidPanzoomGroup(svgEl) + applyPanzoomTransformToSvg(svgEl, group?.transform) + {{- end }} document.dispatchEvent(new CustomEvent('fixit:mermaid-rendered', { detail: { svgId } })) } } catch (e) { + const errDiv = document.getElementById(`d${id}`) + if (errDiv) { + el.innerHTML = errDiv.innerHTML + errDiv.remove() + } el.removeAttribute('data-processing') + el.setAttribute('data-processed', '') console.warn('FixIt Mermaid render failed:', e) } }) @@ -284,6 +292,7 @@ async function renderActiveLayerInContainer(container) { * Render it in idle time for print / fallback scenarios. */ function scheduleNeutralRender() { + if (window.matchMedia('only screen and (max-width: 960px)').matches) return runWhenIdle(() => { const neutralNodes = Array.from(document.querySelectorAll('.mermaid-neutral')) .filter((el) => el && !el.hasAttribute('data-processed')) @@ -661,17 +670,18 @@ async function init() { `%c💫 FixIt Mermaid`, 'color: #FF3670; font-weight: bold; font-size: 16px; text-shadow: 1px 1px 2px rgba(0,0,0,0.1);', ) - // Core: observe containers and render only when they become visible. - observeMermaidContainers() - // Neutral is non-critical, defer to idle time. - scheduleNeutralRender() - bindTabContainerChanged() {{- if $wrapped }} initDiagramControls() bindRenderedPanzoom() bindThemeSync() {{- end }} + bindTabContainerChanged() + + // Core: observe containers and render only when they become visible. + observeMermaidContainers() + // Neutral is non-critical, defer to idle time. + scheduleNeutralRender() if (!mermaidThemeRerenderBound && window.fixit?.switchThemeEventSet?.add) { mermaidThemeRerenderBound = true diff --git a/assets/scss/pages/single/shortcodes/_mermaid.scss b/assets/scss/pages/single/shortcodes/_mermaid.scss index 663d5a17..ba9cacdf 100644 --- a/assets/scss/pages/single/shortcodes/_mermaid.scss +++ b/assets/scss/pages/single/shortcodes/_mermaid.scss @@ -13,10 +13,6 @@ } } - &:not([data-processed])::before { - @include loading; - } - svg { max-width: 100%; height: auto; @@ -38,6 +34,13 @@ pointer-events: auto; } +:is(.mermaid, .mermaid-dark) { + // loading indicator + &:not([data-processed])::before { + @include loading; + } +} + :is(.mermaid, .mermaid-dark, .mermaid-neutral) { @include mermaid-base; }