Typst 初体验

句法

Typst 有三种语法模式:

  • 标记模式(Markup),是 Typst 的默认模式。
  • 数学模式,用来编写公式。
  • 代码模式,用来使用脚本功能。
模式句法例如
代码模式# 作为前缀Number: #(1 + 2)
数学模式$..$ 包围标记$-x$ is the opposite of $x$
标记模式[..] 包围标记let name = [*Typst!*]

注意,用 # 是不需要用两个井号[1]的。

标记模式

Typst 内置的标记类似于 markdown ,主要有:

名字例子参考
段落分隔符Blank lineparbreak
强烈强调*strong*strong
强调[2]_emphasis_emph
原始文本`print(1)`raw
链接https://typst.app/link
标签<intro>label
引用@introref
标题= Headingheading
无序列表- itemlist
编号列表+ itemenum
术语列表/ Term: descriptionterms
数学公式$x^2$Math
换行\linebreak
根据语言,智能地展示文字引用'single' or "double"smartquote
符号简写~, ---Symbols
调用 Typst 代码#rect(width: 1cm)Scripting
转义符Tweet at us \#adBelow
注释/* block */, // lineBelow

数学模式

如果公式中,以至少一个空格开头和结尾,则会将其单独排版到其自己的块中。可以通过删除空格来生成行内公式。

名字例子参考
行内公式$x^2$Math
块级 / 行间公式$ x^2 $Math
下标$x_1$attach
上标$x^2$attach
分数$1 + (a+b)/5$frac
换行$x \ y$linebreak
换行时对齐的点$x &= 2 \ &= 3$Math
调用变量$#x$, $pi$Math
调用字段 / 成员(field)$arrow.r.long$Scripting
省略掉乘号的乘法$x y$Math
符号简写$->$, $!=$Symbols
公式里的字符串$a "is natural"$Math
调用数学函数$floor(x)$Math
调用 Typst 代码$#rect(width: 1cm)$Scripting
转义符$x\^2$Below
注释$/* comment */$Below

代码模式

代码模式下,有些表达式是可以不用 # 作为前缀的,参考表:

名字例子参考
nonenonenone
autoautoauto
布尔值false, truebool
整数10, 0xffint
浮点数3.14, 1e5float
绝对长度2pt, 3mm, 1em, …length
角度90deg, 1radangle
分数2fr [3]fraction
比率50%ratio
字符串"hello"str
标签<intro>label
数学公式$x^2$Math
原文本`print(1)`raw
调用变量xScripting
代码块{ let x = 1; x + 2 }Scripting
内容块[*Hello*]Scripting
括号表达式(1 + 2)Scripting
数组(1, 2, 3)Array
键值对(a: "hi", b: 2)Dictionary
单元运算符-xScripting
双元运算符x + yScripting
赋值[4]x = 1Scripting
访问成员x.yScripting
调用成员函数x.flatten()Scripting
调用函数min(x, y)Function
参数展开[5]min(..nums)Arguments
匿名函数(x, y) => x + yFunction
声明并赋值[6]let x = 1Scripting
非匿名的函数let f(x) = 2 * xFunction
设置规则set text(14pt)Styling
条件设置规则set text(..) if ..Styling
设置 show规则show heading: set block(..)Styling
用函数设置 show规则show raw: it => {..}Styling
Show-everything ruleshow: templateStyling
Context expressioncontext text.langContext
条件if x == 1 {..} else {..}Scripting
for循环for x in (1, 2, 3) {..}Scripting
while循环while x < 10 {..}Scripting
循环控制流break, continueScripting
函数返回return xFunction
包含模块include "bar.typ"Scripting
引入模块[7]import "bar.typ"Scripting
引入模块中的成员import "bar.typ": a, b, cScripting
注释/* block */, // lineBelow

转义符

在 Typst 中如果要转义字符,就要在其前面加上反斜杠 \

可以用十六进制转义序列插入任意 Unicode 字符,比如 \u{1f600} ,转义出来的是😀

样式

set 规则

set 规则可以配置文档元素的基本属性,用来设置大多常用文档样式。它后面紧随一个文档元素的函数调用。例如:

1
2
3
4
5
6
7
8
#set heading(numbering: "I.")
// 设置编号
#set text(
font: "New Computer Modern"
)
= Introduction
With set rules, you can style
your document.

顶层 set 规则一直作用到文件结束,当在块内使用时,只作用到块结束。例如,这个例子中 set 规则只对这个列表起作用:

1
2
3
4
5
6
7
This list is affected: #[
#set list(marker: [--])
- Dash
]

This one is not:
- Bullet

可以使用条件 set 设置:

1
2
3
4
5
6
7
#let task(body, critical: false) = {
set text(red) if critical
[- #body]
}

#task(critical: true)[Food today?]
#task(critical: false)[Work deadline]

show 规则

使用 show 规则可以深度定制特定类型文档元素的外观,最常用的基本形式是 show-set 规则, 以 show 关键字作为开始标记,紧随一个选择器,一个冒号,最后是一个 set 规则。 例如:

