# dsh-pele-mermaid [English](README.md) | 简体中文 · [GitHub](https://github.com/lsy1998/dsh-pele-mermaid) · [Issues](https://github.com/lsy1998/dsh-pele-mermaid/issues) ```powershell git clone https://github.com/lsy1998/dsh-pele-mermaid.git cd dsh-pele-mermaid npm install npm run build ``` 在 DeepSeek Harness(DSH)Web 界面中用 **Pele** 把 Mermaid 围栏代码块渲染为 SVG 图表, **不打包也不加载 mermaid.js 运行时**。 [Pele](https://github.com/obsidianmd/pele) 是 Obsidian 团队出品的轻量 Mermaid 转 SVG 渲染器 (`pele@1.6.0`,MIT)。它支持 **Mermaid 12.1.0** 内置的全部图表类型,并使用 CSS 变量适配主题。 每个 Mermaid 代码块都会获得 **代码 / 图表** 切换、全屏缩放查看器、独立 SVG 导出、DSW 主题适配, 以及渲染失败时回退到源代码的能力。 - 包名:`dsh-pele-mermaid` `0.1.0` - 目标 profile:`desktop`,由 DSH 桌面应用管理 - 渲染器:`pele@1.6.0`,由插件自身的同源路由提供 ## 功能 - 渲染 `mermaid`、`mermaidjs`、`mmd` 围栏代码块;也能识别 DSH/Shiki 的纯文本回退情形 (code 元素没有 `language-` 类)——此时只有 Pele 的 `detectType()` 能识别类型、且首词是已知 Mermaid 关键字才会渲染。 - 绝不处理带有其他 `language-*` 类的代码块,也绝不处理行内 `code`。 - **代码 / 图表** 切换按钮带 `aria-pressed`;默认显示图表视图,切换回代码视图时保留原始 `pre`。 - 工具栏徽标显示识别出的图表类型并标注 “Pele”,另有全屏与 **下载 SVG** 操作。 - 就地缩放与平移:工具栏上的**放大 / 缩小 / 重置缩放**按钮,按住 `Ctrl`(或 `Cmd`)滚动滚轮以指针为中心 缩放,拖拽可平移,也可使用 `+`、`-`、`0` 与方向键。普通滚轮仍会正常滚动页面。该状态按代码块独立保存, 图表重新渲染后重置。 - 全屏查看器:放大 / 缩小 / 重置 / 适应窗口、拖拽平移、`Ctrl` 或 `Cmd` + 滚轮以指针为中心缩放、 `Escape` 关闭;打开时焦点被限制在对话框内,关闭后回到触发控件;使用 `role="dialog"` 与 `aria-modal="true"`。 - 导出名为 `pele--YYYYMMDD-HHmmss.svg` 的独立 `.svg`,其根元素带有解析后的主题变量, 离开 DSH 后外观一致。 - 把 DSW 设计令牌映射为 Pele 的 CSS 变量以适配明暗主题;颜色变化无需重新渲染,纯几何变化才重绘。 - 渲染失败时回退到图表源码并显示本地化错误信息(Pele 提供行/列时一并显示),不会留下破损图表。 - 单个图表超过 **50,000 字符** 或 **2,000 行** 时在渲染前拒绝,保留源码并显示本地化提示。 - 所有插件自带文案均有 **英文** 与 **简体中文**,并随文档语言变化实时切换。 - 通过串行队列渲染,图表之间让出主线程以保持页面响应;流式输出期间丢弃过期的异步结果。 - 幂等且可释放:反复启用/禁用不会残留重复工具栏、观察器或监听器。 - 无障碍:本地化 `aria-label`、渲染图表的可访问名称、`aria-live` 礼貌播报状态, 并保留 `focus-visible` 焦点轮廓。 ## 环境要求 - 使用 `desktop` profile 的 DSH Web 界面。本版本已在随应用分发的桌面运行时 `0.2.1-rc.2` (`@deepseek-ai/dsh-desktop` 与 `@deepseek-ai/dsh` `0.2.1-rc.2`)以及独立 `dsh` CLI `0.1.7-rc.1` 上核对。 - 从源码构建需要 Node.js 22.18 或更高版本(本版本的构建与测试环境);包内声明 `engines.node >= 22.18.0`。 - DSH 目前是开发者预览版,其插件加载器与 Markdown DOM 可能随版本变化。 ## 安装 本插件以 DSH profile 插件包(bundle)的形式发布。其 `package.json` 声明 `dsh.bundle.patch = ./cordis.patch.yml`,插入 bundle 条目 `ui-pele-mermaid`。 ### 推荐:通过 DSH 应用安装(desktop profile) `desktop` profile 由 DSH 桌面 / Web 应用管理,请从应用内安装: 1. 克隆仓库并构建: ```powershell git clone https://github.com/lsy1998/dsh-pele-mermaid.git cd dsh-pele-mermaid npm install npm run build ``` 2. 打开 DSH Web 界面,在侧边栏选择 **Plugins**(插件)页面。 3. 选择安装插件,指向刚才克隆下来的绝对目录,例如 `C:\path\to\dsh-pele-mermaid` (可用 `Resolve-Path` 查看)。 4. 等待执行完成,并启用它新增的 bundle。 5. 重启 DSH Web 或刷新页面,然后打开包含 Mermaid 代码块的会话。 应用会自行执行包管理器调用并注册新的 bundle。等价的命令是: ```powershell dsh plugin --profile desktop add -w --save-exact ``` > **已核实的注意事项。** 独立 `dsh` CLI 会拒绝 `desktop` profile: > `dsh plugin --profile desktop --help` 以状态码 1 退出,并输出 > `error: profile "desktop" is managed exclusively by the Electron application`;该限制 > (`rejectElectronProfile`)同时存在于全局安装的 `@deepseek-ai/dsh` `0.1.7-rc.1` 与随应用 > 分发的 `0.2.1-rc.2` 中。请在应用管理的环境中(**Plugins** 页面)执行该形式,而不要在普通终端 > 中执行。`--profile web` 是可用 CLI 安装的替代方案。 ### 命令行(web profile) ```powershell dsh plugin --profile web add -w --save-exact ``` 若没有全局 `dsh` 命令,可通过 `npx` 调用已发布的 CLI(需要网络): ```powershell npx.cmd --yes @deepseek-ai/dsh plugin --profile web add -w --save-exact ``` 安装后请重启 DSH Web 或刷新页面。 ### 安装脚本 `bin/dsh-pele-mermaid.mjs`(同时以 `dsh-pele-mermaid` 命令名提供)封装了同一条命令: ```powershell # 在包目录下执行 node bin/dsh-pele-mermaid.mjs install node bin/dsh-pele-mermaid.mjs install --profile web --source . node bin/dsh-pele-mermaid.mjs uninstall --profile web node bin/dsh-pele-mermaid.mjs --help ``` - 支持 `install [--profile <名称>] [--source ]` 与 `uninstall [--profile <名称>]`。 - `--profile` 默认是 `web`,因为 CLI 无法管理 `desktop`;传入 `--profile desktop` 会被拒绝并给出 说明。 - `--source` 接受包规格、绝对路径,或相对当前目录解析的 `./` 相对路径;不传时安装脚本自身 所在的包目录。 - `--help` 打印英文与简体中文双语用法。 - 脚本转发为 `dsh plugin --profile <名称> add -w --save-exact `(卸载为 `remove -w <包名>`);找不到 `dsh` 时以非零状态退出并给出清晰提示。 `desktop` profile 请改用应用内的 **Plugins** 页面:CLI 无法管理它。 ## 更新与卸载 web profile: ```powershell dsh plugin --profile web update -w dsh-pele-mermaid dsh plugin --profile web remove -w dsh-pele-mermaid ``` `desktop` profile 请在应用的 **Plugins** 页面更新或移除该 bundle。 更新或卸载后请重启 DSH Web 或刷新页面。 ## 使用 让模型输出一个 Mermaid 围栏代码块: ````markdown ```mermaid flowchart LR A[Code] --> B[Diagram] ``` ```` 该代码块会变成一个包裹原始 `pre` 的卡片。默认显示图表视图;点击 **代码** 显示未改动的源码, 点击 **图表** 切回。渲染成功时,全屏与 **下载 SVG** 始终可用。 ## 行为与限制 | 方面 | 行为 | | --- | --- | | 识别 | class 含 `language-mermaid`、`language-mermaidjs` 或 `language-mmd`(不区分大小写)的 `pre > code` 块。带其他 `language-*` 类的块绝不处理。 | | 纯文本回退 | 没有 `language-` 类的 code 元素,仅当 Pele 的 `detectType()` 返回类型 **且** 首词是已知 Mermaid 关键字时才按 Mermaid 处理。 | | 幂等 | 已在 `[data-dsh-pele-mermaid]` 内的 `pre` 会被跳过;处理过的块标记 `data-dsh-pele-mermaid-block`,仅外层容器带 `data-dsh-pele-mermaid`。重复处理同一块不会产生副作用。 | | 切换 | 工具栏含类型徽标与代码/图表按钮(`aria-pressed`)。默认图表视图,保留原始 `pre`。 | | 渲染 | 通过 `window.pele.mount(element, source, options)`,使布局随容器宽度自适应。选项:`maxWidth`、`autoDirection`、`padding`、`icons: () => null`、`links: true`、`linkRel: 'noopener'`。 | | 主题 | 在插件容器上把 DSW 令牌映射为 Pele CSS 变量;暗色主题或文档语言变化时重新应用。 | | 错误 | `PeleError`(或任何抛出的值)会显示源码与本地化信息,可用时带行列号。错误文本一律按文本插入,绝不作为 HTML。 | | 限制 | 每块 50,000 字符、2,000 行。超限块保留源码并显示本地化提示,永不渲染。 | | 流式 | 每块使用单调递增的代数计数器;源码变化或节点脱离时丢弃结果。渲染经串行队列,图表之间让出主线程。 | | 就地缩放 | 工具栏提供放大 / 缩小 / 重置缩放按钮;内联面板同时支持 `Ctrl`/`Cmd` + 滚轮以指针为中心缩放、拖拽平移,以及 `+`/`-`/`0`/方向键。普通滚轮不会被拦截。状态按块独立保存,重新渲染后重置。 | | 查看器 | 全屏浮层:放大/缩小/重置/适应窗口、拖拽平移、`Ctrl`/`Cmd` + 滚轮缩放、`Escape` 关闭、焦点锁定、标签本地化。打开时沿用内联缩放,关闭时恢复内联的滚动位置与缩放。 | | 导出 | 独立 `.svg`,其根元素带有解析后的主题变量。导出始终是**自然尺寸下的完整图表**,事先缩放或平移不会裁剪它。 | | 国际化 | 所有用户可见文案来自消息表;支持 `en` 与 `zh-CN`;语言取自 `document.documentElement.lang` 或 `navigator.language`,支持实时切换。 | | 释放 | 观察器与监听器注册在插件 effect 作用域内,清理时释放;重复 apply/cleanup/apply 不产生重复。 | 另外,Pele 自身的源码 `limit` 默认也是 50,000 字符,超限时抛出 `limit` 错误,与本插件的检查一致。 ## 主题 插件把 DSW 设计令牌映射为 Pele 的 CSS 变量,并输出在自己的 `.dsh-pm` 容器上,供 Pele 继承。 第一个有定义的令牌生效;令牌为空时保留 Pele 自身默认值。 | Pele 变量 | DSW 令牌(第一个有定义的生效) | | --- | --- | | `--pele-bg` | `--dsw-alias-bg-layer-2` → `--dsw-alias-bg-base` → `transparent` | | `--pele-fg` | `--dsw-alias-label-primary` → `currentColor` | | `--pele-muted` | `--dsw-alias-label-tertiary` | | `--pele-line` | `--dsw-alias-border-l1` → `--dsw-alias-label-secondary` | | `--pele-surface` | `--dsw-alias-bg-layer-1` | | `--pele-surface-alt` | `--dsw-alias-bg-layer-2` | | `--pele-border` | `--dsw-alias-border-l2` → `--dsw-alias-border-l1` | | `--pele-accent` | `--dsw-alias-button-primary-fill` → `--dsw-alias-brand-primary` | | `--pele-font` | `--ds-font-family-default` → `--ds-font-family-interface` → `sans-serif` | | `--pele-error` | `--dsw-alias-state-error-primary` | 未映射的 Pele 变量(例如 `--pele-critical` 以及 `--pele-series-1` 到 `--pele-series-8`) 保留 Pele 内置默认值。图表内 `style`、`classDef`、`linkStyle` 指定的颜色由图表固定,不随主题变化。 插件自身的界面(工具栏、徽标、按钮、查看器)使用 DSW 设计令牌 —— `--dsw-alias-*`、 `--ds-font-family-code`、`--dsw-font-markdown-code-block` —— 并为每个取值提供字面量回退, 同时尊重 `prefers-reduced-motion`。 ## 架构 本包是一个双面(dual-face)DSH 插件 bundle: - **宿主面** — `lib/index.js` 是 Cordis(Node)插件,注入 `webServer` 并注册唯一的精确路由 `/dsh-pele-mermaid/pele-runtime.js`。`GET` 或 `HEAD` 请求返回内置的 Pele 脚本,内容类型为 `text/javascript` 并带不可变缓存头;其他情况返回 404 或 405。路由注册在 `ctx.effect(...)` 内,释放时被移除。 - **客户端面** — `lib/client.js` 以 `dsh-pele-mermaid` 注册到 DSH 客户端模块加载器。它 **不** 打包 Pele。检测到第一个 Mermaid 块时注入 `