📝 Comprehensive Summary: The Mermaid Renderer Saga
1. Timeline of Failures, Mistakes & The Final Fix
The diagram below illustrates the exact chronological order of how our configuration broken down, the technical blind spots we encountered, and the final "De-shelling" injection that fixed everything.
1 2 3 4 5 6 7 8
timeline title The Mermaid Troubleshooting Journey A "Initial State: The Broken Cloud" : Local Typora rendered perfectly <br> Online GitHub Pages showed a black PLAINTEXT box <br> Cause: Hexo server compiler stripped out the Mermaid syntax B "Local Fix Attempts" : Attempted switching Hexo renderers <br> Added exclude rules to _config.yml <br> Mistake: GitHub Actions ran `npm install` blindly, completely ignoring local configurations C "The Script Injection & Typora Fighting" : Tried injecting raw JavaScript into individual `.md` files <br> Fault: Typora's sensitive AST parser panicked at the sight of Javascript loops <br> Wrapped everything into ugly code-blocks locally D "The Silent Config Mistake" : Moved script to Theme `inject` setting <br> Fault: The lines were left commented out with `#` <br> Incorrect 5-space indentation also broken the YAML compilation E "The Cloud Squeeze Breakdown" : Un-commented the inject code <br> Result: A 'Syntax Error' bomb exploded online <br> Discovery: Hexo stripped all NEWLINE `\n` characters in the cloud, squeezing code into one flat line F "The Perfect Resolution" : Upgraded script to use regex auto-healing <br> Reconstructed missing line-breaks in browser <br> Removed the outer `figure.highlight` black shell completely
2. All Faults, Mistakes, and Technical Root Causes
During our multi-round battle, we unmasked four major architectural blind spots spanning from your local text editor up to the Linux server operating in the cloud.
❌ The Typora Illusion (WYSIWYG Defense Mechanism)
What Happened: When pasting raw <script> tags or functions like for (const block of codeBlocks) into the Markdown file, Typora automatically quarantined them inside ugly grey code blocks.
The Mistake: Believing it was an issue with the Markdown syntax itself.
The Root Cause: Typora is a What You See Is What You Get editor. Its internal parser aggressively monitors inputs. To prevent complex Javascript from crashing the live editor UI, it forcefully wraps unauthorized scripts in a display-only code shell.
❌ The GitHub Actions Desync
What Happened: Changing local plugins or adding exclude: ['mermaid'] into your root _config.yml yielded absolutely zero changes online.
The Root Cause: Your automated deployment pipeline utilizes GitHub Actions. Every time you pushed code, the remote Linux instance ran a fresh npm install. It re-downloaded a generic Hexo environment, totally wiping out your specialized local rendering environment.
❌ YAML Syntax & Comment Blunders
What Happened: Modifying the _config.butterfly.yml file to include inject-mermaid.js initially returned a 0-result match in the online HTML source code.
The Mistake: Forgetting to strip the # comment flag, combined with an arbitrary 5-space indentation.
The Root Cause: YAML is strictly hyper-sensitive to spacing. If indentation elements do not align exactly with their parent arrays, the compiler quietly ignores the entire branch without throwing an error message.
❌ The Cloud String-Squeeze (The "Syntax Error" Bomb)
What Happened: Once the script successfully injected, the diagram turned into a Syntax error in text (mermaid version 10.9.6) bomb icon.
The Root Cause: Hexo's online compiler optimization compressed multi-line code into a singular flat string to save packet weight. Because Mermaid's engine relies strictly on NEWLINE indicators to parse nodes, flat-lining the text caused the structural layout to instantly choke.
3. The Final Architecture (How We Fixed It)
We ultimately moved past battling the compiler and applied a client-side injection approach. By decoupling the content from the rendering logic, we achieved maximum stability.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
┌─────────────────────────────────┐ │ Your Local Typora (.md) │ ──► Pure, standard ```mermaid code blocks. └─────────────────────────────────┘ │ (git push) ▼ ┌─────────────────────────────────┐ │ GitHub Actions (Cloud) │ ──► Squeezes code into raw plaintext blocks. └─────────────────────────────────┘ │ (Deploys to Web) ▼ ┌─────────────────────────────────┐ │ User Browser (Execution) │ ──► The `inject-mermaid.js` script awakens: └─────────────────────────────────┘ 1. Intercepts the mangled plaintext block. 2. Auto-heals missing lines using regex. 3. Destroys Hexo's ugly black outer shell. 4. Draws a beautiful, 100%-wide canvas!
🏆 The Winning Code Sitting inside C:\Blogs\source\inject-mermaid.js:
document.addEventListener("DOMContentLoaded", asyncfunction() { const tag = ['p', 'r', 'e'].join(''); const codeBlocks = document.querySelectorAll(tag); let hasMermaid = false; for (const block of codeBlocks) { if (block.textContent.includes('graph TD') || block.className.includes('plaintext') || block.className.includes('mermaid')) { try { hasMermaid = true; // 1. Regex Auto-Healing for flattened cloud strings let rawCode = block.textContent; if (!rawCode.includes('\n') || rawCode.match(/\n/g).length < 3) { rawCode = rawCode .replace(/graph TD\s*/g, 'graph TD\n') .replace(/\s*([A-G](?=\[|\{))/g, '\n$1') .replace(/\s*([A-G]\s*-->)/g, '\n$1') .replace(/\s*(style\s+[A-G])/g, '\n$1'); }
// 2. Set up a clean, full-width container const container = document.createElement('div'); container.className = 'mermaid'; container.style.width = '100%'; container.style.margin = '24px 0'; container.style.background = 'transparent'; container.style.display = 'flex'; container.style.justifyContent = 'center'; container.textContent = rawCode; // 3. De-shelling: Find and rip out the outer Hexo black highlighters let targetElement = block; const figureShell = block.closest('figure.highlight'); if (figureShell) { targetElement = figureShell; } elseif (block.parentNode && block.parentNode.tagName === 'DIV') { targetElement = block.parentNode; } targetElement.parentNode.insertBefore(container, targetElement); targetElement.remove(); } catch(e) { console.error('De-shelling failed:', e); } } }
// 4. Fire up the rendering engine asynchronously if (hasMermaid) { const { default: mermaid } = awaitimport('[https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs](https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs)'); mermaid.initialize({ startOnLoad: false, theme: 'default', securityLevel: 'loose', flowchart: { useMaxWidth: false, htmlLabels: true } }); await mermaid.run(); } });
And, declare and enable it in the theme configuration file
The newer version of the Butterfly theme is very user-friendly. It provides a dedicated interface called inject, which allows you to insert custom scripts at the top or bottom of a webpage without modifying the underlying .pug or .html templates.
Open your _config.butterfly.yml (the theme configuration file), search for inject:, and then add the path to the file you just created under bottom: (the bottom of the page):
1 2 3 4 5 6 7
# Inject # Insert custom code in head on bottom inject: head: # - <link rel="stylesheet" href="/xxx.css"> bottom: -<scriptsrc="/inject-mermaid.js"></script># 👈 牢牢钉死这一行,让它成为线上网站的隐形守护者
In Hexo, the source/ folder serves as the website’s root directory mapping. Any files placed under source/ will be directly flattened to the top level of the website when it is generated.
Therefore, you only need to use the relative path (the virtual path recognized by the website).
The black background frame is still there: Hexo adds too many syntax-highlighting HTML wrappers around code blocks (such as tables with line numbers and nested code tags). Although our script successfully converted the innermost text into a diagram, it failed to completely strip away the heavy outer "black coat."
The diagram is too small: Its parent container is constraining it with a very rigid width or layout style.
Now that the core rendering is working correctly, let's move on to the final step: a complete cleanup and visual polish. We want the script not only to render diagrams, but also to behave like a perfectionist—removing the outer black frame and line numbers entirely, and enlarging the flowchart to 100% width so it fills the page!
🛠️ Ultimate Cleanup: Replace the Contents of inject-mermaid.js
Open your local file C:\Blogs\source\inject-mermaid.js again using EmEditor. Delete all existing content and replace it with the following ultimate version, which includes logic for perfect wrapper removal and adaptive scaling:
Now, your Markdown files remain completely standardized and free of hacky scripts, while the automated script safely corrects the structure directly inside the user's browser. Clean, scalable, and completely bulletproof!