Typst 入门与精通

Typst 是一款新兴的基于标记的排版系统,它致力于在拥有与 LaTeX 同等强大功能的同时,提供更为简洁易学的用户体验 。本指南将系统地介绍 Typst 的各项功能,从基础入门到高级应用,帮助用户全面掌握这款现代排版工具。

Typst 概览 (Typst Overview)

在深入学习 Typst 的具体语法和功能之前,有必要了解其核心设计哲学和主要优势。这些理念贯穿于 Typst 的方方面面,是理解其特性和行为的关键。

Typst 的设计哲学 (Typst’s Design Philosophy)

Typst 的设计围绕三大核心目标:强大 (Power)简洁 (Simplicity)性能 (Performance) 。为了实现这些目标,Typst 遵循以下三项基本设计原则:

  • 通过一致性实现简洁 (Simplicity through Consistency):Typst 力求系统行为的一致性。用户学习掌握某项操作后,应能将其知识迁移应用于其他任务。如果针对同一任务存在多种实现方式,那么这些方式应处于不同的抽象层面。例如,使用 = Introduction#heading[Introduction] 都能创建标题,前者可视为后者的语法糖,这体现了不同抽象级别下的一致性表达 。这种一致性显著降低了用户的学习门槛。
  • 通过可组合性实现强大 (Power through Composability):Typst 的强大并非源于为每一个细枝末节的功能都提供一个独立的”旋钮”,而是提供少量可以灵活组合的核心构建模块 。用户可以通过组合这些基础模块来构建复杂功能,实现意想不到的效果。这与 LaTeX 大量依赖特定包(\usepackage{knob})的模式形成鲜明对比。LaTeX 的包生态系统虽然庞大,但也带来了学习成本的增加和潜在的包冲突问题。Typst 的可组合性原则鼓励用户理解和运用核心机制,这可能意味着初学者在面对非常特定的需求且缺乏现成 Typst 包时,会感觉比在 LaTeX 中寻找专用包更具挑战性。然而,一旦掌握了组合的思维,用户将能更灵活地创造解决方案,减少对特定包的依赖。长远来看,Typst 的包生态可能会更侧重于提供基于核心功能的高级抽象或特定领域工具集,而非弥补核心功能的缺失。这也对模板和高级样式的创建提出了更高的要求,即更多地依赖于对这些可组合原语的巧妙运用。
  • 通过增量编译实现性能 (Performance through Incrementality):Typst 的所有语言特性都为支持增量编译而设计。借助其内置的 comemo 系统,Typst 能够实现极快的编译速度,从而支持即时预览功能 。这极大地提升了用户的写作和调试效率。

这些设计哲学共同塑造了 Typst 的独特体验,使其在功能性、易用性和效率之间取得了良好的平衡。

Typst 的核心优势 (Core Advantages of Typst)

基于其独特的设计哲学,Typst 展现出以下核心优势:

  • 极速编译:得益于增量编译技术,Typst 的编译速度非常快,大型文档也能迅速响应,支持即时预览 。
  • 友好错误提示:当出现问题时,Typst 提供清晰易懂的错误信息,帮助用户快速定位并解决问题 。
  • 易学易用:Typst 的语法设计简洁直观,许多基础标记与 Markdown 类似,显著降低了上手难度 。
  • 强大脚本能力:Typst 内置了与排版过程紧密集成的脚本系统,允许用户通过编程方式实现复杂的文档自动化和样式定制 。

这些优势使得 Typst 成为传统排版工具的一个有力竞争者,尤其对于追求效率和现代体验的用户具有很强的吸引力。

第一部分:Typst 入门基础 (Part 1: Typst Fundamentals)

本部分将引导用户完成 Typst 的安装,熟悉其基本环境,并掌握核心概念与基础语法,为后续深入学习打下坚实基础。

第 1 章:安装与初识 (Chapter 1: Installation and First Look)

开始使用 Typst 的第一步是安装其编译器并熟悉其工作环境。

安装 Typst 编译器 (Installing the Typst Compiler)

Typst 提供了多种安装方式,以适应不同操作系统和用户偏好:

  • Linux, macOS, WSL (Windows Subsystem for Linux)
    • 可以通过 curl | sh 脚本快速安装。在终端执行 curl -fsSL https://typst.community/typst-install/install.sh | sh 即可。
    • 也可以通过 Snapcraft 包管理器安装:sudo snap install typst
  • Windows
    • 可以使用 PowerShell 中的 irm | iex 脚本进行安装:irm https://typst.community/typst-install/install.ps1 | iex
  • 官方二进制文件
    • 用户也可以直接从 Typst 在 GitHub 的官方发布页面 (typst/typst releases) 下载预编译的二进制文件。这通常是最直接且官方推荐的方式之一。

更改安装位置与安装特定版本: 通过 curl | shirm | iex 脚本安装时,可以设置环境变量(如 TYPST_INSTALL)来指定安装位置。同时,这些脚本也支持通过参数安装特定版本的 Typst。例如,在 Linux/macOS 上安装 0.10.0 版本:curl -fsSL https://typst.community/typst-install/install.sh | sh -s 0.10.0

清晰的安装步骤是用户入门的关键。提供多种途径能确保不同背景的用户都能顺利配置好 Typst 环境。

在线编辑器与本地环境 (Web App vs. Local Environment)

Typst 提供了两种主要的工作环境:

  • Typst 官方在线编辑器 (Typst.app):这是一个功能完善的网页应用,用户无需在本地安装任何软件即可开始使用 Typst。其界面通常采用双栏布局:左侧为源码编辑面板,右侧为实时预览面板。在线编辑器极大地降低了初次尝试和快速原型设计的门槛。
  • 本地命令行工具 (CLI):安装 Typst 编译器后,用户可以在本地通过命令行进行操作。常用的命令包括:
    • typst compile <文件名.typ>:将 Typst 源文件编译成 PDF。
    • typst watch <文件名.typ>:监视源文件的改动,并在文件保存时自动重新编译。由于 Typst 的增量编译机制,watch 模式下的重新编译速度非常快,几乎可以实现即时更新预览。

在线编辑器便于快速上手和协作,而本地环境则提供了更大的灵活性,例如与版本控制系统 (Git) 集成、使用自定义脚本进行批处理等。用户可以根据自己的需求和偏好选择合适的环境。

你的第一个 Typst 文档 (Your First Typst Document)

无论是使用在线编辑器还是本地环境,创建第一个 Typst 文档都非常简单。

  1. 打开编辑器(在线应用或本地文本编辑器)。
  2. 在源码面板(或 .typ 文件中)输入一些文本,例如:代码段

    你好,Typst 世界!
    
    这是我的第一个 Typst 文档。
    它使用简单的标记来创建段落和标题。
    
    = 这是一个一级标题
    
    == 这是一个二级标题
    
  3. 如果使用在线编辑器,预览面板会即时显示渲染效果。如果使用本地 CLI,可以运行 typst compile mydocument.typ 生成 PDF,或使用 typst watch mydocument.typ 启动实时编译和预览(通常配合 PDF 阅读器自动刷新功能)。

在这个简单的示例中:

  • 空行用于分隔段落。
  • 以一个 = 开头的是一级标题,两个 == 开头的是二级标题,以此类推。

