Typst-技巧积累

文献引用

指 bibliography/reference listing.

这里需要用到 .bib 文件, 其格式为 (几个示例):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@book{key1,
author = "Author Name1",
title = "Book Title1",
publisher = "Publisher Name1",
year = "Publication Year1"
}

@article{key2,
author = "Author Name2",
title = "Article Title2",
journal = "Journal Name2",
year = "Publication Year2",
pages = "Page Numbers2"
}

@conference{key3,
author = "Author Name3",
title = "Conference Paper Title3",
booktitle = "Conference Name3",
year = "Publication Year3",
pages = "Page Numbers3"
}

这里的 key 是在 Typst 文件中引用这个条目时使用的唯一标识符.

bibliography element function 来载入 .bib 文件, 并可以用 @ 的引用语法进行引用, 如:

1
2
3
4
5
6
7
This was already noted by
pirates long ago. @arrgh

Multiple sources say ...
@arrgh @netwok.

#bibliography("works.bib")

标签等引用

ref 函数

ref 函数其实就是指 @ 符号. 这里都需要借助 <label> 或 bibliography.

可用于引用的元素包括: headings, figures, equations, footnotes.

ref 函数可自动生产 textual reference. (比如引用第一个标题, 就会转换成 “Section 1”)

如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#set heading(numbering: "1.")
#set math.equation(numbering: "(1)")

= Introduction <intro>
Recent developments in
typesetting software have
rekindled hope in previously
frustrated researchers. @distress
As shown in @results, we ...

= Results <results>
We discuss our approach in
comparison with others.

== Performance <perf>
@slow demonstrates what slow
software looks like.
$ O(n) = 2^n $ <slow>

#bibliography("works.bib")

也可以自定义 ref 返回的文本 (借助 show rule):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#set heading(numbering: "1.")
#set math.equation(numbering: "(1)")

#show ref: it => {
let eq = math.equation
let el = it.element
if el != none and el.func() == eq {
// Override equation references.
numbering(
el.numbering,
..counter(eq).at(el.location())
)
} else {
// Other references as usual.
it
}
}

= Beginnings <beginning>
In @beginning we prove @pythagoras.
$ a^2 + b^2 = c^2 $ <pythagoras>

可用于跳转到一个超链接或者 document 中的 location. (label 等)

默认情况下, links 没有任何 style, 一般配合 show rule 使用.

如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#show link: underline

https://example.com \

#link("https://example.com") \
#link("https://example.com")[
See example.com
]

= Introduction <intro>
#link("mailto:hello@typst.app") \
#link(<intro>)[Go to intro] \
#link((page: 1, x: 0pt, y: 0pt))[
Go to top
]

数学 equation 标号

1
#set math.equation(numbering: "(1)")

用 codly 美化代码显示

Codly 是一个第三方 package, 用于创建比较漂亮的 code blocks:

如:

#import "@preview/codly:0.2.0": *
#show: codly-init.with()

#let icon(codepoint) = {
box(
    height: 0.8em,
    baseline: 0.05em,
    image(codepoint)
)
h(0.1em)
}

#codly(
languages: (
    rust: (name: "Rust", icon: "\u{fa53}", color: rgb("#CE412B")),
)
)

1
2
3
pub fn main() {
println!("Hello, world!");
}

用 box 设置 inline content 的大小

box 函数可以用来给 inline-level content 限定大小. (除了 inline math, boxes 这些)

如:

1
2
3
4
5
6
Refer to the docs
#box(
height: 9pt,
image("docs.svg")
)
for more information.

RGB 颜色设置

Typst 支持多种 color space, 这里以 RGB 为例.

一个 RGB(A) 数组由 4 部分组成:

  • red (ratio)
  • green (ratio)
  • blue (ratio)
  • alpha (ratio)

color.rgb 函数来得到 color 类型值, 其声明为:

1
2
3
4
5
6
7
8
color.rgb(
int retio,
int retio,
int retio,
int retio,
str,
color,
) -> color

(这里的 str 指 hex 值, color 是将其他类型的 color 值转换为 RGB(A))

如:

1
2
3
4
#square(fill: rgb("#b1f2eb"))
#square(fill: rgb(87, 127, 230))
#square(fill: rgb(25%, 13%, 65%))
#show heading.where(level: 1): set text(color.rgb(87,127,230))

用 where 通过 element 的 field 筛选

对于 element function (即与对应 element 相关联的函数, 也可以算是构造器) 而言, 可以用 where 函数, 通过 field 值来筛选到要找的 elements (也就是说这个函数的返回值是一个 selector), 如:

1
2
3
4
#show heading.where(level: 2): set text(blue)
= Section
== Subsection
=== Sub-subection

这里找到 level 2 的 heading 并将其设置为蓝色.

show rule 设置

一般 show rule 可以配合 selector 和匿名函数使用, 最基本的是 show-set rule, 即先用 selector 找到指定 element, 再对其应用 set rules:

1
#show heading: set text(navy)

