Tangled 使用 Pandoc 构建静态文档网站技术分析
一、概述
1. 背景
Tangled 团队最近重新组织了文档,并将其发布到 https://docs.tangled.org,仅使用 Pandoc 工具实现。对于小型项目,使用 Pandoc 自建静态网站完全足够。
2. 核心诉求
A. 代码库集成
文档必须存在于 monorepo 中
B. 无 JavaScript 依赖
纯文本页面不需要 JavaScript 即可浏览
C. 可搜索性
自带的搜索引擎效果较差,倾向于使用 Ctrl+F 或真实搜索引擎
D. 低复杂度
构建、测试、部署应当简单
E. 易于样式化
能够灵活定制外观
二、生态系统评估
1. 评估对象
作者对多个文档引擎进行了评估:
A. Mintlify
- 特点:商业文档平台
- 问题:官网显示正在进行 AI 转型,存在方向不明确的风险
B. Docusaurus
- 特点:生成精美的文档网站
- 问题:将页面作为完整 React SPA 提供的价值存疑
C. MkDocs
- 优点:禁用 JS 后工作良好
- 问题:需要通过 mkdocs.yml 维护目录结构,较为繁琐
D. MdBook
- 问题:需要 SUMMARY.md 文件控制目录
2. 评估结论
MkDocs 和 MdBook 仍在考虑范围内,以备将来需要更多功能时使用。
三、Pandoc 方案
1. Pandoc 介绍
Pandoc 是一个高度可定制的标记转换工具,提供了 chunkedhtml 输出格式,非常适合生成文档网站。
A. 默认特性
- 基于文档布局自动生成目录(TOC)
- 每个章节转换为独立页面
2. 定制过程
A. 合并文档
将所有独立的 Markdown 文件合并为一个大的 DOCS.md 文件
B. 模板修改
修改默认模板,使 TOC 出现在每个页面上,形成侧边栏样式
C. 样式统一
插入 Tailwind prose 类,确保 Markdown 内容在 tangled.org 和 docs.tangled.org 之间渲染一致
3. 生成命令
pandoc docs/DOCS.md \
-o out/ \
-t chunkedhtml \
--variable toc \
--toc-depth=2 \
--css=docs/stylesheet.css \
--chunk-template="%i.html" \
--highlight-style=docs/highlight.theme \
--template=docs/template.html★ Insight ─────────────────────────────────────
- Pandoc 的 chunkedhtml 格式自动将单一大文档拆分为多个 HTML 页面,同时保持导航结构完整
- 通过模板定制实现侧边栏 TOC,避免了复杂 JavaScript 代码的依赖
─────────────────────────────────────────────────
四、避免使用 JavaScript
1. 移动端侧边栏
侧边栏式目录需要在移动设备上折叠。大多数评估的文档引擎需要 JavaScript 来折叠和展开侧边栏,只有 MkDocs 使用 checkbox 的 :checked 伪类技巧来避免 JavaScript。
2. 实现方案对比
A. details/summary 方案
- 优点:可实现折叠功能
- 缺点:点击外部无法折叠,是明显的 hack 方案
- 说明:Ctrl+F 或页面内查找仍然有效
B. Popover API 方案(最终采用)
- 优点:非常适合侧边栏组件
- 实现:使用 HTML 原生 popover API
触发按钮:
<button popovertarget="toc-popover">Table of Contents</button>固定定位容器:
<div id="toc-popover" popover class="fixed top-0">
<ul>
Quick Start
<li>...</li>
<li>...</li>
<li>...</li>
</ul>
</div>C. 方案特点
- TOC 可独立滚动
- 点击侧边栏外部任何位置即可折叠
- 页面内查找无法显示 popover 中的内容
- 仅在小视口上可折叠,大视口上始终显示
★ Insight ─────────────────────────────────────
- Popover API 是现代 HTML 原生功能,无需 JavaScript 即可实现复杂的交互效果
- 通过 CSS 媒体查询实现响应式设计,小屏幕自动切换为折叠式侧边栏
─────────────────────────────────────────────────
五、搜索功能
1. 搜索策略
网站目前没有原生搜索功能。参考 htmx.org 的搜索栏,搜索栏直接重定向到 Google:
<form action="https://google.com/search">
<input type="hidden" name="q" value="+[inurl:https://docs.tangled.org]">
...
</form>2. 单页版本
考虑到 Ctrl+F 通常比 Docusaurus 提供的搜索引擎更好用,相同文档也导出为单页格式:
pandoc docs/DOCS.md \
-o out/ \
--variable toc \
--toc-depth=2 \
--css=docs/stylesheet.css \
--highlight-style=docs/highlight.theme \
--template=docs/template.htmlA. 单页版本优势
- 所有内容在一个页面上
- 浏览器搜索功能可轻松遍历整个网站
B. 未来考虑
如果文档规模超出此方案支持范围,会考虑其他选项。
六、构建与部署
1. 技术栈
- Nix:包管理和构建工具
- Colmena:NixOS 部署工具
2. Nix Derivation
使用 runCommandLocal 辅助函数编写文档站点的 Nix derivation:
runCommandLocal "docs" {} ''
...
${pandoc}/bin/pandoc ${src}/docs/DOCS.md ...
...
''3. Nginx 配置
NixOS 机器配置为通过 nginx 提供站点:
services.nginx = {
enable = true;
virtualHosts = {
"docs.tangled.org" = {
root = "${tangled-pkgs.docs}";
locations."/" = {
tryFiles = "$uri $uri/ =404";
index = "index.html";
};
};
};
};4. 部署流程
使用 Colmena 部署:
nix run nixpkgs#colmena -- apply5. 更新流程
更新站点时,首先运行:
nix flake update tangled此命令会更新 tangled flake 输入,从而更新 tangled-pkgs.docs,然后通过 Colmena 应用更改。
七、方案架构
graph TB
subgraph 源文件
A1[Markdown 文件]
A2[样式表 CSS]
A3[模板 HTML]
A4[高亮主题]
end
subgraph Pandoc 构建
B1[合并文档]
B2[chunkedhtml 输出]
B3[TOC 生成]
end
subgraph 输出目录
C1[index.html]
C2[页面 1.html]
C3[页面 2.html]
C4[单页版本.html]
end
subgraph NixOS 部署
D1[Nix Derivation]
D2[Nginx 服务器]
D3[Colmena 部署]
end
A1 --> B1
A2 --> B2
A3 --> B2
A4 --> B2
B1 --> B2
B2 --> B3
B2 --> C1
B2 --> C2
B2 --> C3
B2 --> C4
C1 --> D1
C2 --> D1
C3 --> D1
C4 --> D1
D1 --> D2
D2 --> D3八、工作流程图
graph LR
A[编写 Markdown] --> B[合并到 DOCS.md]
B --> C[Pandoc 构建]
C --> D[chunkedhtml 输出]
C --> E[单页版本]
D --> F[Nix 打包]
E --> F
F --> G[Colmena 部署]
G --> H[Nginx 托管]
H --> I[用户访问]★ Insight ─────────────────────────────────────
- Nix + Colmena 组合实现了声明式部署,确保构建环境可重现
- Pandoc 的多种输出格式能力允许同时生成分页和单页版本,满足不同使用场景
─────────────────────────────────────────────────
九、技术对比
1. 方案对比表
| 特性 | Pandoc | Docusaurus | MkDocs | MdBook |
|---|---|---|---|---|
| 无 JS 依赖 | 是 | 否 | 是 | 是 |
| 构建复杂度 | 低 | 高 | 中 | 中 |
| 样式定制 | 灵活 | 有限 | 中等 | 中等 |
| 目录维护 | 自动 | 自动 | mkdocs.yml | SUMMARY.md |
| 输出格式 | 多种 | HTML | HTML | HTML |
| 学习曲线 | 低 | 高 | 中 | 中 |
2. 核心差异
A. JavaScript 依赖
- Pandoc/MkDocs/MdBook:支持无 JS 浏览
- Docusaurus:需要 React 运行时
B. 目录结构
- Pandoc:基于 Markdown 标题自动生成
- 其他:需要配置文件维护
十、总结与展望
1. 方案优势
A. 简单性
- 构建命令简洁
- 部署流程清晰
- 无需复杂依赖
B. 灵活性
- 模板可定制
- 多种输出格式
- 样式完全可控
C. 性能
- 静态 HTML
- 无 JavaScript 开销
- 浏览器缓存友好
2. 当前局限
A. 渲染差异
Pandoc 的 Markdown 渲染与 Goldmark(Tangled 主站使用)仍存在一些差异
B. 功能限制
- 暂无原生搜索
- 依赖外部搜索引擎
3. 未来计划
如果文档规模持续增长,可能会考虑:
- 开发自己的 SSG(代号 TigerStyle)
- 重新评估 MkDocs/MdBook