Astro 集成 Mermaid:解决 Shiki 高亮导致的渲染失效
Astro
Astro Mermaid 表现
在 Astro 项目中配置 Mermaid 客户端渲染时,常遇到一种情况:脚本加载正常且无报错,但页面上的代码块依然显示为纯文本,无法转化为图表。

根本原因
Mermaid 官方脚本默认寻找类名为 .mermaid 的节点进行转换。然而,Astro 默认集成的 Shiki 高亮引擎在处理 Markdown 时,会生成一层自定义的外壳。
其真实的 DOM 结构类似于: <pre class="astro-code..." data-language="mermaid">
由于节点上没有 .mermaid 类名,原生的 Mermaid 初始化逻辑直接脱靶,导致渲染流程在寻址阶段就中断了。
2. 解决方案
既然 Shiki 的结构不可控,我们就改用属性选择器 data-language="mermaid" 锁定节点。在脚本中手动提取纯文本代码,并销毁 Shiki 渲染的原始节点,替换为 Mermaid 能识别的标准容器。
3. 最终可执行脚本
在全局布局文件(如 src/layouts/BaseLayout.astro)的 </body> 闭合标签上方注入以下代码。这里使用了 is:inline 指令,确保脚本绕过 Astro 的本地打包流程。
<script type="module" is:inline>
// 1. 初始化,禁用自动加载
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: false, theme: 'default' });
// 2. 锁定 Shiki 生成的特定 pre 节点
const mermaidNodes = document.querySelectorAll('pre[data-language="mermaid"]');
if (mermaidNodes.length > 0) {
mermaidNodes.forEach((preNode) => {
// 提取代码块内的纯文本逻辑
const codeNode = preNode.querySelector('code');
const rawCode = codeNode ? codeNode.textContent : preNode.textContent;
// 动态创建标准的 Mermaid 渲染容器
const div = document.createElement('div');
div.className = 'mermaid';
div.style.display = 'flex';
div.style.justifyContent = 'center';
div.style.margin = '2rem 0';
div.textContent = rawCode;
// 用新生成的 div 物理替换原始的 pre 节点
preNode.replaceWith(div);
});
// 3. 手动触发渲染引擎
mermaid.run();
}
</script>
这种处理方式避开了繁琐的高亮配置修改,直接在 DOM 层解决了 Shiki 与 Mermaid 的渲染冲突问题。
修复后:
