@huahao/dsh-mermaid 0.0.0-stage → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,64 @@
1
+ # Changelog
2
+
3
+ ## 0.1.4 — 2026-11-13
4
+
5
+ 渲染不再等滚动,打开文档即出图。
6
+
7
+ - 检测到 mermaid 块后立即渲染(首个块由 `setTimeout(0)` 触发,不再挂
8
+ IntersectionObserver 等进入视口);剩余图表在 `requestIdleCallback` 空闲时段
9
+ 依次渲染,避免和滚动/输入抢主线程。单文档最多预渲染 10 张,超出部分仍按视口
10
+ 懒渲染,卡片回收时释放名额。
11
+ - 配合 0.1.3 的 iframe 隔离渲染:滚动到图表时不再触发任何渲染,实测 4 图文档
12
+ 打开后 811ms 全部出图,随后 26 步滚动 0 个 long task。
13
+
14
+ ## 0.1.3 — 2026-11-13
15
+
16
+ 修复打开长文档、滚动到图表时约 2 秒的主线程卡顿。
17
+
18
+ - 根因:mermaid 渲染会反复插入/测量临时节点,每次布局刷新都会为大正文(预览约 1400 元素)重算样式;trace 里 `UpdateLayoutTree` 累计 1.9s,单次 long task 1.6–2.2s。
19
+ - 渲染改到隐藏的同源 iframe 内完成(`ensureIsolatedRenderer` / `renderIsolated`):iframe 只加载一次 3.5MB runtime,之后通过 `postMessage` 传入源码与主题配置,取回 SVG 标记插入正文。正文 DOM 不再参与 mermaid 的样式重算。
20
+ - 首块检测到即预建 iframe(预取 runtime),避免滚动到位时再付启动成本;iframe `ready`/`render` 分别有 3s/15s 超时,失败自动回退到原来的页内渲染,并记住不可用状态不再重试。
21
+ - 实测(1600×1000 headless,5669px 预览、27 节点中文 flowchart):滚动到图表的 long task 由 2152ms 降到 219ms;同一张图在 iframe 内渲染约 232ms。
22
+ - 单元测试仍为 51 项全通过;`lib/client.js` 35.9KB。
23
+
24
+ ## 0.1.2
25
+
26
+ - 图表配色改为用 `--dsw-alias-state-business-primary` 与页面背景混合出底色(亮色 11%、暗色 26%),修复白色主题下节点几乎不可见的问题;连线改用 `label-secondary`。
27
+ - 首次渲染不再等待 500 ms 去抖(流式更新仍保留),并在检测到 mermaid 块时预取 3.5 MB runtime。
28
+ - 新增按(主题 + 源码)键的 SVG 模板缓存(24 条),预览面板重挂载、主题切换、页面缩放时命中缓存直接插入,避免重复 ~250 ms 的 mermaid 布局。
29
+ - 全屏查看器缩放上限由 5× 降到 4×,viewport/stage 增加 CSS containment,降低大图缩放时的光栅化开销。
30
+
31
+ ## 0.1.1 — 2026-11-13
32
+
33
+ 修复中文界面下 mermaid 代码块不渲染的问题。
34
+
35
+ - DSH 中文 UI 对未知/未标注语言的 fence 显示通用标签「代码块」(英文为
36
+ `Code block`),旧逻辑把它当成真实语言名直接判否,导致中文界面上聊天与
37
+ 文件预览里的 mermaid 块全部不接管。现在「代码块 / 代码片段 / code block /
38
+ codeblock」等按通用标签处理,继续走源码首词判定。
39
+ - 收紧 `graph` / `flowchart` 的源码启发式:要求首行带方向词(TD/TB/BT/LR/RL)
40
+ 或图里存在箭头,避免把 `graph = build_dag()` 这类普通代码误判为 mermaid。
41
+ - 补充对应单元测试;harness 用「代码块」banner 复测通过(3/3 块接管并出图)。
42
+
43
+ ## 0.1.0 — 2026-11-13
44
+
45
+ 首个自定义版本,基于 MrmoLabs/dsh-mermaid 0.4.5 的源码结构(MIT)重写定制。
46
+
47
+ - 重命名为 `@huahao/dsh-mermaid`,插件 id `dsh-mermaid-custom`,DOM/CSS 前缀
48
+ `dsh-mmd-c`,runtime 路由 `/dsh-mermaid-custom/mermaid-runtime.js`。
49
+ - 新增 banner 语言识别:先读 `language-*` class,再读 `[data-code-block-banner]`
50
+ infostring,最后才用源码首词;显式非 Mermaid 语言永不误渲染。
51
+ - 新增 `stripPreamble`:跳过 `%%` 注释、`%%{init}%%` 指令与 `---` YAML frontmatter,
52
+ 再判定 diagram 类型。
53
+ - 文件预览适配:识别 `.md-code-block` 宿主并加 `data-dsh-mmd-c-host`,隐藏 DSH
54
+ 原生语言/复制栏,改由卡片工具栏提供代码/图形、全屏、下载 SVG、复制。
55
+ - 主题改为 DSH token 驱动:`theme: 'base'` + `themeVariables` + 布尔属性指纹
56
+ (修复空属性值与缺失无法区分导致主题切换不重渲染的问题);为 Mermaid 11
57
+ sequence 图补充作用域 `themeCSS`。
58
+ - 新增懒渲染:IntersectionObserver(400px 前置边距)首次接近视口才 import
59
+ 运行时并渲染;保留 500ms 流式去抖与串行渲染队列。
60
+ - 新增复制源码按钮(clipboard API + execCommand 回退,1200ms 反馈)。
61
+ - 新增空 SVG 输出检测(`renderEmpty`)与对应中英文案。
62
+ - 测试与工程:删除 installer/bin,全部测试改用新 id 与路由;新增 banner/foreign
63
+ language/theme/copy/host 接管用例;bundle 体积上限 48KB,构建校验模块 id 与
64
+ runtime revision。
package/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mrmo072
4
+ Copyright (c) 2026 huahao (modifications: banner-aware detection, host chrome handover,
5
+ DSH token theming, sequence themeCSS, copy action, lazy viewport rendering, package
6
+ rename and tests. This derivative remains MIT-licensed under the notice below.)
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ of this software and associated documentation files (the "Software"), to deal
10
+ in the Software without restriction, including without limitation the rights
11
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ copies of the Software, and to permit persons to whom the Software is
13
+ furnished to do so, subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in all
16
+ copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,88 @@
1
- # Temporary Holding Version
1
+ # @huahao/dsh-mermaid
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ [简体中文](README.zh-CN.md) | English
4
+
5
+ Render Mermaid fences as interactive SVG inside DeepSeek Harness (DSH) — in chat
6
+ transcripts and in sidebar file previews. Customized from
7
+ [MrmoLabs/dsh-mermaid](https://github.com/MrmoLabs/dsh-mermaid) (MIT) and adapted
8
+ to the **DSH 0.2.2-rc.1** DOM contract.
9
+
10
+ ## What is different
11
+
12
+ - **File preview support.** DSH's document preview renders Markdown through the same
13
+ `div.md-code-block` structure, so the same decorator covers chat and preview.
14
+ - **Banner-aware detection.** DSH 0.2.2 no longer puts a `language-*` class on the
15
+ shiki `<code>`; the fence language only appears as the infostring text inside
16
+ `[data-code-block-banner]`. The plugin checks classes first, then the banner, and
17
+ only then falls back to the source's first token. `%%{init: …}%%`, YAML
18
+ frontmatter and `%%` comments are skipped; `python`/`json`/`arduino` lookalikes
19
+ stay untouched.
20
+ - **Native chrome handover.** For claimed fences the host `.md-code-block` gets
21
+ `data-dsh-mmd-c-host`; DSH's own language/copy bar is hidden (it duplicated the
22
+ card toolbar in preview) and the card toolbar provides code/diagram, fullscreen,
23
+ SVG download and copy.
24
+ - **Token-derived theme.** Colors come from DSH's `--dsw-alias-*` variables via
25
+ `theme: 'base'` + `themeVariables`; light/dark/acrylic switches re-render. Mermaid
26
+ 11 paints sequence actors from the base theme, so a scoped `themeCSS` block maps
27
+ `[aria-roledescription="sequence"]` back to the same tokens.
28
+ - **Lazy same-origin runtime.** Mermaid 11.17.2 ships as a separate ESM bundle served
29
+ by the host half at `/dsh-mermaid-custom/mermaid-runtime.js?rev=<hash>`; the client
30
+ `import()`s it when the first diagram approaches the viewport. No CDN, no
31
+ telemetry, no extra network origin.
32
+ - **Streaming-safe and bounded.** MutationObserver discovery with a 500 ms debounce,
33
+ IntersectionObserver 400 px margin, 32-entry SVG cache invalidated on theme change,
34
+ `securityLevel: 'strict'`, `htmlLabels: false`, DOMParser-based SVG sanitizing and
35
+ a 50,000-character / 2,000-line limit.
36
+
37
+ Fullscreen zoom/pan (Esc, focus trap), SVG export, source fallback and zh/en i18n
38
+ from upstream are preserved.
39
+
40
+ ## Install
41
+
42
+ ```bash
43
+ node scripts/build.mjs
44
+ dsh plugin --profile web add /Users/huahao/workspace/Project/github/dsh-mermaid-custom
45
+ ```
46
+
47
+ Restart `dsh web` or refresh the page afterwards. Fences tagged `mermaid`,
48
+ `mermaidjs` or `mmd` are supported, plus untagged blocks whose first token is a
49
+ Mermaid diagram keyword or that start with `%%`/`---` frontmatter.
50
+
51
+ ## Verify
52
+
53
+ 1. Chat shows a card with code/diagram/fullscreen/download/copy controls.
54
+ 2. A Markdown file with a Mermaid fence in the sidebar preview shows the same card,
55
+ and the original DSH `mermaid` banner is gone.
56
+ 3. Only one request appears: `GET /dsh-mermaid-custom/mermaid-runtime.js?rev=…` → 200.
57
+ 4. Switching the DSH light/dark theme re-renders diagrams with the new tokens.
58
+ 5. `%%{init: {"theme":"forest"}}%%` blocks render (DSH tokens still win).
59
+ 6. `python`/`json` blocks that start with `graph` remain plain code blocks.
60
+
61
+ ## Develop
62
+
63
+ ```bash
64
+ pnpm install
65
+ node scripts/build.mjs
66
+ node --test
67
+ ```
68
+
69
+ `lib/client.js` is a prebuilt CJS bundle registered through
70
+ `window.__ModuleLoader__.load`; `lib/mermaid-runtime.js` is an ESM bundle of Mermaid
71
+ 11.17.2. The build stamps the runtime's sha256 prefix into the client `?rev=` URL.
72
+
73
+ ## Uninstall
74
+
75
+ ```bash
76
+ dsh plugin --profile web remove @huahao/dsh-mermaid
77
+ ```
78
+
79
+ ## Compatibility
80
+
81
+ Built and hand-verified against DSH `0.2.2-rc.1` (web profile). Declares
82
+ `dsh.engines.dsh >=0.2.2-rc.1 <0.3.0-0`; DSH has no stable third-party renderer
83
+ extension point, so re-run the verification list after DSH upgrades.
84
+
85
+ ## License
86
+
87
+ MIT. Based on MrmoLabs/dsh-mermaid (Copyright © 2026 Mrmo072); modifications in this
88
+ repository are released under the same license. See [LICENSE](LICENSE).
@@ -0,0 +1,111 @@
1
+ # @huahao/dsh-mermaid
2
+
3
+ 简体中文 | [English](README.md)
4
+
5
+ 把 DeepSeek Harness(DSH)里的 Mermaid 围栏代码块渲染为可交互 SVG。它基于
6
+ [MrmoLabs/dsh-mermaid](https://github.com/MrmoLabs/dsh-mermaid)(MIT)的架构重写定制,
7
+ 针对 **DSH 0.2.2-rc.1** 的实际 DOM 契约做了适配,并补上了上游在 chat 与文件预览里
8
+ 的几个缺口。
9
+
10
+ ## 定制点
11
+
12
+ - **文件预览可用**:DSH 的文档预览正文复用了同一套 Markdown 渲染器,插件按
13
+ `div.md-code-block` 结构挂载,聊天流与侧栏文件预览都能渲染。
14
+ - **读 banner 语言**:DSH 0.2.2 的 shiki 输出 `<code>` 不再带 `language-*` class,
15
+ fence 语言只出现在 `[data-code-block-banner]` 的 infostring 文本里。插件先读
16
+ class、再读 banner,最后才用源码首词启发式,因此 `%%{init}%%` 指令、YAML
17
+ frontmatter、`%%` 注释开头的块也能识别,`python`/`json` 等误判被挡住。
18
+ - **接管原生围栏栏**:给命中的 `.md-code-block` 加 `data-dsh-mmd-c-host`,隐藏
19
+ DSH 自带的语言名/复制栏(在文件预览里会产生重复的横幅),由卡片工具栏提供
20
+ 代码/图形、全屏、下载 SVG、复制五个操作。
21
+ - **原生 token 主题**:从 DSH 的 `--dsw-alias-*` 设计变量读取颜色,配合
22
+ `theme: 'base'` + `themeVariables` 生成图表主题;深色/浅色/亚克力主题切换会
23
+ 触发重渲染。Mermaid 11 的 sequence 图不走 `themeVariables` 的 actor 颜色,
24
+ 因此额外用 `themeCSS` 按 `[aria-roledescription="sequence"]` 作用域补一层。
25
+ - **懒加载运行时**:Mermaid 11.17.2 单独打包为 ESM,由 host 半从
26
+ `/dsh-mermaid-custom/mermaid-runtime.js?rev=<hash>` 同源提供,客户端只在第一张
27
+ 图接近视口时才 `import()`;没有 CDN、没有外联请求、没有上报。
28
+ - **流式与性能**:MutationObserver 增量发现代码块,流式更新 500 ms 去抖。检测到
29
+ 块后立即渲染(不再等滚动进视口),后续图表用 `requestIdleCallback` 在空闲时段
30
+ 依次渲染,单个文档最多预渲染 10 张,其余仍交给 IntersectionObserver;按
31
+ 「主题 + 源码」缓存 32 张 SVG,主题变化时失效。
32
+ - **iframe 隔离渲染**:正文很长时,mermaid 在正文里插入测量节点会让每次布局刷新
33
+ 重算整篇样式(实测单张图 1.6–2.2 s 长任务)。渲染改在隐藏的同源 iframe 内完成,
34
+ 只把最终 SVG 标记取回插进正文;iframe 在检测到 mermaid 块时预热,失败自动回退
35
+ 页内渲染。
36
+ - **安全**:`securityLevel: 'strict'`、`htmlLabels: false`、SVG 经 DOMParser +
37
+ 白名单清洗后再插入;拒绝超过 50,000 字符 / 2,000 行的源码。
38
+
39
+ 上游已有的全屏查看器(滚轮缩放、拖拽、Esc 关闭、焦点陷阱)、SVG 下载、源码回退、
40
+ 中英文 i18n 都保留。
41
+
42
+ ## 安装
43
+
44
+ 本机已全局安装 `dsh` 时,把本目录安装进 Web profile:
45
+
46
+ ```bash
47
+ # 在工作区构建
48
+ node scripts/build.mjs
49
+
50
+ # 从本地路径安装(会运行 prepare 重新构建)
51
+ dsh plugin --profile web add /Users/huahao/workspace/Project/github/dsh-mermaid-custom
52
+ ```
53
+
54
+ 安装后重启 `dsh web` 或刷新已打开的页面。在输入框让模型输出:
55
+
56
+ ````markdown
57
+ ```mermaid
58
+ flowchart TD
59
+ A[客户端] --> B{鉴权服务}
60
+ B -->|通过| C[业务后端]
61
+ B -->|拒绝| D[返回 401]
62
+ ```
63
+ ````
64
+
65
+ 也识别 `mermaidjs`、`mmd` fence,以及没有语言标记但首行是
66
+ `flowchart`/`graph`/`sequenceDiagram` 等关键字、或开头带 `%%` 指令 / `---` frontmatter
67
+ 的块。不做行内代码。
68
+
69
+ ## 验收
70
+
71
+ 1. 聊天里出现卡片:代码 / 图形 / 全屏 / 下载 SVG / 复制;切换图形可看到 SVG。
72
+ 2. 侧栏打开含 mermaid 的 Markdown 文件,同样出现卡片,且上方不再有 DSH 原生的
73
+ `mermaid` 语言栏。
74
+ 3. 代码块默认 300 ms 稳定后按需渲染,滚动到附近才加载运行时(Network 里只请求一次
75
+ `/dsh-mermaid-custom/mermaid-runtime.js?rev=…`,状态 200)。
76
+ 4. 切换 DSH 深色/浅色主题,图会按新 token 重渲染。
77
+ 5. 含 `%%{init: {"theme":"forest"}}%%` 的块能渲染(主题仍以 DSH token 为准)。
78
+ 6. `python`/`json`/`arduino` 等以 `graph` 开头的代码块保持原生代码块形态。
79
+
80
+ ## 开发
81
+
82
+ ```bash
83
+ pnpm install # 只装 esbuild / happy-dom / mermaid
84
+ node scripts/build.mjs
85
+ node --test # 51 个用例:detection / client / theme / viewer / tooltip / runtime route
86
+ ```
87
+
88
+ `lib/client.js` 由 `src/*.js` 打包(CJS 入口 + `window.__ModuleLoader__.load`),
89
+ `lib/mermaid-runtime.js` 是 ESM(`mermaid` 11.17.2 + 工具函数)。`scripts/build.mjs`
90
+ 会把 runtime 的 sha256 前 12 位写进客户端 `?rev=`。
91
+
92
+ ## 卸载
93
+
94
+ ```bash
95
+ dsh plugin --profile web remove @huahao/dsh-mermaid
96
+ ```
97
+
98
+ ## 兼容性
99
+
100
+ - 构建与手工验收基于 DSH `0.2.2-rc.1`(`@deepseek-ai/dsh-web-frontend` 的
101
+ `md-code-block` / `[data-code-block-banner]` / `[data-code-block-content]` 结构)。
102
+ - 只支持 Web profile(`platform: 'web'`);DSH Desktop 需要另行验证窗口标题栏相关的
103
+ 全屏布局。
104
+ - `package.json` 声明 `dsh.engines.dsh >=0.2.2-rc.1 <0.3.0-0`;DSH 未提供稳定的
105
+ 第三方渲染扩展点,升级后请按上面的验收步骤回归。
106
+
107
+ ## 许可
108
+
109
+ MIT。基于 MrmoLabs/dsh-mermaid(Copyright © 2026 Mrmo072)修改;本仓库的改动
110
+ (banner 语言识别、host 接管、token 主题、sequence themeCSS、复制按钮、懒渲染等)
111
+ 同样以 MIT 发布,详见 [LICENSE](LICENSE)。
@@ -0,0 +1,4 @@
1
+ # Insert the dual-face plugin into the DSH web profile roster.
2
+ - insert:
3
+ - id: dsh-mermaid-custom
4
+ name: '@huahao/dsh-mermaid'
package/lib/client.js ADDED
@@ -0,0 +1,65 @@
1
+ window.__ModuleLoader__.load({id:"@huahao/dsh-mermaid",factory:(require)=>{var module={exports:{}};var exports=module.exports;
2
+ var ee=Object.defineProperty;var Ve=Object.getOwnPropertyDescriptor;var Ge=Object.getOwnPropertyNames;var Ue=Object.prototype.hasOwnProperty;var He=(e,t)=>{for(var r in t)ee(e,r,{get:t[r],enumerable:!0})},Ke=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of Ge(t))!Ue.call(e,a)&&a!==r&&ee(e,a,{get:()=>t[a],enumerable:!(n=Ve(t,a))||n.enumerable});return e};var Ye=e=>Ke(ee({},"__esModule",{value:!0}),e);var Ht={};He(Ht,{apply:()=>Gt,inject:()=>Ut,setMermaidRuntimeForTesting:()=>Et});module.exports=Ye(Ht);var Xe=/^language-(?:mermaid|mermaidjs|mmd)$/i,We=/^language-/i,Ze=/[\s·|]+/,xe=new Map([["flowchart","flowchart"],["graph","graph"],["sequencediagram","sequenceDiagram"],["classdiagram","classDiagram"],["statediagram","stateDiagram"],["statediagram-v2","stateDiagram-v2"],["erdiagram","erDiagram"],["gantt","gantt"],["pie","pie"],["journey","journey"],["timeline","timeline"],["mindmap","mindmap"],["gitgraph","gitGraph"],["quadrantchart","quadrantChart"],["requirementdiagram","requirementDiagram"],["c4context","C4Context"],["c4container","C4Container"],["c4component","C4Component"],["c4dynamic","C4Dynamic"],["c4deployment","C4Deployment"],["block-beta","block-beta"],["packet-beta","packet-beta"],["architecture-beta","architecture-beta"],["sankey-beta","sankey-beta"],["xychart-beta","xychart-beta"],["radar-beta","radar-beta"],["treemap-beta","treemap-beta"],["zenuml","zenuml"]]),Qe=new Set(["mermaid","mermaidjs","mmd"]);var ve=new Set(["code","code-block","codeblock","code-snippet","snippet","text","txt","plain","plaintext","plain-text","unknown","\u4EE3\u7801","\u4EE3\u7801\u5757","\u4EE3\u7801\u7247\u6BB5","\u6587\u672C","\u7EAF\u6587\u672C"]);function te(e){let t=String(e??"").replace(/\r\n?/g,`
3
+ `).trimStart();for(let r=0;r<64&&t;r+=1){let n=t.split(`
4
+ `);if(n[0].trim()==="---"){let a=n.findIndex((s,i)=>i>0&&s.trim()==="---");if(a>0){t=n.slice(a+1).join(`
5
+ `).trimStart();continue}}if(t.startsWith("%%")){let a=t.indexOf(`
6
+ `);t=a===-1?"":t.slice(a+1).trimStart();continue}break}return t}function ye(e){let t=/^\s*([A-Za-z][\w-]*)/.exec(te(e));return t?t[1]:""}function re(e){return xe.get(ye(e).toLowerCase())||""}var Je=/^(?:flowchart|graph)\b/i,et=/^(?:flowchart|graph)\s+(?:TD|TB|BT|LR|RL)\b/i,tt=/(?:-->|---|==>|-\.->|<-->|--[^-\n]+-->)/;function rt(e){let t=ye(e).toLowerCase();return xe.has(t)?Je.test(te(e))?et.test(te(e))||tt.test(e):!0:!1}function nt(e){let t=e?.querySelector?.("[data-code-block-banner]");if(!t)return"";let r=t.querySelector("[data-text-interaction-exclude]"),n=(r?r.textContent:t.textContent||"").trim();return n?(n.split(Ze)[0]||"").replace(/^[`'"]+|[`'"]+$/g,"").toLowerCase():""}function at(e){return Array.from(e||[]).some(t=>Xe.test(t))}function ot(e){return Array.from(e||[]).some(t=>We.test(t))}function it(e){if(!e||ve.has(e))return!0;let t=e.replace(/(?:块|片段|block)$/u,"").trim();return t!==e&&(ve.has(t)||t==="code"||t==="\u4EE3\u7801")}function Ce(e){if(!e?.closest?.("pre")||e.closest(".dsh-mmd-c, .dsh-mmd"))return!1;if(at(e.classList))return!0;if(ot(e.classList))return!1;let r=nt(e.closest(".md-code-block"));return Qe.has(r)?!0:r&&!it(r)?!1:rt(e.textContent||"")}var ne={en:{viewOptions:"Mermaid view options",diagramView:"Diagram",codeView:"Code",fullscreen:"Fullscreen",downloadSvg:"Download SVG",viewerLabel:"Fullscreen Mermaid diagram viewer",viewerTitle:"{type} \xB7 Mermaid",zoomOut:"Zoom out",resetZoom:"Reset zoom to 100%",zoomIn:"Zoom in",fitWindow:"Fit to window",closeViewer:"Close fullscreen viewer",rendering:"Rendering diagram\u2026",rendered:"Mermaid diagram rendered.",renderFailed:"Diagram rendering failed: {detail}",renderFailedStatus:"Diagram rendering failed. Source code is shown.",tooLong:"Diagram not rendered: source length {actual} characters exceeds the {limit} character limit.",tooManyLines:"Diagram not rendered: source has {actual} lines and exceeds the {limit} line limit.",diagramTitle:"Mermaid {type} diagram",downloaded:"SVG downloaded.",copy:"Copy",copied:"Copied",copyFailed:"Copy failed. Select the source in the Code view instead.",renderEmpty:"Diagram rendering produced no output. Source code is shown."},"zh-CN":{viewOptions:"Mermaid \u89C6\u56FE\u9009\u9879",diagramView:"\u56FE\u5F62",codeView:"\u4EE3\u7801",fullscreen:"\u5168\u5C4F",downloadSvg:"\u4E0B\u8F7D SVG",viewerLabel:"Mermaid \u56FE\u5168\u5C4F\u67E5\u770B",viewerTitle:"{type} \xB7 Mermaid",zoomOut:"\u7F29\u5C0F",resetZoom:"\u6062\u590D\u5230 100%",zoomIn:"\u653E\u5927",fitWindow:"\u9002\u5E94\u7A97\u53E3",closeViewer:"\u5173\u95ED\u5168\u5C4F\u67E5\u770B",rendering:"\u6B63\u5728\u6E32\u67D3\u56FE\u8868\u2026",rendered:"Mermaid \u56FE\u5DF2\u6E32\u67D3\u3002",renderFailed:"\u56FE\u8868\u6E32\u67D3\u5931\u8D25\uFF1A{detail}",renderFailedStatus:"\u56FE\u8868\u6E32\u67D3\u5931\u8D25\uFF0C\u5DF2\u663E\u793A\u6E90\u4EE3\u7801\u3002",tooLong:"\u56FE\u8868\u672A\u6E32\u67D3\uFF1A\u6E90\u7801\u957F\u5EA6\u4E3A {actual} \u5B57\u7B26\uFF0C\u8D85\u8FC7 {limit} \u5B57\u7B26\u9650\u5236\u3002",tooManyLines:"\u56FE\u8868\u672A\u6E32\u67D3\uFF1A\u6E90\u7801\u5171 {actual} \u884C\uFF0C\u8D85\u8FC7 {limit} \u884C\u9650\u5236\u3002",diagramTitle:"Mermaid {type} \u56FE",downloaded:"SVG \u5DF2\u4E0B\u8F7D\u3002",copy:"\u590D\u5236",copied:"\u5DF2\u590D\u5236",copyFailed:"\u590D\u5236\u5931\u8D25\uFF0C\u8BF7\u5728\u4EE3\u7801\u89C6\u56FE\u91CC\u624B\u52A8\u9009\u62E9\u6E90\u7801\u3002",renderEmpty:"\u56FE\u8868\u6E32\u67D3\u6CA1\u6709\u8F93\u51FA\uFF0C\u5DF2\u663E\u793A\u6E90\u4EE3\u7801\u3002"}};function Ee(e){let t=String(e||"").trim().toLowerCase();return t==="zh"||t.startsWith("zh-")?"zh-CN":"en"}function Te(e,t=[]){let r=[e,...t].filter(Boolean);return Ee(r[0])}function Se(e,t,r={}){return((ne[Ee(e)]||ne.en)[t]||ne.en[t]||t).replace(/\{(\w+)\}/g,(s,i)=>Object.prototype.hasOwnProperty.call(r,i)?String(r[i]):s)}var ke=`
7
+ .dsh-mmd-c{position:relative;margin:8px 0 10px;border:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.25));border-radius:10px;background:var(--dsw-alias-bg-layer-2,rgba(127,127,127,.06));overflow:hidden}
8
+ .dsh-mmd-c-bar{display:flex;align-items:center;gap:8px;padding:4px 8px;border-bottom:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.18));background:var(--dsw-alias-bg-layer-1,transparent)}
9
+ .dsh-mmd-c-badge{margin-right:auto;font:12px/20px var(--ds-font-family-code,ui-monospace,monospace);color:var(--dsw-alias-label-tertiary,#888);padding:0 6px}
10
+ .dsh-mmd-c-btn{appearance:none;min-width:28px;min-height:28px;border:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.3));background:transparent;color:var(--dsw-alias-label-secondary,#666);border-radius:5px;font:12px/20px inherit;padding:2px 10px;cursor:pointer}
11
+ .dsh-mmd-c-btn:hover{background:var(--dsw-alias-interactive-bg-hover,rgba(127,127,127,.1))}
12
+ .dsh-mmd-c-btn:focus-visible{outline:2px solid var(--dsw-alias-button-primary-fill,#4c6ef5);outline-offset:2px}
13
+ .dsh-mmd-c-btn[aria-pressed='true']{border-color:var(--dsw-alias-button-primary-fill,#4c6ef5);color:var(--dsw-alias-button-primary-fill,#4c6ef5);background:var(--dsw-alias-interactive-bg-active,rgba(76,110,245,.12))}
14
+ .dsh-mmd-c-action-slot{display:flex;align-items:center;justify-content:flex-end;gap:8px}
15
+ .dsh-mmd-c-body{padding:10px 12px;overflow-x:auto}
16
+ .dsh-mmd-c-pane{display:block}
17
+ .dsh-mmd-c-pane svg{max-width:100%;height:auto;display:block;margin:0 auto}
18
+ .dsh-mmd-c-pane[data-state='loading'],.dsh-mmd-c-pane[data-state='error']{font:12px/20px var(--ds-font-family-code,ui-monospace,monospace);color:var(--dsw-alias-label-tertiary,#888);padding:12px 4px;white-space:pre-wrap}
19
+ .dsh-mmd-c-pane[data-state='error']{color:var(--dsw-alias-state-error-primary,#d33)}
20
+ .dsh-mmd-c-code{display:none;margin:0;padding:12px 14px;overflow-x:auto;font:var(--dsl-code-block-content-font,var(--dsw-font-markdown-code-block,13px/1.7 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace));color:var(--dsw-alias-label-primary,#e6e6e6);white-space:pre;tab-size:4}
21
+ .dsh-mmd-c-error{display:none;font:12px/20px var(--ds-font-family-code,ui-monospace,monospace);color:var(--dsw-alias-state-error-primary,#d33);padding:8px 14px 0;white-space:pre-wrap}
22
+ .dsh-mmd-c-sr-only{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}
23
+ .dsh-mmd-c[data-view='code'] .dsh-mmd-c-body{padding:0}
24
+ .dsh-mmd-c[data-view='code'] .dsh-mmd-c-pane{display:none}
25
+ .dsh-mmd-c[data-view='code'] .dsh-mmd-c-code{display:block}
26
+ .dsh-mmd-c[data-view='code'][data-state='error'] .dsh-mmd-c-error{display:block}
27
+ .dsh-mmd-c[data-state='error'] .dsh-mmd-c-view-control{display:none}
28
+ .dsh-mmd-c:not([data-state='ok']) .dsh-mmd-c-diagram-action{display:none}
29
+ /* Keep native titlebar clearance even when Desktop's fullscreen marker is stale. */
30
+ .dsh-mmd-c-viewer{position:fixed;z-index:2147483000;inset:0;top:max(var(--dsh-mmd-c-titlebar-height,0px),calc(env(titlebar-area-y,0px) + env(titlebar-area-height,0px)));-webkit-app-region:no-drag;display:flex;flex-direction:column;background:#fff;color:var(--dsw-alias-label-primary,#222)}
31
+ html[data-windows-titlebar]:not([data-fullscreen]) .dsh-mmd-c-viewer{--dsh-mmd-c-titlebar-height:var(--dsh-windows-titlebar-height,40px)}
32
+ body[data-ds-dark-theme] .dsh-mmd-c-viewer{background:#121212;color:var(--dsw-alias-label-primary,#f5f5f5)}
33
+ .dsh-mmd-c-viewer[hidden]{display:none}
34
+ .dsh-mmd-c-viewer-bar{display:flex;align-items:center;gap:8px;min-height:48px;padding:6px 12px;border-bottom:1px solid var(--dsw-alias-border-l1,rgba(127,127,127,.3));background:var(--dsw-alias-bg-layer-1,rgba(30,30,30,.98))}
35
+ .dsh-mmd-c-viewer-title{margin-right:auto;font:12px/20px var(--ds-font-family-code,ui-monospace,monospace);color:var(--dsw-alias-label-secondary,#bbb)}
36
+ .dsh-mmd-c-viewer-viewport{position:relative;flex:1;min-height:0;overflow:hidden;cursor:grab;touch-action:none;contain:layout style}
37
+ .dsh-mmd-c-viewer-viewport[data-dragging='true']{cursor:grabbing}
38
+ .dsh-mmd-c-viewer-stage{position:absolute;left:50%;top:50%;transform-origin:center;will-change:transform;contain:layout style;backface-visibility:hidden}
39
+ .dsh-mmd-c-viewer-stage svg{display:block;max-width:none;height:auto;background:transparent}
40
+ .md-code-block[data-dsh-mmd-c-host]{background:transparent!important;border:0!important;box-shadow:none!important;border-radius:0!important}
41
+ [data-dsh-mmd-c-host] [data-code-block-banner]{display:none!important}
42
+ [data-dsh-mmd-c-host] [data-code-block-content]{padding:0!important;background:transparent!important;border:0!important}
43
+ /* \u539F\u59CB\u4EE3\u7801\u5757\u59CB\u7EC8\u9690\u85CF\uFF1A\u4EE3\u7801\u89C6\u56FE\u7531\u5361\u7247\u5185\u90E8\u7684 .dsh-mmd-c-code \u5448\u73B0 */
44
+ .dsh-mmd-c + pre{display:none}
45
+ @media (prefers-reduced-motion:reduce){.dsh-mmd-c *{animation:none!important;transition:none!important}}
46
+ @media (forced-colors:active){.dsh-mmd-c-btn:focus-visible{outline-color:Highlight}}
47
+ `;var st=0,dt=0;function Le(e){return`<?xml version="1.0" encoding="UTF-8"?>
48
+ ${new window.XMLSerializer().serializeToString(e)}`}function ae(e,t){if(!e||(e.setAttribute("role","img"),e.hasAttribute("aria-label")||e.hasAttribute("aria-labelledby")))return;let r=[...e.children].find(n=>n.localName==="title");r||(r=e.ownerDocument.createElementNS("http://www.w3.org/2000/svg","title"),r.dataset.dshMmdTitle="true",r.textContent=t,e.prepend(r)),r.id||(r.id=`dsh-mmd-c-title-${++st}`),e.setAttribute("aria-labelledby",r.id)}function j(e,t){let r=e?.querySelector("title[data-dsh-mmd-c-title]");r&&(r.textContent=t)}function oe(e){let t=(e.getAttribute("viewBox")||"").trim().split(/[\s,]+/).map(Number);return t.length===4&&t.every(Number.isFinite)&&t[2]>0&&t[3]>0?{width:t[2],height:t[3]}:{width:Number.parseFloat(e.getAttribute("width"))||800,height:Number.parseFloat(e.getAttribute("height"))||600}}function Me(e){let t=[e,...e.querySelectorAll("*")],r=new Map,n=`dsh-mmd-c-view-${++dt}-`;for(let a of t){if(!a.id)continue;let s=`${n}${r.size+1}`;r.set(a.id,s),a.id=s}if(r.size){for(let a of t)for(let s of[...a.attributes]){if(s.name==="id")continue;let i=s.value.replace(/url\(\s*(['"]?)#([^)'"\s]+)\1\s*\)/g,(d,m,u)=>r.has(u)?`url(${m}#${r.get(u)}${m})`:d);if((s.name==="href"||s.name==="xlink:href")&&i.startsWith("#")){let d=r.get(i.slice(1));d&&(i=`#${d}`)}(s.name==="aria-labelledby"||s.name==="aria-describedby")&&(i=i.split(/\s+/).map(d=>r.get(d)||d).join(" ")),i!==s.value&&a.setAttribute(s.name,i)}for(let a of e.querySelectorAll("style")){let s=a.textContent||"";for(let[i,d]of r)s=s.split(`#${i}`).join(`#${d}`);a.textContent=s}}}var lt={canvas:"#ffffff",bg:"#f7f7f7",surface:"#fafafa",text:"#222222",line:"#4b5563",muted:"#9ca3af",accent:"#4d6bfe",border:"rgba(0, 0, 0, 0.1)"},ct={canvas:"#1b1b1c",bg:"#1e1e1e",surface:"#2b2b2b",text:"#eeeeee",line:"#a1a7ae",muted:"#767d85",accent:"#6b8dff",border:"rgba(255, 255, 255, 0.12)"},se=["data-ds-dark-theme","data-acrylic-wallpaper","data-acrylic-fluent","class","style"],mt=new Set(["data-ds-dark-theme","data-acrylic-wallpaper","data-acrylic-fluent"]);function ut(){return document.body?.hasAttribute("data-ds-dark-theme")??!1}function V(){let e=document.body;return e?se.map(t=>mt.has(t)?`${t}=${e.hasAttribute(t)?"1":"0"}`:`${t}=${e.getAttribute(t)||""}`).join("|"):"light"}function pt(e,t){let r=e.defaultView,n=e.createElement("span");n.dataset.dshMermaidProbe="",n.style.cssText="position:absolute;visibility:hidden;pointer-events:none",e.body.append(n);let a=t?31:255;function s(i,d){n.style.color=`var(${i},${d})`;let m=r.getComputedStyle(n).color;if(/^#[0-9a-f]{6}$/i.test(m))return m;if(/^#[0-9a-f]{3}$/i.test(m))return`#${[...m.slice(1)].map(l=>l+l).join("")}`;let u=m.match(/^rgba?\(\s*(\d+(?:\.\d+)?)[, ]+\s*(\d+(?:\.\d+)?)[, ]+\s*(\d+(?:\.\d+)?)(?:\s*[,/]\s*([\d.]+))?/);if(!u)return d;let h=u[4]===void 0?1:Math.min(1,Math.max(0,Number(u[4])));return`#${u.slice(1,4).map(l=>Math.round(Number(l)*h+a*(1-h)).toString(16).padStart(2,"0")).join("")}`}return{color:s,dispose(){n.remove()}}}function ie(e,t,r){let n=l=>[1,3,5].map(f=>parseInt(l.slice(f,f+2),16)),[a,s,i]=n(e),[d,m,u]=n(t),h=(l,f)=>Math.round(l*r+f*(1-r)).toString(16).padStart(2,"0");return`#${h(a,d)}${h(s,m)}${h(i,u)}`}function de(e){if(!e.body)throw new Error("Mermaid theme requires a document body");let t=ut(),r=t?ct:lt,n=pt(e,t);try{let a=n.color("--dsw-alias-bg-layer-1",r.canvas),s=n.color("--dsw-alias-markdown-code-block",r.bg),i=n.color("--dsw-alias-label-primary",r.text),d=n.color("--dsw-alias-label-secondary",r.line),m=n.color("--dsw-alias-label-tertiary",r.muted),u=n.color("--dsw-alias-state-business-primary",r.accent),h=n.color("--dsw-alias-border-l2",r.border),l=ie(u,a,t?.26:.11),f=ie(u,a,t?.55:.42),E=ie(u,a,t?.12:.05),T=e.defaultView.getComputedStyle(e.body).fontFamily||"sans-serif";return{startOnLoad:!1,securityLevel:"strict",suppressErrorRendering:!0,theme:"base",themeCSS:['[aria-roledescription="sequence"] rect.actor,','[aria-roledescription="sequence"] .actor-man circle,',`[aria-roledescription="sequence"] .actor-man line { fill: ${l}; stroke: ${f}; }`,`[aria-roledescription="sequence"] text.actor > tspan { fill: ${i}; }`,`[aria-roledescription="sequence"] .actor-line { stroke: ${m}; }`,'[aria-roledescription="sequence"] .messageLine0,',`[aria-roledescription="sequence"] .messageLine1 { stroke: ${d}; }`,`[aria-roledescription="sequence"] [id$="-arrowhead"] path { fill: ${d}; stroke: ${d}; }`,`[aria-roledescription="sequence"] .messageText { fill: ${i}; }`,`[aria-roledescription="sequence"] .labelBox { fill: ${l}; stroke: ${f}; }`,'[aria-roledescription="sequence"] .labelText,',`[aria-roledescription="sequence"] .loopText { fill: ${i}; }`,`[aria-roledescription="sequence"] .note { fill: ${s}; stroke: ${h}; }`,`[aria-roledescription="sequence"] .noteText { fill: ${i}; }`,'[aria-roledescription="sequence"] .activation0,','[aria-roledescription="sequence"] .activation1,',`[aria-roledescription="sequence"] .activation2 { fill: ${l}; stroke: ${u}; }`].join(`
49
+ `),maxTextSize:5e4,maxEdges:2e3,htmlLabels:!1,flowchart:{htmlLabels:!1,curve:"linear",nodeSpacing:36,rankSpacing:44,padding:14},themeVariables:{darkMode:t,fontFamily:T,fontSize:"14px",background:"transparent",primaryColor:l,primaryTextColor:i,primaryBorderColor:f,secondaryColor:E,secondaryTextColor:i,secondaryBorderColor:f,tertiaryColor:s,tertiaryTextColor:i,tertiaryBorderColor:h,lineColor:d,textColor:i,mainBkg:l,nodeBorder:f,clusterBkg:E,clusterBorder:f,edgeLabelBackground:a,actorBkg:l,actorBorder:f,actorTextColor:i,actorLineColor:m,signalColor:d,signalTextColor:i,labelBoxBkgColor:l,labelBoxBorderColor:f,labelTextColor:i,noteBkgColor:s,noteBorderColor:h,noteTextColor:i,activationBkgColor:l,activationBorderColor:u,stateBkg:l,stateBorder:f,labelBackgroundColor:a,compositeBackground:E,compositeBorder:f,compositeTitleBackground:E}}}finally{n.dispose()}}function _e({t:e}){let t=null;function r(){t&&(t.stage.style.transform=`translate(-50%,-50%) translate(${t.panX}px,${t.panY}px) scale(${t.scale})`,t.zoomLabel.textContent=`${Math.round(t.scale*100)}%`)}function n(o,c){if(!t)return;let p=t.scale,g=Math.min(4,Math.max(.1,o));if(c&&p>0&&g!==p){let x=g/p;t.panX=c.x-(c.x-t.panX)*x,t.panY=c.y-(c.y-t.panY)*x}t.scale=g,r()}function a(){if(!t)return;let o=t.stage.querySelector("svg");if(!o)return;let c=oe(o),p=t.viewport.clientWidth||1200,g=t.viewport.clientHeight||800;t.scale=Math.min(4,Math.max(.1,Math.min((p-48)/c.width,(g-48)/c.height))),t.panX=0,t.panY=0,r()}function s(){if(t&&(t.overlay.setAttribute("aria-label",e("viewerLabel")),t.zoomOut.setAttribute("aria-label",e("zoomOut")),t.zoomLabel.setAttribute("aria-label",e("resetZoom")),t.zoomIn.setAttribute("aria-label",e("zoomIn")),t.fit.textContent=e("fitWindow"),t.fit.setAttribute("aria-label",e("fitWindow")),t.close.textContent=e("closeViewer"),t.close.setAttribute("aria-label",e("closeViewer")),t.entry)){let o=t.entry.badge.textContent||"mermaid";t.title.textContent=e("viewerTitle",{type:o}),j(t.stage.querySelector("svg"),e("diagramTitle",{type:o}))}}function i(o,c){if(!t)return;let p=o.pane.querySelector("svg");if(!p)return;let g=p.cloneNode(!0);Me(g);let x=oe(g);g.setAttribute("width",String(x.width)),g.setAttribute("height",String(x.height)),t.stage.replaceChildren(g),t.title.textContent=e("viewerTitle",{type:o.badge.textContent||"mermaid"}),c&&a()}function d(){return t?[...t.overlay.querySelectorAll('button:not([disabled]),[href],[tabindex]:not([tabindex="-1"])')].filter(o=>!o.hidden):[]}function m(o){if(!t||t.overlay.hidden||o.key!=="Tab")return;let c=d();if(!c.length){o.preventDefault(),t.overlay.focus();return}let p=c[0],g=c.at(-1),x=document.activeElement;t.overlay.contains(x)?o.shiftKey&&x===p?(o.preventDefault(),g.focus()):!o.shiftKey&&x===g&&(o.preventDefault(),p.focus()):(o.preventDefault(),p.focus())}function u(){if(!t||t.overlay.hidden)return;let o=t.trigger;t.overlay.hidden=!0,t.entry=null,t.trigger=null,t.stage.replaceChildren(),document.body.style.overflow=t.previousBodyOverflow;for(let[c,p]of t.inertedElements)c.inert=p;t.inertedElements=[],o?.isConnected&&o.focus()}function h(){if(t)return t;let o=document.createElement("div");o.className="dsh-mmd-c-viewer",o.hidden=!0,o.setAttribute("role","dialog"),o.setAttribute("aria-modal","true"),o.setAttribute("aria-label",e("viewerLabel")),o.tabIndex=-1;let c=document.createElement("div");c.className="dsh-mmd-c-viewer-bar";let p=document.createElement("span");p.className="dsh-mmd-c-viewer-title";let g=(b,D)=>{let _=document.createElement("button");return _.type="button",_.className="dsh-mmd-c-btn",_.textContent=b,_.setAttribute("aria-label",D),_},x=g("\u2212",e("zoomOut")),X=g("100%",e("resetZoom")),W=g("+",e("zoomIn")),Z=g(e("fitWindow"),e("fitWindow")),Q=g(e("closeViewer"),e("closeViewer")),y=document.createElement("div");y.className="dsh-mmd-c-viewer-viewport";let J=document.createElement("div");J.className="dsh-mmd-c-viewer-stage",y.appendChild(J),c.append(p,x,X,W,Z,Q),o.append(c,y),document.body.appendChild(o),t={overlay:o,title:p,viewport:y,stage:J,zoomOut:x,zoomLabel:X,zoomIn:W,fit:Z,close:Q,entry:null,scale:1,panX:0,panY:0,dragging:!1,pointerId:null,lastX:0,lastY:0,previousBodyOverflow:"",trigger:null,inertedElements:[]},x.addEventListener("click",()=>n(t.scale/1.2)),X.addEventListener("click",()=>{t.scale=1,t.panX=0,t.panY=0,r()}),W.addEventListener("click",()=>n(t.scale*1.2)),Z.addEventListener("click",a),Q.addEventListener("click",u),y.addEventListener("wheel",b=>{b.preventDefault();let D=y.getBoundingClientRect(),_={x:b.clientX-D.left-D.width/2,y:b.clientY-D.top-D.height/2};n(t.scale*(b.deltaY<0?1.12:1/1.12),_)},{passive:!1}),y.addEventListener("pointerdown",b=>{b.button===0&&(t.dragging=!0,t.pointerId=b.pointerId,t.lastX=b.clientX,t.lastY=b.clientY,y.dataset.dragging="true",y.setPointerCapture?.(b.pointerId))}),y.addEventListener("pointermove",b=>{!t.dragging||b.pointerId!==t.pointerId||(t.panX+=b.clientX-t.lastX,t.panY+=b.clientY-t.lastY,t.lastX=b.clientX,t.lastY=b.clientY,r())});let we=b=>{!t.dragging||b.pointerId!==t.pointerId||(t.dragging=!1,t.pointerId=null,delete y.dataset.dragging)};return y.addEventListener("pointerup",we),y.addEventListener("pointercancel",we),o.addEventListener("click",b=>{b.target===o&&u()}),o.addEventListener("keydown",m),t}function l(o){if(!o.pane.querySelector("svg"))return;let c=h();c.entry=o,c.trigger=o.btnFullscreen,c.previousBodyOverflow=document.body.style.overflow,c.inertedElements=[...document.body.children].filter(p=>p!==c.overlay).map(p=>[p,!!p.inert]);for(let[p]of c.inertedElements)p.inert=!0;document.body.style.overflow="hidden",c.overlay.hidden=!1,i(o,!0),c.close.focus()}function f(o){return!!(t&&!t.overlay.hidden&&t.entry===o)}function E(){return!!(t&&!t.overlay.hidden)}function T(){u(),t?.overlay.remove(),t=null}return{close:u,destroy:T,fit:a,isOpen:E,isOpenFor:f,localize:s,open:l,update:i}}var ft="dsh-mermaid-custom/css",gt=300,bt=500,ht=400,wt=10,vt=1200,Ae=5e4,le=2e3,xt="9da71e0c3cd0",De=`/dsh-mermaid-custom/mermaid-runtime.js?rev=${xt}`,ce=0,be="en",A=null,S=null,k=null,me=!1,G=null,z=null,N=null,yt=24,F=new Map,Ne="__DSH_MMD_C_SVG_ID__";function Ct(e,t,r){let n=r.split(t).join(Ne);F.size>=yt&&F.delete(F.keys().next().value),F.set(Be(e),{template:n})}function Be(e){return`${V()}\0${e}`}var M=new WeakMap,I=new Set,U=[];function Et(e,t,r){let n=S,a=k,s=z,i=N;return S=e,k=Promise.resolve(e),z=t,N=r,()=>{S=n,k=a,z=s,N=i}}function Oe(){return S?Promise.resolve(S):(k||(k=import(De).then(e=>(S={initialize:e.default.initialize,render:e.renderMermaid},z=e.createTooltipPositioner,N=e.preserveViewPosition,S)).catch(e=>{throw k=null,e})),k)}var Tt=3e3,St=15e3,B=null,R="idle",O=null,C=null,pe=!1,Y=0,$=new Map;function $e(e,t){if(typeof window>"u")return;let r=window.__dshMmdCIsolate||(window.__dshMmdCIsolate={});r.state=e,t?r.error=String(t?.message||t):r.error=null,r.at=performance.now()}function Fe(){return typeof window<"u"&&typeof document<"u"&&!!document.body&&typeof HTMLIFrameElement<"u"&&"contentDocument"in HTMLIFrameElement.prototype&&!/HappyDOM/i.test(navigator.userAgent||"")}function H(e,t){$e("failed",e),R="failed",pe=!0;let r=O;O=null,t?.(),r?.reject(e);for(let n of $.values())n.reject(e);$.clear(),B?.remove(),B=null}function Re(e){if(!B||e.source!==B.contentWindow)return;let t=e.data;if(!t||t.__dshMmdC!=="isolated")return;if(t.kind==="ready"){C&&(clearTimeout(C),C=null),$e("ready",null),R="ready";let n=O;O=null,n?.resolve();return}let r=$.get(t.id);r&&($.delete(t.id),t.ok?r.resolve(t.svg):r.reject(new Error(t.error||"isolated render failed")))}function ze(){return pe?Promise.reject(new Error("isolated renderer unavailable")):R==="ready"?Promise.resolve():R==="loading"?new Promise((e,t)=>{O={resolve:e,reject:t}}):Fe()?(R="loading",new Promise((e,t)=>{O={resolve:e,reject:t},C=setTimeout(()=>{C=null,H(new Error("isolated renderer ready timeout"),()=>{})},Tt);let r=document.createElement("iframe");r.setAttribute("aria-hidden","true"),r.tabIndex=-1,r.style.cssText="position:fixed;left:-20000px;top:0;width:1000px;height:800px;border:0;visibility:hidden;pointer-events:none",B=r,r.addEventListener("load",()=>{let n=r.contentDocument;if(!n?.head){H(new Error("isolated renderer document unavailable"),()=>{C&&clearTimeout(C),C=null});return}let a=n.createElement("script");a.type="module",a.textContent=`
50
+ import * as runtime from ${JSON.stringify(new URL(De,window.location.href).href)};
51
+ window.addEventListener('message', async (event) => {
52
+ const data = event.data;
53
+ if (!data || data.__dshMmdC !== 'isolated' || data.kind !== 'render') return;
54
+ try {
55
+ runtime.default.initialize(data.config);
56
+ const result = await runtime.renderMermaid(data.id, data.source);
57
+ parent.postMessage({ __dshMmdC: 'isolated', kind: 'result', id: data.id, ok: true, svg: result.svg }, '*');
58
+ } catch (error) {
59
+ parent.postMessage({ __dshMmdC: 'isolated', kind: 'result', id: data.id, ok: false, error: String(error?.message || error) }, '*');
60
+ }
61
+ });
62
+ parent.postMessage({ __dshMmdC: 'isolated', kind: 'ready' }, '*');
63
+ `,n.head.appendChild(a)},{once:!0}),r.addEventListener("error",()=>H(new Error("isolated renderer failed to load"),()=>{C&&clearTimeout(C),C=null}),{once:!0}),document.body.appendChild(r)})):(pe=!0,Promise.reject(new Error("isolated renderer not supported")))}async function kt(e,t){return await ze(),await new Promise((r,n)=>{let a=setTimeout(()=>{$.delete(e),n(new Error("isolated render timeout"))},St);$.set(e,{resolve:s=>{clearTimeout(a),r(s)},reject:s=>{clearTimeout(a),n(s)}}),B.contentWindow.postMessage({__dshMmdC:"isolated",kind:"render",id:e,source:t,config:de(document)},"*")})}function Lt(){(R==="ready"||R==="loading")&&H(new Error("isolated renderer disposed"))}var fe=null;function w(e,t){return Se(be,e,t)}var v=_e({t:w});function qe(){let e=[...navigator.languages||[]];return navigator.language&&!e.includes(navigator.language)&&e.push(navigator.language),Te(document.documentElement?.lang,e)}function Pe(e){if(e.bar.setAttribute("aria-label",w("viewOptions")),e.btnDiagram.textContent=w("diagramView"),e.btnCode.textContent=w("codeView"),e.btnCopy.textContent=w("copy"),e.btnCopy.setAttribute("aria-label",w("copy")),e.btnFullscreen.textContent=w("fullscreen"),e.btnDownloadSvg.textContent=w("downloadSvg"),e.statusKey&&(e.statusEl.textContent=w(e.statusKey,e.statusParameters)),j(e.pane.querySelector("svg"),w("diagramTitle",{type:e.badge.textContent||"mermaid"})),e.messageKey&&e.pane.dataset.state!=="ok"){let t=w(e.messageKey,e.messageParameters);e.pane.textContent=t,e.wrapper.dataset.state==="error"&&(e.errorEl.textContent=t)}}function Mt(){be=qe();for(let e of I){let t=M.get(e._dshCode);t&&Pe(t)}v.localize()}function _t(e){e.initialize(de(document))}function At(){fe=V()}function Rt(){A||!document.head||(A=document.createElement("style"),A.id=ft,A.textContent=ke,document.head.appendChild(A))}function It(){A?.remove(),A=null}function ge(e,t){e.wrapper.dataset.view=t,e.btnDiagram.setAttribute("aria-pressed",String(t==="diagram")),e.btnCode.setAttribute("aria-pressed",String(t==="code"))}function Ie(e,t){e.wrapper.dataset.view!==t&&(N?N(e,()=>ge(e,t)):ge(e,t))}function K(e,t){e.btnDiagram.hidden=!t,e.btnCode.hidden=!t}function L(e,t,r={}){e.statusKey=t,e.statusParameters=r,e.statusEl.textContent=w(t,r)}function ue(e,t,r,n=t){let a=w(t,r);e.wrapper.dataset.state="error",K(e,!1),e.pane.dataset.state="error",e.messageKey=t,e.messageParameters=r,e.pane.textContent=a,e.errorEl.textContent=a,L(e,n,r),ge(e,"code"),v.isOpenFor(e)&&(v.close(),e.codePane.focus({preventScroll:!0}))}function Dt(e){let t=e.pane.querySelector("svg");if(!t)return;let r=new Blob([Le(t)],{type:"image/svg+xml;charset=utf-8"}),n=URL.createObjectURL(r),a=document.createElement("a"),s=re(e.lastRendered)||"diagram";a.href=n,a.download=`mermaid-${s}.svg`,a.hidden=!0,document.body.appendChild(a),a.click(),a.remove(),setTimeout(()=>URL.revokeObjectURL(n),0),L(e,"downloaded")}function Nt(e){let t=e.code.textContent||"";if(!t)return;let r=()=>{e.btnCopy.textContent=w("copied"),clearTimeout(e.copyTimer),e.copyTimer=setTimeout(()=>{e.copyTimer=null,e.btnCopy.textContent=w("copy")},vt),L(e,"copied")},n=()=>{try{let a=document.createElement("textarea");a.value=t,a.setAttribute("readonly",""),a.style.cssText="position:fixed;top:-1000px;left:-1000px;opacity:0",document.body.appendChild(a),a.select();let s=document.execCommand?.("copy");a.remove(),s?r():L(e,"copyFailed")}catch{L(e,"copyFailed")}};navigator.clipboard?.writeText?navigator.clipboard.writeText(t).then(r,n):n()}function Bt(e){let t=e.code.closest(".md-code-block");return t?(t.setAttribute("data-dsh-mmd-c-host",""),t):null}function Ot(e){e.hostBlock?.removeAttribute("data-dsh-mmd-c-host"),e.hostBlock=null}function $t(e){let t=document.createElement("div");t.className="dsh-mmd-c",t.dataset.view="diagram";let r=document.createElement("div");r.className="dsh-mmd-c-bar",r.setAttribute("role","group");let n=document.createElement("span");n.className="dsh-mmd-c-badge",n.textContent="mermaid";let a=document.createElement("button");a.type="button",a.className="dsh-mmd-c-btn dsh-mmd-c-view-control",a.setAttribute("aria-pressed","true");let s=document.createElement("button");s.type="button",s.className="dsh-mmd-c-btn dsh-mmd-c-view-control",s.setAttribute("aria-pressed","false");let i=document.createElement("button");i.type="button",i.className="dsh-mmd-c-btn";let d=document.createElement("button");d.type="button",d.className="dsh-mmd-c-btn dsh-mmd-c-diagram-action";let m=document.createElement("button");m.type="button",m.className="dsh-mmd-c-btn dsh-mmd-c-diagram-action";let u=document.createElement("div");u.className="dsh-mmd-c-action-slot",u.append(d,m,i);let h=document.createElement("div");h.className="dsh-mmd-c-body";let l=document.createElement("div");l.className="dsh-mmd-c-pane",l.dataset.state="loading";let f=document.createElement("pre");f.className="dsh-mmd-c-code",f.tabIndex=-1,f.textContent=e.textContent||"";let E=document.createElement("div");E.className="dsh-mmd-c-error";let T=document.createElement("div");T.className="dsh-mmd-c-sr-only",T.setAttribute("role","status"),T.setAttribute("aria-live","polite"),T.setAttribute("aria-atomic","true"),h.append(l,f,E,T),r.append(n,s,a,u),t.append(r,h);let o={code:e,wrapper:t,bar:r,pane:l,codePane:f,errorEl:E,statusEl:T,badge:n,btnDiagram:a,btnCode:s,btnCopy:i,btnFullscreen:d,btnDownloadSvg:m,actionSlot:u,lastRendered:"",stableTimer:null,renderTimer:null,renderGeneration:0,viewAdjustment:0,viewportObserver:null,copyTimer:null,hostBlock:null,eager:!1,messageKey:"rendering",messageParameters:{},statusKey:null,statusParameters:{},tooltipPositioner:G};M.set(e,o),Pe(o),Fe()?ze().catch(()=>{}):!S&&!k&&Oe().catch(()=>{}),a.addEventListener("click",()=>Ie(o,"diagram")),s.addEventListener("click",()=>Ie(o,"code")),i.addEventListener("click",()=>Nt(o)),d.addEventListener("click",()=>v.open(o)),m.addEventListener("click",()=>Dt(o)),t._dshCode=e,I.add(t),o.stableTimer=setTimeout(()=>{o.stableTimer=null;let c=e.closest("pre");if(!e.isConnected||!c?.parentNode){P(o);return}c.parentNode.insertBefore(t,c),o.hostBlock=Bt(o),Y<wt&&(Y+=1,o.eager=!0,q(o)),typeof IntersectionObserver=="function"?(o.viewportObserver=new IntersectionObserver(p=>{p.some(g=>g.isIntersecting)&&(o.viewportObserver?.disconnect(),o.viewportObserver=null,o.eager||q(o))},{rootMargin:`${ht}px 0px`}),o.viewportObserver.observe(t)):o.eager||q(o)},gt)}async function Ft(e){let t=(e.code.textContent||"").trim();if(!t){P(e);return}if(t===e.lastRendered&&e.pane.dataset.state==="ok")return;let r=++e.renderGeneration;e.badge.textContent=re(t)||"mermaid",e.codePane.textContent=e.code.textContent||"",e.wrapper.dataset.state="rendering",K(e,!0),e.pane.dataset.state="loading",e.messageKey="rendering",e.messageParameters={},e.pane.textContent=w("rendering"),L(e,"rendering");let n=null;if(t.length>Ae)n={key:"tooLong",parameters:{actual:t.length,limit:Ae}};else{let i=t.split(`
64
+ `,le+1).length;i>le&&(n={key:"tooManyLines",parameters:{actual:i,limit:le}})}if(n){ue(e,n.key,n.parameters);return}let a=Be(t),s=F.get(a);if(s){e.pane.innerHTML=s.template.split(Ne).join(`dsh-mmd-c-${++ce}`);let i=e.pane.querySelector("svg");if(i){ae(i,w("diagramTitle",{type:e.badge.textContent||"mermaid"})),e.lastRendered=t,e.messageKey=null,e.messageParameters=null,e.wrapper.dataset.state="ok",K(e,!0),e.pane.dataset.state="ok",L(e,"rendered"),v.isOpenFor(e)&&v.update(e,!1);return}}try{let i=`dsh-mmd-c-${++ce}`,d=await kt(i,t).catch(()=>null),m=null;if(d&&(r!==e.renderGeneration||!e.wrapper.isConnected)||d&&(e.code.textContent||"").trim()!==t)return;if(!d){let l=await Oe();if(r!==e.renderGeneration||!e.wrapper.isConnected||(e.code.textContent||"").trim()!==t)return;_t(l),{svg:d,bindFunctions:m}=await l.render(i,t)}if(r!==e.renderGeneration||!e.wrapper.isConnected||(e.code.textContent||"").trim()!==t)return;e.pane.innerHTML=d;let u=e.pane.querySelector("svg");if(!u){ue(e,"renderEmpty",{},"renderFailedStatus");return}if(ae(u,w("diagramTitle",{type:e.badge.textContent||"mermaid"})),u&&m)try{m(u)}finally{let l=e.tooltipPositioner;l&&!l.disposed&&(l.instance||=z?.(document),l.instance?.trackCurrent())}e.lastRendered=t,e.messageKey=null,e.messageParameters=null,e.wrapper.dataset.state="ok",K(e,!0),e.pane.dataset.state="ok",L(e,"rendered");let h=`dsh-mmd-c-${ce}`;d.includes(h)&&Ct(t,h,d),v.isOpenFor(e)&&v.update(e,!1)}catch(i){if(r!==e.renderGeneration||!e.wrapper.isConnected||(e.code.textContent||"").trim()!==t)return;let d={detail:i?.message||String(i)};ue(e,"renderFailed",d,"renderFailedStatus")}}function q(e){if(e.renderTimer&&clearTimeout(e.renderTimer),e.renderTimer=null,!(e.code.textContent||"").trim()){P(e);return}let t=e.lastRendered?bt:0;e.renderTimer=setTimeout(()=>{e.renderTimer=null,qt(e)},t)}function zt(){return typeof requestIdleCallback=="function"?new Promise(e=>{requestIdleCallback(()=>e(),{timeout:400})}):new Promise(e=>setTimeout(e,16))}function qt(e){e.renderQueued||(e.renderQueued=!0,U.push(e),je())}async function je(){if(!me){me=!0;try{for(;U.length;){let e=U.shift();e.renderQueued=!1,e.wrapper.isConnected&&e.code.isConnected&&(await Ft(e),await zt())}}finally{me=!1,U.length&&je()}}}function he(e){!e||M.has(e)||!Ce(e)||(e.textContent||"").trim()&&$t(e)}function P(e){e.stableTimer&&clearTimeout(e.stableTimer),e.renderTimer&&clearTimeout(e.renderTimer),e.copyTimer&&clearTimeout(e.copyTimer),e.viewportObserver?.disconnect(),e.viewportObserver=null,e.eager&&(e.eager=!1,Y=Math.max(0,Y-1)),Ot(e),e.renderGeneration+=1,v.isOpenFor(e)&&v.close(),e.wrapper.remove(),I.delete(e.wrapper),M.delete(e.code)}function Pt(){for(let e of I){let t=e._dshCode,r=t?M.get(t):null;(!e.isConnected&&!r?.stableTimer||!t?.isConnected)&&(r?(P(r),t.isConnected&&he(t)):I.delete(e))}}function jt(e){let t=new Set,r=new Set;for(let n of e){if(n.type==="childList")for(let d of n.addedNodes)d.nodeType===Node.ELEMENT_NODE&&(d.matches?.("code")&&t.add(d),d.querySelectorAll?.("code").forEach(m=>t.add(m)));let a=n.type==="characterData"?n.target.parentElement:n.target,s=a?.matches?.("code")?a:a?.closest?.("code"),i=s?M.get(s):null;i?r.add(i):s&&t.add(s)}t.forEach(he),r.forEach(q),Pt()}function Vt(){for(let e of I){let t=M.get(e._dshCode);t&&(t.lastRendered="",q(t))}}function Gt(e){e.effect(()=>{if(typeof document>"u"||!document.body)return;be=qe(),At(),Rt();let t={disposed:!1,instance:null};G=t;let r=new MutationObserver(jt);r.observe(document.body,{childList:!0,subtree:!0,characterData:!0});let n=new MutationObserver(()=>{let d=V();d!==fe&&(fe=d,Vt())});n.observe(document.body,{attributes:!0,attributeFilter:se});let a=new MutationObserver(d=>{d.some(m=>m.attributeName==="lang")&&Mt()});a.observe(document.documentElement,{attributes:!0,attributeFilter:["lang"]});let s=d=>{d.key==="Escape"&&v.close()},i=()=>{v.isOpen()&&v.fit()};return document.addEventListener("keydown",s),window.addEventListener("resize",i),window.addEventListener("message",Re),document.querySelectorAll("pre code").forEach(he),()=>{r.disconnect(),n.disconnect(),a.disconnect(),document.removeEventListener("keydown",s),window.removeEventListener("resize",i),window.removeEventListener("message",Re),Lt();for(let d of[...I]){let m=M.get(d._dshCode);m?P(m):d.remove()}v.destroy(),t.disposed=!0,t.instance?.dispose(),G===t&&(G=null),It()}})}var Ut=[];
65
+ return module.exports;}});
package/lib/index.js ADDED
@@ -0,0 +1,32 @@
1
+ import { readFile } from 'node:fs/promises';
2
+
3
+ const inject = ['webServer'];
4
+ const RUNTIME_PATH = '/dsh-mermaid-custom/mermaid-runtime.js';
5
+ const runtimeFile = new URL('./mermaid-runtime.js', import.meta.url);
6
+
7
+ function apply(ctx) {
8
+ ctx.effect(() => ctx.webServer.register({
9
+ kind: 'exact',
10
+ path: RUNTIME_PATH,
11
+ async handler(req, res) {
12
+ if (req.method !== 'GET' && req.method !== 'HEAD') {
13
+ res.writeHead(405);
14
+ res.end();
15
+ return;
16
+ }
17
+ try {
18
+ const body = await readFile(runtimeFile);
19
+ res.writeHead(200, {
20
+ 'content-type': 'text/javascript; charset=utf-8',
21
+ 'cache-control': 'public, max-age=31536000, immutable',
22
+ });
23
+ res.end(req.method === 'HEAD' ? undefined : body);
24
+ } catch {
25
+ res.writeHead(404);
26
+ res.end();
27
+ }
28
+ },
29
+ }), 'dsh-mermaid-custom: runtime route');
30
+ }
31
+
32
+ export { RUNTIME_PATH, apply, inject };