通过这个”Hello World”式的过程,用户可以立即体验到 Typst 的基本操作和即时预览的便捷性,从而建立初步的信心。

第 2 章:核心概念与基础语法 (Chapter 2: Core Concepts and Basic Syntax)

掌握 Typst 的核心概念和基础语法是高效使用该工具的前提。Typst 的设计力求简洁和一致,使得用户能够快速上手。

标记模式、代码模式与数学模式 (Markup, Code, and Math Modes)

Typst 主要有三种工作模式,它们决定了文本如何被解释和处理:

  • 标记模式 (Markup Mode):这是 Typst 文档的默认模式。在此模式下,用户主要编写文档内容,并使用简单的标记符号进行格式化,如创建标题、列表、强调文本等。
  • 代码模式 (Code Mode):当需要执行 Typst 的脚本功能,如调用函数、定义变量、进行计算或控制流程时,就需要进入代码模式。代码模式通常以 # 符号开头。一旦进入代码模式(例如,在 #let 语句或函数调用中),后续的表达式通常不需要再以 # 开头,除非中间切换回了标记或数学模式。
  • 数学模式 (Math Mode):专门用于排版数学公式。数学模式通过 $ 符号来包裹公式内容。例如,$ax^2 + bx + c = 0$

理解这三种模式及其切换方式对于编写 Typst 文档至关重要,因为不同的语法和功能在不同模式下有其特定的行为和含义。

文本、段落与标题 (Text, Paragraphs, and Headings)

  • 文本输入:直接输入文本即可。
  • 段落创建:通过在两行文本之间插入一个或多个空行来创建新的段落。
  • 标题语法:使用 = 符号创建标题。一个 = 表示一级标题,两个 == 表示二级标题,以此类推,增加 = 的数量可以创建更低级别的标题。例如:代码段

    = 一级标题
    正文内容...
    
    == 二级标题
    更多正文...
    
    === 三级标题
    

这些是构成任何文档最基本的元素,Typst 为它们提供了非常直观且易于记忆的语法。

列表:无序、有序与术语列表 (Lists: Unordered, Ordered, and Term Lists)

Typst 支持创建多种类型的列表,其语法与 Markdown 类似,非常便捷:

  • 无序列表 (Unordered Lists):在列表项前使用 -* 符号。代码段

    - 项目一
    - 项目二
      * 嵌套项目A
      * 嵌套项目B
    - 项目三
    
  • 有序列表 (Ordered Lists):在列表项前使用 + 符号,或者使用数字加点(如 1.)。Typst 会自动为列表项进行编号。代码段

    + 第一项
    + 第二项
      1. 子项目1
      2. 子项目2
    + 第三项
    
  • 术语列表 (Term Lists / Definition Lists):使用 / 术语: 描述 的格式创建。代码段

    / Typst: 一个现代排版系统。
    / LaTeX: 一个经典的科技排版系统。
    

