最近,Anthropic 内部一位 Claude Code 工程师在 X 上说了一句引爆开发者社区的话:
“HTML is the new Markdown。”
他的逻辑是真实的:AI 生成内容时,HTML 能表达表格、图表、交互控件和复杂布局,而标准 Markdown 做不到。他几乎停止写 .md 文件,转而让 Claude Code 替他生成 HTML。
这条推文获得了超过 1000 万次曝光,评论区撕裂成两派。
Redis 之父 antirez 的回应是我见过的最准确的诊断:
“每当我们从语义密集的格式迁移到语义稀疏的格式,就是在倒退。我能理解我们需要一个更好的 Markdown,但我无法理解为什么要用 HTML 来替代它。”
antirez 说对了。而那个”更好的 Markdown”,其实已经有了一个具体实现——就是 Mark.build 正在做的事。
本文是一次完整的展示:这套扩展机制怎么工作,为什么它比 HTML 更对。
问题是真实的,但方向走偏了
先承认那位工程师识别出的问题是真实的:当你用 AI 生成技术文档、项目报告、产品说明时,标准 Markdown 的表达能力确实不够用。你想展示数据指标,只能塞进一个普通表格;想区分不同语言的代码示例,没有标签页;想加一个警告提示框,只能用 > 引用块将就;想做一个定价页面,没有任何选择。
于是 AI 生成 HTML。结果是:
token 成本翻 3-4 倍。 一组定价卡片的 HTML 容易超过 200 行。等效的声明式配置,20 行够了。
人无法直接编辑。 改一个价格数字需要重新提示 AI,或者在开发者工具里找到那行 HTML 手动改。
版本控制失效。 git diff 里一个段落改动可能带出几十行标签变化,完全不可读。
格式绑定渲染环境。 HTML 文件离开浏览器什么都不是。.md 文件在任何编辑器、终端、代码审查工具里都能直接阅读。
用一个更重的格式来解决表达能力不足的问题,代价是真实的,方向是错的。
围栏代码块是唯一的扩展点
正确的答案已经被 Mermaid 验证过了。
Mermaid 的做法很简单:用围栏代码块,语言标识符告诉渲染器”这不是普通代码,这是一种声明式描述”。
```mermaid
graph LR
A[用户请求] --> B{认证}
B -->|通过| C[处理逻辑]
B -->|拒绝| D[返回 401]
C --> E[返回结果]
```这个模式可以推广到所有场景,而不只是图表。Mark.build 所做的,就是把这个模式系统化:任何内容类型都是一个代码块,语言标识符是唯一的区分点。
不需要新语法,不需要自定义组件系统,不需要插件注册机制。.md 文件还是 .md 文件,围栏代码块还是围栏代码块。变化的只是语言标识符的含义。
功能一览:目前已经实现的
以下是 Mark.build 当前实现的全部特殊代码块,每一个都可以在编辑器里直接试用。
Mermaid 图表
14 种图表类型,包括流程图、时序图、ER 图、甘特图、Git 历史、思维导图等。渲染结果支持平移缩放,可下载 SVG 和 PNG。
```mermaid
sequenceDiagram
participant U as 用户
participant API as API 服务
participant DB as 数据库
U->>API: POST /auth/login
API->>DB: 查询用户记录
DB-->>API: 返回用户数据
API-->>U: 200 OK {token}
```KaTeX 数学公式
行内公式:,块级公式渲染为带卡片外壳的独立元素,支持缩放查看和 LaTeX 复制。
CSV 交互表格
CSV 代码块渲染为带搜索框和列排序的交互表格,支持按 CSV/JSON 导出,右键列头可按升降序排序。
| 姓名 | 职位 | 入职时间 | 薪资 |
|---|---|---|---|
| Alice Chen | 后端工程师 | 2023-03 | 32000 |
| Bob Liu | 前端工程师 | 2022-11 | 28000 |
| Carol Zhang | 产品经理 | 2023-07 | 35000 |
| David Wu | 数据工程师 | 2021-06 | 40000 |
| Eve Wang | 设计师 | 2024-01 | 26000 |
HTTP 请求文档
http 代码块把 HTTP 请求格式化为语义化卡片,方法、路径、头部、请求体各有独立样式,支持直接发送请求查看响应。
POST /api/v1/documents HTTP/1.1
Host: api.mark.build
Authorization: Bearer sk-xxxxx
Content-Type: application/json
{
"title": "API 集成指南",
"content": "## 开始之前...",
"theme": "tech-blog"
}
Terminal 命令块
bash/shell 代码块渲染为终端风格,提示符、命令、输出、错误各有颜色区分,一键复制命令行部分(不含输出)。
$ pnpm add @mark-build/renderer
Packages: +47
Progress: resolved 89, reused 43, downloaded 4, added 47, done
✓ 安装完成
$ pnpm build
vite v5.4.19 building for production...
✓ 37 modules transformed.
dist/index.js 42.3 kB │ gzip: 14.1 kB
✓ Built in 1.24s
Diff/Patch 对比块
diff 代码块把增删行用绿/红背景高亮,适合展示代码变更或配置迁移。
- const config = {
- theme: 'default',
- syntaxHighlight: true,
- };
+ const config = defineConfig({
+ theme: 'tech-blog',
+ syntaxHighlight: false, // 改用 rehype-pretty-code
+ markdown: {
+ remarkPlugins: [remarkMath],
+ },
+ });
Output / 程序输出块
output/stdout 代码块渲染为程序输出卡片,支持按级别过滤(error / warn / success / 普通输出)。
[INFO] 服务启动,监听 :8080
[INFO] 数据库连接成功(pool: 10)
[WARN] 缓存未配置,使用内存模式
[ERROR] 邮件服务不可用:SMTP 连接超时
[INFO] 健康检查端点:/healthz
四种新类型:UI 布局类代码块
除了以上面向开发者的工具类代码块,Mark.build 还引入了四种 UI 布局类代码块,用于在文档里直接嵌入视觉组件,无需写任何 HTML。
Callout 提示框
六种类型:note、info、tip、success、warning、danger。每种类型对应不同的图标和配色。
```warning
生产环境 API Key 请勿提交到公开代码仓库。一旦泄露,请立即吊销旧 Key。
```
```tip
开始前,先粘贴一段 Markdown 文本,然后切换主题查看排版变化。
```
```danger
删除账号操作不可撤销,所有文档与配置将被永久清除。
```Warning
生产环境 API Key 请勿提交到公开代码仓库。一旦泄露,请立即在控制台吊销旧 Key 并生成新的。
Tip
开始前,先在编辑器里粘贴一段 Markdown 文本。如果你已有内容,直接切换主题就能看到排版效果的变化。
Danger
删除账号操作不可撤销。所有文档、主题配置和导出历史将被永久清除,且无法恢复。
Tabs 标签页
用 --- tab: Name --- 分隔不同面板,同一内容展示多语言实现时特别有用。
```tabs
--- tab: TypeScript ---
async function fetchUsers(): Promise<User[]> {
const res = await fetch('/api/users');
return res.json();
}
--- tab: Python ---
def fetch_users():
return httpx.get('/api/users').json()
--- tab: Go ---
func fetchUsers() ([]User, error) { ... }
```async function fetchUsers(): Promise<User[]> {
const res = await fetch('/api/users');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
}Tab 标签也支持文件名,自动从扩展名推断高亮语言:
```tabs
--- tab: utils.ts ---
export function formatDate(d: Date): string {
return d.toISOString().slice(0, 10);
}
--- tab: utils.py ---
from datetime import date
def format_date(d: date) -> str:
return d.isoformat()
--- tab: utils.go ---
func formatDate(t time.Time) string {
return t.Format("2006-01-02")
}
```export function formatDate(d: Date): string {
return d.toISOString().slice(0, 10);
}Stats 数据指标
Pipe 分隔格式:标签 | 数值 [| 变化 [| 方向]],direction 填 up / down 控制趋势箭头颜色,渲染为响应式指标卡片网格。
```stats
月活用户 | 12,400 | +18% | up
付费用户 | 396 | +22% | up
周新增 | 2,840 | -3% | down
付费转化率 | 3.2% | +0.4pp | up
```Pricing 定价表
用 == 方案名 分段,features: / excluded: 各是逗号分隔列表,highlight: true 标记推荐方案(加边框 + “推荐”徽章)。
```pricing
== Solo
price: 免费
features: 单用户, 所有主题, HTML 导出
excluded: 商业使用, 去水印, 云同步
== Pro
price: $12
period: /月
highlight: true
features: 无限连接, 去水印, 商业使用, 云同步
== Team
price: $29
period: /用户/月
features: 最多 20 用户, SSO, SLA 保障
```- 单用户
- 5 个模型连接
- 所有主题
- HTML 导出
- 商业使用
- 去水印
- 云同步
- 单用户
- 无限模型连接
- 所有主题
- 去水印
- 商业使用
- 云同步
- 最多 20 用户
- SSO
- SLA 保障
- 专属客服
- 所有 Pro 功能
这是如何工作的
技术架构:unified + rehype 插件管道
整个渲染管道基于 unified 生态——这是 JavaScript 世界里最成熟的内容处理框架,Next.js、Astro、Docusaurus 都依赖它。
Markdown 文本
→ remark-parse(生成 MDAST 语法树)
→ remark-gfm / remark-math
→ remark-rehype(转换为 HAST HTML 树)
→ rehype-katex(渲染 KaTeX 公式)
→ rehype-mermaid-placeholder(Mermaid 转为客户端占位符)
→ rehype-terminal(拦截 bash/shell)
→ rehype-diff(拦截 diff/patch)
→ rehype-csv(拦截 csv/tsv)
→ rehype-http(拦截 http/rest/curl)
→ rehype-callout(拦截 note/warning/tip...)
→ rehype-tabs(拦截 tabs)
→ rehype-stats(拦截 stats)
→ rehype-pricing(拦截 pricing)
→ rehype-pretty-code(Shiki 语法高亮,处理剩余普通代码块)
→ rehype-code-shell(给代码块加外壳:标题栏、复制按钮)
→ rehype-stringify(输出 HTML 字符串)
每个自定义代码块类型对应一个 rehype 插件,插件在 Shiki 处理之前运行,把特定语言标识符的 <pre><code class="language-xxx"> 节点替换为结构化的 HTML 卡片。这条管道同时用于编辑器实时预览和博客页面静态构建。
为什么 YAML/DSL 比 HTML 更适合 AI 生成
有一个鲜为人知的数据:YAML 是 LLM 生成出错率最低的格式之一,而 HTML 标签嵌套层级深,在生成长 HTML 时容易出现标签漏闭合、属性值遗漏或缩进错乱。
让 Claude 生成一组定价卡片对比:
HTML 方案(200+ 行,容易出错):
<div style="display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; padding: 32px;">
<div style="border: 1px solid #e5e7eb; border-radius: 12px; padding: 24px;">
<h3 style="font-size: 20px; font-weight: 600; margin-bottom: 8px;">Solo</h3>
<div style="font-size: 36px; font-weight: 700; margin-bottom: 16px;">免费</div>
<ul style="list-style: none; padding: 0;">
<li style="display: flex; align-items: center; gap: 8px; margin-bottom: 8px;">
<span style="color: #16a34a;">✓</span> 单用户
</li>
<!-- 还有 N 行... -->
</ul>
</div>
<!-- 另外两个方案... 还有 150 行 -->
</div>代码块 DSL 方案(20 行,AI 生成稳定):
```pricing
== Solo
price: 免费
features: 单用户, 5 个模型连接
excluded: 商业使用
== Pro
price: $12
period: /月
highlight: true
features: 单用户, 无限连接, 商业使用
== Team
price: $29
period: /用户/月
features: 20 用户, SSO, SLA
```20 行 vs 200+ 行。token 成本约 1/10,生成可靠性显著更高,diff 可读,文件可在任意编辑器打开。
这也是为什么 Claude 生成 Mermaid 图表的质量普遍好于生成等效 HTML/SVG——道理完全相同:声明式结构命中了语言模型的优势区间。
Design Token:主题与内容解耦
另一个值得单独说的点:代码块渲染出来的效果完全受主题控制。
所有颜色、字体、圆角、边框都通过 CSS 变量(Design Token)注入,切换主题时,不只是正文样式变了,所有代码块外壳、表格、指标卡片、定价表格的颜色同步变化。
这使得同一份 Markdown 文件可以在不同的视觉风格下渲染,发布到不同平台(技术博客、学术论文、营销页面)时无需修改任何内容。
antirez 说的那个”更好的 Markdown”
antirez 的判断:不要从 Markdown 迁移到 HTML,而是扩展 Markdown 的表达能力。
Mermaid 已经验证了这条路是对的。从 mermaid 到 chart、csv、terminal、diff、http、callout、tabs、stats、pricing……每一个新的语言标识符,都是 Markdown 获得的一种新的表达能力。
文件还是 .md,语法还是代码块,渲染效果和精心设计的 HTML 没有差别——但 token 成本是 HTML 的 1/4 到 1/10,人可以直接编辑,git diff 是清晰的文字变化,文件在任何地方都能打开。
那位工程师发现了一个真实问题。antirez 指出了正确方向。Mark.build 在做的,就是那个方向上的具体实现。
想亲自试试? 打开编辑器,把任意 Markdown 粘贴进去 →