baoyu-markdown-to-html
Converts Markdown to styled HTML with WeChat-compatible themes. Supports code highlighting, math, Mermaid (rendered to PNG via headless Chrome), PlantUML, footnotes, alerts, infographics, and optional bottom citations for external links. Use when user asks for "markdown to html", "convert md to html", "md 转 html", "微信外链转底部引用", or needs styled HTML output from markdown.
1实现原理 · 为什么它能做到
主体是本地 Bun 脚本 + 仓库内共享包:渲染用 baoyu-md(marked/juice/highlight.js 管线),Mermaid 出图用 baoyu-chrome-cdp 的 headless Chrome 渲染器。
import { closeRenderer, renderMermaidToPng } from "baoyu-chrome-cdp/mermaid";
Mermaid 代码块被渲染成本地 PNG(headless Chrome + CDP),带内容哈希缓存;Chrome 缺失或渲染失败则回退为 <pre class="mermaid">,转换整体不失败。
Code blocks fenced as ` ```mermaid ` are rendered to PNGs via headless Chrome (CDP) and cached at `imgs/.mermaid-cache/mermaid-<hash>.png`.
PlantUML 代码块默认由公共 PlantUML 服务渲染:管线注册了 markedPlantUML,默认 serverUrl 指向 plantuml.com,因此图表源码会出网到第三方服务。
serverUrl: options.serverUrl || `https://www.plantuml.com/plantuml`,
文档里的远程图片会被下载到临时目录,再在 HTML 里改写为带 data-local-path 的 img 标签(便于下游平台/客户端再上传)。
await downloadFile(imagePath, localPath);
输出与备份纪律:HTML 写回与源文件同目录同名(.html),已存在则先重命名备份,最后把结果作为 JSON 打到 stdout。
backupPath = `${finalHtmlPath}.bak-${formatTimestamp()}`;
主题/颜色/字号/引用模式是外部可配的显式选项;--cite 会把普通外链收成底部编号引用,但微信自家链接保持原位。
`https://mp.weixin.qq.com/...` links stay as direct links and are not moved to the bottom.
流程前置会做中文检测,并在用户同意时先调用 baoyu-format-markdown 清洗(修 CJK 加粗解析失败与中英间距)。
**If user agrees**: Invoke `baoyu-format-markdown` skill to format the file, then use formatted file as input.
配置面是 EXTEND.md(默认主题、自定义 CSS 变量、代码块样式、mermaid 主题/scale/背景),三级路径首个命中即用,未找到则用默认值、不做首次安装流程。
**EXTEND.md supports**: default theme, custom CSS variables, code block style, mermaid defaults (`mermaid_theme`, `mermaid_scale`, `mermaid_background`).
2核心能力
3外部依赖
| Kind | Dependency / Endpoint |
|---|---|
| package | baoyu-md(npm,仓库 packages/ 内的共享包;marked/juice/highlight.js/remark 管线) |
| package | baoyu-chrome-cdp(npm,仓库 packages/ 内共享包;提供 CDP 与 mermaid 渲染器) |
| network | PlantUML 公共渲染服务(默认 serverUrl,图表源码经 GET 送出) |
| network | Markdown 中出现的任意 http(s) 图片主机(下载到本地临时目录) |
| cli | 本地 Chrome/Chromium/Edge(headless 渲染 Mermaid;缺失则回退) |
| cli | bun(首选运行时;无 bun 时 npx -y bun) |
4管控建议与判定依据
- scripts/: 执行本地脚本或命令: bun {baseDir}/scripts/main.ts <markdown_file> [--theme …] [--cite] [--merma
- 网络端点: 声明外部网络访问: https://www.plantuml.com/plantuml(默认,仅当文档含 plantuml 代码块:图表源码作为 URL 编码体发出,返回
- 本地工作目录: 文件读写与工件输出: 与输入同目录同名的 .html(覆盖前重命名为 .html.bak-YYYYMMDDHHMMSS)
5第二遍独立确认
- [ok] 共享包依赖与版本锁定 — scripts/package.json 仅声明 baoyu-md ^0.1.1 与 baoyu-chrome-cdp ^0.1.1,bun.lock 有锁定条目;两包在本仓 packages/ 内有源码(psync 可读),非黑盒。
- [ok] Mermaid 本地渲染且无 CDN — packages/baoyu-chrome-cdp/src/mermaid.ts 从包内 assets 读 mermaid.min.js(`if (fs.existsSync(path.join(candidate, "mermaid.min.js"))) return candidate;`)并注入本地页面,无外部脚本地址。
- [ok] PlantUML 默认出网到公共服务器(判橙依据) — packages/baoyu-md/src/extensions/plantuml.ts 默认 serverUrl=https://www.plantuml.com/plantuml;注册于 renderer.ts 的 markedPlantUML();本 skill 的 document.ts 路径调用 initRenderer,SKILL.md 亦将 PlantUML 列为支持特性。
- [ok] 远程图片会被真实下载 — packages/baoyu-md/src/images.ts 的 downloadFile 使用 node:http/https + Mozilla/5.0 UA 下载并跟随 301/302;本 skill 在 hasRemoteImages 时建临时目录承接,HTML 内保留原 URL 并附 data-local-path。
- [ok] 本 skill 的 Chrome 启动参数无安全降级/反检测项 — packages/baoyu-chrome-cdp/src/index.ts 的 launchChromeBase args 仅为 --remote-debugging-port/--user-data-dir/--no-first-run/--no-default-browser-check(+headless);全包 grep bypass/detect/webdriver/stealth 零命中,无 --no-sandbox。
- [ok] 无凭证读取 — 本目录 token 扫描 process.env/API_KEY/TOKEN/SECRET/.env 零命中;仅 EXTEND.md 偏好文件(路径在 SKILL.md 明列)。
- [ok] mermaid securityLevel: loose 的渲染面 — packages/baoyu-chrome-cdp/src/mermaid.ts 以 `mermaid.initialize({ startOnLoad: false, theme: …, securityLevel: "loose" })` 渲染文档中的图表代码,属本地无头浏览器内执行用户文档内容;已在 injection_surface 与 verdict.risks 标注。
- [ok] 『微信友好』定位与实际产物 — CSS 由 juice 内联(baoyu-md 依赖含 juice ^11.0.1),图片输出 localPath 供下游上传;--cite 默认关闭,与 SKILL.md 'Default: Off. Do not ask by default.' 一致。
6结论
548cfdf151b66892…