[Hexo] 解決 Mermaid 無法正確在 shoka 主題顯示的問題

Les Lee
一個小小工程師的隨手筆記
4 min readJan 6, 2023

Mermaid 作為 markdown 的流程圖繪製解決方案大大增加了 markdown 的實用性。

對於繪圖苦手的我來說 Mermaid 簡直是一大救星。

因此在開始自己搭建 hexo 部落格之後,我第一件事也是確認 Mermaid 是否可用。

後來選上 shoka 這套主題不單是它漂亮的佈景,還有豐富的內建 markdwon 語法支援。其中當然包括了今天的主角 Mermaid

在一切搭建都接近完成後,我依依確認功能是否完備時發現 Mermaid 無法正確顯示流程圖。無論怎麼修改 _config.yml 的配置,其永遠都是死死地顯示純文字的格式。

```mermaid 
graph LR
A[Square Rect] - Link text → B((Circle))
A → C(Round Rect)
B → D{Rhombus}
C → D
```
```mermaid
sequenceDiagram
loop Daily query
Alice->>Bob: Hello Bob, how are you?
alt is sick
Bob->>Alice: Not so good :(
else is well
Bob->>Alice: Feeling fresh like a daisy
end
opt Extra response
Bob->>Alice: Thanks for asking
end
end
```

爬了很久的文,找了很多文章。

一開始以為應該是 dependency 不正確,或是 css style 沒有載入之類的。

嘗試了諸多方法依然無解。

偏偏官方文檔完全沒有多加說明。

就在窮盡所有方法之後,決定去爬 mode_modules 中的 source code

(就乖乖的 console.log 看看吧!)

幸好這個 Plugin 的 code 不長,很快就定位到了實際運作的位置

md.renderer.rules.fence = (tokens, idx, options, env, self) => {
const token = tokens[idx]
const code = token.content.trim()
if (token.info === 'mermaid') {
var firstLine = code.split(/\n/)[0].trim()
if (firstLine.match(/^graph (?:TB|BT|RL|LR|TD);?$/)) {
firstLine = ' graph'
} else {
firstLine = ''
}
return mermaidChart(code, config, firstLine)
}
return defaultRenderer(tokens, idx, options, env, self)
}

經過各種的 console.log 之後,終於發現原因!

原因在於 markdown-it 在針對文章 parse token 時,將 marmaid 的 token.info 定義為 mermaid2 。因此 if condition 一定比對失敗。

知道了問題點就好辦了,接下來我只需要決定如何修理即可。

有兩種我比較喜歡的修改方式:

  • if (token.info === ‘mermaid’) 改成 if (token.info === ‘mermaid2’) ,未來在用的時候統一使用 mermaid2
  • if (token.info === ‘mermaid’) 改成 if (token.info.includes(‘mermaid’)) ,未來只要 type 有關鍵字 mermaid 即可自動 parse 出 graph。 我也不用管是 mermaid 或是 mermaid2

最終我選擇了第二種方案。

這兩種方案其實殊途同歸,唯一的問題在於未來在重新佈局時一定要記得手動修改 node_modules 裡的這段 code.

我目前已經將部落格文章都轉移至「專屬的部落格(https://z20240.github.io/)」這邊也依然會同步更新。不嫌棄的話也歡迎來看看吧~

--

--

Les Lee
一個小小工程師的隨手筆記

對新事物總是興緻勃勃、嘗試新技術、解決新挑戰; 也時常陷入許多無謂的思索,卡在其中得不出答案。