跳到內容

Mermaid 圖表

建構器透過兩階段處理支援 Mermaid 圖表:remark 外掛在建構時準備標記,客戶端渲染器則產生 SVG。

remark-mermaid 外掛(由 docs-theme npm 套件提供)在 Astro 建構期間執行。它使用 unist-util-visit 尋找 lang === 'mermaid' 的圍欄程式碼區塊,並將其替換為 HTML:

visit(tree, 'code', (node, index, parent) => {
if (node.lang !== 'mermaid' || index === undefined || !parent) return;
const escaped = node.value
.replace(/&/g, '&')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;');
parent.children[index] = {
type: 'html',
value: `<div class="mermaid-container" data-mermaid-src="${escaped}">
<pre class="mermaid">${node.value}</pre>
</div>`,
};
});

關鍵細節:

方面
匹配的節點類型lang === 'mermaid'code 節點
HTML 實體跳脫&<>" — 防止 data-mermaid-src 中的屬性注入
輸出結構<div class="mermaid-container"> 搭配 data-mermaid-src 屬性存放跳脫後的原始碼
備用內容<pre class="mermaid"> 搭配原始原始碼(在 JS 渲染前可見)

src/scripts/placeholder-dom.ts 中的 renderMermaidDiagrams() 函式負責在瀏覽器中產生 SVG。

Mermaid 從 CDN 按需載入——並非打包在內:

const mermaid = (await import('https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs')).default;
mermaid.initialize({
startOnLoad: false,
theme: 'default',
securityLevel: 'loose',
themeVariables: {
primaryColor: '#ffffff',
primaryBorderColor: '#cccccc',
background: '#ffffff',
mainBkg: '#ffffff',
secondBkg: '#ffffff',
tertiaryColor: '#ffffff',
},
});

startOnLoad: false 防止 Mermaid 自動掃描頁面。securityLevel: 'loose' 允許圖表中的點擊事件和連結。

對於每個 .mermaid-container 元素:

  1. data-mermaid-src 讀取原始圖表原始碼
  2. 對原始碼執行佔位符替換(見下方)
  3. 清除容器並移除任何 data-processed 屬性
  4. 呼叫 mermaid.render() 使用隨機 ID 產生 SVG
  5. 在渲染的 <svg> 元素上設定 backgroundColor: 'white'

在渲染之前,圖表原始碼會通過 DOM 遍歷器使用的相同 substituteText() 函式進行處理(遍歷器機制請參閱佔位符系統):

const template = container.getAttribute('data-mermaid-src') || '';
const substituted = substituteText(template, values);

這意味著像 xCUSTOMER_ASNx 這樣的佔位符符記可以在 Mermaid 圖表定義中使用。當使用者在表單中更改值時,placeholder-change 事件會觸發所有圖表使用更新後的值進行完整重新渲染。

如果 mermaid.render() 拋出錯誤(例如,因為圖表原始碼中的語法錯誤),catch 區塊會直接在容器中顯示錯誤:

} catch (e) {
container.textContent = `Diagram error: ${e}`;
}

這使得撰寫錯誤可見,而不會破壞頁面的其餘部分。

圖表在兩種情況下會重新渲染:

觸發條件事件發生什麼
佔位符值變更placeholder-changehandleChange() 使用新值呼叫 renderMermaidDiagrams()
Astro 頁面導航astro:page-loadinit() 為新頁面呼叫 renderMermaidDiagrams()

使用 mermaid 語言標籤撰寫標準的圍欄程式碼區塊:

```mermaid
flowchart LR
A[Customer ASN: xCUSTOMER_ASNx] --> B[F5 XC ASN: xF5_XC_ASNx]
```

remark 外掛在建構時將其轉換為容器 div。客戶端會將其渲染為替換了佔位符值的 SVG。