- 开发工具
- IDE
- 代码编辑器
- 后端
【免费下载链接】openvscode-server
Run upstream VS Code on a remote machine with access through a modern web browser from any device, anywhere.
openvscode-server 继承了 VS Code 的内置扩展体系,其中mermaid-chat-features专门负责为内置聊天(built-in chat)提供基础的 Mermaid.js 图表渲染能力。本文以仓库中 extensions/mermaid-chat-features/README.md 为骨架,结合扩展的package.json、扩展宿主源码与聊天 Webview 前端源码,从配置开关、语言模型工具、输出渲染器、平移缩放交互到安全策略,完整梳理该扩展的工作机制与使用方式。读完本文,你将理解 Mermaid 图表在聊天输出中从"语言模型生成标记"到"Webview 交互式渲染"的完整链路,并掌握mermaid-chat.enabled、renderMermaidDiagram工具及上下文菜单命令的配置与行为。
扩展定位:内置、可禁用、不可卸载
mermaid-chat-features在 VS Code / openvscode-server 中属于随产品捆绑(bundled)的内置扩展。README 开篇即给出明确约束:
This extension is bundled with Visual Studio Code. It can be disabled but not uninstalled.
即:该扩展无法被卸载,但可以在扩展面板中禁用。其本地化描述(见 extensions/mermaid-chat-features/package.nls.json)将其功能概括为 "Adds Mermaid diagram support to built-in chats."——为内置聊天添加 Mermaid 图表支持,与 README 中 "Adds basic Mermaid.js diagram rendering to build-in chat" 相互印证。
从 package.json 可以看到它的关键元信息:
name/publisher:mermaid-chat-features/vscodeengines.vscode:^1.104.0(要求宿主至少为 1.104.0 版本)enabledApiProposals:["chatOutputRenderer"](依赖尚处于提案阶段的 Chat Output Renderer API,对应声明见 src/vscode-dts/vscode.proposed.chatOutputRenderer.d.ts)capabilities:支持virtualWorkspaces,且声明untrustedWorkspaces.supported = true(可在不受信任的工作区中运行)- 运行时依赖:
mermaid ^11.11.0、dompurify ^3.2.7(前者用于图表解析渲染,后者作为输出净化类依赖声明)
构建层面,扩展同时提供 Node 侧(esbuild.mts输出至dist)与浏览器侧(esbuild.browser.mts输出至dist/browser)两套产物,其聊天 Webview 资源则由 esbuild.webview.mts 以index、index-editor、codicon三个入口打包到chat-webview-out,分别对应聊天内联渲染页和编辑器预览页。
开关配置:mermaid-chat.enabled
扩展通过contributes.configuration暴露唯一一个用户可配置项:
"mermaid-chat.enabled": { "type": "boolean", "default": true, "description": "%config.enabled.description%", "scope": "application" }- 类型为布尔值,默认开启(
true),本地化描述为 "Enable a tool for Mermaid diagram rendering in chat responses."(在聊天回复中启用 Mermaid 图表渲染工具); scope为application,即该设置作用于应用级而非单个工作区,跨工作区保持一致;- 该开关的生效点体现在
languageModelTools贡献中的when条件:config.mermaid-chat.enabled,即只有在开关为真时,renderMermaidDiagram语言模型工具才会被暴露给聊天模型使用。
语言模型工具:renderMermaidDiagram
扩展向聊天模型注册了一个名为renderMermaidDiagram(展示名 "Mermaid Renderer")的语言模型工具,声明位于 package.json 的contributes.languageModelTools,并在 src/chatOutputRenderer.ts 中通过vscode.lm.registerTool完成实际注册。
工具的输入 Schema 如下:
{ "type": "object", "properties": { "markup": { "type": "string", "description": "The mermaid diagram markup to render as a Mermaid diagram. This should only be the markup of the diagram. Do not include a wrapping code block." }, "title": { "type": "string", "description": "A short title that describes the diagram." } } }markup:必填,仅允许传入 Mermaid 图表标记本身,不得包含包裹它的代码围栏(wrapping code block);title:可选,一句话概括该图表。
工具被调用后,invoke逻辑(writeMermaidToolOutput)做两件事:
- 生成标准的 Markdown Mermaid 代码块:通过
getFenceForContent动态计算围栏——统计内容中连续反引号的最大长度,取max(3, 最长连续反引号数 + 1),从而避免图表源码自身含反引号时破坏代码块;随后返回形如```mermaid\n<markup>\n```的LanguageModelTextPart,保证在纯文本环境(如不支持自定义渲染器的客户端)也能降级展示; - 附带自定义渲染数据:将
{ source, title }序列化为 JSON,以text/vnd.mermaid为 MIME 类型写入toolResultDetails2(提案 API 中的ToolResultDataOutput,见 vscode.proposed.chatOutputRenderer.d.ts),提示宿主使用自定义输出渲染器来渲染这段内容。
聊天输出渲染器:text/vnd.mermaid与vscode.chat-mermaid-features.chatOutputItem
扩展在contributes.chatOutputRenderers中声明了一个输出渲染器:
{ "viewType": "vscode.chat-mermaid-features.chatOutputItem", "mimeTypes": [ "text/vnd.mermaid" ] }viewType是渲染器的唯一标识,与 src/chatOutputRenderer.ts 中vscode.chat.registerChatOutputRenderer(viewType, renderer)注册时传入的字符串一致;mimeTypes声明该渲染器负责的 MIME 类型。结合源码注释(src/chatOutputRenderer.ts),该渲染器既会被工具生成的数据触发,也会用于渲染聊天历史中遗留的旧 Mermaid 图表——这正是decodeMermaidData兼容性的由来。
renderChatOutput的渲染流程(src/chatOutputRenderer.ts)可拆解为:
- 解码数据:
decodeMermaidData先把Uint8Array解码为文本,优先尝试按 JSON 解析(新格式,含source与可选title),解析失败则整体当作纯文本(旧格式),保证历史聊天记录仍可渲染; - 注册 Webview:为每次渲染生成唯一
webviewId,交给MermaidWebviewManager登记,并把openInEditor消息转发为_mermaid-chat.openInEditor命令; - 装配 Webview:
enableScripts: true、localResourceRoots指向chat-webview-out;HTML 中通过escapeHtmlText将 Mermaid 源码插入<pre class="mermaid">(对& < > " '五类字符做实体转义),并加载打包后的index.js与codicon.css; - 设置 CSP:页面采用严格的 Content-Security-Policy——
default-src 'none'; script-src 'nonce-…'; style-src <cspSource> 'unsafe-inline'; font-src data:;,脚本仅允许携带随机 nonce 的入口模块执行。
数据流总览:从模型输出到交互式图表
综合以上各环节,一条完整的数据链路是:
聊天模型调用 renderMermaidDiagram(markup, title) │ vscode.lm.registerTool → writeMermaidToolOutput ▼ 返回 Markdown 围栏代码块 + toolResultDetails2(text/vnd.mermaid, JSON) │ registerChatOutputRenderer 按 viewType 匹配 ▼ MermaidChatOutputRenderer.renderChatOutput → decodeMermaidData │ generateUuid + registerWebview(webviewManager 登记为 'chat' 类型) ▼ webview.html 注入(escapeHtmlText + CSP + nonce) → 加载 index.js ▼ mermaidWebview.ts:mermaid.initialize + mermaid.run → SVG 渲染 │ PanZoomHandler 接管平移缩放;MutationObserver 监听主题切换 ▼ 用户交互:悬停"Open in Editor"按钮 / 右键菜单(Reset Pan and Zoom、Copy Diagram Source)Webview 管理与单图单面板:webviewManager 与 editorManager
MermaidWebviewManager
src/webviewManager.ts 用一个Map<string, MermaidWebviewInfo>统一管理聊天输出与编辑器预览两类 Webview:
registerWebview(id, webview, mermaidSource, title, type):登记时若 id 已存在会抛出错误,返回的Disposable在销毁时自动注销并清理"活跃 Webview"标记;activeWebview/setActiveWebview:跟随编辑器面板焦点变化维护当前活跃项,供无参命令(如重置缩放、复制源码)定位目标;resetPanZoom(id?):向目标 Webview 发送{ type: 'resetPanZoom' }消息。
MermaidEditorManager
src/editorManager.ts 管理编辑器预览面板(viewType 为vscode.chat-mermaid-features.preview):
- 内容哈希去重:
getWebviewId对 Mermaid 源码做简单的 32 位哈希并转为十六进制作为面板 ID,保证"同一份图表内容只存在一个预览";再次打开同源图表时调用reveal()直接聚焦既有面板,避免重复创建; - 面板创建与恢复:新建面板时设置
ThemeIcon('graph')图标、retainContextWhenHidden: false,并注册WebviewPanelSerializer;窗口重开时通过deserializeWebviewPanel按持久化的{ webviewId, mermaidSource }状态恢复,恢复失败则显示错误页而非空白页; - 生命周期:预览关闭时从 Webview 管理器注销并从
_previews中移除,dispose()会级联销毁所有面板。
前端渲染与交互:平移、缩放与主题联动
聊天与编辑器共用同一套前端渲染逻辑 chat-webview-src/mermaidWebview.ts:
- 渲染入口:
mermaid.initialize({ startOnLoad: false, theme })后调用mermaid.run({ nodes: [diagram] })手动渲染,渲染完成后给元素加上rendered类使其从visibility: hidden变为可见; - 主题自适应:
getMermaidTheme依据vscode-dark/vscode-high-contrast等 body 类判定深色主题;MutationObserver监听 body class 变化,主题切换时清空data-processed并用新主题重新渲染; - PanZoomHandler(mermaidWebview.ts)提供完整的图表浏览交互:
- 缩放范围限制在0.1x ~ 5x(
minScale/maxScale),默认zoomFactor = 0.002; - Alt + 鼠标拖拽平移、Alt + 单击放大(×1.25)、Alt + Shift + 单击缩小(×0.8);
- 触控板**双指捏合(pinch)**缩放(走
ctrlKey分支,放大因子 ×5 以补偿较小的 deltaY)、Alt + 双指滚动缩放; - 平移/缩放后的
{ scale, translateX, translateY }通过vscode.setState持久化,再次打开同一 Webview 时restoreState直接恢复,未交互过则居中显示并在 resize 时重新居中; - 收到
resetPanZoom消息(来自右键菜单命令)时重置为 1x 并清除持久化状态。
- 缩放范围限制在0.1x ~ 5x(
- 两个入口页面的差异:聊天页 index.ts 额外绑定"Open in Editor"悬浮按钮,点击向扩展宿主发送
openInEditor消息;编辑器页 index-editor.ts 则装配右上角放大 / 缩小 / 重置三枚缩放控制按钮。
命令与菜单:面向 Webview 上下文的三个内部命令
package.json 的contributes.commands注册了三个内部命令(_前缀表明是私有命令):
| 命令 | 标题 | 使用场景 |
|---|---|---|
_mermaid-chat.resetPanZoom | Reset Pan and Zoom | 重置平移与缩放 |
_mermaid-chat.openInEditor | Open Diagram in Editor | 在编辑器预览中打开图表 |
_mermaid-chat.copySource | Copy Diagram Source | 复制图表 Mermaid 源码 |
它们的调度逻辑:
commandPalette菜单项全部设置"when": "false",因此不会出现在命令面板,只能通过 Webview 上下文触发;webview/context菜单按webviewId条件投放:resetPanZoom仅出现在聊天输出项(vscode.chat-mermaid-features.chatOutputItem);copySource在聊天输出项与编辑器预览(vscode.chat-mermaid-features.preview)中均可用;- 实现上(src/extension.ts),命令接收
{ mermaidWebviewId? }上下文参数,优先定位指定 Webview,缺省时回退到activeWebview;copySource直接调用vscode.env.clipboard.writeText写入该 Webview 保存的mermaidSource。
安全设计:CSP、HTML 转义与不受信任工作区
由于聊天输出可能来自模型生成的内容,渲染侧在安全上做了多重防护:
- 严格的 CSP:聊天与预览页面均声明
default-src 'none',仅放行带 nonce 的内联脚本与cspSource样式的 webview(见 chatOutputRenderer.ts 与 editorManager.ts); - 输出转义:Mermaid 源码在注入
<pre>前经过 src/util/html.ts 的escapeHtmlText(转义& < > " '),阻断 HTML 注入;随后浏览器页面本身先隐藏(visibility: hidden),待mermaid.run完成渲染、内容由 Mermaid 库解析为 SVG 后才显示; - 依赖净化库:扩展依赖中声明了
dompurify ^3.2.7作为净化类依赖; - 工作区策略:
capabilities.untrustedWorkspaces.supported = true,表明扩展在不受信任工作区中也被判定为安全可用,与上述内容不直接执行任意页面脚本的设计一致。
使用方式与注意事项
- 开关控制:在设置中搜索
mermaid-chat.enabled即可启用/禁用聊天中的 Mermaid 渲染工具(默认开启,应用级作用域)。禁用后renderMermaidDiagram工具的when条件不满足,聊天模型将不再暴露该工具; - 提示词使用:直接请聊天模型"画一个 Mermaid 流程图/时序图/状态图"即可触发该工具;模型会返回
markup(仅图表标记)与可选的title; - 交互操作:在聊天输出或编辑器预览中,按住 Alt 拖拽平移、Alt+单击缩放、触控板捏合缩放;右键可重置缩放或复制图表源码;聊天输出右上角悬浮按钮可一键把图表打开到编辑器预览;
- 内置属性限制:该扩展随产品捆绑、不可卸载,只能在扩展管理中禁用;它提供的是"基础(basic)"渲染能力,依赖宿主版本 ≥ 1.104.0 及
chatOutputRenderer提案 API。
小结
mermaid-chat-features是 openvscode-server 聊天生态中一个小而完整的内置扩展:它以renderMermaidDiagram语言模型工具为入口、以text/vnd.mermaid自定义 MIME 为传输媒介、以ChatOutputRenderer提案 API 为渲染桥梁,最终在严格 CSP 的 Webview 中交付带平移缩放、主题联动、编辑器预览与源码复制能力的 Mermaid 图表。阅读 README.md、package.json、src/chatOutputRenderer.ts、src/editorManager.ts 与 chat-webview-src/mermaidWebview.ts,可以完整复现这套"模型生成 → 工具输出 → 渲染器分发 → Webview 交互"的扩展开发范式。
- 开发工具
- IDE
- 代码编辑器
- 后端
【免费下载链接】openvscode-server
Run upstream VS Code on a remote machine with access through a modern web browser from any device, anywhere.
相关推荐
beautiful-mermaid 实战:Mermaid 图表的 SVG / ASCII 双渲染与双色主题系统深度解析
beautiful mermaid 实战:Mermaid 图表的 SVG / ASCII 双渲染与双色主题系统深度解析 本文以 beautiful mermai
数据可视化@streamdown/mermaid:为 Streamdown 打造的流式 Mermaid 图表渲染插件
@streamdown/mermaid:为 Streamdown 打造的流式 Mermaid 图表渲染插件 Streamdown 是一个面向 AI 流式输出的
前端AI 应用UI组件在 react-pdf 文档中渲染 Mermaid 图表:@react-pdf/mermaid 完全指南
在 react pdf 文档中渲染 Mermaid 图表:@react pdf/mermaid 完全指南 导读 本文基于 react pdf 仓库中的 pack
PDF生成后端前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考