这里的 heading 是一个 element function selector, 其返回一个 array, 之后 set 会应用到 array 中的每一个 element 上.

一个结合匿名函数的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#set heading(numbering: "(I)")
#show heading: it => [
#set align(center)
#set text(font: "Inria Serif")
\~ #emph(it.body)
#counter(heading).display(
it.numbering
) \~
]

= Dragon
With a base health of 15, the
dragon is the most powerful
creature.

= Manticore
While less powerful than the
dragon, the manticore gets
extra style points.

这里的 heading 先匹配到所有的 headers, it 指代 array 中的一个 element, 之后便是对这个 heading 的配置.

show rule 指定方式

Everything

即指定 show rule 之后的所有 content, 语法为:

1
show: rest => ..

(这个 rest 只是随便取的变量名)

如:

1
2
3
4
5
#show: rest => [
#set text(blue)
#rest
]
#lorem(100)

Text

即匹配一个字符串, 将所有这个字符串替换为新的 content, 语法为:

1
#show "Text": ..

如:

1
2
#show "hello": "world"
hello

这里把所有的 hello 换成 world

又如:

1
2
3
#show "hello": it => [
#it world
]

hello 换成 hello world.

Regex

将正则匹配到的文本替换为新的 content, 语法为:

1
show regex("\w+"): ..

如:

1
2
3
4
show regex("\d+"): num => [
The number is #num
]
123

把所有数字如 123 换成 The number is 123.

Function with fields

匹配函数返回的设置了特定 field 的 element, 语法如:

1
2
3
4
5
show heading.where(level: 1): head => [
>> #head <<\
]

= Hello

替换所有的一级标题.

Label

匹配 label 标记的位置, 语法如:

1
show <label>: ..

如:

1
2
3
#show <hello>: "Hello Hello World"

hahaha <hello>

查看一个 content 类型的所有 fields

fields 方法:

1
2
3
4
5
6
#context {
let headers = query(heading)
for header in headers [
#header.fields()
]
}

这里先找到所有 headings, 然后查看这些 headings 各有什么 fields.

Math block 中让文本对齐

如全部左对齐:

1
2
3
4
5
6
$
&"First line"
&"Second line"
&"Third line"
&"Fourth line"
$

如全部右对齐:

1
2
3
4
5
6
$
"First line"&
"Second line"&
"Third line"&
"Fourth line"&
$

上下行 & 标记的位置会对齐.

分页

pagebreak 函数进行手动分页, 该函数不能用于任何的 container 中.

如:

1
2
3
4
5
6
The next page contains
more details on compound theory.
#pagebreak()

== Compound Theory
In 1984, the first ...

绘制 Outline

outline 函数的官方文档位置.

即 table of contents, 如:

1
2
3
4
5
6
7
#outline()

= Introduction
#lorem(5)

= Prior work
#lorem(10)

这里默认是以标题来列 Outline, 可以通过修改 target 来更改, 如以 figure 制作:

1
2
3
4
5
6
7
8
9
#outline(
title: [List of Figures],
target: figure.where(kind: image),
)

#figure(
image("tiger.jpg"),
caption: [A nice figure!],
)

让 title 标有序号

1
2
3
4
5
6
7
8
#set heading(numbering: "1.")

= Introduction
= Background
== History
== State of the Art
= Analysis
== Setup

利用 rect 观察布局

rect 指 rectangle, 也就是一个矩形, 通过设置矩形颜色来观察:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#set rect(
width: 100%,
height: 100%,
inset: 4pt,
)

#set page(
paper: "iso-b7",
header: rect(fill: aqua)[Header],
footer: rect(fill: aqua)[Footer],
number-align: center,
)

#rect(fill: aqua)

这里的 rectangle 是指定百分比来对区域进行契合.

又比如观察 margin 的设置:

1
2
3
4
5
6
7
8
9
10
11
12
#set rect(
width: 100%,
height: 100%,
inset: 4pt,
)

#set page(
width: 12cm, height: 12cm,
margin: 4cm,
)

#rect(fill: aqua)

page 设置

一般需要考虑:

  • line length
  • margins
  • columns
  • right headers
  • footers
  • page number
    等.

在 Typst 中, 每一页都有 width, height 以及四边的 margin, 在 top 和 bottom 的 margin 中可以包含 header 和 footer, 需要在 set 函数中完成所有设置. (一般放开头)

设置预定义的 page size

Typst 默认的 page size 是 A4 paper, 可以用 page 函数更改:

1
2
3
#set page("us-letter")

This page likes freedom

可以在 page’s pager argument 中查看列表.

设置自定义 page size

1
2
3
#set page(width: 12cm, height: 12cm)

This page is a square.

Margin 设置

Margin 在一定程度上影响了 line width.

通过 pagemargin 参数设置. 若不指定方向, 则应用到全部四个方向, 也可以单独指定方向设置:

1
2
3
4
5
6
7
#set page(margin: (
top: 3cm,
bottom: 2cm,
x: 1.5cm,
))

#lorem(100)

