dsh-md-html-render:把 Markdown 渲染成可以直接發走的單文件 HTML

前言

在 DSH(DeepSeek Harness)裏跑任務,經常有一種中間產物不知道往哪放:模型寫的遷移方案、對比表、報告草稿。留在對話裏就是一大坨 Markdown,複製出去排版就散;丟給別的渲染器又多一步導出。這個插件解決的就是這一步:在 profile 裏裝一個渲染器,模型那邊直接產出一份自包含的 HTML 文件,Web GUI 那邊有一個抽屜式的預覽與導出入口,兩條路背後是同一個渲染器。

插件倉庫目錄頁在 SkillHub 的「客戶端」分類下,記錄星標 1 個。維護者是 YaoleWu,倉庫地址爲 https://github.com/YaoleWu/dsh-md-preview 。下面介紹它的能力、安裝方式和使用注意點。

這是什麼

一句話:md_html_render 是模型可調用的工具,給它 Markdown,返回一份完整的自包含 HTML 文檔,可選寫入磁盤;同時在 Web 會話頭部有一個 MD 抽屜,可以就地瀏覽工作目錄裏的 Markdown 文件、渲染、編輯並導出。兩者共用 lib/render.js 這一個渲染器,因此模型生成的頁面與抽屜導出的頁面逐字節一致,作者用測試在語料的每個用例上斷言了這一點。

它定位的是“把 Markdown 變成可以發給別人、可以在離線機器上打開的單文件頁面”,不是替代已有的 Markdown 查看器。倉庫 README 的口號是「Turn Markdown into a page you can send to someone」。包版本爲 0.3.0,許可證 MIT。

核心功能

1. md_html_render 工具

md_html_render(markdown, title?, save_path?) -> { html, savedPath?, error? }

回調結構裏 html 總是返回,savedPath 與 error 只在涉及寫盤時出現。兩個可選參數:

  • title:頁面 <title>,默認是 Markdown。
  • save_path:目標路徑,通過會話的 filesystem service 解析,因此與其他寫入一樣遵循同一套沙箱策略。

輸出是自包含的:樣式內嵌,不加載任何 stylesheet、font、script 或圖片。從磁盤、U 盤或隔離網機器打開,外觀一致;跟隨閱讀器的深色模式;沒有任何外聯請求。如果 save_path 被沙箱拒絕,工具仍會返回 HTML 與錯誤,迭代不會被權限問題打斷。

2. Web GUI 的 MD 抽屜

在 Web 會話頭部按 MD,抽屜打開在當前工作目錄上。功能包括:

  • 就地瀏覽:點擊文件夾進入,↑ 返回,不走系統文件對話框。
  • 渲染:標題、粗體/斜體/刪除線、行內代碼、圍欄代碼、引用、有序/無序/任務列表、表格、鏈接、圖片、分割線。
  • 編輯:切換成純 textarea 做筆記或修一行,再切回來。
  • 導出:在源文件旁寫出一份自包含 HTML,與 md_html_render 產出的是同一份文檔。
  • 主題感知:讀取 harness 的主題變量,亮暗模式無需配置。

3. 安全邊界

  • 無運行時依賴。客戶端半個是純腳本加載,不帶 bundler,因此 marked / markdown-it 不可用;渲染器是約 150 行手寫 JavaScript,需要審計的依賴樹只有一個文件。
  • 沒有第二條磁盤通道。所有讀寫都過 harness 的 fs service,繼承會話已有的沙箱策略;抽屜的 readFile 只接受 .md、.markdown、.mdx、.txt。
  • 不執行原始 HTML。文檔文本先做 HTML 轉義再跑行內語法;鏈接目標只放行 http(s):、#、/、mailto:,其餘摺疊成 #。含 <script> 或 javascript: 鏈接的文檔會渲染成字面字符。

兼容性:headless / CLI profile 可用 md_html_render;Web GUI 同時有工具和抽屜;profile 沒有 fs service 時,插件只打日誌保持不激活,不做半加載。需要 Node ^22.19.0 || >=24.0.0。

安裝與啓用

