☰
Mermaid源码排版规则
2026/9/27 22:58:50 网站建设 项目流程

适配 flowchart / sequenceDiagram / classDiagram / erDiagram,优先流程图(最常用)

1. 行预处理

  1. 每一行先trimEnd(),移除行尾空格
  2. 跳过空行压缩:连续多个空行 → 只保留最多1个空行
  3. 识别行类型:
    • 图表声明行:flowchart TD/graph LR/sequenceDiagram→直接顶格输出,重置缩进
    • 块开始:subgraph xxx/alt/loop/par→ 当前缩进输出本行,缩进+1
    • 块结束:end→缩进-1,再输出本行(end和块关键字同级)
    • 注释行:%% xxx→ 跟随当前缩进,原样保留注释内容
    • 连线/语句:A-->B、style A fill:#ccc、classDef→ 当前缩进输出,并且自动给连线两侧补空格:A-->B→A --> B

2. 连线空白规则

(重点美化)匹配正则:/(\s*)([A-Za-z0-9_\-]+)(\s*)(--[>-]|-.->|==>)(\s*)([^;]+)/

  • 箭头运算符:-->,-.->,==>,---两侧强制加单个空格
  • ❗ 标签内字符串["hello --> world"]内部不替换,需要跳过引号包裹区域(难点)

3. 缩进规则分图表类型

✅ flowchart / graph
flowchart TD A --> B subgraph Group B --> C C --> D end D --> E
  • subgraph:本行按当前缩进,之后层级+1
  • end:层级先-1,再打印 end
  • 节点连线、style、classDef:使用当前层级缩进
✅ sequenceDiagram
sequenceDiagram participant U as User participant S as Server loop 循环 U->>S: 请求 S-->>U: 返回 end
  • participant/actor:永远顶格,不受缩进影响
  • loop/alt/opt/par:块开启,缩进+1;end 回退缩进
✅ classDiagram
classDiagram class User { +String name +login() }
  • class X {:当前缩进,遇到{缩进+1
  • }:缩进-1,输出}

4. 注释处理(非常影响可读性)

  • %%单行注释:跟随当前缩进,原样保留内容
  • 不移动注释位置:注释属于当前行,不会漂移到别的节点旁边

限制:不支持多行注释%% ... \n ... %%,Mermaid原生也很少用

边界 case(必须做判断,否则会破坏图表)

  1. 引号内文本跳过:A["Hello --> World"],里面的-->不要替换空格!

    实现小技巧:Lexer 扫描时维护inQuote标记,碰到"切换开关,引号内部不做箭头正则替换。

  2. 多行标签:A["line1\nline2"],内部换行保持原样。
  3. 单行多连线A-->B B-->C:可选配置项「是否强制拆分成多行」,建议默认不拆分(避免破坏用户意图)。
  4. 非法语法容错:遇到无法识别的行,原样输出,不报错,不要直接中断格式化。
  5. 特殊字符# , : |在标签内,不做任何修改。

极简可运行 JS Demo

(流程图格式化核心,可嵌入编辑器按钮点击事件)

仅演示 flowChart,可扩展其他图表

functionformatMermaid(source){constlines=source.split(/\r?\n/);letindentLevel=0;constindent=" ";constresult=[];letinQuote=false;functionformatArrow(line){// 简单替换箭头,跳过引号内部letout="";for(leti=0;i<line.length;i++){constc=line[i];if(c==='"')inQuote=!inQuote;out+=c;if(!inQuote){out=out.replace(/(-->|-.->|==>|---)/g," $1 ");}}// 清理多余连续空格out=out.replace(/\s+/g," ").trim();returnout;}for(constrawLineoflines){constline=rawLine.trim();if(line===""){result.push("");continue;}// 图表声明行if(/^(flowchart|graph|sequenceDiagram|classDiagram|erDiagram)/.test(line)){indentLevel=0;result.push(line);continue;}// end 块结束,先减缩进if(/^end\b/.test(line)){indentLevel=Math.max(0,indentLevel-1);result.push(indent.repeat(indentLevel)+line);continue;}// subgraph / loop / alt 块开始if(/^(subgraph|loop|alt|opt|par)\b/.test(line)){constformatted=formatArrow(line);result.push(indent.repeat(indentLevel)+formatted);indentLevel++;continue;}// 注释行if(/^%%/.test(line)){result.push(indent.repeat(indentLevel)+line);continue;}// 普通连线、style、classDefconstformatted=formatArrow(line);result.push(indent.repeat(indentLevel)+formatted);}// 合并空行,连续空行只保留1个returnresult.join("\n").replace(/\n\s*\n+/g,"\n\n");}

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询