首页
/ Typst 贡献指南详解:从 Fork 到进入 Changelog 的完整流程与配套 CI、测试体系

Typst 贡献指南详解:从 Fork 到进入 Changelog 的完整流程与配套 CI、测试体系

2026-09-05 19:23:49作者:殷蕙予

本文基于 Typst 仓库的官方贡献文档 CONTRIBUTING.md,系统讲解在 Typst 项目中提交代码的完整路径:如何选择贡献目标、六步落地一个贡献、什么样的 PR 才被视为"好 PR",以及 PR 背后的 CI 检查与集成测试体系。读完本文,你可以按仓库真实的命令与流程完成一次贡献准备,并理解每个环节(CI 矩阵、clippy 规则、参考图测试)在源码与配置中的对应位置。

一、从哪里开始贡献

官方贡献文档的第一条建议是:找到一件你自己真正感兴趣的事情。仓库中提供了带标签的 issue 分类作为入口:good first issue(适合首次贡献者的入门问题)与 good contribution(体量更大的贡献主题)。但文档同时强调,比起标签,更推荐选择你自己希望被改进的部分——开源贡献应该是一件有乐趣的事。

对新贡献者最重要的两条原则:

  • 从小的改动开始。 文档原话强调("start with something small"):小改动能帮助你熟悉项目、流程与设计哲学;大型架构提案或来自新贡献者的大型 PR 很难获得推动力。开源开发是高度协作的过程,信任需要逐步建立。
  • 先讨论,再动手。 在开始一个较大的功能或重构之前,请先开一个 issue,或在 Discord 的 #contributors 频道发起讨论,确认设计方向。文档提醒:Typst 是一个具有长期愿景的复杂项目,"实现完之后"才发现自己的想法与项目愿景不符,是一件令人沮丧的事。

文档中给出的讨论入口(issue 列表、Discord 频道)属于外部协作渠道,本文不展开外部链接;重点是这个"先对齐设计"的纪律本身。

二、落地一个贡献的六个步骤

CONTRIBUTING.md 将贡献落地过程拆分为六个步骤,下面逐步展开,并结合仓库中的实际配置补充每个步骤背后的工程事实。

第 1 步:Fork 仓库,理解代码库

Fork Typst 仓库后开始你的贡献。文档建议:如果在任何时候不确定代码库中某件事该怎么做,请联系维护者或更有经验的贡献者;同时推荐阅读 docs/dev/architecture.md,它概述了编译器的整体工作方式。

这份架构文档是理解"改动会影响哪个 crate"的关键。从 docs/dev/architecture.md 可以看到仓库的目录职责划分(每个 crate 的 Cargo.toml 位于 crates/ 下,工作区定义在 Cargo.toml):

  • crates/typst:主编译器 crate,定义完整的语言与库;
  • crates/typst-cli:命令行界面,是编译器与导出器之上相对薄的一层;
  • crates/typst-eval:Typst 语言的解释器;
  • crates/typst-syntax:解析器与语法树定义;
  • crates/typst-layout:排版引擎;
  • crates/typst-realize:realization(展示规则展开)子系统;
  • crates/typst-library:标准库;
  • crates/typst-pdf / crates/typst-svg / crates/typst-html:PDF、SVG、HTML 导出器;
  • crates/typst-render:帧渲染器;
  • crates/typst-ide:IDE 功能(自动补全、跳转等);
  • crates/typst-macroscrates/typst-utilscrates/typst-timingcrates/typst-kit:过程宏、通用工具、计时与 CLI 默认实现。

编译流程分四个阶段:Parsing(源字符串到语法树)→ Evaluation(语法树与依赖到内容)→ Layout(内容到每页一帧)→ Export(帧到 PDF/SVG 等输出),编译器基于 comemo 增量编译框架。理解这条管线有助于你把改动放在正确的 crate 里。

第 2 步:实现改动(明确不接受 AI 代写的贡献)

