深夜提醒

现在是深夜,建议您注意休息,不要熬夜哦~

🏮 🏮 🏮

新年快乐

祝君万事如意心想事成!

share-image
中
ESC

A Battle with Mermaid Diagrams: A Debugging Chronicle from Syntax Error to Successful Rendering

English 阅读中文版

The art of debugging: from Syntax error to successful rendering

Debugging is an art, and this time I nearly cooked myself into a “braised crayfish.”

Background

Today I wrote a technical analysis article about Apple’s chips, and I wanted to use Mermaid to draw a flowchart showing the architectural relationship between the A-series and M-series chips. The code was as follows:

graph TD
A[Apple in-house ARM architecture] --> B[A-series chips]
A --> C[M-series chips]

B --> B1[Design philosophy: mobile first]
B1 --> B2[Strength: unmatched single-core NPU efficiency]
B1 --> B3[Trade-off: memory bandwidth, multicore sustained output]

C --> C1[Design philosophy: desktop first]
C1 --> C2[Strength: powerful multicore GPU and I/O capability]
C1 --> C3[Trade-off: cost and die area]

B2 --> D[MacBook Neo core experience]
D --> D1[Scenario: web, office, media, light creation]
D --> D2[Ace in the hole: seamless local AI tasks and app ecosystem]
D --> D3[Foundation: deep macOS optimization]

But the moment the page rendered, it hit me with:

Syntax error in text
mermaid version 10.9.5

Me at that moment: ???

Round One: Assuming It Was a Syntax Problem

My first reaction was that I’d written the Mermaid syntax wrong. I checked for ages:

  • The arrows --> were fine
  • The node definitions A[text] were fine
  • The indentation was fine too

I pasted the code into the Mermaid Live Editor and tested it — it rendered perfectly!

That told me it wasn’t a syntax problem; it was a problem with the HTML structure after Hexo rendering.

Round Two: HTML Structure Problem

Looking at the page source, I found the Mermaid code block was rendered by highlight.js into this:

<code class="hljs mermaid">
graph TD<br>
A[苹果自研ARM架构] --&gt; B[A系列芯片]<br>
...
</code>

Found it!

  1. The <br> tags weren’t being handled correctly as line breaks
  2. --> was encoded as --&gt; (an HTML entity)
  3. There was also the double-encoding problem of &lt;br&gt;

Round Three: JavaScript Conversion Logic

My layout.ejs had a piece of JavaScript responsible for converting code blocks into the div that Mermaid can render:

function convertMermaidBlocks() {
var codeBlocks = document.querySelectorAll("code.hljs.mermaid");
codeBlocks.forEach(function(codeEl) {
var html = codeEl.innerHTML;
// Replace <br> with a line break
html = html.replace(/<br\s*\/?>/gi, "\n");
// Decode HTML entities
var tempDiv = document.createElement("div");
tempDiv.innerHTML = html;
var code = tempDiv.textContent || tempDiv.innerText;

// Create the mermaid div...
});
}

The logic looked fine to me? So why was it still erroring?

Round Four: Add Logs! Go Crazy Adding Logs!

I started adding console.log like crazy, and finally found the problem:

console.log("[Mermaid] Block 0 closest:", codeEl.closest(".mermaid"));
// Output: <code class="hljs mermaid" data-processed="true">

So this code element was already inside a .mermaid container!

That meant the code had already been processed once, but processed wrongly — it had stuffed the raw HTML with <br> directly into the .mermaid div, and then the Mermaid parser saw a string like graph TD<br/> and just blanked out.

Round Five: textContent vs. innerText

The core of the problem was: how do you correctly handle <br> tags in HTML?

I tried all sorts of things:

Method Result
innerHTML + replace No — because <br> might be &lt;br&gt;
textContent No — <br> gets treated as text
innerText Yes! Automatically turns <br> into a line break

But wait — I’d tried innerText in the old code, so why didn’t it work?

It turned out to be because of execution order! What I had before was this:

// Wrong order: replace first, then decode
html = html.replace(/<br\s*\/?>/gi, "\n"); // still &lt;br&gt; here, won't match
tempDiv.innerHTML = html;
var code = tempDiv.textContent; // after decode, <br> is still there

The correct order should be: decode first, then handle <br>, or just use innerText directly:

// Correct approach: use innerText directly
var code = (codeEl.innerText || "").trim();

innerText automatically handles all HTML tags — it turns <br> into a line break and &gt; into >.

The Final Solution

function convertMermaidBlocks() {
// First clean up already-corrupted .mermaid elements
document.querySelectorAll('.mermaid').forEach(function(el) {
if (el.textContent.includes('<br')) {
el.remove();
}
});

var mermaidCodes = document.querySelectorAll("code.hljs.mermaid");
mermaidCodes.forEach(function(codeEl) {
// Use innerText to automatically handle <br> as a line break
var code = (codeEl.innerText || "").trim();

// Validate that it's valid mermaid code
if (!/^(graph|flowchart|sequenceDiagram)/im.test(code)) {
return;
}

// Create the mermaid div
var mermaidDiv = document.createElement("div");
mermaidDiv.className = "mermaid";
mermaidDiv.textContent = code;

// Replace the container
var container = codeEl.closest("figure, pre");
if (container && container.parentNode) {
container.parentNode.replaceChild(mermaidDiv, container);
}
});
}

Key fixes:

  1. Use innerText to automatically handle <br> tags
  2. Clean up corrupted elements to avoid processing them twice
  3. Disable startOnLoad: false and call mermaid.run() manually

