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 ─────────────────────────────────────

  1. Pandoc 的 chunkedhtml 格式自动将单一大文档拆分为多个 HTML 页面,同时保持导航结构完整
  2. 通过模板定制实现侧边栏 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 ─────────────────────────────────────

  1. Popover API 是现代 HTML 原生功能,无需 JavaScript 即可实现复杂的交互效果
  2. 通过 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.html

A. 单页版本优势

  • 所有内容在一个页面上
  • 浏览器搜索功能可轻松遍历整个网站

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 -- apply

5. 更新流程

更新站点时,首先运行:

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 ─────────────────────────────────────

  1. Nix + Colmena 组合实现了声明式部署,确保构建环境可重现
  2. Pandoc 的多种输出格式能力允许同时生成分页和单页版本,满足不同使用场景
    ─────────────────────────────────────────────────

九、技术对比

1. 方案对比表

特性PandocDocusaurusMkDocsMdBook
无 JS 依赖
构建复杂度
样式定制灵活有限中等中等
目录维护自动自动mkdocs.ymlSUMMARY.md
输出格式多种HTMLHTMLHTML
学习曲线

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

参考资料

  1. we rolled our own documentation site - Tangled Blog
  2. docs.tangled.org
  3. Pandoc - Universal markup converter
最后修改:2026 年 01 月 24 日
如果觉得我的文章对你有用,请随意赞赏