[开源] 我用 Rust 写了一个 LaTeX 转 Typst 工具(AST 解析 + TikZ 支持)

52 阅读3分钟

👋 大家好,我是 Tylax 的作者

Typst 作为一个新兴的排版系统,以其极快的编译速度和现代化的脚本语法吸引了很多人。我也是其中之一,想要从 LaTeX 迁移过来。但在迁移过程中,我发现现有的转换工具大多基于正则表达式。对于简单的数学公式,正则确实够用;但一旦遇到复杂的嵌套环境(比如 \begin{align}...\end{align} 里套矩阵)、自定义宏,或者是那种写得“不太规范”的 LaTeX 代码,正则脚本往往会失效,输出一堆乱码。为了解决这个问题,也为了让大家能更顺滑地“入坑” Typst,我们开发了 Tylax。

  • Crates.io: cargo install tylax

🤔 为什么要造这个轮子?

核心原因只有一个:精度。Tylax 不使用正则替换,而是采用了完整的 AST(抽象语法树)解析方案。

  • LaTeX 解析: 基于 MiTeX (Rust 编写的高性能解析器)。
  • Typst 解析: 基于官方的 typst-syntax。

这意味着 Tylax 真的“读得懂”你的代码结构。它知道哪里是公式,哪里是文本,哪里是引用,从而进行语义层面的转换,而不是字符串层面的替换。

✨ 核心特性

1. 双向转换 (Bidirectional)

很多时候我们虽然想用 Typst 写文章,但会议或期刊可能只收 LaTeX。Tylax 支持 LaTeX ↔ Typst 双向互转。你可以用 Typst 爽快地写作,最后转回 LaTeX 投稿。

2. 复杂的数学公式支持

对于矩阵、分段函数 (cases)、积分、求和等复杂结构,Tylax 都能处理。输入 (LaTeX):

\mathbf{X} = \begin{pmatrix}

x_{11} & \cdots & x_{1n} \\

\vdots & \ddots & \vdots \\

x_{m1} & \cdots & x_{mn}

\end{pmatrix}

输出 (Typst):

upright(bold(X)) = mat(delim: "(", x_(1 1), ..., x_(1 n) 

dots.v, dots.down, dots.v 

x_(m 1), ..., x_(m n))

3. 实验性的 TikZ → CeTZ 转换 🎨

LaTeX 的绘图神器 TikZ 非常强大,但语法也很复杂。Typst 有一个类似的库叫 CeTZ。Tylax 内置了一个 TikZ 解析器,可以将基础的 TikZ 绘图命令(线条、圆形、节点、样式、颜色)转换为 CeTZ 代码。输入 (TikZ):

\begin{tikzpicture}
  \draw[thick, ->] (0,0) -- (4,0) node[right] {$x$};
  \draw[thick, ->] (0,0) -- (0,3) node[above] {$y$};
  \draw[blue, thick] (0,0) -- (3,2);
  \draw[red, dashed] (0,2) -- (3,2) -- (3,0);
  \draw[green, fill=green!20] (2,1.5) circle (0.5);
  \node at (3,2) [above right] {$(3,2)$};
\end{tikzpicture}

输出 (CeTZ):

 #import "@preview/cetz:0.2.2": canvas, draw

#canvas({
  import draw: *

  content((4, 0), [\$x\$], anchor: "west")
  line((0, 0), (4, 0), stroke: (thickness: 0.8pt), mark: (end: ">"))
  content((0, 3), [\$y\$], anchor: "south")
  line((0, 0), (0, 3), stroke: (thickness: 0.8pt), mark: (end: ">"))
  line((0, 0), (3, 2), stroke: (paint: blue, thickness: 0.8pt))
  line((0, 2), (3, 2), (3, 0), stroke: (paint: red, dash: "dashed"))
  circle((2, 1.5), radius: 0.5, stroke: green, fill: green.lighten(80%))
  content((3, 2), [\$(3,2)\$], anchor: "south-west")
})

4. 纯前端运行 (WebAssembly)

得益于 Rust 的生态,我将核心逻辑编译成了 WASM。你可以在 在线 Demo 中直接试用,所有转换都在你的浏览器本地完成,数据不会上传服务器,安全隐私。


🛠️ 技术栈

  • 语言: Rust 🦀
  • 解析器: mitex-parser (Rowan), typst-syntax
  • Web: WASM (wasm-bindgen), Vite
  • 构建: Cargo

🙏 欢迎贡献

这是一个完全开源的项目,目前刚刚发布 v0.1.0 版本,肯定还有很多 Edge Case 没有覆盖到。如果你在使用中遇到转换不正确的代码片段,欢迎在 GitHub 提 Issue,或者直接提交 PR。每一个 Star 和 Issue 都是对我最大的鼓励!希望能帮助到正在从 LaTeX 迁移到 Typst 的朋友们!传送门: github.com/scipenai/ty…