Mermaid setSiteConfig():站点级配置(siteConfig)机制源码解析
2026/9/7 19:15:21 网站建设 项目流程

Mermaid setSiteConfig():站点级配置(siteConfig)机制源码解析

【免费下载链接】mermaidGeneration of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown项目地址: https://gitcode.com/GitHub_Trending/me/mermaid

本文基于 Mermaid 官方 API 文档 setSiteConfig.md,结合 packages/mermaid/src/config.ts 的源码实现,完整讲解 Mermaid 的 defaultConfig → siteConfig → currentConfig 三级配置模型、setSiteConfig的深合并与主题解析逻辑、secure安全边界,以及initialize/reset/updateSiteConfig等配套 API 的协作方式。读完你可以正确完成站点级全局配置、理解为什么图作者通过指令无法改写某些配置项,并在自定义渲染行为时定位到具体源码。

一、setSiteConfig() 在 Mermaid 配置体系中的位置

官方文档对setSiteConfig的定义如下(该页为 TypeDoc 自动生成的 API 参考,源文件位于仓库内packages/mermaid/src/docs/config/setup/config/functions/setSiteConfig.md,文档中标注 "DO NOT EDIT"):

setSiteConfig(conf): MermaidConfigSets thesiteConfigto the desired values. ThesiteConfigis a protected configuration for repeat use. Calls to reset will reset thecurrentConfigtositeConfig. Defined in: packages/mermaid/src/config.ts:64 参数 conf(MermaidConfig):The config to use assiteConfig. This will be merged with thedefaultConfig. 返回值(MermaidConfig):The new siteConfig。

要理解这个函数,先要看清 Mermaid 的配置分层。Configuration 文档 说明 Mermaid 启动时从以下来源提取配置:

  • defaultConfig:内置默认值;
  • siteConfig:由站点集成方通过initialize调用设置的站点级覆盖,作用于该站点/应用中的所有图表;
  • Frontmatter(v10.5.0+):图作者可以在图文件顶部的 YAML 块中覆盖选定的配置参数(除 secure 配置外);
  • Directives(已被 Frontmatter 取代):图作者通过图代码中的指令直接更新选定配置参数。

最终用于渲染的配置称为render config,即上述各层合并后的结果。8.6.0 变更文档 则给出了经典的三级模型表述:

配置层级说明
Global ConfigurationMermaid 的默认配置
Site Configuration由站点所有者(site owner)设置
Current Configuration由实现者/图作者(implementor)设置

源码中的对应模块状态见 config.ts#L19-L22:

let siteConfig: MermaidConfig = assignWithDepth({}, defaultConfig); let configFromInitialize: MermaidConfig; let directives: MermaidConfig[] = []; let currentConfig: MermaidConfig = assignWithDepth({}, defaultConfig);

