工作原理
这个包出现的原因很直接:原始 Mermaid HTML 只解决了第一段工作,真正的文档站还需要挂载 重渲染 导出 缩放 全屏 与路由切换后的生命周期控制
它解决了什么
markdown-it 只负责把 fence 变成 HTML,不负责浏览器状态,不负责路由切换后的再初始化,也不会自带工具栏
markdown-it-mermaid-enhanced 把这部分工作拆成两段
- markdown-it 插件把 Mermaid fence 改写成面向运行时的 wrapper
- 浏览器运行时把 wrapper 升级成可交互的图表壳层
渲染管线
Loading diagram…
主包架构
Loading diagram…
这样拆分之后,编译期 HTML 生成 浏览器交互 共享配置 与 VitePress 接入边界会更清晰
工作流程图
Loading diagram…
关键边界在于 markdown-it 侧只负责序列化状态,运行时侧才负责异步渲染与交互状态
插件实际输出了什么
每张图都会变成一层 wrapper,核心元素有三块
- 隐藏的
<pre>,负责保留原始 Mermaid 源码 data-mermaid-config,负责携带解析后的配置- 默认工具栏,负责缩放 复制 导出 与全屏
这套结构的意义在于原地重渲染,而不是整块替换 DOM
运行时模型
浏览器运行时会按需把 wrapper 升级成 Vue 应用
initMermaidIt()查找未挂载 wrapper,并只挂载一次rerenderMermaidIt()重新读取 wrapper 状态,再原地刷新- 缩放状态与 wrapper 绑在一起,所以纯配置刷新时可以保住当前视口
运行时设计图
Loading diagram…
每个 wrapper 都会保留一份很小的运行时状态,这样重渲染时可以原地替换 SVG,而不是销毁整个宿主节点
为什么路由切换需要额外处理
单页文档框架切换页面时不会重载整个浏览器环境,所以新的 wrapper 需要在路由切换后重新发现并挂载
VitePress helper 的工作就是等待 DOM 更新 重试 wrapper 发现 然后再执行挂载
关键源码
src/markdown-it/plugin.ts负责 fence 解析与 wrapper HTMLsrc/runtime.ts负责公开运行时入口src/runtime/MermaidWrapperRuntime.vue负责交互壳层src/runtime/core.ts负责渲染 导出 SVG 挂载 与缩放控制src/vitepress.ts负责把运行时接入 VitePress 路由