Mermaid 网页集成配置与渲染 API 使用指南:从 CDN 安装到 mermaid.run 全流程实战
【免费下载链接】mermaidGeneration of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown项目地址: https://gitcode.com/GitHub_Trending/me/mermaid
Mermaid 是一个基于 JavaScript、采用类 Markdown 语法渲染可定制图表(流程图、时序图等)的库——只要修改图表的文字描述,就能让图随之重新渲染。本文聚焦 docs/config/usage.md 这一使用指南,系统讲解如何把 Mermaid 安装并托管到自己的网页中,如何通过mermaid.initialize配置安全级别、如何用mermaid.run、mermaid.render、mermaid.parse等核心 API 完成从「拿到图定义文本」到「把 SVG 插入页面」的完整集成,并对照仓库源码给出实现层面的印证。
阅读本文后,你将能够:用一行 npm 命令或 CDN 脚本把 Mermaid 嵌入任意网页;根据业务场景正确选择securityLevel取值;在 SPA 或动态页面里精确控制图表渲染的时机与范围;利用mermaid.render把文本渲染结果(含交互事件绑定)接入自己的编辑器或内容管线。
先选路线:Live Editor、本地安装还是依赖部署
对于绝大多数初次接触的用户,使用官方提供的 Live Editor(所见即所得的在线编辑器)就足够了。不过当需要把图表能力内嵌到自己的站点或产品中时,就需要在下面两种路线中二选一:
- 把 Mermaid 作为 npm 依赖安装到自己的前端工程中,再在页面里渲染;
- 直接把浏览器版脚本(含 ESM 版本)托管到网页中,作为前端运行时库使用。
仓库还维护了一批由社区用户录制的视频教程,可以按需参考 docs/ecosystem/tutorials.md 中的列表;如果你是完全没有接入经验的入门读者,建议先阅读 docs/intro/getting-started.md 中的新手指南,它对本主题有更展开的讲解。
CDN 引入与版本选择
Mermaid 以 npm 包mermaid的形式发布,官方推荐通过 CDN 直接引用浏览器版产物。最常用的 CDN 是 jsDelivr 上维护的 npm 包镜像托管页——在该页面右上角的下拉框中,你可以自由切换想要使用的版本号(如需固定版本,可把 URL 中的版本号锁定为具体版本而不是用@latest之类浮动标签)。
通过 CDN 引用时,完整的浏览器 ES Module 产物地址形如:
<CDN_URL>/mermaid@<MERMAID_VERSION>/dist/mermaid.esm.min.mjs其中<CDN_URL>是所选 CDN 的基础域名,<MERMAID_VERSION>是你锁定的 Mermaid 版本号。后续示例统一用上述占位写法,实际使用时请替换成你选定的 CDN 域名与版本。
在网页中安装并托管 Mermaid
方式一:通过 npm 安装
Mermaid 官方仓库使用 pnpm workspace 管理多包,但作为用户,你可以用任何一种主流包管理器把它安装进自己的项目。安装的环境要求是Node.js >= 16。
# NPM npm install mermaid # Yarn yarn add mermaid # PNPM pnpm add mermaid安装完成后,Mermaid 的 ESM 构建产物会出现在依赖目录下的dist/中(dist/mermaid.esm.min.mjs、dist/mermaid.esm.mjs等),供打包工具或直接以type="module"脚本引用。
方式二:直接在 Web 页面托管
把 Mermaid 托管到一个 HTML 页面上,是接入成本最低的用法。按官方使用指南,只需要两个要素:
要素一:用class="mermaid"的<pre>标签包住图定义。Mermaid 在页面加载完成后会遍历 DOM,找到这些标签,读取其中的文本并按对应语法渲染成 SVG。
<pre class="mermaid"> graph LR A --- B B-->C[fa:fa-ban forbidden] B-->D(fa:fa-spinner); </pre>要素二:用<script type="module">的 ESM import 引入 mermaid 脚本。
<script type="module"> import mermaid from '<CDN_URL>/mermaid@<MERMAID_VERSION>/dist/mermaid.esm.min.mjs'; </script>按照以上两个步骤,Mermaid 会在页面加载完成后自动定位到所有class="mermaid"的<pre>标签,依据其中的图定义返回 SVG 形式的图表。
从源码层面看,这一自动行为在 packages/mermaid/src/mermaid.ts 中实现:模块加载时,如果环境中存在document与window,会注册window.addEventListener('load', contentLoaded, false)(对应源码约 L296-L301);contentLoaded检查mermaid.startOnLoad与配置中的startOnLoad,为真则调用mermaid.run()开始批量渲染。
一份可保存运行的最小完整示例
把下面的代码保存为 HTML 文件,用任意现代浏览器打开即可看到效果(请注意:不要在 Internet Explorer 中使用)。
<!doctype html> <html lang="en"> <body> <pre class="mermaid"> graph LR A --- B B-->C[fa:fa-ban forbidden] B-->D(fa:fa-spinner); </pre> <script type="module"> import mermaid from '<CDN_URL>/mermaid@<MERMAID_VERSION>/dist/mermaid.esm.min.mjs'; </script> </body> </html>注意事项
- 对没有设置
id的 mermaid 标签,Mermaid 会为它自动补一个id属性; - 同一个页面可以同时加载多个 Mermaid 图表;
- 被处理过的元素会被打上
data-processed标记,重复执行run时会跳过已处理的元素,因此同一个页面可以安全地多次触发渲染。
关于第二、三点,源码 packages/mermaid/src/mermaid.ts 中run/runThrowsErrors的实现给出了明确依据:遍历候选节点时先检查element.getAttribute('data-processed'),已处理则跳过,否则设置该标记并渲染(L175-L183);渲染前会通过dedent(utils.entityDecode(txt))去除缩进并解码 HTML 实体,再把结果.trim()后交给render(L186-L199),这正是图定义可以写在带缩进、带实体字符的<pre>里的原因。
更轻量的选择:Tiny Mermaid
如果只想要更小的包体积,官方仓库还提供体积约为完整库一半的简化版 Mermaid,位于 packages/tiny/README.md。精简版有以下能力取舍,接入前请先确认你的图表类型不受影响:
- 不支持Mindmap 图;
- 不支持Architecture(架构)图;
- 不支持KaTeX 数学公式渲染;
- 不支持懒加载(lazy loading)。
当你的页面只需要常规的流程图、时序图等能力,且对首屏体积敏感时,可以评估切换到 Tiny 版本。
开启节点点击与富文本标签:securityLevel 安全配置
Mermaid 解析自不可信文本时,默认会限制点击类交互功能。securityLevel自 8.2 版本引入,用于设定「解析出的图表可被信任的程度」,是防止恶意使用的一项重要安全改进。需要启用节点点击或标签 HTML 功能时,必须先调整该配置。
这里需要明确责任边界:判断自己的用户群体是否可信,是站点所有者(site owner)的责任,官方文档明确鼓励你谨慎行使这一判断权。
securityLevel参数一览:
| 参数 | 描述 | 类型 | 必填 | 取值 |
|---|---|---|---|---|
| securityLevel | 对解析图表的信任级别 | String | 否 | 'sandbox'、'strict'、'loose'、'antiscript' |
四种取值的行为差异:
strict(默认值):文本中的 HTML 标签会被编码,点击功能被禁用;antiscript:文本中的 HTML 标签被允许(仅移除<script>元素),点击功能被启用;loose:文本中的 HTML 标签被允许,点击功能被启用;sandbox:所有渲染发生在一个被沙箱化的 iframe 中,阻止任何 JavaScript 在页面上下文里运行。这会削弱图表的一些交互能力,例如脚本、时序图中的弹窗、跳转到其他标签页/目标的链接等。
需要注意,该配置改变了 Mermaid 在 8.2 之前的默认行为:升级到 8.2 之后,除非显式修改securityLevel,否则流程图中的标签会被当作标签文本编码展示、点击事件被禁用。另外sandbox级别仍处于 beta 阶段。
如果你对图源文本的安全性负责,可以把securityLevel设为你认为合适的值,从而允许点击与标签。
在 packages/mermaid/src/schemas/config.schema.yaml 的配置模式中,securityLevel的默认值被定义为strict,可枚举值为上述四种,与文档表格完全一致;同一 schema 中startOnLoad默认值为true(L248-L251),这印证了「默认页面加载即自动渲染」。
修改 securityLevel 的正确方式
修改securityLevel必须通过调用mermaid.initialize完成:
mermaid.initialize({ securityLevel: 'loose', });为什么要强调「通过initialize」?因为源码中有专门的secure 配置列表保护这一开关:见 packages/mermaid/src/schemas/config.schema.yaml,secure数组默认包含securityLevel、startOnLoad、maxTextSize、suppressErrorRendering、maxEdges等键。位于该列表中的配置项只能通过mermaid.initialize调用修改,图文本内的%%{init: {...}}%%指令无法覆盖它们——这能有效防止恶意图定义绕过站点的安全设置。
不同 securityLevel 在渲染管线中的落地
从渲染实现 packages/mermaid/src/mermaidAPI.ts 可以看到三种取值的具体代码路径:
sandbox:渲染前判断config.securityLevel === 'sandbox'(约 L503),若为真,则整个渲染发生在sandboxedIframe()创建的沙箱 iframe 中(sandbox属性为空字符串以阻止脚本执行,见 L424-L433),最终通过putIntoIFrame()把 SVG 序列化后以data:text/html;charset=UTF-8;base64的 iframe 形式返回(L367-L375)。loose:跳过 DOMPurify 清理,isLooseSecurityLevel为真时不执行 sanitize(L626-L633)。strict/antiscript等其余级别:SVG 序列化结果会经过DOMPurify.sanitize,其中放行了渲染流程必需的foreignobject标签与dominant-baseline属性(DOMPURIFY_TAGS/DOMPURIFY_ATTR,L69-L70)。
标签越界(Labels out of bounds)问题
如果你通过 CSS 动态加载字体(例如通过@font-face引入的字体文件),Mermaid 应当等待整个页面加载完成(DOM 与资源、尤其是字体文件都就绪)后再渲染。一个常见做法是把初始化放到 jQuery 的 ready 回调中:
$(document).ready(function () { mermaid.initialize(); });如果不这样做,渲染出来的图表很可能出现标签超出边界(labels out of bounds)的问题。Mermaid 的默认集成正是通过window.load事件才开始渲染的(见前文contentLoaded的注册逻辑),这是为了避免字体度量尚未就绪就进行文字排版。
如果页面 body 中存在其他字体,它们可能被错误地用来代替 Mermaid 指定的字体。此时在样式表中显式指定 mermaid 文本区域的字体族是一个有效的规避手段:
pre.mermaid { font-family: 'trebuchet ms', verdana, arial; }使用 mermaid.run 精确控制渲染(v10 起推荐)
mermaid.run是 v10 引入的 API,也是处理复杂集成的首选方式。
默认情况下,当文档就绪后mermaid.run会被自动调用,渲染所有带class="mermaid"的元素。如果你希望自己掌控调用时机,可以执行await mermaid.run(<config>)自定义其行为;执行mermaid.initialize({ startOnLoad: false })则能阻止mermaid.run在加载完成后被自动调用。
run的入参对象RunOptions在 packages/mermaid/src/mermaid.ts 的类型定义中有完整描述:querySelector默认".mermaid";nodes用于直接传入节点集合(设置了它则忽略querySelector);postRenderCallback在每张图渲染后被回调;suppressErrors为true时错误只记录到 console、不再抛出。
场景一:渲染所有匹配某个选择器的元素
mermaid.initialize({ startOnLoad: false }); await mermaid.run({ querySelector: '.someOtherClass', });场景二:渲染传入的节点数组
mermaid.initialize({ startOnLoad: false }); await mermaid.run({ nodes: [document.getElementById('someId'), document.getElementById('anotherId')], }); await mermaid.run({ nodes: document.querySelectorAll('.yetAnotherClass'), });nodes既可以是ArrayLike的普通数组,也可以直接传入querySelectorAll返回的NodeList,两种写法上方示例都已给出。
场景三:渲染全部.mermaid元素并抑制错误
mermaid.initialize({ startOnLoad: false }); await mermaid.run({ suppressErrors: true, });源码层面,run最终由runThrowsErrors执行:若同时缺少nodes与querySelector会直接抛出'Nodes and querySelector are both undefined';找到的节点数会被记录到 debug 日志(Found ${nodesToProcess.length} diagrams);每个图都会生成mermaid-${...}形式的唯一 id,id 是否稳定取决于deterministicIds与deterministicIDSeed配置(L168-L199)。因此,在异步加载内容后再调用run,Mermaid 不会重复渲染已经带data-processed标记的旧节点,这正是动态页面多次调用run的安全基础。
调用 mermaid.init(已废弃,勿用于新代码)
mermaid.init在 v10 中被标记为废弃,并将在未来的某个版本中移除,请改用mermaid.run。它目前保留仅用于兼容旧代码。
历史上,mermaid.init默认在文档就绪时被调用,查找所有带class="mermaid"的元素。如果你在 mermaid 加载完成之后又向页面追加了内容,或需要更细粒度的控制,可以自行调用init,其参数是:
- 一个配置对象;
- 若干节点,形式可以是:
- 单个节点(a node)
- 一个类数组的节点集合(array-like of nodes)
- 一个能定位到节点的 W3C 选择器(W3C selector)
示例:
mermaid.init({ noteMargin: 10 }, '.someOtherClass');或者不传配置对象、直接传 jQuery 选择结果:
mermaid.init(undefined, $('#someId .yetAnotherClass'));在源码中,init的实现(packages/mermaid/src/mermaid.ts)会先打印废弃警告,然后把配置透传给initialize,再根据nodes的不同形态构造RunOptions——字符串被解释为querySelector,单个HTMLElement被包装成单元素数组,其余按nodes传入run。可以看到它本质上已经是initialize + run的封装。
与 webpack 等打包工具配合
Mermaid 对 webpack 提供完整支持,你可以把mermaid作为依赖安装后,用import mermaid from 'mermaid'的方式在打包产物中按需引入。仓库内已包含 webpack 的可用演示示例,参考目录 tests/webpack 下的工程(含 tests/webpack/webpack.config.js 与示例入口),其结构与公开的 mermaid-webpack-demo 一致,适合作为脚手架参考。
API 用法:把渲染完全掌握在自己手里
Mermaid API 的核心思想是:把图定义文本作为字符串传给渲染函数,渲染函数把图渲染出来,并通过回调返回生成的 SVG 代码。在这种模式下,图定义从哪里来(比如取自页面某个<textarea>)、渲染结果插入到页面哪里,完全由站点开发者自己决定。
下面这个例子展示了最基础的用法——它只是把渲染得到的 SVG 输出到 JavaScript 控制台:
<script type="module"> import mermaid from './mermaid.esm.mjs'; mermaid.initialize({ startOnLoad: false }); // Example of using the render function const drawDiagram = async function () { element = document.querySelector('#graphDiv'); const graphDefinition = 'graph TB\na-->b'; const { svg } = await mermaid.render('graphDiv', graphDefinition); element.innerHTML = svg; }; await drawDiagram(); </script>值得说明的是,mermaid.initialize({ startOnLoad: false })在这里是必须的:它关闭自动渲染,避免页面加载时contentLoaded抢先触发run,从而保证只有你手动调用的渲染发生。
在 packages/mermaid/src/mermaid.ts 中可以看到render的排队实现:多次对render的调用会被推入内部executionQueue串行执行,以保证渲染顺序确定、互不干扰。render最终委托给mermaidAPI.render,其渲染主流程(见 packages/mermaid/src/mermaidAPI.ts)大致是:预处理文本并应用指令配置 → 校验maxTextSize上限(默认 50000 字符,超出则替换为提示错误图)→ 根据securityLevel决定常规渲染还是沙箱 iframe 渲染 →Diagram.fromText解析 → 注入主题/用户样式 → 调用具体图类型渲染器draw→ 序列化并(按级别)清理 SVG → 返回{ diagramType, svg, bindFunctions }。
用 detectType 判断图类型
给定一段文本,可以用mermaid.detectType判断它属于哪一类图。示例如下:
<script type="module"> import mermaid from './mermaid.esm.mjs'; const graphDefinition = `sequenceDiagram Pumbaa->>Timon:I ate like a pig. Timon->>Pumbaa:Pumbaa, you ARE a pig.`; try { const type = mermaid.detectType(graphDefinition); console.log(type); // 'sequence' } catch (error) { // UnknownDiagramError } </script>绑定交互事件(bindFunctions)
有时候生成的图还带有已定义的交互,例如 tooltip 与 click 事件。使用 API 渲染时,必须在图插入 DOM 之后再补绑这些事件。下面的示例代码摘自 mermaid 内部使用 API 时的处理流程,演示了渲染时如何取得并调用绑定函数:
// Example of using the bindFunctions const drawDiagram = async function () { element = document.querySelector('#graphDiv'); const graphDefinition = 'graph TB\na-->b'; const { svg, bindFunctions } = await mermaid.render('graphDiv', graphDefinition); element.innerHTML = svg; // This can also be written as `bindFunctions?.(element);` using the `?` shorthand. if (bindFunctions) { bindFunctions(element); } };完整流程分五步:
- 使用
render调用生成图; - 生成结束后,render 把结果交给你的回调(示例中即插入 SVG 的这段逻辑);
- 回调收到两个参数:生成的 SVG 代码,以及一个函数——该函数负责在 SVG被插入 DOM 之后绑定事件;
- 把 SVG 代码插入 DOM 进行展示;
- 调用绑定函数完成事件绑定。
顺序之所以重要,是因为点击、tooltip 这类交互需要依赖真实存在于文档中的 DOM 节点与事件委托关系。源码中render的返回值bindFunctions直接取自解析后数据库的diag.db.bindFunctions(packages/mermaid/src/mermaidAPI.ts),内部依赖interactionDb.attachFunctions(见 packages/mermaid/src/interactionDb.ts)将点击/链接处理挂接到对应 SVG 上。
与 marked 等 Markdown 渲染器集成
Mermaid 官方文档本身就是这样把 Markdown 渲染成带图表的 HTML 的——用一个自定义的 marked 渲染器,把以sequenceDiagram或graph开头的代码块改写成<pre class="mermaid">:
const renderer = new marked.Renderer(); renderer.code = function (code, language) { if (code.match(/^sequenceDiagram/) || code.match(/^graph/)) { return '<pre class="mermaid">' + code + '</pre>'; } else { return '<pre><code>' + code + '</code></pre>'; } };另一个 CoffeeScript 版本还演示了如何判断语言标签为mermaid,并只在首次出现时向生成的标记中注入一次 mermaid 脚本标签:
marked = require 'marked' module.exports = (options) -> hasMermaid = false renderer = new marked.Renderer() renderer.defaultCode = renderer.code renderer.code = (code, language) -> if language is 'mermaid' html = '' if not hasMermaid hasMermaid = true html += '<script src="'+options.mermaidPath+'"></script>' html + '<pre class="mermaid">'+code+'</pre>' else @defaultCode(code, language) renderer两种做法的共同点是:把图定义代码块转换为带有class="mermaid"的<pre>,之后交给 mermaid 自身的自动渲染(run)即可,无需针对每个代码块手动调用渲染函数。
高级用法:仅做语法校验而不渲染
mermaid.parse(text, parseOptions)用于在不渲染图表的前提下校验图定义语法。
- 传入一段文本字符串,如果定义符合 mermaid 语法,函数返回
{ diagramType: string }; - 如果定义非法,且
parseOptions.suppressErrors为true,则返回false;否则抛出错误; parseError函数会在parse抛错时被调用;当suppressErrors为true时不会被调用。你可以覆写它,以应用特定的错误处理方式。
从 packages/mermaid/src/mermaidAPI.ts 的实现看,parse会先注册所有图类型,再对文本做预处理与指令提取(processAndSetConfigs),然后Diagram.fromText完成真正的解析;捕获到错误时,若设置了suppressErrors则返回false,否则原样抛出。同时外层mermaid.parse(packages/mermaid/src/mermaid.ts)同样经过执行队列串行化,并把错误转发给mermaid.parseError。
下面的伪代码展示了「文本域内容变化 → 校验语法 → 合法才重新渲染」的典型实时校验场景:
mermaid.parseError = function (err, hash) { displayErrorInGui(err); }; const textFieldUpdated = async function () { const textStr = getTextFromFormField('code'); if (await mermaid.parse(textStr)) { reRender(textStr); } }; bindEventHandler('change', 'code', textFieldUpdated);这种模式非常适合构建「编辑器 + 实时预览」类产品:先廉价校验,语法通过再走完整的render渲染,避免无效文本触发无意义的渲染开销。
配置:把参数传给 mermaid.initialize
把所需的配置传给mermaid.initialize调用,是官方推荐的首选配置方式。完整的配置对象清单见 docs/config/setup/README.md(mermaidAPI 配置文档)。
<script type="module"> import mermaid from './mermaid.esm.mjs'; let config = { startOnLoad: true, htmlLabels: true, flowchart: { useMaxWidth: false } }; mermaid.initialize(config); </script>示例中出现了三种典型配置:startOnLoad控制页面加载后是否自动渲染;htmlLabels控制流程图等图表是否使用 HTML 标签;flowchart.useMaxWidth控制流程图是否按最大宽度缩放。你可以按需组合这些键。
initialize的源码实现见 packages/mermaid/src/mermaidAPI.ts:它会对用户配置做assignWithDepth深合并、把顶层fontFamily映射进themeVariables、依据theme选项合并对应主题变量,最终经configApi.setSiteConfig写入站点级配置并据此设置日志级别——因此它应该在任何渲染/解析动作之前调用。
已废弃的旧式配置写法
下面的方式已经废弃,仅因向后兼容而保留。它只支持两个参数,且应被initialize替代:
mermaid.startOnLoadmermaid.htmlLabels
mermaid.startOnLoad = true;在 packages/mermaid/src/mermaid.ts 的Mermaid对象上,startOnLoad仍作为可直接赋值的公开属性存在(默认值为true),contentLoaded正是读取它来决定是否在window.load后自动运行渲染;但这种做法官方不推荐用于新项目,请统一走initialize配置通道。
附:相关仓库资源速查
- 使用指南原始文档:docs/config/usage.md(源稿位于 packages/mermaid/src/docs/config/usage.md)
- 配置(API)完整文档:docs/config/setup/README.md
- 配置 schema 与默认值:packages/mermaid/src/schemas/config.schema.yaml
- 页面集成模块(
run/render/parse/initialize/init):packages/mermaid/src/mermaid.ts - 渲染管线与安全清理实现:packages/mermaid/src/mermaidAPI.ts
- 新手入门指南:docs/intro/getting-started.md
- 精简版(Tiny)说明:packages/tiny/README.md
【免费下载链接】mermaidGeneration of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown项目地址: https://gitcode.com/GitHub_Trending/me/mermaid
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考