除了这些基础标记外,Typst 还提供了 listenum 函数,用于实现更高级或更定制化的列表功能。列表是组织和呈现信息的重要方式,Typst 的简洁语法使得创建列表非常高效。

  • 强调 (Emphasis)
    • 加粗 (Strong Emphasis):使用一对星号 * 包裹文本,例如 *重要内容*。这对应于 strong 函数。
    • 斜体 (Emphasis):使用一对下划线 _ 包裹文本,例如 _强调文本_。这对应于 emph 函数。
  • 链接 (Links)
    • 自动链接:文本中出现的标准 URL (如 http://example.comhttps://typst.app) 会被自动转换为可点击的链接。
    • 自定义文本链接:使用 #link 函数,格式为 #link("URL")[显示文本]。例如:#link("https://typst.app")
  • 原始文本 (Raw Text):使用一对反引号 ` 包裹文本,例如 `code_snippet()`。原始文本块中的内容通常不会被 Typst 的标准标记规则所解释,适合用于显示代码片段、特殊字符序列等。

这些是富文本表达中常用的元素,Typst 为它们提供了简洁明了的语法。

函数调用基础 (Basic Function Calls)

函数是 Typst 实现各种排版效果和高级功能的核心机制。在标记模式中调用函数的基本语法如下:

  1. # 符号开头。
  2. 紧跟函数名称。
  3. 函数参数放在一对圆括号 () 内。
  4. 参数分为位置参数 (Positional Arguments)命名参数 (Named Arguments)
    • 位置参数按顺序传递,无需指定参数名。
    • 命名参数使用 参数名: 值 的形式指定,顺序通常不重要。
  5. 如果参数是字符串,通常需要用双引号 " 包裹。
  6. 多个参数之间用逗号 , 分隔。

示例

代码段

// 插入一张图片,并设置其宽度为页面宽度的50%
#image("images/logo.png", width: 50%)

// 创建一个红色的文本块
#text(fill: red)[这是红色文本]

在第一个例子中,"images/logo.png" 是一个位置参数(通常是图像路径),width: 50% 是一个命名参数。在第二个例子中,fill: red 是命名参数,[这是红色文本] 是一个特殊的”内容块”参数,我们将在后续章节中详细讨论。

理解函数调用的基本语法是掌握 Typst 的关键一步,因为 Typst 的许多高级功能都是通过调用各种内置或自定义函数来实现的。

Typst 基础语法的 Markdown 兼容性与差异性

Typst 的许多基础标记语法,如列表、强调等,确实与 Markdown 高度相似。这种相似性并非偶然,而是有意为之,目的是降低熟悉 Markdown 的用户的学习门槛,使他们能够快速上手 Typst 进行基本的文本编辑。正如 Typst 的设计者所述,其标记语法在很大程度上遵循了 Markdown 的风格,因为这大致符合人们在纯文本邮件中尝试格式化时会采用的方式。

然而,尽管存在诸多相似之处,Typst 并非 Markdown 的完全克隆或超集。一个显著且重要的区别在于标题的语法。Markdown 通常使用 # 符号来表示标题级别(例如 # H1, ## H2),但这个符号在 Typst 中被保留用于函数调用。因此,Typst 采用了 = 符号来定义标题:一个 = 代表一级标题,两个 == 代表二级标题,以此类推。

这种设计选择体现了 Typst 在易用性和系统自身功能优先级之间的一种权衡。选择与 Markdown 相似的语法是为了”易读易写”,吸引用户;但不完全兼容(如 # 的用途冲突)则是为了保证 Typst 自身核心功能(如强大的函数调用和脚本系统)的实现和一致性。Typst 的设计哲学中提到,”如果存在多种方式做同一件事,其中一种应该是另一种在不同抽象级别上的体现”。例如,= Introduction#heading[Introduction] 都可以创建标题,前者是后者的语法糖。这暗示 Typst 鼓励用户最终掌握并使用其原生语法体系,以充分发挥其全部潜力,而不是长期依赖于对 Markdown 的模拟。

对于那些希望在习惯的 Markdown 编辑器(如 Obsidian, iA Writer, Ulysses 等)中直接编写 Typst 内容的用户来说,这种不兼容性,尤其是标题语法的差异,可能会带来一些不便。这些编辑器通常依赖 Markdown 的标题语法来实现大纲视图、快速导航和内容折叠等功能,当它们遇到 Typst 的 = 标题时,这些便捷功能可能会失效。

因此,对用户的建议是:可以利用对 Markdown 的熟悉感来快速开始 Typst 的基础文本写作,但应尽早学习并适应 Typst 的原生语法,特别是像标题这样的核心结构元素。这样做才能无缝地利用 Typst 提供的所有高级特性和功能。

第二部分:内容创作与文档结构 (Part 2: Content Creation and Document Structure)

掌握了基础语法后,本部分将深入探讨如何使用 Typst 创作更丰富的内容,并构建结构清晰的文档,包括文本的进阶处理、图像与表格的应用、科学公式的精通排版,以及文档导航和文献管理等关键功能。

第 3 章:文本处理进阶 (Chapter 3: Advanced Text Handling)

Typst 提供了丰富的文本格式化选项,远超基础的强调。本章将介绍如何对文本进行更细致的修饰,以及如何处理特殊字符。

文本格式化:加粗、斜体、下划线、删除线等 (Text Formatting: Bold, Italic, Underline, Strikethrough, etc.)

Typst 提供了多种方式来修饰文本,既有简洁的标记语法,也有功能更强大的函数调用。

  • 加粗 (Bold/Strong Emphasis)
    • 标记:*strong text*
    • 函数:#strong[text]
    • 自定义字重:Typst 的 strong 效果默认是给当前字重增加 300 个单位(具体单位取决于字体)。如果需要更精确的控制,例如使用特定的”semibold”字重,可以通过 show 规则来实现:#show strong: set text(weight: "semibold")
    • 数学模式中的加粗:使用 bold() 函数,例如 $bold(A)$
  • 斜体 (Italic/Emphasis)
    • 标记:_emphasized text_
    • 函数:#emph[text]
    • 数学模式中的斜体:使用 italic() 函数,例如 $italic(A)$。对于罗马字母和希腊小写字母,斜体通常是默认样式。
  • 下划线 (Underline)
    • 函数:#underline[text]
    • 自定义样式:underline 函数接受多个参数以定制下划线的外观。
      • stroke:定义线的样式,可以是颜色、粗细、虚线模式等。例如:#underline(stroke: 1.5pt + red, [care])
      • offset:定义下划线相对于基线的偏移量。例如:#underline(offset: 2pt, [care])
      • extent:定义下划线超出内容两端的长度。
      • evade:布尔值,控制下划线是否避开字符的下降部分,默认为 true
      • background:布尔值,控制下划线是否置于文本之后,默认为 false
  • 删除线 (Strikethrough)
    • 函数:#strike[text]
    • 自定义样式:与 underline 类似,strike 函数也支持 stroke, offset, extent, background 等参数进行定制。例如:#strike(stroke: 1.5pt + red)[very stricken through]
  • 其他文本函数:Typst 的 text 模块还提供了许多其他有用的文本处理函数 ,例如:
    • #highlight(color)[text]:用指定颜色高亮文本背景。
    • #lower:将文本转换为小写。
    • #upper[text]:将文本转换为大写。
    • #smallcaps:将文本以小型大写字母显示。
    • #sub[script]:创建下标。
    • #super[script]:创建上标。

这些丰富的文本格式化工具,使得用户能够精确控制文档的视觉表现,满足各种排版需求。

特殊字符与转义 (Special Characters and Escaping)

在排版过程中,经常需要输入一些键盘上难以直接打出、或者在 Typst 中具有特殊语法含义的字符。Typst 提供了完善的机制来处理这些情况:

  • 转义字符 (Escape Character):反斜杠 \ 是 Typst 的主要转义字符。当需要在文本中直接显示一个具有特殊语法意义的字符(如 *, _, $, #, = 等)时,可以在其前添加反斜杠。例如,要显示美元符号 $1.50,应写作 \$1.50
  • Unicode 转义序列 (Unicode Escape Sequence):为了能够插入任意 Unicode 字符,Typst 支持十六进制的 Unicode 转义序列 \u{...}。花括号内填写字符的十六进制码点。例如,笑脸表情 😂 (U+1F602) 可以通过 \u{1f602} 输入。这种转义方式在普通文本和字符串中都有效。
  • 常用符号简写 (Symbol Shorthands):Typst 为一些常用的特殊字符和排版符号提供了简写形式,使得输入更为便捷。例如:
    • ~:非断行空格 (Non-breaking space, nbsp)。
    • --:短破折号 (en dash, –)。
    • ---:长破折号 (em dash, —)。
    • ...:省略号 (ellipsis, …)。
    • -?:软连字符 (soft hyphen, shy),用于指示可选的断词位置。
    • 数学模式中的简写更为丰富,例如 -> 代表右箭头 (→),<= 代表小于等于号 (≤) 等。

掌握这些特殊字符的输入和转义方法,对于确保文档内容的准确性和排版的多样性至关重要,尤其是在处理技术文档、多语言内容或包含特殊数学符号的文本时。

第 4 章:图文并茂:图像与表格 (Chapter 4: Visuals and Data: Images and Tables)

图像和表格是现代文档中传递信息、增强可读性的重要元素。Typst 提供了简洁而强大的功能来处理它们。

插入与调整图像 (Inserting and Adjusting Images)

Typst 支持多种常见的图像格式,包括 PNG, JPEG, GIF, 和 SVG。

  • 基本插入:使用 #image() 函数来插入图像。最简单的形式是提供图像文件的路径作为参数: 代码段

    #image("path/to/your/image.png")
    

    路径可以是相对于当前 .typ 文件的相对路径,也可以是以 / 开头的项目绝对路径(项目根目录通常是主 Typst 文件所在的目录,或通过 CLI 的 --root 参数指定)。

  • 调整图像大小#image() 函数接受 widthheight 命名参数来控制图像的显示尺寸。这些值可以是绝对长度(如 5cm, 100pt),也可以是相对于页面宽度或原始图像尺寸的百分比(如 50%)。 代码段

    // 设置宽度为10厘米,高度会自动按比例缩放
    #image("logo.svg", width: 10cm)
    
    // 设置宽度为页面可用宽度的60%,高度为4厘米
    #image("photo.jpg", width: 60%, height: 4cm)
    

    如果只指定 widthheight 中的一个,另一个通常会按图像原始比例自动缩放。

  • 图像描述与对齐#image() 函数还接受 alt 参数为图像提供替代文本,这对于可访问性非常重要。图像的对齐可以通过外部容器(如 #align(center)[...])或与其他布局元素结合来实现。
  • 将图像作为图例 (Figure):为了给图像添加标题、编号并使其可被引用,通常会将 #image() 函数包装在 #figure() 函数内。 代码段

    #figure(
      image("diagram.svg", width: 80%),
      caption: [这是一个流程图示例。]
    ) <fig-diagram>
    

    这里,<fig-diagram> 就是为这个图例设置的标签,后续可以通过 @fig-diagram 来引用它。

Typst 对图像的处理力求简单直接,同时通过参数提供了足够的控制能力,满足常见的图文混排需求。

创建与美化表格 (Creating and Styling Tables)

表格是展示结构化数据的关键工具。Typst 提供了 #table() 函数及其辅助元素来创建和定制表格,功能强大且灵活。

  • 基础表格语法:创建一个表格至少需要指定列的数量(或列宽分布)以及各个单元格的内容。单元格内容按从左到右、从上到下的顺序填充。 代码段

    #table(
      columns: 3, // 定义3列
      [*姓名*], [*年龄*], [*城市*], // 表头行 (用*强调*通常表示表头)
      [张三], , [北京],
      [李四], , [上海],
      [王五], , [广州],
    )
    

    在上面的例子中,[*姓名*] 等是内容块,每个内容块代表一个单元格。

  • 表头 (Header):为了语义清晰和更好的样式控制(以及未来的可访问性支持),建议使用 table.header() 来明确标记表头行或列。 代码段

    #table(
      columns: 2,
      table.header[*产品*][*价格*],
      [笔记本电脑], [¥5000],
      [智能手机], [¥3000],
    )
    
  • 列宽设置 (Column Widths)columns 参数不仅可以是一个整数(表示等宽列的数量),还可以是一个数组,用于精确定义每一列的宽度。宽度单位可以是:
    • auto:列宽根据内容自动调整(默认行为)。
    • 绝对长度:如 5cm, 80pt
    • 相对长度 (em):如 10em,相对于当前字体大小。
    • 百分比:如 40%,相对于表格可用总宽度。
    • 比例单位 (fr):如 1fr, 2frfr 单位会按比例分配剩余空间。 代码段
    #table(
      columns: (60pt, 1fr, 2fr, auto), // 四列,不同宽度定义
      //... 单元格内容...
    )
    
  • 单元格对齐 (Cell Alignment)#table() 函数的 align 参数可以控制所有单元格内容的对齐方式。它可以接受单个对齐值(如 center, right, top, horizon 的组合),一个对齐值数组(按列循环应用),或一个函数(根据单元格的 x, y 坐标返回对齐方式)。 代码段

    // 所有单元格居中对齐
    #table(columns: 2, align: center,...)
    
    // 第一列左对齐,第二列居中,第三列右对齐
    #table(columns: 3, align: (left, center, right),...)
    

    也可以使用 table.cell() 为单个单元格指定不同的对齐方式。

  • 单元格填充与边框 (Fill and Stroke)
    • fill 参数用于设置单元格的背景。它可以是单一颜色,一个颜色数组(Typst 会按列或行循环使用这些颜色,从而轻松创建斑马条纹表格),或者一个函数(基于单元格坐标 (x, y) 返回颜色,用于实现更复杂的填充模式,如棋盘格)。
    • stroke 参数用于定义表格和单元格的边框线。它可以接受颜色、粗细、线条样式等,也可以是一个函数来动态决定边框样式。 代码段
    // 水平斑马条纹表格 (简化示例)
    #table(
      columns: 2,
      fill: (row) => if calc.odd(row) { luma(240) } else { white },
      //... 单元格内容...
    )
    
  • 合并单元格 (Spanning Cells):使用 table.cell() 函数并指定 colspan (跨列数) 或 rowspan (跨行数) 参数来实现单元格合并。 代码段

    #table(
      columns: 3,
      table.cell(colspan: 3, align: center)[*年度报告*], // 跨3列的标题单元格
      [A],, [C],
     , table.cell(rowspan: 2, fill: silver)[E F], [G], // E F 跨2行
      [H],                                             [I],
    )
    
  • 内边距与间距 (Inset and Gutter)
    • inset 参数控制单元格内容与边框之间的内边距。
    • gutter 参数控制单元格之间的间距(列间距和行间距)。
  • 将表格作为图例 (Table as Figure):与图像类似,可以将 #table() 函数包装在 #figure() 函数内,以便添加标题、编号和标签,使其可以被交叉引用。

下表总结了 table 函数及其相关元素的一些核心参数和用法:

参数 (table 函数)类型描述示例
columnsautointrelativearray定义列的数量和宽度。可以是整数(列数),也可以是包含宽度定义的数组。columns: 3, columns: (2cm, 1fr, auto)
rowsautointrelativearray定义行的高度。rows: (1cm, auto)
fillcolorarrayfunction设置单元格背景填充。可以是单一颜色,颜色数组(用于斑马纹),或函数。fill: rgb("EAF2F5"), fill: (luma(240), white), fill: (x,y) =>...
strokenonelengthcolordict设置表格和单元格边框。stroke: 1pt + blue, stroke: (x,y) =>...
alignalignmentarrayfunction设置单元格内容的对齐方式。align: center + horizon, align: (left, center, right)
insetlengthdictionary设置单元格内边距。inset: 10pt, inset: (x: 5pt, y: 2pt)
gutterlengtharray设置行和列之间的间距。gutter: 0.5em
table.cellcontent用于创建具有特定属性(如 colspan, rowspan, fill)的单元格。table.cell(colspan: 2, fill: yellow)
table.headercontent标记表格的表头行/列,有助于可访问性和样式定义。table.header[*Col1*], [*Col2*]

表格参数众多且灵活,一个清晰的概览表能显著降低学习和使用难度,帮助用户快速查阅和理解 #table 函数及其子函数的核心功能。Typst 对表格的强大支持使其能够应对从简单数据列表到复杂出版级表格的各种需求。

第 5 章:精通科学公式排版 (Chapter 5: Mastering Scientific Formula Typesetting)

科学公式排版是 Typst 的一项核心功能。它借鉴了 TeX/LaTeX 的成功经验,同时力求提供更简洁、更直观的语法和更现代的交互体验。

数学模式详解 (Math Mode Explained)

如前所述,Typst 的数学模式通过 $ 符号来激活。

  • 行内公式 (Inline Math):将公式直接嵌入文本流中,使用单个 $ 包裹。 代码段

    爱因斯坦的质能方程是 $E = mc^2$。
    
  • 块级公式 (Display/Block Math):将公式单独展示为一个段落,通常会居中显示。块级公式的 $ 之间,以及公式内容与 $ 之间,需要有空格。 代码段

    毕达哥拉斯定理可以表示为:
    $ a^2 + b^2 = c^2 $
    这是一个著名的数学公式。
    
  • 多字母标识符 (Multi-letter Identifiers):在数学模式中,连续的字母序列(如 sin, cos, log, max)默认会被视为函数名或特殊常量,并以直立体显示,无需像 LaTeX 中那样使用反斜杠(如 \sin)。如果希望将多个字母作为普通变量序列(每个字母都应为斜体),则需要用引号将它们括起来,或者用空格隔开。 代码段

    $ sin(x) + cos(y) $ // sin 和 cos 会被正确识别
    $ floor(x/2) $      // floor 会被正确识别
    $ Q = rho A v + "time offset" $ // "time offset" 作为带空格的变量
    

    这种设计减少了冗余的命令输入,使得公式代码更为简洁。

Typst 的数学模式旨在让用户能够以接近自然书写的方式输入公式,同时保持排版的美观和准确性。

常用数学符号与输入 (Common Math Symbols and Input)

Typst 内置了大量常用的数学符号,并为它们提供了便捷的输入方式,包括直接的文本名称和快捷符号序列。

  • 通过名称输入:许多希腊字母、数学运算符和关系符号可以直接通过其英文名称输入。例如:alpha, beta, sum, integral, in, subset 等。
  • 快捷方式:Typst 为一些非常高频的符号设计了类似编程语言中的快捷输入。例如:
    • <= 得到 $ \le $ (小于等于)
    • >= 得到 $ \ge $ (大于等于)
    • != 得到 $ \ne $ (不等于)
    • -> 得到 $ \to $ (右箭头)
    • => 得到 $ \Rightarrow $ (双线右箭头)
    • oo 得到 $ \infty $ (无穷大)
  • 特殊字体符号:如黑板粗体 (Blackboard Bold) 可以通过重复大写字母输入,例如 RR 得到 $ \mathbb{R} $ (实数集),CC 得到 $ \mathbb{C} $ (复数集)。
  • 符号变体 (Symbol Variants):某些符号有不同的变体形式,可以通过在符号名称后附加 .variant_name 来选择。例如,phi.alt 可以得到 $ \phi $ 的另一种形式 $ \varphi $ 。
  • sym 模块:除了数学模式中直接可用的符号外,sym 模块(以及 emoji 模块)提供了更全面的符号集合,可以通过 #sym.symbol_name 的方式在标记模式或代码模式中插入。

下表列出了一些常用数学符号及其在 Typst 中的输入方式,并与 LaTeX 进行了对比,方便用户参考和迁移:

符号 Typst 输入 (Math Mode) Typst 输入 (sym) LaTeX 等效 备注
$ \le $ <= sym.leq \leq 小于等于
$ \ge $ >= sym.geq \geq 大于等于
$ \ne $ != sym.neq \neq 不等于
$ \to $ -> sym.arrow.r \rightarrow 右箭头
$ \leftarrow $ <- sym.arrow.l \leftarrow 左箭头
$ \leftrightarrow $ leftrightarrow sym.arrow.lr \leftrightarrow 双向箭头
$ \Rightarrow $ => sym.arrow.r.double \Rightarrow 双线右箭头
$ \alpha $ alpha sym.alpha \alpha 希腊字母 Alpha
$ \beta $ beta sym.beta \beta 希腊字母 Beta
$ \Gamma $ Gamma sym.Gamma \Gamma 希腊字母 Gamma (大写)
$ \infty $ oo sym.infinity \infty 无穷大
$ \mathbb{R} $ RR sym.RR \mathbb{R} 实数集 (双线 R)
$ \mathbb{C} $ CC sym.CC \mathbb{C} 复数集 (双线 C)
$ \sum $ sum sym.sum.big \sum 求和符号
$ \int $ integral sym.integral \int 积分符号 (math mode 中用 int 即可)
$ \sqrt{x} $ sqrt(x)   \sqrt{x} 平方根
$ \frac{x}{y} $ x/y   \frac{x}{y} 分数,自动形成
$ x_i $ x_i   x_i 下标
$ x^2 $ x^2   x^2 上标
$ \nabla $ nabla sym.nabla \nabla Nabla 算子
$ \partial $ partial sym.partial \partial 偏导数符号
$ \forall $ forall sym.forall \forall 全称量词
$ \exists $ exists sym.exists \exists 存在量词
$ \in $ in sym.in \in 属于
$ \notin $ notin sym.notin \notin 不属于
$ \subset $ subset sym.subset \subset 真子集
$ \approx $ approx sym.approx \approx 约等于
$ \cdot $ dot sym.dot.c \cdot 点乘
$ \times $ times sym.times \times 叉乘
$ \oplus $ oplus sym.oplus \oplus 异或和
$ \otimes $ otimes sym.otimes \otimes 张量积

丰富的内置符号和便捷的输入方式是 Typst 数学排版高效性的重要保障。这个表格能帮助用户,特别是从 LaTeX 过渡的用户,快速查找和掌握常用符号的 Typst 输入法。

方程、矩阵与多行对齐 (Equations, Matrices, and Multiline Alignment)

Typst 提供了构建复杂数学表达式所需的各种工具。

  • 方程函数 (equation):虽然简单的 $... $ 已经可以满足很多需求,但 #math.equation() 函数提供了更多控制,例如自动编号和块级显示 。 代码段

    #set math.equation(numbering: "(1)") // 设置公式编号格式
    
    #math.equation[
      e^(i pi) + 1 = 0
    ] <euler-identity> // 为公式添加标签
    如公式 @euler-identity 所示...
    
  • 矩阵 (mat):使用 mat() 函数创建矩阵。矩阵的行与行之间用分号 ; 分隔,同一行内的元素用逗号 , 分隔。 代码段

    $ mat(
        1, 2, 3;
        4, 5, 6;
        7, 8, 9
      ) $
    

    mat() 函数还支持许多参数进行定制:

    • delim:设置矩阵的括号,例如 delim: "。当一行中包含多个&` 时,会形成交替的右对齐-左对齐的列块。 代码段
    $ (3x + y) / 7 &= 9        && "给定" \
      3x + y      &= 63       &  "两边乘以 7" \
      3x          &= 63 - y   && "移项" \
      x           &= 21 - y/3 &  "两边除以 3" $
    

    在上述例子中,第一个 & 使得等号对齐。第二个 && (等效于 & &) 创建了两个连续的对齐点,使得注释文本 “给定”、”两边乘以 7” 等左对齐。

  • 分数 (frac):Typst 的 / 运算符在数学模式中通常会自动将其两侧的表达式转换为分数形式,并且括号也会自动调整大小。如果需要更明确的控制或处理复杂分子分母,可以使用 frac(numerator, denominator) 函数。 代码段

    $ 1/2 + (a+b)/(c+d) $ // 自动分数
    $ frac(sum_(i=1)^n x_i, n) $ // 使用 frac 函数
    
  • 其他常用数学函数:Typst 的 math 模块还包含了许多其他用于构建数学结构的函数 ,例如:

    • binom(n, k):二项式系数 $ \binom{n}{k} $。
    • cases(case1; case2;...):分情况讨论表达式,每种情况可以用 & 分隔条件和结果。
    • lr(content):自动调整大小的左右括号。也可以用 leftright 配合具体括号符号。
    • sqrt(x), root(n, x):平方根和 n 次方根。
    • vec(a, b, c):向量。
    • accent(base, acc):在 base 上方添加 acc 作为重音符号(如 $\hat{x}$ 可用 accent(x, hat))。
    • attach(base, t: top, b: bottom, tl:..., tr:...,...):在 base 的不同位置附加内容(上下标是其特例)。
    • underover(base, under:..., over:...):在 base 的上下方添加内容。

这些功能共同构成了 Typst 强大而易用的数学排版系统。

自定义数学宏的思路 (Approaches to Custom Math Macros - via functions)

熟悉 LaTeX 的用户可能会寻找类似 \newcommand\def 这样的宏定义机制来创建可复用的数学表达式片段。Typst 本身并没有直接对应的”文本替换式”宏定义命令 。然而,Typst 强大的函数定义和脚本能力为其提供了另一种实现相似甚至更强大功能的方式 。

在 Typst 中,创建可复用的数学片段或自定义”数学命令”的推荐方式是将其封装成一个函数。这个函数可以接受参数,并在其函数体内构造和返回所需的数学内容(通常是一个包含数学模式代码的内容块)。

从”文本替换”到”函数抽象”的转变: LaTeX 的 \newcommand 本质上更接近一种参数化的文本替换机制。虽然功能强大,但在处理复杂逻辑、参数类型检查或作用域管理方面有时会显得笨拙,甚至导致难以调试的嵌套问题。

Typst 的函数模型则更为规范和强大:

  1. 明确的参数和返回值:函数有清晰的输入(参数)和输出(返回的内容)。
  2. 作用域控制:函数内部定义的变量具有局部作用域,不会意外污染外部环境。
  3. 逻辑表达能力:函数体可以使用 Typst 的全部脚本能力,包括条件判断 (if/else)、循环 (for, while)、变量定义、调用其他函数(包括内置数学函数和自定义函数)等。这使得自定义的”数学宏”可以实现远比简单文本替换复杂得多的逻辑。

示例:

假设我们想创建一个表示偏导数的常用符号,如 LaTeX 中的 \newcommand{\pdv}{\frac{\partial #1}{\partial #2}}。在 Typst 中,可以这样定义一个函数:

代码段

#let pdv(numerator, denominator) = $ partial #numerator / partial #denominator $

// 使用
$ pdv(f, x) $  // 输出 ∂f/∂x
$ pdv(y^2, z) $ // 输出 ∂y²/∂z

在这个例子中:

  • #let pdv(numerator, denominator) =... 定义了一个名为 pdv 的函数,它接受两个参数。
  • 函数体 $ partial #numerator / partial #denominator $ 是一个数学模式的内容块。
  • #numerator#denominator 会被替换为调用函数时传入的实际参数值。

更复杂的例子:带可选参数的向量表示

代码段

#let myvec(content, arrow_style: "r") = {
  // 默认使用右箭头,可传入其他箭头符号的名称
  let arrow_symbol = symbol("arrow." + arrow_style)
  $ vec(#arrow_symbol, #content) $
}

$ myvec(A) $
$ myvec(B, arrow_style: "l.double") $ // 使用双线左箭头

虽然这种基于函数的方式与 LaTeX 的宏定义在底层机制上有所不同,但它为用户提供了极大的灵活性和表达力。用户需要从”定义一个简写”的思维模式,逐渐转变为”定义一个接受参数并返回特定排版结果的函数”的编程思维模式。这种转变一旦完成,用户会发现 Typst 的函数机制在创建可维护、可复用和功能强大的自定义数学结构方面具有显著优势。

此外,一些第三方工具如 tex2typst-rs 提供了将包含自定义宏的 TeX 公式转换为 Typst 格式的功能,这可能对迁移现有工作有所帮助。

总而言之,Typst 通过其统一的函数和脚本系统,为自定义数学表达提供了强大而一致的解决方案,鼓励用户采用更结构化和编程化的方式来构建复杂的数学文档。

第 6 章:文档导航:标签、引用与目录 (Chapter 6: Document Navigation: Labels, References, and Outlines)

对于较长的文档,如书籍、报告或学术论文,清晰的导航结构至关重要。Typst 提供了标签、交叉引用和自动目录生成功能,以帮助读者方便地在文档中定位信息。

使用标签与交叉引用 (Using Labels and Cross-References)

Typst 允许用户为文档中的几乎任何元素(如标题、图、表、公式、甚至特定文本位置)附加一个唯一的标签 (Label),然后通过这个标签在文档的其他地方创建交叉引用 (Cross-Reference)

  • 附加标签:在希望标记的元素之后,使用尖括号 <...> 来定义标签名称。标签名称在文档中应该是唯一的。 代码段

    = 简介 <sec-intro>
    本章节介绍项目的背景。
    
    #figure(
      image("data-flow.png"),
      caption: [系统数据流图]
    ) <fig-data-flow>
    
    $ E = mc^2 $ <eq-emc2>
    
  • 创建引用
    • 基本语法:使用 @ 符号后跟标签名称来创建一个到该标签的引用。Typst 会自动根据被引用元素的类型生成合适的引用文本(例如,”Section 1.1”,”Figure 2”,”Equation (3)”),并且这个引用本身也是一个可点击的链接,直接跳转到被引用的位置。代码段

      在章节 @sec-intro 中我们讨论了背景。
      详细流程参见图 @fig-data-flow。
      根据公式 @eq-emc2 可知...
      
    • #ref() 函数:为了更精细地控制引用的文本和行为,可以使用 #ref() 函数。

      • #ref(<label-name>):基本功能同 @label-name
      • supplement 参数:可以为引用添加前缀或后缀文本。supplement 可以是固定的内容,也可以是一个函数,该函数接收被引用元素作为参数并返回要显示的内容。代码段

        // 为对 <sec-intro> 的引用添加 "Chapter" 前缀
        #ref(<sec-intro>, supplement: [Chapter])
        // => Chapter 1 (假设 <sec-intro> 是第一个一级标题且编号为1)
        
        // 使用函数动态决定 supplement
        #show ref: it => {
          if it.element.func() == heading { "章节" } else { "图" }
        }
        
      • form 参数:#ref() 函数有一个重要的 form 参数,默认为 "normal",即生成上述的文本引用。如果将其设置为 "page",则引用会显示被标记元素所在的页码。代码段

        更多细节请参见第 #ref(<fig-data-flow>, form: "page") 页的图示。
        // => 更多细节请参见第 5 页的图示。(假设图在第5页)
        
  • 可引用元素:默认情况下,标题 (headings)、图 (figures,通过 #figure 创建的)、公式 (equations,通过 #math.equation 创建的且设置了编号) 和脚注 (footnotes) 是”可引用”的,意味着 @#ref 会自动生成它们的编号信息。对于其他元素,或者想要自定义引用行为,可能需要结合 show 规则或将元素包装在 figure 中并指定 kind

标签和交叉引用是确保长文档内部一致性和易读性的关键工具。Typst 的实现既简单易用,又提供了足够的灵活性。

生成文档目录 (Generating a Table of Contents)

Typst 可以自动根据文档中的标题或其他指定元素生成目录 (Table of Contents, ToC)。这是通过 #outline() 函数实现的。

  • 基本用法:在文档中希望插入目录的位置调用 #outline() 即可。默认情况下,它会收集所有级别的标题。代码段

    #set heading(numbering: "1.a.i") // 设置标题编号格式
    
    = 文档标题
    
    == 目录
    #outline() // 在此处生成目录
    
    = 第一章:引言 <chap1>
    

… == 1.1 背景 ... = 第二章:方法 ... \`\`\`

  • 自定义目录#outline() 函数提供了多个参数来定制目录的外观和内容:
    • title:设置目录的标题。可以是文本内容(如 title:),也可以是 auto(根据文档语言自动生成,如”目录”或”Contents”),或者 none(不显示标题)。
    • target:指定哪些元素应该被包含在目录中。默认是 heading。可以设置为其他元素选择器,例如 figure(生成图目录),table(生成表目录),或者更复杂的 figure.where(kind: image)(只包含图片类型的图例)。
    • depth:一个整数,限制目录包含的标题层级深度。例如 depth: 2 表示只显示一级和二级标题。
    • indent:控制目录条目的缩进。可以是 auto(自动根据编号或固定值缩进),一个相对长度(如 2em,每级缩进这么多),或者一个函数,该函数接收嵌套级别并返回缩进量(例如 level => level * 1.5em)。
    • fill:指定在目录条目标题和页码之间填充的字符,例如点线 .
  • 定制目录条目外观:可以通过 show outline.entry: it => {... } 规则来完全自定义每个目录条目的显示方式。it 代表一个目录条目对象,它包含如 level (层级), element (被引用的实际元素), body (条目文本), page (页码) 等字段。用户可以利用这些信息重新组织和格式化条目,例如改变字体、颜色,或者将整个条目变成一个自定义格式的链接。 代码段

    // 示例:将一级条目加粗,并修改链接样式
    #show outline.entry: it => {
      let body = it.body
      if it.level == 1 {
        body = strong(body)
      }
      link(it.element.location(), body + h(1fr) + it.page)
    }
    
    #outline(depth: 2)
    

Typst 的目录功能非常灵活,既能满足标准目录的需求,也为高级定制留下了充足的空间。通过与标签、引用和脚本功能的结合,可以创建出高度定制化的导航结构。

第 7 章:文献管理与引用 (Chapter 7: Bibliography Management and Citations)

规范的文献管理和引用是学术写作和许多专业文档的必备环节。Typst 提供了内置的文献处理功能,支持从外部文献数据库(如 BibTeX 文件)导入数据,并根据指定的样式在文档中生成引文和参考文献列表。

创建和使用参考文献 (Creating and Using Bibliographies)

  • 文献数据文件:Typst 通常使用 .bib (BibTeX) 格式的文件作为文献数据源。用户需要准备一个包含所有参考文献条目的 .bib 文件。
  • #bibliography() 函数:在文档中希望显示参考文献列表的位置,调用 #bibliography() 函数 。 代码段

    // 在文档末尾插入参考文献列表
    #bibliography(
      "references.bib", // 指定.bib 文件路径
      title: "参考文献",   // 设置参考文献列表的标题
      style: "ieee.csl"  // 指定引文样式语言 (CSL) 文件
    )
    
    • 第一个参数是文献数据文件的路径(字符串)。
    • title 参数可以设置参考文献列表的标题,默认为 “Bibliography” 或根据文档语言确定的相应文本。
    • style 参数用于指定引文样式,通常是一个 CSL (Citation Style Language) 文件的路径或名称。
  • 引用文献 (Citing Sources):在文档正文中引用文献条目,使用与引用标签类似的 @ 语法。@ 后面跟的是文献条目在 .bib 文件中定义的唯一键 (citation key)。 代码段

    Typst 的设计目标是简洁与强大 [@typst-whitepaper]。
    早期的研究表明 [@doe2023, p. 45],... // 引用多个文献,并为第二个指定页码
    

    当 Typst 处理文档时,它会解析 .bib 文件,并在遇到 @key 时,根据选定的 CSL 样式在正文中生成相应的引文格式(如 ``, (Doe, 2023), Doe et al., 2023 等)。同时,所有被引用的文献条目会自动收集并格式化后显示在 #bibliography() 函数的位置。

引用样式与自定义 (Citation Styles and Customization)

  • CSL (Citation Style Language):Typst 的文献引用和列表格式主要通过 CSL 文件来控制。CSL 是一种基于 XML 的开放标准语言,用于描述引文和参考文献的格式规则。网络上有大量预定义的 CSL 样式文件,涵盖了数千种期刊和出版机构的格式要求(例如,APA, MLA, IEEE, Chicago 等)。用户可以从 Zotero Style Repository (zotero.org/styles) 等地获取所需的 CSL 文件。
  • 自定义引用
    • 页码等附加信息:在引用时,可以在 @key 后面的方括号中添加补充信息,如页码、章节号等。具体如何解释这些补充信息取决于所使用的 CSL 样式。 … 如 Smith 所述 [@smith2022, pp. 12-14]。 ```
    • #cite() 函数:除了 @key 语法糖,还可以使用更底层的 #cite() 函数进行引用,它提供了对引用过程更细致的控制,例如可以指定引用的形式(如 form: "prose"form: "parenthetical")或添加前缀/后缀。
  • 通过包增强功能:Typst 社区也提供了一些包来增强文献管理功能。例如,blinky 包可以将参考文献列表中的论文标题自动转换为指向其 DOI 或 URL 的超链接,这需要对 CSL 文件进行少量修改以配合 blinky 的工作机制。

CSL 的依赖及其影响: Typst 对 CSL 的依赖是一把双刃剑。 优势在于:

  1. 利用现有成熟生态:无需重新发明轮子,可以直接利用数以千计的现有 CSL 样式,满足绝大多数常见需求。
  2. 标准化:CSL 是一个广泛应用的开放标准,有助于保证样式在不同工具和平台间的一致性。
  3. 庞大的社区支持:CSL 本身拥有活跃的社区和丰富的文档资源。

潜在的挑战或局限性可能包括:

  1. CSL 本身的复杂性:对于那些需要高度自定义样式,但又找不到完全匹配的现有 CSL 文件的用户,学习编辑或从头创建 CSL 文件本身具有一定的学习曲线。
  2. 与 Typst 特性的集成深度:CSL 的设计可能并未完全预料到 Typst 所有的排版特性和强大的脚本能力。某些非常规的、需要 Typst 深度脚本介入的复杂引用样式调整,可能难以仅通过 CSL 文件实现。例如,blinky 包通过修改 CSL 文件插入”魔法表达式”来实现标题超链接,这间接说明了标准 CSL 可能不足以直接支持某些 Typst 特有的交互功能或动态内容生成。

因此,对于大多数用户而言,找到并使用一个合适的 CSL 文件即可满足需求。对于有特殊要求的用户,则可能需要投入时间学习 CSL,或者依赖社区提供的修改版 CSL 文件以及辅助 Typst 包来扩展功能。Typst 社区可能会围绕 CSL 的使用、修改和功能增强形成一部分讨论和贡献,例如分享特定期刊的 CSL 文件,或者创建专门的 Typst 包来弥补 CSL 在 Typst 环境下可能存在的不足。

本指南建议用户首先从官方 CSL 仓库寻找合适的样式。如果需要定制,可以先尝试修改现有样式,或者查阅 Typst 社区是否有相关的解决方案或包。

第三部分:样式设计与高级定制 (Part 3: Styling and Advanced Customization)

Typst 提供了强大而灵活的样式系统,允许用户从细微的行内调整到整个文档外观的彻底重塑。本部分将深入探讨 Typst 的样式机制,包括基础的行内样式、强大的 setshow 规则,以及页面布局、字体管理和针对中文排版的优化等高级主题。

第 8 章:基础样式设置 (Chapter 8: Basic Styling)

最直接的样式修改方式是通过函数参数进行行内设置,或者使用简单的 set 规则来影响后续元素的默认外观。

行内样式与简单 set 规则 (Inline Styles and Simple set Rules)

  • 行内样式 (Inline Styles):许多 Typst 函数在调用时接受直接影响其输出样式的参数。这允许对单个元素进行精确的、局部的样式控制。 代码段

    这是 #text(fill: blue)[蓝色文本],而这是 #text(font: "Arial", size: 14pt)[14号的Arial文本]。
    一个带有红色边框的 #box(stroke: red)[盒子]。
    

    在这种方式下,样式仅应用于该函数调用产生的特定内容。

  • 简单 set 规则 (Simple set Rules):当需要为某一类元素设定一个通用的默认样式,或者改变文档后续部分的整体风格时,可以使用 set 规则 。set 规则通过在元素函数名前加上 set 关键字(或在标记模式的行首使用 #set)来定义。 代码段

    // 将后续所有文本的默认字号设置为12pt
    #set text(size: 12pt)
    
    这是12pt的文本。
    这也是12pt的文本。
    
    // 改变标题的编号方式和下方间距
    #set heading(numbering: "I.A.1", below: 1.5em)
    
    = 第一个主标题
    //...
    

    set 规则只能用于修改元素函数定义中那些本身就是”可设置 (Settable)”的参数。通常,这些是影响元素外观和行为的非必需参数。

  • set 规则的作用域 (Scope of set Rules)set 规则的效果范围取决于其定义的位置 :

    • 如果在文档的顶层(没有任何代码块或内容块包裹)定义,则其效果会持续到文件末尾,或者直到遇到另一个针对相同元素相同参数的 set 规则将其覆盖。
    • 如果 set 规则定义在一个代码块 {...} 或内容块 [...] 内部,则其效果仅限于该块的内部。这为创建局部样式区域提供了便利。 代码段
    #set text(fill: black) // 全局黑色文本
    
    这是一个黑色文本段落。
    
    { // 开始一个新的代码块作用域
      #set text(fill: green) // 此处开始,块内文本为绿色
      这是绿色文本。
      #box[
        #set text(fill: red) // 嵌套块,此处文本为红色
        这是红色文本。
      ]
      这是绿色文本。 // 回到上一层块作用域
    }
    
    这仍然是黑色文本。 // 回到全局作用域
    

简单的 set 规则是调整文档基础风格和进行局部覆盖的有效工具。对于更复杂的样式逻辑和元素重定义,则需要依赖下一章将要介绍的更强大的 show 规则。

第 9 章:强大的 setshow 规则 (Chapter 9: Powerful set and show Rules)

Typst 的样式系统核心在于 set 规则和 show 规则。前者主要用于配置元素的现有参数,而后者则提供了更深层次的定制能力,甚至可以完全重定义元素的渲染方式。

全局与局部样式 (Global vs. Local Styles)

正如在上一章简单 set 规则中提到的,样式规则的作用域是理解和控制其影响范围的关键 :

  • 全局样式 (Global Styles):在 Typst 文档的顶层(即不被任何代码块 {...} 或内容块 [...] 包裹)定义的 setshow 规则,其效力会从定义点开始,一直持续到当前文件的末尾,或者直到被后续的同类规则所覆盖。这适用于设定整个文档的基础风格,如默认字体、页面边距、标题格式等。
  • 局部样式 (Local Styles):当 setshow 规则被嵌套在一个代码块或内容块内部时,它们的效果就被限制在该块之内。一旦离开该块,之前由这些局部规则所做的样式更改就会失效,恢复到该块外部的样式状态。这使得用户可以为文档的不同部分(如章节、引言、附录、特定段落或自定义环境)应用不同的样式,而不会相互干扰。

这种作用域机制为 Typst 提供了清晰且可预测的样式层叠行为。

针对特定元素的样式重定义 (Redefining Styles for Specific Elements)

  • set 规则回顾set 规则主要用于修改元素函数已有的、可设置的参数。例如,改变所有一级标题的编号格式和颜色: 代码段

    #set heading(level: 1, numbering: "第 一 章", fill: blue)
    
  • show 规则:更强大的定制:当 set 规则不足以满足需求时(例如,需要根据条件改变样式、组合不同元素的属性,或者完全替换元素的默认渲染逻辑),就需要使用 show 规则 。show 规则的基本思想是:”当 Typst 遇到某种元素(或满足某种条件的文本)时,按照我指定的方式来显示它”。

    • Show-Set 规则 (Show-Set Rules):这是 show 规则最简单的形式。它允许将一个 set 规则的效果限定于特定类型的元素。语法为 show <选择器>: set <元素函数>(<参数设置>) 。 代码段

      // 仅将页面链接的文本颜色设置为蓝色,并添加下划线
      #show link.where(dest: str): set text(fill: blue)
      #show link.where(dest: str): underline
      
      // 将所有一级标题的上下间距增大
      #show heading.where(level: 1): set block(above: 2em, below: 1em)
      

      Show-set 规则的强大之处在于,set 部分可以调用与选择器不同的元素函数,从而实现属性的”混入”。例如,可以为一个自定义的 theorem 元素(假设它本身没有 fill 参数)通过 show theorem: set block(fill: lightgray) 来设置背景色。

    • Show 规则与函数 (Show Rules with Functions):这是 show 规则最灵活的形式。它可以将元素的渲染逻辑完全替换为一个自定义函数。语法为 show <选择器>: <函数>。该函数会接收被选中的元素(通常命名为 it)作为参数,并需要返回一些内容作为该元素的新的渲染结果 。 代码段

      // 将所有强调文本(_italic_)替换为红色加粗文本
      #show emph: it => {
        strong(text(fill: red, it.body)) // it.body 是强调文本的原始内容
      }
      
      // 自定义一级标题的显示:在标题前添加一个装饰性方块
      #show heading.where(level: 1): it => {
        block[
          #box(square(width: 0.5em, fill: navy))
          #h(0.3em) // 水平间距
          #text(weight: "bold", size: 1.2em, it.body)
        ]
      }
      

      函数内部可以使用任意 Typst 脚本逻辑,这为实现高度动态和上下文相关的样式提供了无限可能。

    • show 规则的选择器 (Selectors for Show Rules)show 规则的左侧(选择器部分)决定了该规则将作用于哪些元素。Typst 支持多种类型的选择器 :

      • 元素函数名:如 heading, link, image。可以配合 .where(...) 进一步筛选具有特定字段值的元素,例如 heading.where(level: 1)
      • 文本字符串:如 show "Typst": strong("TYPST"),将所有出现的 “Typst” 替换为加粗的 “TYPST”。
      • 正则表达式 (Regex):如 show regex("\b[A-Z]{2,}\b"): it => text(smallcaps, it.text),将所有两个或以上大写字母组成的单词以小型大写字母显示。
      • 标签 (Label):如 show <important-note>: it => block(fill: yellow, stroke: red, it),为带有 <important-note> 标签的元素添加特殊背景和边框。
      • everything 选择器show: rest => {... } 作用于规则定义点之后的所有剩余文档内容。这通常用于定义整个文档的布局模板。

下表对比了 set 规则与 show 规则的核心特性:

特性set 规则show 规则
基本用途修改元素函数已定义的可选参数(预设样式) </span>。</td>完全重定义元素的外观和行为,或有条件地修改样式,甚至替换元素 </span>。</td></tr>
语法示例#set text(font: "Arial", size: 12pt)#show heading: set text(fill: blue) <br> #show link: it => underline(it.body) <br> #show "TODO": box(fill