Cris.Q

Back

使用 Typst 渲染数学公式Blur image

原理#

尝试使用 astro-typst 渲染数学公式。

笑死,完全用不了,样式也是乱的,目录也是乱的,渲染也是乱的。

于是使用 rehype-typst,并大量定制主题样式,有了现在这个勉强可以接受的渲染方案。这样今后我 Obsidian 上的数学笔记就能同步过来了。

参考了博主 huawen 的方案,在此致谢。

如果只需要渲染 Typst Math,装个rehype-typst后直接写就行了。但我遇到了三个问题:

  • 明暗页面总有一个会吃掉Typst的文字
  • 内联公式总是会自己换行。
  • TOC识别元素时会将渲染出的svg里的标题元素渲染成目录项

经过和 AI 的对骂探讨,得出了修改方法

解决方案与修改内容#

1. 创建自定义Rehype插件:rehype-filter-svg-headings.ts#

问题:TOC会识别Typst生成的SVG内部的h5:div元素作为标题

解决方案

  • 创建了src/plugins/rehype-filter-svg-headings.ts插件
  • 检测并过滤SVG内部的命名空间标题元素(h5:div
  • 在构建时自动移除这些内部标题,防止它们出现在目录中

关键代码

// 检测SVG内部的标题元素
const isHeading = node.tagName && (
  /^h[1-6]$/.test(node.tagName) || // 标准HTML标题
  node.tagName.includes('h5:') ||  // 命名空间标题如 h5:div
  classNameStr.includes('tsel')    // Typst选择元素
)
typescript

2. 优化CSS样式:src/assets/styles/app.css#

问题1:内联公式总是换行显示

解决方案

  • 为段落内的Typst SVG添加内联显示样式
  • 优化垂直对齐和大小缩放
/* 行内公式样式 */
p .typst-doc,
p svg.typst-doc {
  display: inline !important;
  vertical-align: -0.3em !important;
  margin: 0 0.1em !important;
  max-height: 1.4em !important;
  transform: scale(1.15) !important;
  transform-origin: 0 0.5em !important;
}
css

问题2:块级公式大小异常

解决方案

  • 确保块级公式不受行内样式影响
  • 保持块级公式的原始大小
/* 块级公式 - 不受样式影响 */
.typst-doc {
  display: block;
  max-width: 100%;
  height: auto;
}
css

问题3:主题切换时Typst公式显示异常

解决方案

  • 添加JavaScript控制的深色模式支持
  • 使用CSS滤镜实现颜色反转
/* JavaScript控制的深色模式 */
html.dark svg.typst-doc {
  filter: invert(100%) sepia(0%) saturate(367%) 
          hue-rotate(19deg) brightness(105%) contrast(101%) !important;
}

/* 浅色模式重置滤镜 */
html:not(.dark) svg.typst-doc {
  filter: none !important;
}
css

3. 配置Astro插件#

astro.config.ts中配置了自定义插件:

// 添加自定义rehype插件
rehypePlugins: [
  // ... 其他插件
  rehypeFilterSvgHeadings,
]
typescript

最终效果#

经过这些修改,现在Typst数学公式能够:

  • ✅ 行内公式正确显示在行内,不换行
  • ✅ 块级公式保持原始大小和块级显示
  • ✅ TOC只显示真正的文章标题,不包含数学公式字符
  • ✅ 在深色/浅色主题切换时正确显示
  • ✅ 支持复杂的数学表达式和矩阵

大部分代码使用 Cline + DeepSeek V3.2 完成,感谢Vibe Coding救我等不会前端的小白于水火。

简单公式示例#

这是一个行内公式示例: 看起来不错的。

而这里就可以接下一行了

这里是再下一行

行间公式也能正常显示

矩阵与向量#

渲染一段完整的数学笔记#

证明:

(1).

(2).

(3).

使用 Typst 渲染数学公式
https://crisq.top/blog/test_typst
Author Cris.Q
Published at 2025年10月15日
Comment seems to stuck. Try to refresh?✨