何时使用
对于任何详细的技术撰写——调查报告、架构总结、根本原因文档、迁移说明,使用 Typst 而非 Word/.docx。目标文档应满足以下条件:
- 阅读起来像真正的技术报告:包含标题页、执行摘要、编号章节
- 打印效果好(LaTeX 风格排版:
#set page、#set heading(numbering: "1.1")、两端对齐正文) - 包含图表(架构图/流程图,不仅仅是文字)
- 包含表格(对比表、证据表、状态表)
- 包含指向来源的可点击链接(聊天线程、GitHub PR、Wiki 页面)
- 引用主要来源,并附有直接引语(消息、PR 正文),注明作者和日期
触发短语:"write this up"、"create a doc"、"typst it"、"make a report on this"——尤其是在多源调查(聊天搜索、GitHub PR 审查、实时系统证据)之后,需要将其综合成可共享的成果。
在编译之前,保留并查阅个人的 Typst 注意事项文件(例如 ~/notes/typst.md),用于记录已知的语法陷阱(脚注位置、#N 冲突、fletcher 导入、表格列大小等)——并在发现新的编译错误类别时追加记录。
关键语法规则(typst compile 前的预检清单):
- 粗体标记使用单个
*word*,绝不使用**word**:Markdown 双星号会产生数十个编译器警告(warning: no text within stars; using multiple consecutive stars has no additional effect)。 - 数学模式中的字符串需要引号:在
$ ... $中,多字母标识符如$Count=65$或$RTO$会编译失败(unknown variable)。请写成$"Count"=65$或将代码放入反引号中(`Count=65`)。 - 数学中不使用 LaTeX 反斜杠运算符:编写
$\approx$会失败(unknown variable: pprox)。Typst 使用裸符号:$approx$,不带反斜杠。
深入内容;在呈现上节约资源
两个指导每份报告的常设指令:
- 深入真正的技术内容。 追求极致的技术深度,而不是浅显的总结——更完整的原始控制台输出,更多的架构/状态机图表,当主题与硬件相关时提供寄存器/位字段或数字电路级别的细节,当主题与软件执行相关时提供 CPU 指令/汇编级别的细节。当草稿在 5-6 页时感觉"完成",这是一个信号,需要再深入一层(多一个
redis-cli/systemctl/寄存器 dump,多一个架构图,多一个行业比较角度),而不是停止。具体章节深度期望见下文。 - 但在呈现上节约资源,而不是内容。 内容的深度和样式的资源节约是两个独立维度——在事实/证据/图表上深入,但保持视觉呈现本身的油墨轻盈:浅色调背景 + 彩色边框/文字代替实心颜色填充,颜色仅在承载意义时使用(见下文配色方案)。油墨轻盈主导的是页面正文油墨,而非标题块——标题本身就是带框的(见配色方案第 1 条)。更多页的真实技术内容是目标;每页更多实心颜色油墨则不是。
工作流程
- 在写作之前,首先收集所有证据(聊天搜索、GitHub PR 阅读、实时命令输出、问题追踪器/聊天先例搜索)——不要在研究中途开始
.typ文件;完成综合后再动笔。 - 通过一两个
write/eval调用编写完整的.typ源代码,使用上述结构模板(单引号框标题、强调色标题带细线、浅色调表格表头、选择 2-4 个有意义的关键时刻使用语义标注、浅色控制台块、使用#figure包装的 fletcher 节点图、默认无目录)。如果使用 fletcher,始终以#import "@preview/fletcher:0.5.7": diagram, node, edge开头文件——省略此导入是第一次编译时最常见的错误。 - 编译:
typst compile file.typ(从文件所在的工作目录运行——每次会话检查一次typst --version以确认二进制可用;如果使用 fletcher,一次临时的/tmp测试编译可以在将其集成到正式文档前确认网络/包解析)。遇到编译错误?在从头调试之前先检查你的注意事项文件。 - 在声明完成之前始终进行视觉验证——将每一页渲染为 PNG(
typst compile --format png --ppi 100 file.typ "page-{p}.png"——对输出模式加引号)并read每个 PNG 以检查布局/间距/渲染,特别是任何包含图表、表格或标注的页面。具有 3 条以上边或双向边对的图表需要特别关注标签碰撞。 - 然后进行单独的内容阅读检查——布局验证不是内容验证。 步骤 4 证明没有渲染错误;它绝对不证明任何内容是真实的。再次
read每个渲染的页面,这次将正文与源材料进行对比阅读,并特别寻找:(a) 手工输入的部分交叉引用("参见 §9.1.3")在插入章节后失效;(b) 表单元格中相对于源材料反转或调换的主张;(c) 并非来自主要工件而是二手转录的数字——将它们标记为[INFERENCE]或去验证。实践证实是必要的:一份通过完整布局检查的文档仍然包含一个悬空的§引用和一个事实上反转的表单元格,两者都仅通过阅读发现。一次写入生成的 40 KB 文档仅因为编译通过并不意味着已经被校对。 - 将最终的
.typ+.pdf移入项目的文档位置(例如docs/generated/)并提交两者,然后删除任何中间 PNG 检查文件——将源代码与编译输出放在一起,以便以后可重新编辑。
使用语义标记
根据 Typst 自身的无障碍指南:始终使用真实的语义元素(= Heading、#quote(...)、#table(...)),而不是手动将纯文本/正文样式化为看起来像那个元素(例如 #text(size: 16pt, weight: "bold")[Heading])。绝不要发明一种并行的"看起来像标题"的约定;始终通过真实的标记元素驱动外观。
配色方案
- 正文字体:
New Computer Modern。 基准是"像 LaTeX"——NCM 就是 LaTeX 的外观,并且随 Typst 一起提供,因此始终可解析。绝不要选择未安装在机器上的字体(使用typst fonts验证):Typst 仅对缺失的字体系列发出警告并静默回退,导致文档虽然"干净"地编译但看起来不对。如果出现unknown font family警告,这是需要修复的缺陷,而不是可以容忍的警告。 - 语义标注调色板。 绿色
#1a7f37、黄色#9a6700、红色#cf222e、蓝色#0969da、紫色#6639ba、橙色#bc4c00;控制台/表格色调#f2f6fb/#eaf1fb带边框#9fb8d6/#c8d6e8。内联和块级raw应使用机器上存在的等宽字体系列(例如Consolas、JetBrains Mono、Menlo)。
一种结构性强调色,仅用于装饰——加上语义标注块用于意义。 这是已确定的模式;默认应用它,无需从头重新推导:
- 标题块:居中对齐的彩色文本,带边框框。使用
#box(fill: white, stroke: 1.5pt + accent, ...)包裹标题。 - 表格表头:浅色调填充 + 强调色文本,绝不使用实心颜色填充。
- 用于有意义发现的语义标注块——这是额外颜色获得使用的地方,因为它是功能性的,而非装饰性的。根据内容选择以下适合的标注;不要强制在每个文档中都使用全部——每份报告总共 2-4 个标注是良好的密度,而不是每段一个。
- 已验证(绿色勾号)——已确认良好的发现,一行。
- 异常(黄色感叹号)——意外但尚未确认为缺陷。
- 已确认缺陷(红色 X)——已确认的不良发现,一行。
- 注释(蓝色信息)——一个非关键的值得强调的观察。
- 提示(紫色灯泡)——一个有用的建议或最佳实践。
- 开放问题(橙色问号)——一个真正的未解决差异或疑问。
- 在有助于打印可读性的文档/章节中变化色调。
- 图表框色保持基于角色/语义。
- 任何地方都没有大的实心深色填充(例如带有白色文本的深蓝色横幅)。章节标题:彩色文本 + 下方一条细彩色线,而不是填充的颜色带或框。
- 控制台/代码输出块:浅色调背景,不是灰色。 平坦的
#f4f4f4灰色看起来沉闷/像复印件。使用带微妙匹配边框的浅色调。 - 绝不在章节之间使用
#pagebreak()。 在每个=标题前进行分页会每章留下半页空白纸,打印时浪费真正的纸张。让章节流动;新章节从中页开始是正确的。唯一可接受的#pagebreak()是分隔标题页和正文的那个。
两个默认章节——自动包含它们
- 竞争/行业背景。 替代方案如何解决这个问题,这种架构立场在结构上获得和付出了什么?将每个优势视为一个相应的可测试风险。除非来自真实的竞争文档,否则将该部分标记为一般行业知识,使用
[INFERENCE]。 - 自动化/测试工具,具体地。 确切调用方式、运行主机、虚拟环境和固定依赖项、标记选择,以及如何读取收集、取消选择和执行的计数。"有一个测试套件"不是覆盖范围。
图形放置:将图表/表格包裹在 #figure(...) 中,让 Typst 浮动它们
根据 Typst 自身的布局指南,图形默认在内容流中内联放置,但将图表或表格包裹在 #figure(..., caption: [...]) 中会解锁 placement: top/placement: bottom,让 Typst 将它们浮动到页面顶部/底部,而不是在段落中间尴尬地分割内容。始终为图表提供带有真实标题的 #figure(...) 包装器(永远不要在正文中浮动一个裸的 #diagram(...) 调用)——这也是使图表通过 @sec-label 可交叉引用,并为屏幕阅读器/重用工具提供正确的语义图形+标题配对,而不仅仅是一个未标记的图像。
用于节点/边图的 Fletcher
工作模式,确认编译和渲染正确(根据上述放置指南包裹在 #figure 中)。记住导入(见工作流程步骤 2)——此代码片段假定它已在文件顶部:
#figure(
diagram(
node-stroke: 0.6pt,
spacing: (3em, 2em),
node((0,0), [Step 1], fill: rgb("#dbe9ff"), corner-radius: 4pt),
node((0,1), [Step 2], fill: rgb("#dbe9ff"), corner-radius: 4pt),
edge((0,0), (0,1), "-|>", bend: 10deg),
edge((0,1), (0,0), "-|>", bend: 10deg),
),
caption: [由于此处省略了内联标签,用一行标题解释两个方向/边。],
)
坐标是 (列,行) 元组;node-stroke/fill/corner-radius 样式化单个节点;edge(from, to, "-|>") 绘制箭头(标记字符串,不是关键字参数,选择箭头头——"-|>" 和 "->" 都有效;"..|>" 用于虚线箭头)。多个独立链可以共享一个 diagram(...) 调用,使用不同的列索引和每个链带 stroke: none 的标题行节点。保持边标签为一个短单词/短语,并将完整解释移动到图形的 caption 中——内联边标签长于一个单词是经典的标签碰撞失败情况。
深度期望:默认长篇、极客深度,而非摘要
除非明确要求简短,否则对于完整的调查报告,目标为 10-12 个渲染页面——一个简短、正确但薄弱的报告是一种失败模式,而不是高效的结果。具体来说,"深入"意味着在主题支持的情况下,包含以下内容:
- 完整的原始控制台/日志输出,而非截断的片段——实际命令 + 实际输出,逐字逐句,对于每个来自实时系统证据的主张。
- 至少一个架构或状态机图(通过 fletcher,见上文),展示各部分实际如何连接,而不仅仅是描述它的文字。
- 寄存器/位字段或数字电路级别的细节,当主题与硬件相关时(例如,特定配置寄存器的位布局、信号时序图、ASIC 块的端口映射表、从实际驱动程序源中获取的实 结构体/操作码定义)——不要停留在"硬件执行 X",展示实际机制。
- CPU 指令/汇编或系统调用级别的细节,当主题与软件执行相关时(例如,驱动程序实际发出的系统调用、热路径的反汇编是什么样子)——不要停留在"驱动程序执行 X",展示实际代码路径。
- 专门的行业/外部背景章节(见下文)——绝不要在孤立中呈现内部机制。
- 真正的先例/历史搜索——检查问题追踪器、聊天历史和 git 历史,以确定这个确切问题之前是否被问过(甚至几年前);一份关闭了多年未解决问题的报告是比将发现视为全新更强的证据。
结构: (1) 标题 + 执行摘要, (2) 背景, (3) 证据时间线/方法论——每个不同发现一个子章节,附有自己的引用证据块,通常是最长的章节, (4) 如果主题名称与其他内容重叠则加上消歧章节, (5) 对比表格, (6) 行业/外部背景, (7) 架构/综合,作为带图表的编号端到端列表, (8) 带有具体后续措施的开放问题, (9) 与起源调查的关联, (10) 附录,包含从正文中修剪的完整原始证据。当草稿感觉完成但很短时,进行一轮真正的额外调查(另一次实时检查、另一次寄存器 dump、另一次网络搜索、另一个图、另一次历史搜索寻找先例),而不是填充现有正文——深度必须来自真实内容,绝不要来自文字