HTML↔Markdown 转换、GFM 表格规范化、目录生成。
安装
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:omdsh-dev/dsh-tool-markdown
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
DSH Markdown 工具插件 —— HTML↔Markdown 转换、GFM 表格规范化、目录生成。零依赖、纯函数、手写轻量解析器。
动机
模型最常见的文档场景:用户贴一段 HTML(网页源码、邮件、导出文件)、贴表格要求整理、或要求"转成 markdown"。没有工具时模型只能硬编码处理——HTML 实体会错、表格会乱、网页噪音(导航/脚本/广告)会混入。本插件提供确定性转换,与 dsh-tool-csv 互补:csv 管结构化表格,markdown 管文档/网页。
安全模型
- 零依赖:手写递归下降 HTML 解析器(不引入 cheerio/jsdom——净增数十 MB 且是攻击面)
- 零执行面:不 eval、不 new Function、不加载远程资源、不解析 CSS 布局
- 内容剥离:script/style/iframe/object/noscript 内容整体剥离(安全 + 噪音)
- md2html 白名单:只输出
p h1-h6 ul ol li blockquote pre code a img strong em br hr table thead tbody tr th td;文本一律 HTML 转义——markdown 内嵌<script>只会显示为文本 - 链接 scheme 白名单:
http/https/mailto;javascript:/data:链接降级为纯文本 - 资源上限:嵌套深度 64 层报错(防栈溢出);输入
maxBytes默认 256KB、硬顶 1MB(超限报错不截断) - 工具参数会记入会话日志,不要传入含密钥/会话数据的 HTML
工具声明
注册 markdown 工具(@deepseek-ai/dsh-tool-markdown,row id tool-markdown),统一输出文本。
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
action |
string | ✅ | html2md / md2html / table / toc |
html |
string | html2md 输入(片段或完整文档) | |
markdown |
string | md2html/toc 输入 | |
text |
string | table 输入(HTML <table> 或管道分隔文本) |
|
baseUrl |
string | 相对 href/src 解析基准(naive join) | |
maxBytes |
integer | 输入上限,默认 256000,硬顶 1000000 |
Actions
| action | 功能 |
|---|---|
html2md |
HTML → GFM Markdown:块级/行内全映射、表格转 GFM(colspan 占位补齐)、实体解码、script/style 剥离、链接 scheme 过滤(不做 readability 正文选择,nav/header/footer 默认透传) |
md2html |
Markdown → 白名单安全 HTML:全文本转义,无标签可逃逸 |
table |
HTML <table> 或含未转义 | 的管道分隔文本 → GFM 表格(列补齐、| 转义、分隔行识别;无管道输入报错) |
toc |
Markdown 标题 → 嵌套目录列表(简化 GitHub 风格锚点:重复标题自动 -1/-2 后缀、跳过代码围栏内伪标题) |
示例
markdown { action: "html2md", html: "<h1>标题</h1><p>你好 <b>世界</b></p>" }
→ # 标题\n\n你好 **世界**
markdown { action: "md2html", markdown: "[x](javascript:alert(1))" }
→ <p>x</p> ← javascript: 链接降级为纯文本
markdown { action: "table", text: "a|b\n1|2" }
→ | a | b |\n| --- | --- |\n| 1 | 2 |
markdown { action: "toc", markdown: "# 标题一\n## 小节" }
→ - [标题一](#标题一)\n - [小节](#小节)
边界行为
| 情况 | 处理 |
|---|---|
| 未闭合标签 | EOF 自动闭合(与浏览器方向一致);<p> 中遇块级自动关闭 |
| 大小写 | 标签/属性名归一为小写 |
| 注释/DOCTYPE/CDATA | 剥离 |
| 实体 | 命名 + 数字实体解码;未知实体按字面保留(&lt; → <,不二次解码) |
| 嵌套列表 | li 只被新 li 关闭——嵌套 ul/ol 合法(2 空格/层缩进) |
| 空白 | 行内折叠为单空格;pre/code 原样保留 |
| 表格 | 首行(thead th 或首行 td)为表头;colspan=N 补 N-1 个占位单元格 |
| 深度 > 64 层 | markdown: HTML nesting exceeds 64 levels |
| 输入超限 | markdown: <label> exceeds N bytes(不截断) |
| md2html 内嵌 HTML | 原样转义为文本,绝无白名单外标签输出 |
DSH 0.1.5-rc.1 兼容(已验证)
本插件已迁移到 DSH 0.1.5-rc.1 依赖线,并在 local harness 0.1.5-rc.1 的隔离 consumer 中完成全链路验证:
- 类型/运行时:
@deepseek-ai/cordis@^4.0.1+@deepseek-ai/dsh-tools@>=0.0.1-rc.1 <0.2.0+@deepseek-ai/dsh-invariants@>=0.0.1-rc.1 <0.2.0(peer);不再依赖 unscopedcordis - 独立构建:
npm install(devDependencies 自包含 typescript/vitest/@types/node)→npm run typecheck→npm test→npm run build→npm pack - 消费验证:tarball 装入 0.1.5-rc.1 consumer →
dsh --profile compat --dump-config出现本插件 row → 工具真实注册与执行通过 - 启动方式:
npx -p @deepseek-ai/dsh@next dsh web(lib 生产模式;勿install -g全局安装)
安装
插件源码仓库:https://github.com/omdsh-dev/dsh-tool-markdown(public)。
Profile Bundle(推荐)
将本插件作为独立 bundle 安装到 profile(DSH 0.1.5-rc.1,npm):
# 交互式(web)profile
dsh plugin --profile web add github:omdsh-dev/dsh-tool-markdown
# 一次性任务(headless)profile —— dsh run 默认使用 headless
dsh plugin --profile headless add github:omdsh-dev/dsh-tool-markdown
包内 dsh.bundle.patch 会在安装后自动把插件加入 profile 的 layer stack(row id:tool-markdown)。
⚠️ web 与 headless 是不同 profile:web 安装不会自动覆盖 headless;
dsh run默认使用 headless profile。
npm pack tarball 安装
npm pack # 生成 dsh-tool-markdown-*.tgz
dsh plugin --profile web add ./dsh-tool-markdown-*.tgz
dsh plugin --profile headless add ./dsh-tool-markdown-*.tgz
验证安装
dsh --profile web --dump-config | grep tool-markdown
运行验证
dsh run "使用 markdown 工具把 <h1>标题</h1> 转成 Markdown"
手动安装与旧版本兼容
仅适用于不支持 Profile Bundle 的旧快照或插件开发调试环境(本地 junction/symlink、手动编辑 profile 层)。
测试
node <monorepo>/node_modules/vitest/vitest.mjs run tests
html.spec.ts:解析器边界(嵌套/未闭合/大小写/自闭合/注释/script 剥离/实体/畸形属性/深度守卫)html2md.spec.ts:块级与行内映射全表、表格(colspan/表头/转义)、scheme 过滤、baseUrlmd2html.spec.ts:白名单结构 + 安全(内嵌 script 转义、javascript: 降级、引号转义)table.spec.ts:HTML/管道输入、列补齐、\|转义;toc.spec目录与 slugifyregister.spec.ts:注册契约(AUDIT-CROSS-02 风格)
许可
MIT
链接
同类插件
tt-a1i/archify#integrations/deepseek-harness★ 92724
从仓库或系统描述生成经过校验的自包含交互式架构图、流程图、时序图、数据流图和生命周期图。
dream-num/dsh-univer-office★ 657
为 DeepSeek Harness 打造一个真正的办公环境。Univer Office 插件将电子表格、文档、幻灯片、画布、多维表格等汇聚到同一个运行时——数据互联、修改经过校验、变更按版本管理,并以隔离工作树支持多 Agent 协作。
ECNU/EduWork#dsh-knowledge-studio★ 275
基于工作区资料的 Studio,复用 DSH 模型与共享成果服务,制作报告、演示文稿、表格、思维导图、测验、闪卡及音视频。Office 生成需 Python 3.12+ 及相关依赖,并配置 DSH_OFFICE_PYTHON;媒体渲染需 Chromium;本地语音转写另需 whisper.cpp 和模型。
PerryLink/dsh-industry-research★ 215
面向 DeepSeek Harness 的确定性行业研究报告:公司与行业研究流程基于分阶段证据产出结构化、可核验的报告。
HuanLinOTO/dsh-plugin-mineru★ 51
向模型暴露 MineRU 文档解析工具。
PolinniZhong/dsh-knit★ 48
把会话工作区里已有的 Markdown 文档、源码、图片与视频列进 DSH 侧边栏,按与当前对话的相关性排序。默认的词法模式用最近几条消息在本地与标题、摘要、正文做带 IDF 加权的匹配(BM25)—— 不调用模型、没有网络出口,内容不出本机。列表来自工作区扫描,而不是「最近打开记录」,所以重启 DSH 或新开会话都不会变空。排序结果组织成主要 / 辅助 / 相关三层的阅读顺序,每一条都写明可核验的理由(命中了哪个字段、被哪一篇引用),点一行即可就地预览:Markdown 按渲染后的样子显示、相对路径图片真实渲染、源码走宿主自带的语法高亮、视频走 HTTP Range 流式播放。同一份 Context Pack 也作为 knit_docs 工具交给 agent。后续版本陆续补上读取证据与生命周期(归因在读那一刻冻结)、固定 / 排除(排除先于检索生效,且可恢复)、关系证据(引用 / 导入 / 测试,带行号)与增量索引(重启后复用)。v0.23 起还多一条可选的混合检索:默认关闭,只有你自己配好 Ollama 或 OpenAI 兼容的 embedding 服务才会生效。它生效时,发出去的是你这句查询原话加上每篇候选文件的标题与摘要 —— Markdown 的摘要取自正文首段(不超过 60 字),代码的摘要是它所在的工作区相对目录,图片 / 视频贡献的是文件名;完整正文与绝对路径都不发送,指向本机服务(loopback)时内容不出这台机器。v0.24 起还能做变更关联:用一条只读的 git status(固定 argv、不走 shell、子进程环境白名单),配合同一套引用 / 导入 / 测试 / 提及证据,指出这次改动大概率该一起看哪些文件 —— 默认关闭。语义检索的收益仍待真 provider 实测,因此不承诺召回提升。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。