文档在此步有一条非常醒目的红线:"Do not vibecode the change! Contributions that were implemented by an AI model will not be accepted."(不要凭 AI 辅助"感觉"直接写代码;由 AI 模型实现的贡献不会被接受。)文档给出的理由值得注意:

  • 在维护者与 AI 模型之间加一个外部贡献者作为"中介"价值很有限;
  • 所有贡献都由时间有限的真人审阅;
  • AI 驱动的贡献容易造成危险的失衡——维护者花在某个 PR 上的时间超过贡献者本人投入的时间。

第 3 步:创建 PR 并写清技术理由

提交 Pull Request 时,需要说明贡献内容、其背后的技术理由(technical rationale),以及如果包含新功能,用户将如何使用它。最好在此处链接到对应的 issue。文档同时明确要求:不要用 AI 撰写 PR 描述,要用自己的话描述想法——这既帮助你梳理思路,也让维护者看到变更背后的人类思考过程。如果英文表达有困难,可以使用翻译工具。

第 4 步:通过自动化 CI 检查

提交 PR 后 CI 会自动运行,且只有在 CI 通过、PR 获得绿色勾之后,才经常才会进入第一轮人工评审。如果遇到 CI 失败不知道如何处理,可以直接在 PR 中留言求助。

CI 的具体内容定义在 .github/workflows/ci.yml 中,从源码与配置可以确认以下检查项:

  • 测试矩阵cargo test --workspaceubuntu-latest(64 位 + 32 位 i686 目标)与 windows-latest 上并行运行;全局设置 RUSTFLAGS: "-Dwarnings",即任何警告都会导致编译失败。矩阵失败时 CI 还会上传 tests/store/ 下的测试产物与 tests/store/report.html 测试报告作为工件;
  • 静态检查 job(checks)cargo clippy --workspace --all-targets --all-features--no-default-features 各一遍,cargo fmt --check --all(rustfmt),以及 cargo doc --workspace --no-deps --document-private-items——最后一条意味着所有 Rust 文档注释(包括私有项)都必须能无错生成,这直接呼应下文"新 Rust 类型必须有文档注释"的要求;
  • 文档 job(docs)cargo docit compile --format website --deny-warnings--format pdf,即官网文档与 PDF 文档都必须无警告地编译通过(docit 别名定义在 .cargo/config.toml);
  • 最低 Rust 版本 job(min-version):用 1.92.0 工具链跑 cargo check --workspace,与 Cargo.tomlrust-version = "1.92" 的声明一致;
  • fuzz 与 miri job:构建 tests/fuzz 下的模糊测试器;用 Miri 检查 unsafe 代码。

代码风格层面,Cargo.toml[workspace.lints.clippy] 段启用了约 30 条 warn 级 clippy 规则(如 get_unwrapimplicit_cloneredundant_type_annotations 等),配合 CI 的 -Dwarnings,实际上等价于强制。此外 clippy.tomlrustfmt.toml 进一步约束了风格细节。

第 5 步:维护者评审

维护者在评审中会检查代码质量、潜在 bug、以及贡献是否与之前的讨论一致。文档鼓励:如果你觉得某条评审评论遗漏了什么或不够准确,请大胆质疑("please challenge it!")——这体现了该项目对协作沟通的预期。

第 6 步:合并并进入下一个版本的 Changelog

评审通过后,PR 将被合并并随 Typst 的下一个版本发布;贡献者会出现在 changelog 中。从 docs/content/changelog/index.typ 的源码可以看到,每个版本的 changelog 页面在 HTML 目标下会渲染一个 Contributors 章节,通过 slot 机制列出该版本区间内的所有贡献者——这就是"你的名字进入 changelog"的具体实现位置。

三、什么样的 PR 是一个"好 PR"

文档给出了"好 PR"的五条具体特征,每一条都可以对照仓库结构落地:

  1. 实现单一、自包含、且事先讨论过的功能或 bug 修复。
  2. 改动尽量小。 增加/修改的代码与接口尽量少;若必须改动较大范围的抽象,应在实现过程中持续讨论。
  3. 在合适处添加测试(视觉/HTML 测试需附参考输出),详见 tests/README.md
  4. 所有新的 Rust 类型都带文档注释。 这一点由 CI 的 cargo doc --document-private-items 步骤强制保障。
  5. 所有新的 Typst 定义(元素/函数)附带简要文档,理想情况是配一个约 5–10 行、宽度小于 38 列的简洁示例(可参考现有示例的写法)。文档注明这部分"不是太关键",因为发布前官方会统一润色文档。

