typst
typst
Typst is a new markup-based typesetting system that is designed to be as powerful as LaTeX while being much easier to learn and use.
非官方中文指南,我一般拿来快速找第三方包
typst 并没有一个给开发者的清晰的文档。。examples book可以抄点东西。
我不是很喜欢 latex,所以尝试使用 typst 作为我的论文排版工具。
优点:
- typst 使用 rust 语言编写,编译极快,几乎秒出
- 据群聊天记录所传,latex 编译 30min 的 typst 只要 46s
- 小,二进制也就数十 MB;第三方包只有源码,约等于不占空间
缺点:
- 新兴工具,bug 较多
- 社区不够完善,网上模版/教程不多,文档很烂
- 面向 user 的文档还行,但是面向 developer 的…一点没有。
- 自创的 DSL 比较折磨(这是一个连标准输出都没有的弱类型语言(src),debug 很容易红温)
- 要我说,还不如直接用 rust(但是这样二进制大小也压不下来)
安装与配置
基础用法是 CLI 使用,但我配合 VSCode 使用。
进 release 下载,解压后把
typst.exe
直接丢进C:\Windows\System32
就行。- 或者也可以
scoop install typst
一行搞定。
- 或者也可以
vscode 扩展:
使用 vscode-pdf 查看 pdf。
- 我不推荐 Typst Preview。
- 曾经遇到过无法生成的 bug;
- 很慢,10 页的 pdf 就会卡了。
- 我不推荐 Typst Preview。
LSP
传统官方插件:Typst LSP
- 缺点:慢,没有 formatter
- 优点:0 配置,懒人福音
新起之秀- 安装 Tinymist Typst - Myriad Dreamin
ctrl + ,
进入设置:- Tinymist: ExportPdf 改为 onSave
- Tinymist: FormatterMode 改为 typstyle(也是一个新起之秀的 formatter)
或:什么也不装,只要
typst watch example.typ
即可。
然后就可以愉快地敲论文了。每次保存时会自动生成 pdf,拖到侧边就能看了。
资源
编译导出
typst compile xxx.typ # 基础编译指令
typst compile --root .. xxx.typ # 如果需要 include 父级目录的文件,则需要指定 root
typst compile --format svg xxx.typ '{n}.svg' # 导出为 svg 格式
基础
这里有许多大学的毕业论文模版,多抄抄就会用了
简单来说,[]
内是正文(content
),{}
内是代码,()
是数组(array
),正文调用函数要加 #
,代码里可以直接调。
关键字也就 set
和 show
常用,set
设置作用域内的属性,show
相当于每次使用都调用某个函数。
剩下的 let
,if
什么的都是 rust 的东西,这里不说(
数组
typst 没有 list
类型,只有 array
。
("12")
这样其实还是 string 类型,如果要数组类型需要 ("12",)
数学
表格
- tablem,类 markdown 语法的表格,简单快速,功能不强。
- 无法通过
\|
转义打出|
字符 - 超出列数报错(与 markdown 行为不同;在 markdown 中会直接忽略)
- 无法通过
- tablex,更麻烦但更强大的表格。
- 如果表格中含有粗体斜体,批量处理就比较麻烦。(ex) 我的解法,甚至还发现了个 bug?
- 这个预计算是很难改的(源码访问
at
时的default
已经是Option<Value>
了)。说到底,根本问题还是 typst 选择自创的这个 DSL 的问题,你像 rust 那样 Option 套or_else
哪有这么多事。
- 这个预计算是很难改的(源码访问
- 如果表格中含有粗体斜体,批量处理就比较麻烦。(ex) 我的解法,甚至还发现了个 bug?
- excel 表格转为 typst 表格,支持合并的单元格,很好用。可惜 windows only。
代码
大段代码不要直接写 typ
文件里,最好从外部引用,解耦,还方便扔 formatter。小段就无所谓了。放个我的带边框代码块:
// 带边框代码块
#let frame(title: none, body) = {
let stroke = black + 1pt
let radius = 5pt
let txt = (font: 字体.代码)
set text(..txt)
let name = block(
breakable: false,
fill: color.linear-rgb(0, 0, 0, 10),
stroke: stroke,
inset: 0.5em,
below: -1.5em,
radius: (top-right: radius, bottom-left: radius),
title,
)
block(
stroke: stroke,
width: 100%,
inset: (rest: 0.5em),
radius: radius,
)[
#if title != none {
place(top + right, dx: radius + stroke.thickness, dy: -(radius + stroke.thickness), name)
}
#body
]
}
// 引入外部代码块
#let include_code(file_path) = {
let name = file_path.split("/").at(-1)
let lang = name.split(".").at(-1)
frame(title: name)[
#raw(read(file_path), lang: lang)
]
}
我的折腾历程
从 #1494 摸了个好看的代码块样式来,然后自己改改,就是下面的了。
#let frame(title: none, body) = {
let stroke = black + 1pt
let radius = 5pt
let font = (font: "Fira Code", size: 10pt)
let name = block(
breakable: false,
fill: color.linear-rgb(0, 0, 0, 10),
stroke: stroke,
inset: 0.5em,
below: -1.5em,
radius: (top-right: radius, bottom-left: radius),
title,
)
set text(..font)
show raw: set text(..font)
box(stroke: stroke, radius: radius)[
#if title != none {
align(top + right, name)
}
#block(
width: 100%,
inset: (rest: 0.5em),
body,
)
]
}
#let include_code_file(file_path, name, lang) = {
frame(title: name)[
#raw(read(file_path), lang: lang)
]
}
这样用 box 包的代码块有一个致命缺陷:若 box 高度大于剩余页面高度,则会自动换页;若 box 高度大于整个页面的高度,则超出部分不会显示。因此只适合用来引用小块代码,否则就别想要边框了。我去其他地方寻找解法,BUAA 的用 figure 包的也会有这个问题。
然后偷窥交流群发现,如果不需要 name
参数的话,简单用 block
包一下就能实现自动切割。抄来的代码用的是 box
,因此才会自动换页。
#let 字体 = (代码: ("Fira Code", "Times New Roman", "SimSun"))
#let frame(body) = {
set text(font: 字体.代码)
block(
stroke: black + 1pt,
width: 100%,
inset: (rest: 0.5em),
radius: 7pt,
body,
)
}
// 使用方法:
#frame[
```js
console.log("1")
```
]
伪代码
目前在用algorithmic,并且修了个 bug。
不过目前看来,还是lovelace更泛用一点。
目录
众所周知,中文报告一般会要求页码遵循 第 x 页,共 x 页
的格式。这没问题,在 set page(numbering: (..nums) => ...)
即可。
然而 typst 的目录(outline
)默认使用页面的页码格式,也就是说,会出现这样的情况:
我尝试问群友,没人理 几个月后才又聊到这个话题;尝试看源码,发现写死了;最后在 repo 里乱搜,居然被我搜到了一个究极自定义方案,改一改就是解法。
box
如果你想要好看的框(box),不需要自己写。
- showybox:好看,强大
- typst-boxes:简易
- gentle-clues:常用框
bug
这东西 bug 其实还真不少。。
中文粗体斜体
广为诟病的一条了,typst 不支持伪粗体伪斜体。不过据说是会修。
参考文献
从 .bib
引入参考文献时,如果文献类型是 thesis
,本该在适当位置加 [D]
的,然而它不会加。。
感觉是 hayagriva 的锅,但是我翻了下源码发现看不懂。爆了!
看了一下 issue 时间,3 days ago。。那我这次课程论文寄了,唉,扣点分不重要
其他大学模版的解法是用 python 写了个处理脚本,通过 CSL 解析,半自动加参考文献。
后续:修了,0.10.0 正常。
缩进
中文等语言需要在每行开头缩进两个宽字符。typst 提供了 par()
控制缩进行为,但是在标题下面一行的文字却不会被缩进。。
所以下面有人提供了一个解法:
show heading: it => {
it
par()[#text(size:0.5em)[#h(0.0em)]]
}
这个方法在上一行是 figure 啊,raw 啊什么的时候还是无法缩进,如果手动 linebreak()
的话又多出了不必要的间距,太丑了。