Markdown HTML 编排器

markdown-html-orchestrator
分类编程
作者Alireza Rezvani
许可MIT
评分4.80/5
使用4.2K

Markdown → HTML — 领域编排器 (Domain Orchestrator)

Thariq Shihipar 的观点(Claude Code HTML 输出论文,Medium 2026):对于智能体生成的产出,当篇幅超过 100 行时,markdown 的表现会下降。 长篇规范、代码审查和架构解释文档一旦超过一屏文本,就会失去密度、层级感和轻量级交互能力。HTML 能够恢复这三者 —— 单文件、浏览器原生且易于分享。

本编排器通过分叉上下文,对输入 markdown 进行确定性分类,路由至正确的转换子技能,并返回包含输出路径的摘要。大量输入(完整的 markdown 正文、diff、幻灯片组)将保留在分叉的上下文中。

领域状态(已完成): 所有五个技能均已上线 —— 编排器 + design-system(引导 + 共享品牌 Token)+ 三个转换子技能(md-document, md-review, md-slides)。始终将转换任务路由至已发布的转换脚本;绝不要在行内手动渲染 HTML。

调用时机

| 症状 | 子技能 |
|---|---|
| "将此 RFC / 规范 / 报告 / 解释文档转换为 HTML" —— 长篇文档 | md-document |
| "将此 PR 描述 / 代码审查转换为 HTML" —— 包含 diff 代码块的 markdown | md-review |
| "根据此 markdown 制作幻灯片" —— 包含 --- 分隔符或 H1 节奏 | md-slides |

预检门禁(硬性拒绝条件)

1. 低于 100 行阈值。 根据 Shihipar 的观点,100 行以下 markdown 胜出。分类器将打印 below_min_lines: trueroute_explainer.py 将拒绝执行。告知用户保留 markdown 格式。
2. 设计系统未完成引导。 如果 ~/.config/markdown-html/design-system.json 不存在(或其 setup_completed_at 为空),则拒绝。引导用户运行 python3 markdown-html/skills/design-system/scripts/onboard.py(或使用 --defaults 进行零干预运行)。
3. 保存位置不可写。 如果配置的 default_output_dir(或 --out 覆盖路径)不可写,output_path_resolver.py 将拒绝执行。

路由逻辑(确定性)

采用自 research-ops/skills/research-ops-skills/SKILL.md 借鉴的双信号阈值模式。文件名暗示 = 2 分;每个内容信号 = 1 分。当获胜者 $\ge 3$ 且(亚军 $= 0$ 或 获胜者 $\ge 2 \times$ 亚军)时,允许静默路由。低于阈值 $\rightarrow$ 一个 c
澄清问题及建议答案。

信号表

