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.
1How It Works & Mechanism
The core consists of local Bun scripts and shared packages within the repository: rendering uses baoyu-md (marked/juice/highlight.js pipeline), and Mermaid diagram rendering uses the headless Chrome renderer in baoyu-chrome-cdp.
import { closeRenderer, renderMermaidToPng } from "baoyu-chrome-cdp/mermaid";
Mermaid code blocks are rendered into local PNGs (headless Chrome + CDP) with content hash caching; if Chrome is missing or rendering fails, it falls back to <pre class="mermaid">, ensuring overall conversion does not fail.
Code blocks fenced as ` ```mermaid ` are rendered to PNGs via headless Chrome (CDP) and cached at `imgs/.mermaid-cache/mermaid-<hash>.png`.
PlantUML code blocks are rendered by default via a public PlantUML service: the pipeline registers markedPlantUML, whose default serverUrl points to plantuml.com, meaning diagram source code is sent outbound to a third-party service.
serverUrl: options.serverUrl || `https://www.plantuml.com/plantuml`,
Remote images in the document are downloaded to a temporary directory and rewritten in the HTML into img tags with data-local-path (facilitating re-uploading by downstream platforms/clients).
await downloadFile(imagePath, localPath);
Output and backup discipline: The HTML is written to the same directory and base name as the source file (.html); if it already exists, it is renamed as a backup first, and the final result is emitted as JSON to stdout.
backupPath = `${finalHtmlPath}.bak-${formatTimestamp()}`;
Theme, color, font size, and citation mode are explicit, externally configurable options; --cite collects standard external links into numbered citations at the bottom, while native WeChat links remain in place.
`https://mp.weixin.qq.com/...` links stay as direct links and are not moved to the bottom.
Chinese language detection is performed upfront in the workflow, and upon user consent, baoyu-format-markdown is invoked first for cleaning (fixing CJK bold parsing failures and Chinese-English spacing).
**If user agrees**: Invoke `baoyu-format-markdown` skill to format the file, then use formatted file as input.
The configuration surface is EXTEND.md (default theme, custom CSS variables, code block styles, mermaid theme/scale/background); the first match across a three-level path is used, and if not found, default values are used without running an initial setup wizard.
**EXTEND.md supports**: default theme, custom CSS variables, code block style, mermaid defaults (`mermaid_theme`, `mermaid_scale`, `mermaid_background`).
2Core Capabilities
3External Dependencies
| 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) |
4Recommended Governance & Evidence
- scripts/: Execute local script or command: bun {baseDir}/scripts/main.ts <markdown_file> [--theme …] [--cite] [--merma
- 网络端点: Declared external network access: https://www.plantuml.com/plantuml (default, only when document contains plantuml code blocks: diagram source code is sent as a URL-encoded payload and returns diagram)
- 本地工作目录: File read/write and artifact output: .html with the same base name and directory as the input (renamed to .html.bak-YYYYMMDDHHMMSS before overwriting)
5Second-Pass Verification
- [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.' 一致。
6Verdict & Scenarios
548cfdf151b66892…