x 是同时设置 leftright, 而 y 是同时设置 bottomtop.

若想设置一个方向之后, 让其他的也设置为同一长度, 则使用 rest (即剩下的) 参数:

1
#set page(margin: (left: 1.5in, rest: 1in))

设置页脚页眉

使用 pageheaderfooter 参数:

1
2
3
4
5
6
7
#set page(header: [
_Lisa Strassner's Thesis_
#h(1fr)
National Academy of Sciences
])

#lorem(150)

若想给除第一页以外的页设置 header 和 footer, 则可以:

1
2
3
4
5
6
7
8
9
#set page(header: context {
if counter(page).get().first() > 1 [
_Lisa Strassner's Thesis_
#h(1fr)
National Academy of Sciences
]
})

#lorem(150)

和 label 配合

如, 让有 <big-table> 标签的 page 不添加 header 和 footer:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#set page(header: context {
let page-counter =
let matches = query(<big-table>)
let current = counter(page).get()
let has-table = matches.any(m =>
counter(page).at(m.location()) == current
)

if not has-table [
_Lisa Strassner's Thesis_
#h(1fr)
National Academy of Sciences
]
}))

#lorem(100)
#pagebreak()

#table(
columns: 2 * (1fr,),
[A], [B],
[C], [D],
) <big-table>

page numbers 设置

用 numbering 参数设置

pagenumbering 参数传递一个 numbering pattern 字符串:

1
2
3
#set page(numbering: "1")

This is a numbered page.

常见的设置有 “1”, “i”, “a”, “1 of 1”, “- 1 -“.

若想让 page number right or left align, 则需要设置 pagenumber-align 参数 (默认值是 center + bottom).

默认情况下, 使用了 footer 后, numbering 参数的设置便不会起作用, 此时可以通过设置 context, 利用 counter 函数中记录的 page number 来让其一起起作用:

1
2
3
4
5
6
7
8
9
10
#set page(footer: context [
*American Society of Proceedings*
#h(1fr)
#counter(page).display(
"1/1",
both: true,
)
])

This page has a custom footer.

另一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#set page(footer: context [
*Fun Typography Club*
#h(1fr)
#let (num,) = counter(page).get()
#let circles = num * (
box(circle(
radius: 2pt,
fill: navy,
)),
)
#box(
inset: (bottom: 1pt),
circles.join(h(1pt))
)
])

This page has a custom footer.

Reset the page number 或 skip pages

主要利用 counter 记录的 page number.

如将某一页设置成 1 然后重新计数后面的页:

1
#counter(page).update(1)

让 page number 加 5:

1
#counter(page).update(n => n + 5)

Add columns

Columns 就是指把一个 page 分成多列, columns 之间的 space 称作 gutter.

若想把所有文本都通过 columns 排列, 则可直接用 pagecolumns 参数:

1
2
#set page(columns: 2)
#lorem(30)

若只是在某一个地方应用 columns 排列

则直接使用 columns 函数:

1
2
3
4
5
6
7
= Impacts of Odobenidae

#set par(justify: true)
#columns(2)[
== About seals in the wild
#lorem(80)
]

使用 show rule 设置:

1
2
3
4
5
6
7
= Impacts of Odobenidae

#set par(justify: true)
#show: columns.with(2)

== About seals in the wild
#lorem(80)

字体与大小设置

text 函数配合 set 来设置.

比如直接指定字体大小:

1
2
3
4
5
6
#set text(18pt)
With a set rule.

#emph(text(blue)[
With a function call.
])

字体设置

Typst 在处理 text 时, 比如设置了一个字形 (“字形” (Glyph)是指字符在视觉上的具体表现形式. 在不同的字体和样式中, 同一字符的字形可能会有所不同. 例如, 字母 “A” 在 Arial 字体中的字形与在 Times New Roman 字体中的字形就不一样) 为 Arabic Glyph, 字体为 Inria Serif, 但 Inria Serif 中没有 Arabic Glyph, 此时 Typst 会按顺序遍历 font list 来找到一个有相应 glyph 的字体, 如 Noto Sans Arabic.

Typst 查找 font 的路径可以通过 typst 命令的 --font-path 选项设置, 或者设置 TYPST_FONT_PATHS 环境变量.

示例如:

1
2
3
4
5
6
7
8
9
10
#set text(font: "PT Sans")
This is sans-serif.

#set text(font: (
"Inria Serif",
"Noto Sans Arabic",
))

This is Latin. \
هذا عربي.

用 query 查找 document 中的 elements

可以用 query 函数, 查找 document 中的有 “particular type” 或者 “particular label” 的 elements.

其函数声明为:

1
2
3
4
query(
label selector location function,
none location,
i) -> array

这里的 label, selector, location, function 都是 typst 的类型.

如:

1
2
3
4
5
6
= Real
#context {
let elems = query(heading)
let count = elems.len()
count * [= Fake]
}

Typst-技巧积累
http://example.com/2024/05/01/Typst-技巧积累/
作者
Jie
发布于
2024年5月1日
许可协议