毕竟是和 Typst 相关了,所以我拿出了 typst-hugo 来写这篇博客的第一个 Typst 文章。 好吧,感觉 typst-hugo 导出来的格式我自己调得不太满意,所以又拿回了 Markdown(亵渎啊亵渎)。从 24 年春季学期开始到刚结束的秋季学期短短三个学期,能用 Typst 写的实验报告基本都是用 Typst 写的,使用的版本也从 0.11 到 0.12 再到即将要发布的 0.13,见证了 Typst 的不断进步。
仔细一想,实际上我了解到 Typst 的时间还是蛮早的,应该在 23 年底就看过类似的推荐文章,大约就是德国学生因为不满 LaTeX 于是自己手搓一个排版引擎的故事(没错就是 Laur 和 Martin)。但是当时编程语言基础应该是比较薄弱,不是很会写代码也不是很会用 LaTeX,于是就没有继续深入了解。直到后来开始使用 Typst 好像是因为觉得找不到好用的 Markdown 主题,LaTeX 又太笨,笑笑提醒了一下有这么个东西之后才开始使用的。
应该是到大二下学期修老登的计算机系统工程导论和部长的图像处理与分析才有比较大的实验报告的需求。当时某一天突然醒悟,实验报告得好看,助教/老师才会看得下去 ,才会给高分赏脸。于是就开始了一系列的尝试,从 Word 到 LaTeX,再到 typst。其实 Word 并不是不能排版或者排得好看,熟练使用样式库而不是手动设置文档各部分的格式就可以做到比较规范的排版。但是我总觉得 Word 排出来的东西不是很具有一致性,尽管它是所见即所得的而且功能强大。而 LaTeX 在有模板的前提下,排版的一致性就比较好,但是模板的定制性就比较差,而且我也不是很喜欢它的语法,一大堆的反斜杠和花括号实在让人头疼。相反呢,Markdown 就是另一个极端,语法简单,但是排版能力有限。为了实现比较复杂的控制或者排版需要在 Markdown 里嵌入 HTML 或者 LaTeX 代码,这样就破坏了 Markdown 的简洁性。
而 Typst 则结合了 Markdown 和 LaTeX 的优点,语法简单,排版能力强大。而且 Typst 的编译比 LaTeX 快了非常多,这对于我这种经常在实验报告里插入图片的人来说是非常重要的。初期上手其实只要做一下 Markdown 语法到 Typst 语法到映射就可以。而为了实现一些比较复杂的效果,则需要进一步阅读官网的文档或者求助于社区。比如说我在这篇文章里使用了一个表格,这个表格的每个单元格的背景颜色是根据单元格的坐标来决定的。这个效果在 Markdown 里是做不到的,而在 LaTeX 里也是比较麻烦的。而在 Typst 里,只需要简单的几行代码就可以实现这个效果。
#grid(
column-gutter: 1em,
columns: (1fr, 1fr),
align: center + horizon,
```typ
#table(
columns: 5,
align: center + horizon,
fill: (x, y) => {
if calc.even(x + y) {
gray
} else {
white
}
},
..range(1, 26).map(i => [#i])
)
```,
table(
columns: (2em,) * 5,
rows: (2em,) * 5,
align: center + horizon,
fill: (x, y) => {
if calc.even(x + y) { gray } else { white }
},
..range(1, 26).map(i => [#i])
),
)
这种很简洁的语法给人一种写 Python 的快感,而不带 #
或者是 {}
的内容中默认是正文的设计也让人觉得很舒服。
就这么写实验报告写了大半年,中途要把 Typst 的内容搬到博客或者文档库的时候其实有思考过为什么用 Typst 或者 Markdown。有时候写 Typst 因为太依赖预览,所以也很拘泥于局部的排版或者布局,有点违背了以内容为主的初衷。而且到现在(2025.2.6),其实 Typst 的 HTML 导出也只是在一个初步的阶段,还有很多功能没有实现。所以有一段时间,24 年夏季学期到秋季学期初吧,我在一些课程又用回了 Markdown(因为要发博客),不过这时候看 Markdown 的感觉就是一个好看的小茅房了。
后来想一想,会拘泥于局部排版布局实际上可能只是因为我自己模版老调老换,所以固定那么几个模版其实就可以了。作为一个 Typst 用户大概许多人也是跟我一样差不多的状态,用社区的模版改一改写自己的实验报告,替代掉 Markdown 或者 Word 的工作流。
后来逐渐有了一点开发者的苗头,但直到现在因为个人能力一般也没能做得很好。目前我做了几个跟 Typst 有关的小东西:
模版相关的
这个模版就是上面两张截图的模版,用来写实验报告的。这个模版 fork 自 gRox167 的 typst-assignment-template,我在这个模版的基础上做了一些修改,主要是跟中文有关的设置。我还挺喜欢那个浅绿色框的,很有一种仪式感,而且它算是一眼可以看得出来 Typst/LaTeX 可以做到而 Word/Markdown 一般不会这么做的东西哈哈哈哈哈哈。
OUC-Typst-Assignment-Templates
这个仓库是一系列的模版,起源是 yyz 问我有没有数据库的模版,我就做了一个。然后我就想既然数据库有了,那别的课需要模版的是不是也可以有一下,然后就有了这个仓库。
工具相关的
这个
包代码其实一开始只是给我自己的作业模版用。后来群主 mgt 大佬在群里提起来 codly 编译效率太低了,我就把我这段代码发群里,然后就有了这个包。这个包的功能是给 Typst 的代码块加上行号,而且还可以给代码块加上背景色。这个包的名字是我随便起的,因为我觉得代码块加上行号就像斑马线一样,所以就叫 Zebraw 了。这个工具是用来把 Excel 表格转换成 Typst 的表格的。起因是群友有问起有没有这样的工具,flaribbit 当时有一个类似的 Python 脚本,我就
借助 AI 的力量用类似的逻辑写了个 HTML/JavaScript 版本的。后来突然想到,这玩意本身是 XML 富文本,也可以复制粘贴成 HTML 来着,那不如做个可以直接粘贴的工具。于是就有了这个工具。顺着这个思路的发展,纸夜当时说到单独写成 ts 的话就可以放进 Tinymist 了。我就在期末周的那会儿写了个 ts 版本的,但发现 VSCode 对剪贴板的支持很有限,它只让粘贴纯文本,如果要粘贴成 HTML 得调用命令行,不优雅,而且纸夜说粘贴的快捷键绑定他也有用,所以这个方案就没有继续。后来还是纸夜姐姐提起来,可以做成一个纯 Typst 解析的包(毕竟它可以解析 XML 文件),这样就可以在 Typst 里直接使用 Excel 表格了。于是有了 exmllent。
这两个包放一起是有点匪夷所思吧()其实原因是它们都是我期末周摸鱼开发的(谁家好人期末周 GitHub 全绿啊喂)
也是顺着 exmllent 的思路继续往下,要用户多一步导出 XML 有点太麻烦了,而且并不是每个标签、情况我都能解析得到。既然 Python 有 openpyxl,那是不是 Rust 也有类似的包,借助 WebAssembly 也可以做类似的解析呢?于是我翻了翻 universe,发现原来之前有人做过表格解析了 lublak/typst-spreet-package。但 lublak 用的 Calamine 包并不支持解析富文本格式,无法还原表格的样式,而且他只导出成一个字典而不是表格本身(虽然字典到表格这一步也有一个包…),所以我还是接着往下开发了(毕竟没人做过直接从表格到表格的形式)。找找找了很久,最后发现一个效率不如 Calamine 但是可以解析几乎所有 Excel 表格特性的包 umya-spreadsheet,这就是我需要的!
然后我就想办法解析表格成:
( merged_cells: (), dimensions: ( columns: (0.0, 0.0), rows: (0.0, 0.0), max_columns: 2, max_rows: 2, ), rows: ( ( row_number: 1, cells: ( (value: "1", column: 1, style: (:)), (value: "2", column: 2, style: (:)), ), ), ... ), )
这样的格式,这样就可以保留绝大部分的样式了。
直到这其实都没有 handy-dora 什么事,一直到我发现我写的代码怎么死活放 Typst 的 plugin 里用不了,一怒之下决定摸另一个鱼就写了 handy-dora,简单封装了一个麻将牌面的 Rust 库,这样就可以输入字符串打牌面了。这个导出的 wasm 能用,怎么 rexllent 就不行!后来发现 spreet 仓库里也放了个 build.sh,它手动指定了 wasi stub 的返回值是 0 就可以了,莫名其妙。
这个包也让我第一次有了 21 star 的 GitHub 仓库,开心。
前段时间也第一次给 Typst 提了 PR,读了一部分它的代码。不过我不是很熟悉 Rust,有些地方读得还是有点不太明白。还有一方面是通过 Typst 这个窗口感受到开源社区的美好,也慢慢接触了许多大佬,入 Typst 门不虚此行呐。但不管怎么说,一个 Typster 慢慢就诞生了,希望能慢慢等待他革了 LaTeX 命那天的到来。