@benz-ai-x/dsh-md-preview
v0.10.0
Published
DSH markdown preview: clicking a markdown document in the conversation opens a rendered preview panel docked to the right of the chat.
Maintainers
Readme
English | 中文
@benz-ai-x/dsh-md-preview
DSH Web GUI 插件:点击对话中出现的 Markdown 文档,在对话右侧打开渲染后的预览面板;支持受守卫编辑与工作区目录树浏览。
效果
- 回合产出文件 chip 行中的
.md/.markdown文档:点击打开右侧预览面板,渲染 GFM、代码高亮和 TeX。 - 每条助手消息的操作区新增「预览文档」按钮,列出该回合产出的 Markdown 文档。
- 非 Markdown 产出文件保持原有行为(交给系统打开)。
- 文档侧边栏:宽屏展开时让对话区自动缩窄,低于 1056px 或全屏时覆盖展开。头部「Session 日志」右侧使用原生回形针图标,一键开合工作区浏览,面板右上 × 关闭;未保存修改仍先询问。宽度默认取半屏、最多 720px,记忆 360–1200px 的手动拖宽偏好,并按可用空间钳制。原生导航与工具详情保留各自操作;Esc 关闭后焦点返回入口。布局适配依赖锁定基线,见 ADR-0004。
- 没有预览目标时面板不渲染。
- 字体与主题对齐 Harness:导航主文字 14px/20px、父目录路径 12px/18px,统一图标与控件尺寸。搜索固定在浏览区顶部,条目独立滚动;导航初始宽 220px,保留手动宽度偏好。面板从框架顶部停靠,自身保留工作区/返回与关闭入口;聚焦文档身份可查看完整路径和版本。编辑器使用平台浅/深主题与代码字体,正文在各种宽度下均保持平台 Markdown 段落节奏。
- 编辑:面板「编辑」进入 CodeMirror 编辑器(行号、GFM 高亮、Cmd/Ctrl-S 保存),「保存」写回工作区、显示「✓ 已保存」提示并回到渲染视图,「取消编辑」丢弃草稿;只编辑已存在的文件。保存失败(非冲突)会显示错误码并提供【重试】。
- 冲突保护:保存时若文件已被其它方(agent、其它会话、外部编辑器)修改,提示「文件已变化」,由你选择【重新加载】或【强制覆盖】;带未保存修改关闭面板会先询问。
- 工作区浏览:面板头部「工作区」进入目录树(懒展开、加载/空/失败三态);单击
.md富渲染、.txt等纯文本等宽展示、其它类型明确提示不支持;当前文档在树中高亮并自动定位;支持方向键/Enter 键盘遍历;头部路径面包屑。已展开目录在每次重进浏览脸时静默重验(树工具栏也有刷新按钮)——agent 会在会话中途持续产出文件,刷新失败绝不清空现有列表。 - 大纲导航:头部「大纲」弹层列出文档的 ATX 标题(代码围栏内的
#不算);点击后查看脸滚动到渲染标题、编辑脸跳转光标到源行。 - 侧栏 rail(≥640px):文件树与大纲常驻面板左侧(「文件|大纲」记忆选择),文档不再被浏览替换;<640px 回退换脸/弹层;Mod-Shift-O/E 直达、Esc 收弹层。
- 分段控件与编辑反馈:「预览|编辑」常驻切换(脏草稿切回走守卫);状态栏实时 Ln/Col/字数与常驻「已保存」时间;撤销/重做按钮;Mod-B/I/K 排版键(? 查看键位);含内联 HTML 的文档进编辑时一次性预警。
- 工作区搜索:浏览区搜索框按名称搜索整个会话工作区的文档——未展开目录也覆盖——由宿主可取消遍历完成,绝不读取正文。名称不区分大小写子串匹配;每条结果同时显示名称与工作区相对路径(同名文档可分辨);打开结果仍走完整读取与守卫。状态诚实可辨:搜索中…;「没有结果」只在完整搜索且零命中时出现;「结果不完整」会说明原因(目录读取失败/遍历或数量上限)并保留已得结果;失败给出错误码与重试。输入新词即取消旧搜索,清空后精确恢复原浏览展开状态。(与编辑器内查找是两回事。)
- 快捷入口:树上方两小节——「当前回合产出」列出最新回合产出的可预览文档(owning service 回合事实、按关闭序号截断、回合进行中实时更新),「最近阅读」按近期使用列出本会话读过的文档。两节均显示名称加路径,打开走同一守卫路径并重新读取;来源为空时该节隐藏;「继续阅读」入口保持自己的独立席位与语义。
- 阅读位置跟踪:大纲弹层高亮当前阅读位置所在的节——查看脸按滚动位置、编辑脸按光标源行推导,并保持该条目在弹层视野内。头部在草稿未保存时显示脏点,版本号折入路径提示,查找/保存按钮标注快捷键;查找面板已本地化并显示匹配计数(n/m)。
- 编辑器查找:编辑脸带 CodeMirror 搜索面板(头部按钮与 Mod/Ctrl-F)。
- Mermaid 图表:
```mermaid围栏块在文档渲染定型后增强为图表;块横幅保留(复制仍取源码),任何失败回退纯代码块。mermaid 内联进 client bundle 但惰性求值(首个图表才付解析成本;bundle 约 3.9 MB minified / 1.1 MB gzip)。
安装
要求 DSH 基线 0.1.2-rc.1(即 peerDependencies 所列版本)和 web profile。
dsh plugin --profile <name> add @benz-ai-x/dsh-md-preview
dsh --profile <name> --dump-config # 应出现 id: md-preview 的行
dsh --profile <name> # 打开 Web GUI;回合产出 .md 后点击 chip 预览
dsh plugin --profile <name> remove @benz-ai-x/dsh-md-preview三种安装形态(依 DSH 打包与安装规范)
| 形态 | 命令 | 状态 |
| --- | --- | --- |
| npm(推荐) | dsh plugin --profile <name> add @benz-ai-x/dsh-md-preview | ✅ 预构建产物,即装即用 |
| tarball | dsh plugin --profile <name> add ./benz-ai-x-dsh-md-preview-<ver>.tgz(tarball 由源码 pnpm pack:publishable 产出) | ✅ 预构建产物,无需任何构建授权 |
| Git 直装 | dsh plugin --profile <name> add github:benz-ai-x/dsh-md-preview#<sha> | ✅ 由包自带的自包含 prepare 从源码构建(纯转译,此形态不带类型声明)——见下文 |
git 安装拉取的是源码,pnpm 在得到显式允许前拒绝运行 git 依赖的 prepare。首次 add 失败后,把 pnpm 打印的确切包键复制进该 profile 的 pnpm-workspace.yaml:
allowBuilds:
'@benz-ai-x/dsh-md-preview': true然后重新执行 add。授权构建 = 允许该包的代码在安装时于你的机器上执行 —— 只对可信源码授权,并用 #<sha> 锁定 commit,让后续推送无法悄悄改变实际运行的内容。
配置
- id: md-preview
name: '@benz-ai-x/dsh-md-preview'
config:
maxBytes: 1048576 # 单文件读取上限(字节)
allowedExtensions: ['.md', '.markdown']| 字段 | 类型 | 默认 | 说明 |
| --- | --- | --- | --- |
| maxBytes | number | 1048576 | 单文件读/写上限,超出返回 too-large |
| allowedExtensions | string[] | [".md", ".markdown"] | 可编辑的扩展名白名单 |
| previewExtensions | string[] | [".md", ".markdown", ".txt"] | 可预览的扩展名(可编辑集的超集;纯文本成员只读展示) |
失败码
读取失败时面板显示 md-preview/<reason>。所有失败码:
| 码 | 含义 |
| --- | --- |
| md-preview/bad-request | path 为空或非法;或保存时既无指纹也未强制 |
| md-preview/unknown-session | 会话不存在 |
| md-preview/no-workspace | 会话没有工作目录 |
| md-preview/unsupported-extension | 扩展名不在白名单 |
| md-preview/forbidden | 路径超出会话工作区 |
| md-preview/not-found | 文件不存在(编辑只针对已存在文件) |
| md-preview/too-large | 文件(读取)或内容(写入)超过 maxBytes |
| md-preview/conflict | 保存时文件已变化(指纹不匹配且未强制) |
| md-preview/unavailable | 读/写过程发生 IO 错误 |
已知限制
- 正文中内联提到的
.md文件名仍走系统打开(归 ui-deliverables 所有,不归本插件)。 - 文档侧边栏通过锁定基线的可释放布局适配预留空间,窄屏覆盖展开;升级 Harness 需重新验证布局适配,原生工具详情贡献保留。
- 用户上传的文档附件不可预览(目前没有对应的会话面)。
- 大纲只收 ATX 标题(setext 下划线式标题会渲染但不进弹层)。
- Mermaid 用默认主题;混用缩进代码块与围栏块的文档整体跳过图表增强(顺序对齐安全检查)。
开发(source-linked)
pnpm install
pnpm verify # context:check:strict + typecheck + test + build + built:check
pnpm context:link # 需要源码联调时:重写 link: 指向 Harness 检出并刷新 lockfile(默认 registry)
pnpm watch:client # 客户端 bundle 热构建结构
| 部分 | 位置 | 说明 |
| --- | --- | --- |
| Host Remote | src/remote.ts | mdPreview/read(sessionId, path, signal);工作区限域、扩展名白名单、字节上限 |
| Remote contribution | src/typert/remote-client.ts | 手工维护的浏览器端描述符(生成器产物的等价物) |
| 浏览器入口 | src/client/index.ts | 挂载 Remote + 注册三个 Slot 贡献 |
| 预览面板 | src/client/PreviewOverlay.tsx | shell.overlay(list,增量);仅渲染 + 几何 |
| 会话机器 | src/client/preview-session.ts | 纯 reducer:读取/编辑/保存/提示的完整状态代数 |
| 编辑器 | src/client/editor.tsx | CodeMirror 6(精选扩展集含搜索面板,构建期内联) |
| 工作区树 | src/client/WorkspaceBrowser.tsx | 懒树:高亮/自动定位/键盘遍历 + 静默重验 |
| 大纲 | src/client/outline.ts | ATX 标题扫描 + 渲染标题定位 |
| 图表增强 | src/client/diagrams.ts | 渲染后 mermaid 增强,失败回退代码块 |
| chip 行接管 | src/client/MdChips.tsx | conversation.chat.turnTail(chain,仅认领含 Markdown 的回合) |
| 消息操作 | src/client/PreviewAction.tsx | conversation.chat.assistant-actions(list,增量) |
真实 profile 验证(本地检出)
pnpm build
dsh plugin --profile <name> add ./dsh-md-preview
dsh --profile <name> --dump-config
dsh --profile <name> # 打开 Web GUI,写一个 README.md 产出并点击 chip
dsh plugin --profile <name> remove @benz-ai-x/dsh-md-preview打包与发布
pnpm pack:publishable # 打出净化 manifest 的 tarball 并复检(无 devDeps、无 link:/workspace:)
pnpm publish:registry # 以同一净化流程发布到 npmsource-linked 验证证明与固定 Harness 检出(见 dsh-reference.lock.json)的兼容性;发布形态以 packed tarball 在干净 profile 中的安装/启动/移除冒烟为准。
许可证
MIT