siteConfigcurrentConfig都起始于defaultConfig的深拷贝(defaultConfig本身被Object.freeze冻结,见 config.ts#L8),而siteConfig每次变更都会触发currentConfig的刷新——这正是setSiteConfig的核心职责。

二、setSiteConfig() 的签名、参数与返回值

项目内容
签名setSiteConfig(conf: MermaidConfig): MermaidConfig
参数conf要用作siteConfig的配置,会与defaultConfig做深合并
返回值新的siteConfig完整对象(默认值 + conf + 解析后的主题变量)
定义位置packages/mermaid/src/config.ts#L64
文档入口docs/config/setup/config/functions/setSiteConfig.md,配置函数索引见 docs/config/setup/config/README.md

结合文档语义与源码,有三点必须强调:

  1. 是"重建"而非"叠加":每次调用都从defaultConfig出发重新构建siteConfig,因此conf相对默认值是"全量声明",而不是在上一次siteConfig上打补丁。需要增量合并时应改用updateSiteConfig(见第六节)。
  2. 返回值是完整配置对象,可直接用于后续判断或断言,而不是只返回增量部分。
  3. 立即同步渲染配置:函数末尾的updateCurrentConfig(siteConfig, directives)保证调用后当前渲染配置即刻生效,无需等待下一张图渲染。

三、setSiteConfig 源码逐步拆解

完整实现见 config.ts#L64-L76:

export const setSiteConfig = (conf: MermaidConfig): MermaidConfig => { siteConfig = assignWithDepth({}, defaultConfig); siteConfig = assignWithDepth(siteConfig, conf); if (conf.theme && theme[conf.theme]) { siteConfig.themeVariables = theme[conf.theme].getThemeVariables(conf.themeVariables); } updateCurrentConfig(siteConfig, directives); return siteConfig; };

逐行解析:

  1. siteConfig = assignWithDepth({}, defaultConfig):深拷贝全局默认值。因为defaultConfig是冻结对象,必须拷贝后才能安全修改,且保证多次调用互不污染。
  2. siteConfig = assignWithDepth(siteConfig, conf):把用户传入的conf深合并进默认值——这就是官方文档所说 "This will be merged with the defaultConfig"。注意合并语义中"类型不同互不覆盖"(详见第四节)。
  3. 主题解析:若conf.theme是已注册的主题名,则调用该主题的getThemeVariables(conf.themeVariables)生成完整的themeVariables并写回siteConfig。这就是"只传主题名加少量变量覆盖,其余颜色体系自动补齐"的实现原理。
  4. updateCurrentConfig(siteConfig, directives):以新siteConfig叠加当前累积的 directives 刷新currentConfig,最后返回siteConfig

currentConfig 的刷新管线:updateCurrentConfig

刷新逻辑在 config.ts#L24-L53:

const updateCurrentConfig = (siteCfg: MermaidConfig, _directives: MermaidConfig[]) => { // start with config being the siteConfig let cfg: MermaidConfig = assignWithDepth({}, siteCfg); // Join directives let sumOfDirectives: MermaidConfig = {}; for (const d of _directives) { sanitize(d); sumOfDirectives = assignWithDepth(sumOfDirectives, d); } cfg = assignWithDepth(cfg, sumOfDirectives); if (sumOfDirectives.theme && sumOfDirectives.theme in theme) { // ...以 theme 为基准重算 themeVariables } currentConfig = cfg; checkConfig(currentConfig); return currentConfig; };

三个关键点:

  • 每条 directive 合并前先经过sanitize(d)处理——这是安全边界的执行点(见第五节);
  • 当合并结果包含有效theme时,以该主题为基准重算themeVariables(config.ts#L39-L48),因此指令只需声明"主题名 + 要覆盖的变量";
  • 最后执行checkConfig(config.ts#L217-L225),对弃用选项发出警告,例如设置了lazyLoadedDiagrams/loadExternalDiagramsAtStartup时会提示改用registerExternalDiagrams

四、setSiteConfig 背后的深合并工具:assignWithDepth

setSiteConfig的合并行为完全由assignWithDepth决定,其实现见 packages/mermaid/src/assignWithDepth.ts,语义如下:

  • 任意深度递归合并:对src中每个键递归执行合并;目标对象缺失该键时先自动初始化为{}再合并,不会因键缺失报错;
  • 类型不同互不覆盖(dissimilar types will not clobber):例如dst.foo{bar: 'bar'}src.foo是字符串'foo',结果为{bar: 'bar'}。普通Object.assign会直接用'foo'覆盖对象结构,assignWithDepth则保留原对象,避免误传标量把默认配置结构打碎;
  • 数组语义src是数组而dst不是数组时,逐个元素依次合并;两者都是数组时做去重并集;
  • 支持depth参数控制递归深度(默认 2)。

在 8.6.0 变更文档 中,assignWithDepth也被列为该版本的关键新特性,并被明确描述为"类似Object.assign但带深度的对象合并机制",上述图片即展示了两种合并方式的差异示例。

五、安全边界:secure 数组与 sanitize

siteConfig是"受保护"的站点级配置,它同时是下层配置的安全边界定义者。sanitize(config.ts#L131-L166)在每条 directive 并入currentConfig之前被调用,做三类防护:

  1. secure 键保护:遍历['secure', ...(siteConfig.secure ?? [])],若指令携带其中任一键,记录日志并就地删除——这正是图作者无法通过%%{init}%%指令抬高站点securityLevel等原因;
  2. 原型污染防护:删除所有以__开头的键;
  3. XSS 防护:删除包含<>url(data:的字符串值,因为 base64 的 data URL 可以内嵌含内联脚本的 SVG。

需要精确区分的是:传入setSiteConfigconf来自可信的站点所有者,不会被sanitize;被清洗的是渲染管线中的每条 directive。

secure的默认值定义在配置 Schema 中(packages/mermaid/src/schemas/config.schema.yaml#L259-L276):

secure: description: | This option controls which currentConfig keys are considered secure and can only be changed via call to mermaid.initialize. This prevents malicious graph directives from overriding a site's default security. default: - 'secure' - 'securityLevel' - 'startOnLoad' - 'maxTextSize' - 'suppressErrorRendering' - 'maxEdges'

8.6.0 变更文档 用"套娃"比喻解释了规则:全局 secure 数组不可变,站点所有者只能通过initialize追加(如initialize({ secure: ['secure', 'securityLevel', 'parameter1'] })),实现者(图作者)则完全不能修改该数组。注意 8.6.0 文档中的默认列表(['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'])是早期快照,当前仓库 Schema 还包含suppressErrorRenderingmaxEdges,以当前 Schema 为准。

测试 packages/mermaid/src/config.spec.ts#L19-L38 精确验证了这条边界:setSiteConfigfontSize追加进 secure 后,再通过addDirective尝试修改fontSizesecurityLevel,断言getConfig()返回的仍是站点值,而fontFamily这类非 secure 项则正常生效。

六、公共入口:mermaid.initialize()

站点集成方通常不直接调用setSiteConfig,而是经由initialize(packages/mermaid/src/mermaidAPI.ts#L663-L690):

function initialize(userOptions: MermaidConfig = {}) { const options: MermaidConfig = assignWithDepth({}, userOptions); // 兼容旧版:顶层 fontFamily 迁移到 themeVariables.fontFamily if (options?.fontFamily && !options.themeVariables?.fontFamily) { options.themeVariables = { ...options.themeVariables, fontFamily: options.fontFamily, }; } // 记录 initialize 的原始输入 configApi.saveConfigFromInitialize(options); if (options?.theme && options.theme in theme) { options.themeVariables = theme[options.theme].getThemeVariables(options.themeVariables); } else if (options) { options.themeVariables = theme.default.getThemeVariables(options.themeVariables); } const config = typeof options === 'object' ? configApi.setSiteConfig(options) : configApi.getSiteConfig(); setLogLevel(config.logLevel); addDiagrams(); }

要点:

  • 官方文档明确 initialize只应调用一次("The initialize call is applied only once"),它通过saveConfigFromInitialize先保存用户输入(供 getUserDefinedConfig 后续读取),再调用setSiteConfig(options)建立siteConfig
  • 顶层fontFamily属于旧版配置位置,会被自动迁移进themeVariables.fontFamily
  • 主题解析在initializesetSiteConfig中各有一次(逻辑一致),最后设置日志级别并注册内置图表。

一个典型的站点级用法:

import mermaid from 'mermaid'; mermaid.initialize({ startOnLoad: false, theme: 'forest', themeVariables: { primaryColor: '#00ff00' }, fontFamily: 'monospace', secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize', 'maxEdges', 'suppressErrorRendering'], flowchart: { curve: 'basis' }, });

与之对照,图作者(implementor)只能覆盖非 secure 项,Configuration 文档 给出的 frontmatter 示例:

--- title: Hello Title config: theme: base themeVariables: primaryColor: "#00ff00" --- flowchart Hello --> World

frontmatter 中"整份配置除 secure 项外均可覆盖"的边界,正是第五节sanitize机制在解析层的体现。

七、配套 API 全家福:reset / getSiteConfig / updateSiteConfig / setConfig

config.ts 围绕siteConfig暴露的一组 API(官方索引见 docs/config/setup/config/README.md):

API行为源码位置
setSiteConfig(conf)以 默认值 + conf 重建 siteConfig,并刷新 currentConfigL64-L76
updateSiteConfig(conf)在当前 siteConfig 上增量合并 conf 后刷新 currentConfigL82-L87
getSiteConfig()返回 siteConfig 的深拷贝L94-L96
reset(config = siteConfig)清空 directives,把 currentConfig 重置为给定配置(默认 siteConfig)L194-L198
setConfig(conf)已废弃(@deprecated):只更新 currentConfig,且会被下一次addDirective/reset覆盖L106-L110

reset的语义就是文档中"protected"承诺的落地:"Calls to reset will reset thecurrentConfigtositeConfig"。Configuration 文档 进一步说明:每次渲染图表前,Mermaid 都会在最早期调用reset,回到站点基线,从而保证不同图之间配置互不串扰。config.spec.ts#L89-L101 验证了setSiteConfig → setConfig → reset → 回到站点值的完整往返。

此外 packages/mermaid/src/diagram-api/diagramAPI.ts 内部重新导出了setSiteConfig,供各图表模块测试使用,例如 sequenceDiagram.spec.js#L1885 中用setSiteConfig({ logLevel: 5, sequence: conf })注入序列图配置。

八、实践要点清单

  1. 站点配置只在应用初始化时设置一次(通过initialize);setSiteConfig每调用一次都是"回到默认值再重新合并",反复调用不会累积。
  2. 需要增量微调站点配置时用updateSiteConfig,避免重复传递全量配置。
  3. 读取配置:getSiteConfig()取站点基线,getConfig()取当前生效配置(均为深拷贝)。getConfig的 JSDoc 建议避免反复调用,应将结果存入变量并向下传递(config.ts#L113-L122)。
  4. 站点所有者要把自定义项也受保护起来,应在initializesecure数组中追加声明;图作者侧传入 secure 键、__前缀键或含</>/url(data:的字符串都会被sanitize就地移除。
  5. 注意弃用项:setConfig已废弃;flowchart.htmlLabels应改用全局htmlLabelslazyLoadedDiagrams/loadExternalDiagramsAtStartup应改用registerExternalDiagrams,这些都会由checkConfig/ 相关工具函数发出弃用警告。

九、延伸阅读

  • API 文档:setSiteConfig、MermaidConfig 接口
  • 配置模型总览:Configuration
  • 指令机制与 8.6.0 新 API:8.6.0 变更文档
  • 配置核心实现:config.ts
  • 默认配置与 Schema:defaultConfig.ts、config.schema.yaml
  • 深合并工具:assignWithDepth.ts
  • 单元测试:config.spec.ts

【免费下载链接】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),仅供参考

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

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

立即咨询