关于测试的补充要求,tests/README.md 提供了完整细节,这里给出与贡献直接相关的要点:

  • 集成测试输入位于 tests/suite/(按 crate 平行组织),参考输出位于 tests/ref/;每个测试以 --- {name} {attr}+ --- 声明,例如 tests/suite/math/attach.typ 中的 --- math-attach-mixed paged html ---;测试名必须全局唯一;
  • 属性至少包含一个测试目标:eval(纯脚本断言,不产生输出)、paged(分页输出,含 render/pdf/pdftags/svg 阶段)、html(对比参考 HTML 文件)等;辅助属性如 large(允许参考图超过 20 KiB,应谨慎使用)、empty(声明不应产生非平凡输出);
  • 本地运行用仓库内置的 cargo 别名 cargo testit(定义于 .cargo/config.toml,其本质是运行 test-wrapper 包),例如:
    • cargo testit math:名称中含 "math" 的所有测试;
    • cargo testit --exact math-attach-mixed:精确名称匹配;
    • cargo testit --stages html,pdftags:只跑部分阶段以加快速度;
    • cargo testit --exact my-test-name --update:更新/生成某测试的参考输出;
  • 测试分三类:断言类(调用 testassert.eq 校验脚本行为)、诊断类(用 // Error: 2-7 ... 行内注解校验诊断信息与代码跨度)、输出类(视觉渲染图、参考 HTML、PDF 标签树对比)。文档建议:能在断言与参考图之间二选一时,优先断言,便于独立理解且避免图片膨胀。

四、评审周期与项目愿景

评审周期(Review cycle): 贡献者在评审过程中长期无响应是可以理解的,但维护者会在一段时间后将"等待贡献者响应"的 PR 关闭,以免 PR 追踪区堆满陈旧 PR。同理,维护者评审也需要时间——如果超过约一个月没有回应,可以 ping 一位维护者。

愿景契合度(What fits with the vision): Typst 虽然是开源项目,同时也是一家创业公司的产品。技术贡献始终基于其技术价值来判断;但作为公司,其短期优先级会变化(有时不预先通知),这会影响设计与决策流程以及开发/评审的速度;某些提案若直接影响公司存续,会从商业角度审慎考虑。文档给出的核心判断问题是:"这个想法是否有助于让 Typst 成为首要的技术排版应用?" 若答案是肯定的,这个想法大概率适合 Typst;拿不准时,先来讨论。

五、贡献前自检清单

综合 CONTRIBUTING.md 与配套文档,提交 PR 前可以对照以下清单:

  1. 改动是否单一、自包含,且事先与社区讨论过?
  2. 新增 Rust 类型是否都有文档注释(CI 会执行 cargo doc --document-private-items)?
  3. 是否添加了合适的测试;视觉/HTML 测试是否用 cargo testit --exact <name> --update 生成了参考输出?
  4. 新 Typst 定义是否附上了简短文档与 5–10 行、<38 列的示例?
  5. 本地 cargo fmt --check --allcargo clippy --workspace 是否干净(CI 以 -Dwarnings 运行)?
  6. PR 描述是否用自己的话写明了技术理由与用户视角的使用方式,并链接了相关 issue?

附:关键文件索引

文件 说明
CONTRIBUTING.md 官方贡献流程(本文主文档)
docs/dev/architecture.md 编译器架构与 crate 目录总览
tests/README.md 集成测试套件:目录结构、testit 命令、参考图策略
.github/workflows/ci.yml PR 触发的 CI:测试矩阵、checks、docs、min-version、fuzz、miri
Cargo.toml 工作区定义:版本 0.15.1、最低 Rust 1.92、clippy 规则集
.cargo/config.toml cargo testit / cargo docit 别名定义
docs/content/changelog/index.typ 版本 changelog 与贡献者名单的生成逻辑
登录后查看全文
热门项目推荐
相关项目推荐