本地离线编辑器:Mermaid 本地编辑器从零到可用的完整指南
【免费下载链接】mermaidGeneration of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown项目地址: https://gitcode.com/GitHub_Trending/me/mermaid
Mermaid Local Editor 是仓库自带的零依赖本地编辑器:左侧敲 Mermaid 源码,右侧立刻出 SVG,全程不需要外网。跑通本文的流程后,你能在断网的内网机器上托管并使用这套纯静态图编辑器,还能把它的三层渲染防护搬进自己的项目。
构建产物长什么样
官方对它的定位只有一句话(见 README.md):
Standalone local editor for Mermaid diagrams. Runs entirely from
dist/with no external dependencies.
构建完成后,成品落在packages/mermaid/dist/mermaid-local-editor/,目录构成很简单:
- 入口
index.html与styles.css; - 逻辑代码
app.js加js/下的 5 个模块(config、renderer、storage、ui、navigation); vendor/目录,里面是两个打包好的运行时:mermaid.min.js和purify.min.js(DOMPurify 净化库,一个用来过滤不可信 HTML 的库)。
这里的考虑是彻底自包含:index.html 只按相对路径引用本地样式表、两个 vendor 文件和app.js,没有任何一行指向外部 CDN。所以断网后它照样能渲染,整个目录拷到任意机器、挂上任意静态服务器即可运行。
本地编辑器离线构建:三条命令
先说明一个前置条件:根目录 package.json 要求 Node 版本不低于 22.12。
克隆仓库并进入目录:
git clone https://gitcode.com/GitHub_Trending/me/mermaid cd mermaid验证方式:目录里能看到
packages/mermaid-local-editor。安装依赖:
pnpm install验证方式:命令正常结束,没有报错输出。
执行完整构建链:
pnpm build:mermaid:full验证方式:终端输出 sirv 启动日志,提示服务监听 8081 端口。
第三条命令实际串联了 5 个步骤:clean(清空旧产物)、build:mermaid(编译 Mermaid 运行时)、copy:editor(拷贝编辑器源码)、copy:mermaid加copy:dompurify(把两个运行时 bundle 放进 vendor)、serve:dist(用 sirv 在 8081 端口托管产物)。浏览器打开 http://localhost:8081 就能看到编辑器界面:左侧源码输入区,右侧预览区默认渲染一张四节点流程图:
顶部工具栏有图表下拉框、名称输入框和 Save / New / Delete / Reset View / Export SVG 按钮。另外支持按方向键上下在节点间移动查看,焦点会带高亮;navigation.js 里的定位故意取 1/6 偏移而非严格居中,让 LR、TD 布局下的后续节点留在可视区内。
关键实现拆解
整条链路的核心逻辑集中在 static/js/ 目录,五个文件总量不过千行。下面挑三个信息量最大的点。
预览锁进不带脚本权限的沙箱
renderer.js 把净化后的 SVG 写进一个沙箱 iframe,再补一刀手工剥离:
iframe.sandbox = 'allow-same-origin'; // 只给同源,不给 allow-scripts svgEl.querySelectorAll('*').forEach((el) => { [...el.attributes].forEach((attr) => { if (attr.name.startsWith('on')) el.removeAttribute(attr.name); // 剥掉 on* 内联事件 }); });这里的考虑是把执行面彻底关死:即便图里藏了残余载荷,iframe 内也没有脚本环境,剥事件属性只是双保险。配合 config.js 里securityLevel: 'strict'的初始化,解析端、DOM 端、运行端各挡一道。代价是图内点击跳转、回调全部失效,需要节点交互时要到宿主页面处理。
净化白名单只放行两项
DOMPurify 的调用只加了两条放行规则:
const cleanSvg = DOMPurify.sanitize(svg, { ADD_TAGS: ['foreignObject'], // Mermaid 渲染文本的载体 ADD_ATTR: ['xmlns'], // SVG 命名空间声明 });默认白名单会剥掉foreignObject,节点文字直接消失,所以必须放行;放行这两项之后,其余潜在危险节点仍被清除。多一项都不加,攻击面保持在最小。
视图状态和源码存在同一条记录里
storage.js 在浏览器 localStorage 里用两个 key 管数据,每图的记录结构是{ src, view: { scale, panX, panY } }。首次访问若main图不存在,会自动补一条默认记录:
diagrams[current] = { src: `flowchart LR\n UI --> RuntimeBus --> Orchestrator --> Agents`, view: { scale: 1, panX: 0, panY: 0 }, };每次缩放、平移,app.js 里的applyTransform()都会把视图状态回写进这条记录。所以关掉浏览器再打开,还能从上次离开的位置继续看。代价也很直接:localStorage 按浏览器和 origin 隔离,换设备或清缓存,图就没了。输入侧的处理同样克制:ui.js 里每次击键立即渲染,但写存储延迟 300 毫秒,预览零延迟和存储写入频率就都顾到了。
和线上版的差异
本地编辑器保留了"输入即渲染"这条主链路,其余部分都做了裁剪:
| 对比项 | 线上版(mermaid.live) | 本地编辑器 |
|---|---|---|
| 网络要求 | 需联网访问 | 断网可用,纯静态托管 |
| 图数据存放 | 云端账号 | 浏览器 localStorage |
| 节点点击交互 | 支持链接跳转 | 沙箱禁用 |
| 多人协作 | 支持 | 无 |
为此放弃的是账号、云同步和协作能力,换来的是整条渲染链路只发生在本机浏览器。对"图内容不能离机"的合规场景来说,这笔交换是成立的。
出问题时先查这里
| 症状 | 先查什么 | 处理办法 |
|---|---|---|
| 8081 端口被占用,服务起不来 | 端口是否被别的进程占用 | 在本地克隆里改 package.json 中serve:dist的端口号 |
| 换电脑或清完缓存后图全没了 | localStorage 按浏览器与 origin 隔离,不跨环境 | 提前用 Export SVG 留档,或从 DevTools 复制mermaid-diagrams这个 key 的 JSON |
| 右侧预览区出现红色文字 | 这是mermaid.render抛错被捕获后原样展示,不是页面故障 | 按报错信息修正左侧语法 |
换个项目也能用
这套编辑器里有两个做法可以直接搬。第一个发生在构建期:不追求单文件 bundle,而是把运行时和净化库以静态文件拷进产物的 vendor 目录,HTML 只写相对路径。产物目录天然自包含,拷到任何静态服务器都能跑,适合"离线分发"优先于"产物体积"的内网工具。第二个发生在运行时:把渲染用户输入的高危动作串成固定流水线,渲染、净化、隔离三层各管一段,任何一层失效都不致命。所以它才敢完全离线、不做服务端校验。
动手任务:照这条流水线写一个 50 行左右的单页页面,用本地静态服务器打开,验证断网环境下用户输入的高危内容被完整拦下。
核心代码都在 packages/mermaid-local-editor/static/js/ 目录,五个文件加起来不过千行,逐行读一遍就能复刻整套防护思路。构建链路的细节则收录在 README.md 的 Build Pipeline 一节。
【免费下载链接】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),仅供参考