包在 0.3.0 改名了:此前包名是 dsh-md-preview,npm 上這個名字在 2026-08-17 被另一個作者的項目註冊走,本包因此改發佈名爲 dsh-md-html-render(即它一直提供的那工具名)。從 npm 裝 dsh-md-preview 拿到的不是本包。倉庫路徑未變,但依賴鍵必須匹配新包名。

目前還沒上 npm,直接從 GitHub 裝。編輯 profile 的 package.json:

// ~/.dsh/profiles/<profile>/package.json
{
  "dependencies": {
    "dsh-md-html-render": "github:YaoleWu/dsh-md-preview#v0.3.0"
  },
  "dsh": {
    "profile": {
      "bundles": ["dsh-md-html-render"]
    }
  }
}

README 原文寫作 github:LeslieWylie/dsh-md-preview#v0.3.0(該倉庫先前的歸屬名)。GitHub API 返回的 full_name 現在是 YaoleWu/dsh-md-preview,舊歸屬名重定向到同一倉庫,兩種寫法都指向同一個倉庫;按當前歸屬名引用更穩妥。

然後重裝並重啓 profile:

cd ~/.dsh/profiles/<profile> && pnpm install
dsh --profile <profile>

去掉 #v0.3.0 就跟蹤默認分支而不是固定版本。

不想改 profile 也可以臨時 patch:

dsh --profile web --patch <(printf -- "- insert:\n    - id: md-preview\n      name: dsh-md-html-render\n")

包仍須能從 profile 的 node_modules 解析,所以要先跑上面的 pnpm install。

典型用法

模型側直接下指令,例如:

Render this migration plan to ~/Desktop/plan.html

適合把報告、方案、對比表這類本來會整段堆在對話裏的內容變成可以直接打開或發走的 HTML 文件。

GUI 側:在會話頭部按 MD,瀏覽工作目錄,點一個 .md 文件就地渲染;需要改一行時切到純文本編輯,改完切回;要分發時點導出,源文件旁多出一份單文件 HTML。

倉庫自帶的測試有四個可執行套件,分別覆蓋客戶端渲染器、host 渲染器與二者一致性(含工具形狀、RPC 端點、沙箱拒絕路徑)、抽屜路徑渲染、以及真實 Context 引導加載後向真實工具註冊表取 md_html_render 並對真實磁盤執行:

npm test

最後一項的意義在於:DSH 插件可以 import 乾淨、單元測試全過,卻在 Context 實際引導時什麼都沒註冊,而且不報錯,單元測試看不到這一點。harness 相關包被聲明爲普通 devDependencies 而不是可選 peer,所以全新 clone 上直接 npm install && npm test 就能真跑。日誌裏出現 SKIPPED 時,按未驗證對待。XSS 相關斷言是結構性不變量:產出的標籤不會出現未終結的屬性或 on*= 處理器,套件裏還包含讓檢查器在真正不安全標記上轉紅的用例,防止安全斷言悄悄退化成恆真。

適用場景與注意

適合:在 DSH 裏用模型產出文檔類產物、希望結果是一個能離線打開和轉發的文件的人;Web GUI 用戶想要不需要開新標籤、不需要第二個編輯器的就地預覽。裝了 headless profile 只拿到工具,GUI 用戶兩樣都有。

注意幾點:

  • 插件以當前 dsh 進程的權限運行,寫入路徑仍由會話沙箱決定;安裝前應檢查源碼與許可證(本包許可證爲 MIT)。
  • 工具依賴 fs service;沒有它的 profile 上插件只打警告保持惰性,功能不可用。
  • 包名 dsh-md-preview 在 npm 上指向別的項目,別按舊名裝。
  • SkillHub 目錄是獨立的社區站點,與 DeepSeek / 幻方沒有官方從屬關係,插件需自行評估後使用。

結尾

這個插件的價值在於把「Markdown 渲染」這一步收斂到 harness 內部:同一個渲染器,既是模型工具,也是 GUI 的預覽與導出按鈕;零運行時依賴、無第二條磁盤通道、不執行原始 HTML,審計面很小。目錄頁在 https://www.skillhub.cn/plugins/YaoleWu/dsh-md-preview ,源碼在 https://github.com/YaoleWu/dsh-md-preview 。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