| 信号类别 | 文件名提示 | 内容信号 | 子技能 |
|---|---|---|---|
| DOCUMENT (文档) | report.md, *-doc.md, spec.md, rfc-*.md, *-analysis.md, *-explainer.md | ## Table of Contents (2), ^# , ^## , markdown 表格行, > [!NOTE]/[!TIP]/[!IMPORTANT] 标注 | md-document |
| REVIEW (评审) | review.md, *-pr-*.md, *.diff.md, code-review*.md | `diff (2), ^[-+]{3} (2), ^@@ (2), > [!BLOCKER]/[!MAJOR]/[!MINOR]/[!NIT] (2), LGTM/nit:/blocker: | md-review |
| SLIDES (幻灯片) | deck.md, slides.md, *-talk.md, presentation*.md | ^---$ ≥ 3 (2 + 每个边界), <!-- notes: (2), H1 数量 ≥ 5 且中位数间隔 ≤ 12 行 (2) | md-slides |

流水线:

bash
python3 markdown-html/skills/markdown-html-orchestrator/scripts/doctype_classifier.py \
    --input <path>.md --output json \
  | python3 markdown-html/skills/markdown-html-orchestrator/scripts/route_explainer.py

route_explainer.py 会检查设计系统状态,应用“少于 100 行则拒绝”的规则,并打印以下结果之一:ROUTE_SILENTLY -> md-<type>(静默路由)、ASK_USER one question: ...(询问用户一个问题)或 REFUSE — fix the issues above(拒绝——请修复上述问题)。

工作流

第 1 步 — 确认引导配置 (Onboarding)

如果用户从未运行过引导程序,则提示一次性设置:

bash
python3 markdown-html/skills/design-system/scripts/onboard.py

包含 10 个问题,耗时 1-2 分钟。用于采集品牌主色 + 强调色 + 标题/正文 Google 字体 + 设计风格(编辑风/技术风/极简风/俏皮风)+ 默认输出目录 + 语法高亮主题 + TOC 行为 + 可选的 Logo/公司名称。配置存储在 ~/.config/markdown-html/design-system.json。可通过 --scope project 重新运行以实现单仓库覆盖。

第 2 步 — 对输入进行分类

对 markdown 文件运行 doctype_classifier.py 并检查判定结果。

第 3 步 — 路由或询问

将分类结果通过管道传输给 route_explainer.py。如果结果为 ROUTE_SILENTLY,则将原始 markdown 和设计系统配置转发至分叉上下文中对应子技能的渲染器。如果结果为 ASK_USER,则提出一个问题并给出建议答案。

第 4 步 — 解析输出路径

bash
python3 markdown-html/skills/markdown-html-orchestrator/scripts/output_path_resolver.py \
    --input <path>.md --doctype <document|review|slides>

冲突处理默认使用 -2 / -3 / ... 后缀;使用 --on-collision timestamp 可生成带时间戳的文件名。

第 5 步 — 移交给子技能

路由后的转换子技能渲染器(位于 md-document/scripts/, md-review/scripts/md-slides/scripts/)接收输入 markdown、设计系统配置和解析后的输出路径,并写入一个独立的 HTML 文件。编排器最后返回一个 ≤ 100 字的摘要:包含输入行数、输出路径、应用的设计风格、使用的前 3 项功能(TOC、搜索、代码复制等)以及一个引导用户思考的强制性问题。严禁手动渲染 HTML —— 渲染工作由转换脚本完成。

强制性问题库 (Matt Pocock 文档质询模式)

依次提出这些问题,每个问题附带一个建议答案并引用权威依据。将此列表提取至 /cs:grill-markdown-html 用于计划阶段的质询。

1. 此 HTML 旨在驱动什么样的决策 —— 读者是在快速浏览、做决定还是在演示?
建议答案:先定义目的;信息密度随目的而定。依据:Shihipar —— “使输出格式与消费场景匹配”;Tufte —— 《定量信息的视觉显示》第一章。
2. 输入 markdown 是否 ≥ 100 行?
建议答案:...
推荐:是 —— 低于此长度,保持为 markdown。规范:Shihipar —— 100 行以下 markdown 仍是首选。
3. 设计系统是否已引导(onboarded)?
推荐:是,全局配置 (~/.config/markdown-html/design-system.json)。规范:research-ops 引导模式 (research-ops/CLAUDE.md §8);WCAG 2.2 §1.4.3(文本对比度 4.5:1)。
4. 输出保存位置,是否会覆盖现有文件?
推荐:配置的 default_output_dir 并使用 --on-collision suffix。规范:Matt Pocock 的 handoff 技能 —— 绝不静默覆盖正在使用的产出物。
5. 文档类型置信度 —— 静默路由还是询问一次?
推荐:仅当分类器判定结果为 document/review/slidessilent_route_allowed: true 时才静默路由。否则请询问。规范:research-ops 双信号阈值 (research-ops/skills/research-ops-skills/SKILL.md §"Routing logic")。

在确定路径(lane)之前,绝不要运行子技能。

前提假设

1. 用户拥有一个 $\ge 100$ 行且希望转换的 markdown 文件。
2. 用户已运行过一次引导 (~/.config/markdown-html/design-system.json 存在且 setup_completed_at 已填充)。
3. 接受单文件 HTML 输出(无需多文件站点、无需嵌入式服务器、无需构建步骤)。
4. 外部依赖仅限于 Google Fonts CSS + Prism.js CDN (jsdelivr / cdnjs)。

非目标

  • 不是落地页生成器(请使用 marketing/landing/)。
  • 不是交互式提示词调优操场(请使用 Anthropic 官方的 playground 插件)。
  • 不是静态站点生成器(无多文件输出,无站点索引)。
  • 不是 PDF 生成器(幻灯片使用 @media print;用户通过浏览器打印)。
  • 不是监听/实时重载流水线(转换是一次性的)。

区别于

  • Anthropic Playground 插件 (/playground) —— 为提示词调优构建交互式控件(滑块、旋钮、拖拽)并支持提示词回写。本插件是将现有 markdown 文档转换为 HTML。不同工具用于不同场景。
  • marketing/landing/ —— 从零生成落地页(Phase-0 需求采集 $\rightarrow$ 3 个板块 $\rightarrow$ 品牌化 TSX/HTML)。本插件是转换你已有的 markdown 文件。
  • engineering/handoff/ + productivity/handoff/ —— 保持 Claude 对话之间的会话连续性。产出物类型不同(交接简报 vs 文档转换)。

输出产出物

| 子技能 | 产出物 | 状态 |
|---|---|---|
| md-document | doc-<slug>.html (单文件,固定目录 TOC,可折叠内容,搜索,代码复制,滚动监听) | ✓ 已上线 |
| md-review | review-<slug>.html (两栏对比 + 严重程度边注 + 跳转导航) | ✓ 已上线 |
| md-slides | deck-<slug>.html (方向键导航 + 演讲者模式 + 打印至 PDF) | ✓ 已上线 |

反模式(避免这样做)

  • ❌ 转换 < 100 行的 markdown —— markdown 依然是更好的选择。请拒绝并告知用户。
  • ❌ 在设计系统引导完成前运行编排器。没有 token 的输出看起来会是损坏的。
  • ❌ 静默地链式调用两个子技能(例如:“转换文档并据此制作幻灯片”)。选择一个,完成后在链式调用前询问。
  • ❌ 使用外部 JS 框架 (React/Vue/Svelte)。仅使用原生 JS + IntersectionObserver。Prism.js CDN 是唯一例外。
  • ❌ 多文件输出(提取 CSS,资源目录)。要么单文件,要么没有 —— 这正是本插件的核心。
  • ❌ 默认覆盖现有输出文件。路径解析器应添加后缀 -2, -3…;--on-collision overwrite 仅限手动开启。

参考资料

  • 规范:Thariq Shihipar — "Claude Code HTML output" (Medium, 2026)
  • 分叉模式 (Forking pattern)
  • research-ops/skills/research-ops-skills/SKILL.md(上下文:fork,双信号路由)
  • 定制化模式:research-ops/skills/clinical-research/scripts/onboard.pyconfig_loader.py
  • 品牌色板计算:marketing/landing/skills/landing/scripts/brand_palette_validator.py(WCAG + HSL 衍生)
  • 信息密度准则:Tufte;Shihipar 的 thariqs.github.io/html-effectiveness/ 展馆;Wattenberger 交互式论文;Maggie Appleton 数字花园