Debugging Takeaways

This debugging session lasted almost 2 hours and took countless wrong turns:

  1. Don’t assume the code’s execution order — the order of decoding and replacing matters
  2. Make good use of console.log — no logs is like driving blindfolded
  3. Understand the differences between browser APIs — innerText and textContent look similar but behave completely differently
  4. Clean up the scene — the bad data produced during debugging will interfere with later debugging

Finally, thanks to someone’s “braised crayfish” threat for keeping me from giving up on the treatment 😂

Reference Code

The complete Mermaid integration code is open-sourced — see the GitHub commit.

文章作者:阿文
文章链接: https://www.awen.me/post/8f7106c0.html
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 阿文的博客!
本文于 2026-03-06 20:00 发布,已超过半年(224天),请注意甄别内容是否已过期。

评论

0 条评论
😀😃😄 😁😅😂 🤣😊😇 🙂🙃😉 😌😍🥰 😘😗😙 😚😋😛 😝😜🤪 🤨🧐🤓 😎🥸🤩 🥳😏😒 😞😔😟 😕🙁☹️ 😣😖😫 😩🥺😢 😭😤😠 😡🤬🤯 😳🥵🥶 😱😨😰 😥😓🤗 🤔🤭🤫 🤥😶😐 😑😬🙄 😯😦😧 😮😲🥱 😴🤤😪 😵🤐🥴 🤢🤮🤧 😷🤒🤕 🤑🤠😈 👿👹👺 🤡💩👻 💀☠️👽 👾🤖🎃 😺😸😹 😻😼😽 🙀😿😾 👍👎👏 🙌👐🤲 🤝🤜🤛 ✌️🤞🤟 🤘👌🤏 👈👉👆 👇☝️✋ 🤚🖐️🖖 👋🤙💪 🦾🖕✍️ 🙏💅🤳 💯💢💥 💫💦💨 🕳️💣💬 👁️‍🗨️🗨️🗯️ 💭💤❤️ 🧡💛💚 💙💜🖤 🤍🤎💔 ❣️💕💞 💓💗💖 💘💝💟 ☮️✝️☪️ 🕉️☸️✡️ 🔯🕎☯️ ☦️🛐⛎ ♈♉♊ ♋♌♍ ♎♏♐ ♑♒♓ 🆔⚛️🉑 ☢️☣️📴 📳🈶🈚 🈸🈺🈷️ ✴️🆚💮 🉐㊙️㊗️ 🈴🈵🈹 🈲🅰️🅱️ 🆎🆑🅾️ 🆘❌⭕ 🛑⛔📛 🚫💯💢 ♨️🚷🚯 🚳🚱🔞 📵🚭❗ ❕❓❔ ‼️⁉️🔅 🔆〽️⚠️ 🚸🔱⚜️ 🔰♻️✅ 🈯💹❇️ ✳️❎🌐 💠Ⓜ️🌀 💤🏧🚾 ♿🅿️🈳 🈂🛂🛃 🛄🛅🛗 🚀🛸🚁 🚉🚆🚅 ✈️🛫🛬 🛩️💺🛰️
加载中...

留言反馈

😀😃😄 😁😅😂 🤣😊😇 🙂🙃😉 😌😍🥰 😘😗😙 😚😋😛 😝😜🤪 🤨🧐🤓 😎🥸🤩 🥳😏😒 😞😔😟 😕🙁☹️ 😣😖😫 😩🥺😢 😭😤😠 😡🤬🤯 😳🥵🥶 😱😨😰 😥😓🤗 🤔🤭🤫 🤥😶😐 😑😬🙄 😯😦😧 😮😲🥱 😴🤤😪 😵🤐🥴 🤢🤮🤧 😷🤒🤕 🤑🤠😈 👿👹👺 🤡💩👻 💀☠️👽 👾🤖🎃 😺😸😹 😻😼😽 🙀😿😾 👍👎👏 🙌👐🤲 🤝🤜🤛 ✌️🤞🤟 🤘👌🤏 👈👉👆 👇☝️✋ 🤚🖐️🖖 👋🤙💪 🦾🖕✍️ 🙏💅🤳 💯💢💥 💫💦💨 🕳️💣💬 👁️‍🗨️🗨️🗯️ 💭💤❤️ 🧡💛💚 💙💜🖤 🤍🤎💔 ❣️💕💞 💓💗💖 💘💝💟 ☮️✝️☪️ 🕉️☸️✡️ 🔯🕎☯️ ☦️🛐⛎ ♈♉♊ ♋♌♍ ♎♏♐ ♑♒♓ 🆔⚛️🉑 ☢️☣️📴 📳🈶🈚 🈸🈺🈷️ ✴️🆚💮 🉐㊙️㊗️ 🈴🈵🈹 🈲🅰️🅱️ 🆎🆑🅾️ 🆘❌⭕ 🛑⛔📛 🚫💯💢 ♨️🚷🚯 🚳🚱🔞 📵🚭❗ ❕❓❔ ‼️⁉️🔅 🔆〽️⚠️ 🚸🔱⚜️ 🔰♻️✅ 🈯💹❇️ ✳️❎🌐 💠Ⓜ️🌀 💤🏧🚾 ♿🅿️🈳 🈂🛂🛃 🛄🛅🛗 🚀🛸🚁 🚉🚆🚅 ✈️🛫🛬 🛩️💺🛰️