恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
diagram-design:用 JSON 配置打造统一风格的 Mermaid 图表工作流
首页
资讯中心
/
diagram-design:用 JSON 配置打造统一风格的 Mermaid 图表工作流
diagram-design:用 JSON 配置打造统一风格的 Mermaid 图表工作流
发布时间:2026/9/9 12:23:54
做技术写作这几年我越来越觉得“图示”是文档里最容易被低估的部分。代码写得再清晰架构图一塌糊涂读者理解成本依然很高。我平时写博客、做技术分享、整理项目文档最常用的就是 Mermaid语法简单、渲染快也不用装一堆绘图软件。但用久了就发现一个问题Mermaid 默认样式实在太“素”了配色、字体、间距都不太可控生成出来的图放在博客里总觉得差了点质感。于是就有了 diagram-design 这个小项目。简单说它是一套基于 Mermaid 之上的图表设计工作流先用 JSON 描述图表的结构和样式再自动生成 Mermaid 语法最后通过命令行工具批量渲染成统一风格的 SVG/PNG。核心目标是解决“Mermaid 能画图但画不出符合个人审美的图”这个痛点。这篇文章我会把这个项目的设计思路、核心实现、渲染流水线到自动化集成全部拆开讲清楚适合正在折腾 Mermaid、想搭建个人图表设计方案的开发者参考。1. 项目整体设计与核心思路1.1 为什么不做渲染引擎而是包一层配置层刚开始我其实纠结过要不要自己写一个基于 Canvas/SVG 的渲染引擎后来仔细想了一下这个方向太重了。Mermaid 已经解决了最难的部分语法解析、布局计算、箭头路径生成这些都是非常复杂的算法问题自己从头造轮子光是节点自动布局就够写几个月的。而我的真实需求只是“在保持 Mermaid 便利性的前提下把样式和排版变得更可控”。所以我确定了一条核心设计原则不重写渲染引擎做 Mermaid 之上的可视化配置层。项目的输入是一份 JSON 配置输出是一段经过优化的 Mermaid 语法和最终的图片文件。JSON 配置负责描述图表类型、节点内容、分组关系、样式主题、颜色映射Mermaid 只负责把这段语法变成 SVG。这样分工的好处很明显语法解析和布局算法的复杂性问题全部交给 Mermaid 社区解决我只需要专注于样式生成和自动化流程把有限的精力放在真正影响出图质量的部分。在设计配置层的接口时我参考了 D3 的数据驱动思路数据与样式分离。配置里用data字段描述图表的业务内容用theme字段描述视觉外观。这样同一个数据切换不同的主题就能生成不同风格的图非常适合“一套架构图白天版和夜间版”这样的场景。实际使用时只需要改一行配置不用动任何一个数据节点整个图中所有颜色都会自动切换。1.2 技术栈选型的取舍过程技术栈的选择我前后调整过三轮。最初想用纯 JavaScript 写依赖少、上手快但项目做到后面发现要维护的类型越来越多节点配置、主题配置、图表产物都有复杂的结构约束没有类型系统真的很痛苦。后来换成了 TypeScript类型定义不仅是给编译器看的更像是给配置接口做的“隐形式文档”团队协作或者自己几个月后回来看代码都能快速搞清楚某个字段到底能填什么值。构建工具方面我用的是 tsup因为它的零配置体验确实好默认就能同时输出 ESM 和 CJS对 Node.js 双格式兼容非常友好。打包成 CLI 工具后用npm link在你的全局环境中挂载一下就能随时在任意目录执行diagram-design命令不需要繁琐的路径配置。渲染流程上我做了两级方案本地场景用 Mermaid CLI 直接渲染 SVG速度极快需要高保真 PNG 或者复杂样式时用 Playwright 驱动浏览器无头渲染。为什么要两套方案而不是一套走到底因为 Mermaid CLI 的 Puppeteer 依赖有时会因为网络原因安装失败国内环境下载 Chromium 经常超时而 Playwright 的浏览器管理更稳定下载失败时可以自动重试。两个方案互补能应对不同的使用场景。2. 核心细节解析与关键技术实现2.1 可视化配置 DSL 的设计diagram-design 的入口是一个 JSON 配置文件我用它替代直接手写 Mermaid 语法。原因是 Mermaid 语法虽然简单但一旦图表复杂起来——节点多了、关系乱了、案例多了——文本形式的语法在维护上的劣势就暴露了改了 A 节点忘了改 B 节点的关联或者想批量把某个模块的颜色统一换掉手写语法要一个个去改非常容易漏。配置结构我设计成了这样{ type: flowchart, direction: LR, data: { nodes: [用户请求, 网关层, 服务发现, 配置中心], links: [ [用户请求, 网关层], [网关层, 服务发现] ] }, theme: { primary: #4F46E5, secondary: #10B981, background: #FFFFFF, fontFamily: Inter, PingFang SC, Microsoft YaHei } }type字段决定图表类型data字段是纯粹的图表内容theme字段是视觉样式。还有第五个字段options用于控制一些特殊行为比如流程图是否开启紧凑模式、时序图的消息字体大小等。这个设计的核心思路是把结构structure和样式style彻底分开结构字段描述“画什么”样式字段描述“画成什么样”互不干扰。JSON 配置生成之后真正执行的流程是配置读取 → 语法生成 → 语法校验 → 渲染。语法校验非常重要我在这上面踩过很深的坑。Mermaid 的语法错误提示有时候相当隐晦少一个分号或者某个特殊字符没有转义报错信息根本指向不到正确位置。所以我写了一个预校验层在把语法交给 Mermaid 渲染之前先自己检查一遍语法的基本结构方括号、圆括号、分号是否匹配节点 ID 是否合法箭头符号是否被正确解析。2.2 从 JSON 配置到 Mermaid 语法的生成逻辑语法生成层是项目中最核心的模块。流程图为例最简单的转换逻辑是遍历data.links数组把每个链接转成A -- B的形式。但真实场景比这个复杂得多节点可能需要分组、需要添加自定义样式、需要设置不同的形状。我的生成器支持了三种节点类型的映射默认矩形节点A[节点文本]、圆角节点A(节点文本)和圆形节点A((节点文本))。这个设计其实来自于我总结的实际需求主流程节点用矩形子流程入口用圆角关键判断节点用圆形视觉上就能区分不同语义不用额外加注释。样式的注入是另一层逻辑。Mermaid 的classDef机制允许你给一类节点定义一个样式类然后在节点上引用。我的生成逻辑会扫描data.nodes中的节点分组信息假设有两个分组核心模块橙色系和基础设施蓝色系那么就会生成类似这样的代码classDef coreModule fill:#F59E0B,stroke:#B45309,color:#FFFFFF; classDef infraModule fill:#3B82F6,stroke:#1D4ED8,color:#FFFFFF; node1[用户请求]:::coreModule;这里有个细节值得说一下Mermaid 的 classDef 中填充色fill、边框色stroke、文字颜色color三个属性必须同时出现才能确保样式不被覆盖。我在实际测试中发现Mermaid 的默认主题在某些情况下会覆盖掉只设置了部分属性的 classDef特别是文字颜色不显式指定的话在深色背景下会变得几乎不可读。所以生成器在输出样式代码时一定会强制补全这三维属性。2.3 数据处理与高级语法特性项目还实现了几个“手写 Mermaid 时非常痛苦”的高级特性。第一个是子图subgraph的自动归属。手写子图语法时子图名不能有中文但显示名可以用中文这个靠subgraph sg1[核心服务]这样的语法解决。我封装成配置字段后是这样的{ subgraphs: { sg1: { label: 核心服务, nodes: [服务发现, 配置中心] } } }生成器会先输出子图的声明再把属于该子图的节点全部放进去最后输出子图中的内部连线。这个逻辑听起来简单但实现时要注意子图中的节点 ID 不能和其他子图重复否则渲染时会莫名奇妙地合并子图但不报任何错误。第二个是自定义链接样式。流程图里经常需要强调某些关键链路比如异常处理路径用红色虚线正常路径用蓝色实线。Mermaid 的语法是A -.- B表示虚线A B表示粗线。我的配置里可以直接指定某个链路的样式级别normal、bold、dotted、thick生成器根据级别自动映射到不同的 Mermaid 箭头符号。这个特性在我画灾难恢复流程图、降级链路图时特别有用关键路径一眼就能看出来。第三个是 HTML 标签的转义处理。节点文本里如果包含、、这样的特殊字符直接拼进 Mermaid 语法里会导致渲染异常。生成器会对这些字符做 HTML 实体转义这算是从实际问题中逼出来的功能。第一次用 diagram-design 画一个包含“用户输入 1000ms 时正常响应”的节点时整个图渲染失败定位了半天才发现是小于号的问题。3. 渲染流水线与图形输出的完整实现这段是整个项目里“技术含量最密集”的部分——配置和语法生成只是做好菜怎么把菜端上桌、摆盘好看完全是另一套功夫。3.1 渲染主流程解析渲染模块的工作流程是输入 Mermaid 语法文本 → 选择渲染引擎 → 输出目标格式文件 → 按配置做后处理。整个流程用流程图来理解就是JSON 配置 -- Mermaid 语法字符串 -- Mermaid CLI/Playwright 渲染 -- SVG 文件 -- Sharp 后处理 -- PNG 文件为什么中间产物一定要是 SVG而不是直接渲染成 PNG因为 SVG 是矢量格式可以无损缩放到任意尺寸方便后期嵌入到网页或文档里。而且 SVG 的结构可编程控制我想在后续版本里做“自动给节点加编号”、“自动加背景网格”这些功能时直接操作 SVG 的 DOM 结构就能实现。PNG 则适合放在没有矢量渲染能力的场景比如微信聊天记录、某些内部 Wiki 系统。3.2 Mermaid CLI 参数选择的实战经验Mermaid CLI 的命令行参数我踩过的坑比想象中多。首先是-b参数背景色默认是白色但我在浅色模式下设置透明背景时发现一个问题SVG 文件确实变成透明了但打开 PNG 时还是会看到白色底。原因是 SVG 的background-color属性被显式设置为white透明背景只对 SVG 自身有效。解决方案是渲染完成后用 Sharp 库把白色像素替换成透明这一步在后处理模块里处理。其次是-s缩放倍数。Mermaid CLI 的默认缩放是 1但如果你要输出高清图片建议设置为 2 或者 3。设置缩放倍数后生成的 SVG 尺寸会按倍数放大但内部的字体、线条宽度也会等比放大。实际操作时我一般用-s 2既能保证清晰度又不会让文件体积膨胀得太离谱。如果追求极致清晰可以输出 SVG 后自己用工具转高清 PNG那个效果比单纯加大-s好得多。还有一个值得注意的参数是-w最大宽度。这个参数的作用是控制输出图片的最大宽度当图表比较宽的时候Mermaid 会压缩整体宽度。但如果你已经用 JSON 配置控制了图表的节点数量和排版方向一般不需要设置这个参数让它按布局算法自然输出就行。我用得最多的命令组合是这样的mmdc -i input.mmd -o output.svg -b transparent -s 2 -f -p puppeteer-config.json-f参数是启用“流程图安全模式”它会禁用流程图中的某些潜在危险功能比如 HTML 标签解析但这会让某些自定义样式失效所以我在项目里默认不开启。-p参数指定 Puppeteer 的配置文件里面可以设置浏览器路径和启动参数。3.3 高保真 PNG 渲染的方案Playwright 无头浏览器当 Mermaid CLI 解决不了问题时我引入了 Playwright 作为第二种渲染方案。核心思路是用 Playwright 打开一个本地 HTML 页面页面里加载 Mermaid 的 JavaScript 库再把 Mermaid 语法传给mermaid.render()方法渲染完成后通过document.querySelector(svg)拿到 SVG 字符串最后用 Sharp 转成 PNG。具体实现分四个步骤第一步启动无头浏览器实例第二步通过page.setContent()加载嵌入了 Mermaid 库的 HTML 页面第三步调用page.evaluate()在浏览器环境中执行渲染脚本获取 SVG 代码第四步把 SVG 代码写入临时文件再用 Sharp 处理成目标格式。import { chromium } from playwright; const renderSVGWithPlaywright async (mermaidCode, theme default) { const browser await chromium.launch(); const page await browser.newPage(); await page.setContent( html headscript srchttps://cdn.jsdelivr.net/npm/mermaid10/dist/mermaid.min.js/script/head bodypre iddiagram${mermaidCode}/pre/body /html ); await page.evaluate(async () { await mermaid.initialize({ startOnLoad: false, theme: ${theme} }); }); const result await page.evaluate(async () { const { svg } await mermaid.render(diagram-svg, document.getElementById(diagram).textContent); return svg; }); await browser.close(); return result; };这个方案的优点是渲染质量和浏览器保持一致——Mermaid CLI 本质上也是用 Puppeteer 驱动浏览器渲染但 Playwright 的多浏览器支持更好。缺点是需要额外安装 Playwright 依赖配置较重。我对接 Dark 主题时用的是 Mermaid 内置的theme参数比如theme: dark但自定义主题就要通过themeVariables传入这个后面讲样式时细说。4. 样式美化、主题系统与多场景适配有了能干活的渲染引擎接下来就是“好不好看”的问题了。这一节聊我是怎么把默认样式处理成有设计感的图。4.1 颜色系统的统一管理与生成逻辑写样式代码容易陷入一个误区直接写死颜色值。这样短期看很方便但改主题时就要在几十个 classDef 里反复替换效率极低。diagram-design 在项目里定义了一套颜色 token 系统——类似设计系统里的 Design Token。我们把颜色抽象成几个语义化变量primary主色、secondary辅助色、accent强调色、bgDefault默认背景色、textDefault默认文字色。但这里有一个很实际的问题Mermaid 的 classDef 里需要的是具体颜色值它不认识primary这种变量。所以生成器要做一次计算转换。我用了一个轻量级颜色处理库来处理亮度、对比度计算比如根据主色自动计算 hover 态的加深色import Color from color; const getDerivedColors (primary) { const base Color(primary); return { primaryLight: base.lighten(0.2).hex(), primaryDark: base.darken(0.2).hex(), primaryAlpha: base.alpha(0.15).hex(), }; };lighten()方法是通过 HSL 空间的亮度计算生成的比手动调 HEX 字符串靠谱得多。这样定义的好处是你只需要给一个主色其他相关的浅色、深色、半透明色都由程序生成最大的优势是“一套代码任何颜色都能用”完全不需要手动配十几二十个氛围色。4.2 字体渲染的坑与新方案中文文档的项目最大的痛点是Mermaid 默认字体是 Trebuchet MS、Verdana 这种西文字体一旦节点里有中文就会 fallback 到系统默认中文字体在 SVG/PNG 渲染时经常出现中英文混排错位、文字被截断的问题。解决字体问题的关键是配置fontFamily而且要配置好 fallback 顺序。我最终用的是--font-family: Inter, PingFang SC, Hiragino Sans GB, Microsoft YaHei, sans-serif;这个顺序的意思是英文首先用 Inter干净的几何风格字体中文依次回退到 PingFang SCmacOS 系统字体、Hiragino Sans GBmacOS 日语字体包含的中文、微软雅黑Windows 系统字体最后兜底到系统默认 sans-serif。另外一个容易忽略的点是Mermaid CLI 在服务器端渲染时服务器上未必安装了 PC 上那些字体。之前我在服务器跑渲染出来的 PNG 中文全部变成“豆腐块”排查半天才发现服务器没有中文字体后来在 Docker 镜像里加装fonts-noto-cjk才解决。这个问题如果你在本地开发可能完全感知不到但跑 CI/CD 流水线时非常致命。所以要么保证渲染环境有目标字体要么先在 SVG 阶段把所有文字转为矢量路径。后者我用过一段时间的方案是每张图先生成 SVG 再调用字体转轮廓工具处理效果最稳定但速度慢一些。后续我还发现了第二套可用方案用 WeasyPrint 代替浏览器渲染。WeasyPrint 是一个 HTML/CSS 渲染引擎对字体渲染的支持比 Chromium 好很多在 Linux 环境下尤其稳中文渲染效果清晰锐利。它没有浏览器那么重的依赖只需要安装 Python 包和几个系统字体库就能用。我现在项目里对质量要求高的图首选 WeasyPrint 方案。4.3 暗黑模式与主题适配dark mode 是一张图的“第二张脸”。Mermaid 默认支持的主题里有neutral、dark、forest但实际效果比较粗糙尤其是节点里的文字在暗色背景下容易和边框混淆而且整个图的对比度偏低。我的方案是先定义一套全局语义色板然后按主题模式切换整套色板。比如{ light: { bg: #FFFFFF, text: #1F2937, nodeFill: #F3F4F6, line: #6B7280 }, dark: { bg: #111827, text: #F9FAFB, nodeFill: #1F2937, line: #9CA3AF } }生成时根据theme.mode字段选择对应色板动态生成 Mermaid 的themeVariables。其中比较关键的一个变量是lineColor决定图表的连线颜色另一个是nodeBorder决定节点边框暗黑模式下要降低亮度让节点的轮廓在深色背景上还保持明显。在做一个技术分享的暗黑版系统架构图时我把主色调调成紫蓝色#818CF8配合深灰蓝背景生成的图整体质感比 Mermaid 默认的 “dark” 主题好非常多。看图的人都不用我解释就能感受到两版图的视觉高度差异。5. 从流程图到复杂图表的全场景实践这块是项目最具“纵深感”的部分——流程图只是最基础的一类图。真实文档里要画的图远不止这些类图、时序图、饼图、甘特图各有各的语法和样式控制方式。5.1 类图的定制实现类图是面向对象设计的常用表达方式。Mermaid 的类图语法中用class关键字声明类表示 public-表示 private。但直接写语法中的一个痛点是类名、属性名、方法名一旦多了代码会非常难维护。diagram-design 里我把类图也抽象成 JSON 配置{ type: class, classes: [ { name: UserService, members: [ { name: findById, type: User, visibility: , static: true } ] } ] }生成器根据配置决定属性和方法的顺序输出标准的 Mermaid 类图语法。样式方面类图支持对背景色、边框色的自定义我就把服务类的底色设成暖色系表示业务逻辑领域模型类设成冷色系表示数据结构读者一眼能看清分层。5.2 时序图的脚本化生成时序图在 Mermaid 里是最容易写乱的图。最麻烦的是参与者顺序和消息类型的管理。参与者每增加一个后面所有消息的上下顺序都要跟着调整非常容易出错。我封装成了配置形式后只要定义参与者列表和消息列表生成器会自动维护顺序和参与者声明{ type: sequence, participants: [客户端, 网关, 订单服务], messages: [ [客户端, 网关, 创建订单, solid], [网关, 订单服务, 生成订单号, dotted] ] }生成器会按消息顺序动态确定哪些参与者需要提前声明避免 “actor 未定义” 的渲染报错。时序图的样式定制点主要是消息字体大小和激活条颜色激活条是 Mermaid 时序图中表示方法调用占用的色条颜色选得合适能显著提升图的层级感。5.3 饼图与甘特图项目里还实现了饼图和甘特图的支持。甘特图其实是个硬件挑战项目里有个内部周报需求需要每周生成一张“本周任务进度甘特图”任务有十几项每项的起止时间每周都在变。手动调 Mermaid 甘特图语法最崩溃的是日期计算某个任务要延期三天就得手动改dateFormat和-或的偏移量改错一次图就全乱了。我封装了数据接口之后只要在配置里按 ISO 格式给出任务的startDate和endDate字段程序会自动计算工期并转成 Mermaid 甘特图的内置语法。如果某个任务延期只改endDate一个字段重新生成就完事了。这个功能极大解放了手动绘图的工作量也是后来项目被团队里其他人“借用”最多的一个能力。6. 自动化流水线与 CI/CD 集成图做出来了但真正提升效率的是把整套流程自动化。我期望的效果是以后写文档时只需要维护 JSON 配置提交代码后 GitHub Actions 自动跑渲染把生成的图片回传到仓库。这样人只需要关注内容和结构不可能再去纠结图片的样式细节。6.1 本地脚本化的便捷一键生成最先实现的是本地 CLI。项目的scripts/generate.mjs是打包后的入口只要传入配置文件路径就自动执行“解析 → 生成 → 渲染 → 输出”流程。核心脚本逻辑#!/usr/bin/env node import { generateDiagram } from ../src/index.js; const configPath process.argv[2]; if (!configPath) { console.error(用法: diagram-design config.json); process.exit(1); } generateDiagram(configPath);这个脚本里我特意加了一个目录检查逻辑目标输出目录不存在时自动创建并提示。这个细节看上去微不足道但实际用起来很关键。因为配置文件和输出目录如果不在同一个目录遇到“output/images 不存在”的情况之前每次都要手动mkdir -p很烦。6.2 GitHub Actions 自动渲染CI 流水线的价值体现在团队协作时任何成员提交新的 JSON 配置流水线自动渲染成最新图片确保文档的配图永远和代码同步。我的 Actions 工作流用了一个简单可靠的结构name: generate-diagrams on: push: paths: - diagrams/** jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - uses: actions/setup-nodev3 with: node-version: 18 - name: Install dependencies run: npm ci - name: Generate diagrams run: node scripts/generate-all.mjs - name: Commit changes run: | git config user.name github-actions[bot] git config user.email 41898282github-actions[bot]users.noreply.github.com git add docs/img git commit -m docs: regenerate diagrams git push这里有一个我在试跑时反复踩的坑如果渲染环境的PUPPETEER_SKIP_DOWNLOAD环境变量被设置Puppeteer 就不会下载 Chromium 内核导致渲染直接失败。在 GitHub Actions 上有些基础镜像默认包含这个变量所以要显式地在工作流中删掉或覆盖它env: PUPPETEER_SKIP_DOWNLOAD: false还有一个细节由于自动 commit 会触发新的 workflow 运行需要在提交信息上加上[skip ci]或者配置 Actions 不在github-actions[bot]提交时触发匹配的路径。我两种都加了避免无限循环。6.3 性能优化与缓存策略渲染的瓶颈通常出现在批量生成多张图的时候。项目里generate-all.mjs会遍历diagrams/目录下所有 JSON 配置文件挨个渲染。最直接的问题是每张图都要启动一次浏览器链路开销很大。我做的优化是让 Playwright 的浏览器实例在整个批量任务中只启动一次渲染完所有图再关闭成本从“每张图启动一次”降为“整个流程只启动一次”。大批量出图的场景下这个优化能缩短接近一倍的耗时。7. 常见问题与实战排查实战过程中积攒了一批“Mermaid/命令行工具会隐瞒你”的问题这一块专门做个梳理方便大家遇到类似报错时有地方可查。问题现象根本原因解决方案渲染时报Syntax error in text节点文本含特殊字符未转义生成器强制对//做 HTML 实体转义图片中文全部变“豆腐块”渲染环境缺中文字体安装fonts-noto-cjk或 SVG 阶段转轮廓背景设了透明仍出现白底SVG 自带background-colorwhite用 Sharp 做白色像素替换为透明DNS 解析失败导致mmdc装不上Puppeteer 下载 Chromium 超时设置镜像源或改用 Playwright 管理浏览器自动提交触发无限 Actionscommit 行为又匹配了同一触发路径提交信息加[skip ci]某条链路样式没生效classDef 未定义到具体节点检查引用部分是否漏掉了:::语法GitHub Actions 里渲染直接退出PUPPETEER_SKIP_DOWNLOAD 误设工作流中显式设回false7.1 语法生成层最常见的坑我遇到频次最高的一个问题是节点 ID 含有中文。Mermaid 对节点 ID 的规则是“允许中文 ID”但后续引用时容易出现问题尤其是在子图内部引入外部节点时。后来我强制要求“节点 ID 必须是英文/数字/下划线”显示名称用[中文文本]来注入。这个习惯坚持下来之后基本再也没遇到过中文 ID 导致的诡异渲染失败。另一个高频坑是 Mermaid 新老版本的语法差异。Mermaid 10 以后有一些老版本里的写法被标记弃用了比如graph TD在新版本中只是兼容保留推荐使用更明确的写法。如果你的环境装的是 v9有些配置在 v10 里渲染结果可能完全不同。项目里我会在配置文件里加一个mermaidVersion字段锁定渲染用的 Mermaid 版本避免升级带来的不确定性。7.2 渲染引擎选择的经验总结到目前这个阶段我的经验判断是图表简单、追求速度时优先用 Mermaid CLI图表复杂、需要自定义样式精细调整时优先用 Playwright 控制浏览器渲染服务器环境或对中文排版有极致要求时用 WeasyPrint。三者之间不是替代关系而是互相补充。项目里我把渲染引擎抽象成了一个可配置项命令行加--engine cli/playwright/weasyprint就能切换十分灵活。8. 后续扩展与最终心得diagram-design 这个项目的核心价值不在于它重新发明了图表渲染技术而在于它把“画图”这个行为从“零散的手工操作”变成了“统一的工程流程”。通过一个配置层把图表的内容、样式、输出格式、自动化流程全部标准化。现在写文档遇到需要插图的需求我不再面临开启画图软件、手动对齐节点、调整样式的漫长流程而是通过修改 JSON 和重新运行命令交付一套风格统一的图。这个项目后续的扩展方向我在实践中也想到不少。第一是引入预制模板库把不同的配色方案、排版风格封装成可直接引用的 npm 包使用者在配置里直接用template: corp-tech就能应用一整套风格体系。第二是增加“导出 React/Vue 组件”的支持把渲染结果封装成前端组件配合mermaidnpm 库直接在前端项目里动态渲染。第三是增加“语法检查”的在线服务让配置在提交前就能在浏览器里实时预览效果而不是等 CI 跑了半天才发现语法有问题降低试错的成本。最后分享一个实际使用心得。这个项目开发的初衷是解决“我自己画图丑”的问题但开发完成后意外收获是它把我从前种种对图表设计的模糊偏好转变成了明确的工程规范。比如什么样的图用圆角节点什么时候需要给节点分组重点链路如何突出表示。现在团队里其他人画图也会拿我的 JSON 配置当模板改一改就用了。好的工具不一定需要找到一个足够复杂的值得去解决的技术问题能把一件每天都在做的小事变得顺手又省心就已经很有价值了。