提示:本教程存在过时问题,更详细教程请阅读 小蓝书Typst 中文社区导航 FAQ
注意:该中文文档为社区驱动的非官网文档,可能存在错译、漏译或过时等问题,请以官网文档 Documentation 为准,如发现错漏,也欢迎 您的贡献镜像)。Typst 非官方中文交流 QQ 群:793548390
Warning: the Chinese document is a community-driven non-official document, there may be mistranslation, omission or outdated problems, please refer to the official website documentation.
Typst 中文文档

脚本

Typst 内置了一个强大的脚本语言。可以使用代码自动生成文档,生成丰富多彩的样式。 下面是关于脚本语言的综述。

表达式

Typst 里面,标记和代码相互交融在一起。 除了最常用的文档元素,其他所有均是由 函数 生成。 为了尽可能的便利,Typst 设计了精巧的语法,用来将代码嵌入在标记中:用 #(井号) 来引入一个代码表达式, 表达式结束后,再恢复到正常的标记语法解析。 有些字符能够使其后字符继续解析为表达式,如果想将其解释为文本,可以用分号(;)来强制结束表达式解析。

#emph[Hello] \
#emoji.face \
#"hello".len()
Preview

上面示例展示了一些用到的表达式, 有函数调用字段访问方法调用。 本章余下部分讲解更多类型表达式。 有几种表达式与井号语法不一致(比如二元运算表达式), 如果需要插入标记模式中,需要使用圆括号,比如 #(1+2)

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

文档内容块和代码块可以相互内嵌,下面示例中,[hello]a + [ the ] + b 合并,生成 [hello from the *world*]

#{
  let a = [from]
  let b = [*world*]
  [hello ]
  a + [ the ] + b
}
Preview

绑定和解构

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

#let name = "Typst"
This is #name's documentation.
It explains #name.

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

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

#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.
]
Preview

在解构匹配模式中,可以使用 _ 下划线来丢弃一个元素。

#let (_, y, _) = (1, 2, 3)
The y coordinate is #y.
Preview

解构形式也可用于函数的参数列表中...

#let left = (2, 4, 5)
#let right = (3, 2, 6)
#left.zip(right).map(
  ((a,b)) => a + b
)
Preview

... 和普通赋值的左半部分,这通常用于交换两个变量的值。

#{
  let a = 1
  let b = 2
  (a, b) = (b, a)
  [a = #a, b = #b]
}
Preview

条件控制

使用条件控制语句,可以根据某种条件是否满足,来展示或计算不同的事情。 Typst 设计了 if, else if, else 表达式。 当条件值为 true 时,条件语句会返回 if 从句的值,否则返回 else 从句的值。

#if 1 < 2 [
  This is shown
] else [
  This is not.
]
Preview

每个分支从句可以写为语句块或者文档内容块。

循环控制

使用循环控制语句,可以反复的显示文档内容或者计算。 Typst 支持两种循环控制: for 循环和 while 循环。 for 循环用来遍历特定集合,while 循环根据某条件是否满足来决定是否再次迭代循环。 和块类似,循环结构 合并 每一次迭代循环的结果。

下面示例中,for 循环生成了三句话,然后将其合并成一个文档内容。 while 循环生成数个长度为1的数组,然后将其合并成一个大数组。

#for c in "ABC" [
  #c is a letter.
]

#let n = 2
#while n < 10 {
  n = (n * 2) - 1
  (n,)
}
Preview

for 循环可以遍历多种集合:

Typst 用 breakcontinue 语句来控制循环的执行, break 用来跳出循环,continue 用来提前结束本次循环,然后执行下一次循环。

#for letter in "abc nope" {
  if letter == " " {
    break
  }

  letter
}
Preview

循环体可以是代码块,也可以是文档内容块:

字段

可以使用 点号 来访问一个值的字段,这个值可以是:

#let dict = (greet: "Hello")
#dict.greet \
#emoji.face

#let it = [= Heading]
#it.body \
#it.level
Preview

Methods

A method call is a convenient way to call a function that is scoped to a value's type. For example, we can call the str.len function in the following two equivalent ways:

#str.len("abc") is the same as
#"abc".len()
Preview

The structure of a method call is value.method(..args) and its equivalent full function call is type(value).method(value, ..args). The documentation of each type lists it's scoped functions. You cannot currently define your own methods.

#let array = (1, 2, 3, 4)
#array.pop() \
#array.len() \

#("a, b, c"
    .split(", ")
    .join[ --- ])

#"abc".len() is the same as
#str.len("abc")
Preview

There are a few special functions that modify the value they are called on (e.g. array.push). These functions must be called in method form. In some cases, when the method is only called for its side effect, its return value should be ignored (and not participate in joining). The canonical way to discard a value is with a let binding: let _ = array.remove(1).

模块

一个 Typst 工程项目可以拆解为多个 模块 文件。 一个模块可以使用多种方式引用其他模块的文档内容和定义。

除了使用路径,也可以使用 模块值,如下面示例:

#import emoji: face
#face.grin
Preview

可以创建并导入 Typst ,在多个工程项目中进行复用。 一个包的导入需有三部分指定:包命名空间,包名称,包版本号。

#import "@preview/example:0.1.0": add
#add(2, 7)
Preview

preview 包命名空间包含了 Typst 社区分享的包。可以在 package 章节搜索可用的社区分享包。

在本地使用 Typst 时,可以创建本地包。更多详情参考 包仓库

操作符

下表类出了所有一元和二元操作符的作用、参数数量(一元、二元)和优先级(优先级越高,越优先执行)

操作符作用说明参数数量优先级
-负号一元7
+正号,无作用,仅仅为了对称性一元7
*乘号二元6
/除号二元6
+加号二元5
-减号二元5
==等号二元4
!=不等于号二元4
<小于号二元4
<=小于等于号二元4
>大于号二元4
>=大于等于号二元4
in属于二元4
not in不属于二元4
not逻辑非一元3
and短路式逻辑并二元3
or短路式逻辑或二元2
=赋值二元1
+=相加赋值二元1
-=相减赋值二元1
*=相乘赋值二元1
/=相除赋值二元1