1
2
3
4
#show heading: set text(navy)

= This is navy-blue
But this stays black.

选择器有:

  • 所有文档: show: rest => ..
    转换 show 规则后的所有文档元素,这样就免于将所有文档元素都包含在一个巨大的函数调用中,来实现更复杂的布局。
  • 特定文本: show "Text": ..
    设置特定文本样式,转变或替换特定文本。
  • 正则表达式: show regex("\w+"): ..
    更自由的选择并转换匹配特定正则表达式的文本,详见于 regex 函数文档。
  • 字段选择函数: show heading.where(level: 1): ..
    转换具有特定字段的文档元素。比如,可以只设置文档一级标题样式。
  • 标签: show <intro>: ..
    选择并转换具有特定标签的文档元素,详见于标签函数文档。

脚本表达式

Typst 中,除了最常用的文档元素,其他所有均是由函数生成。

Typst 可以将代码嵌入在标记中:用 #(井号) 来引入一个代码表达式, 表达式结束后,再恢复到正常的标记语法解析。 有些字符能够使其后字符继续解析为表达式,如果想将其解释为文本,可以用分号(;)来强制结束表达式解析。

Typst 为了架构代码以及将代码嵌入内容中,设计了两种

  • 代码块: { let x = 1; x + 2 }
    编写代码时,一个计算过程可能需要分解为多个语句,创建多个中间变量,等等。 可以将多个表达式组成一个代码块,就像一个表达式一样。在代码块中,多个表达式由换行符或者分号分割。 其中每个表达式的输出值被合并起来,作为代码块的值。 有些表达式没有有用的输出,比如 let 绑定返回 none,与其他值合并,没有任何效果。上面的表达式输出 3
  • 文档内容块 [*Hey* there!]
    使用文档内容块,可以将标记/文档内容作为可编程值,存储到变量,传送给函数。 文档内容块由方括号包裹,可以包含任何标记。 一个文档内容块产生一个 content 类型的值。 文档内容块可以后缀参数形式任意多个传递给函数,就是说,list[A][B] 等效于 list([A], [B])

文档内容块和代码块可以相互内嵌,例如:

1
2
3
4
5
6
#{
let a = [from]
let b = [*world*]
[hello ]
a + [ the ] + b
}

绑定

上面已经展示,变量由 let 绑定定义。 = 符号后表达式的值被赋值给变量,这里赋值可以被省略,如果没有赋值,变量会初始化为 nonelet 关键词也可以用来生成一个自定义的有名函数

let 绑定的变量可以在接下来的块中或者文档中被访问。

1
2
3
4
5
6
#let name = "Typst"
This is #name's documentation.
It explains #name.

#let add(x, y) = x + y
Sum is #add(2, 3).

let 绑定也常用来解构数组字典, 解构时,等号左边的形式需要与数组或字典相似, .. 模式操作符只可被使用一次,用来指代数组或字典剩余的条目。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#let (x, y) = (1, 2)
The coordinates are #x, #y.

#let (a, .., b) = (1, 2, 3, 4)
The first element is #a.
The last element is #b.

#let books = (
Shakespeare: "Hamlet",
Homer: "The Odyssey",
Austen: "Persuasion",
)

#let (Austen,) = books
Austen wrote #Austen.

#let (Homer: h) = books
Homer wrote #h.

#let (Homer, ..other) = books
#for (author, title) in other [
#author wrote #title.
]

#let (_, y, _) = (1, 2, 3)
The y coordinate is #y.
// 用 _ 丢弃一个元素

  1. 这句话的文档原文是“Once you have entered code mode with #, you don’t need to use further hashes unless you switched back to markup or math mode in between.”,本人英语不好,一开始把 “hash” 理解成了哈希,所以没读懂这是什么意思。其实 “hash” 这个词指的就是井号 # 这个符号,和哈希没关系。外国人也会把 # 叫做pound sign,number sign,hex 或者 square,可以看看这篇文章:https://zhuanlan.zhihu.com/p/683936872。类似的称呼有:ampersand - & ,asterisk - * ,tilde - ~ ,caret - ^
  2. 强调(emphasis)在英语中一般对应的是斜体,强烈强调(strong emphasis)则对应加粗
  3. frfraction 的缩写,表示比例份数,一般用在分配空间的时候,相当于给这部分分几份。
  4. 原文是 assign ,指定,赋值。
  5. 原文是 arguments spreading ,也就是把一个参数(arguement)集合(比如数组、列表、元组等)“摊开”,一个个作为独立的参数传给函数。
  6. 原文是 let binding 。 let: 声明,binding: 绑定。所以字面意思就是声明+赋值。
  7. include 的字面意思就是把对应的内容在本位置展开,简单粗暴;import 就则是结构化的导入了。

Typst 初体验
https://blog.kisechan.space/2025/typst-hatsutaiken/
作者
Kisechan
发布于
2025年4月28日
更新于
2025年4月29日
许可协议