@jxpeng98/markdown-it-typstex
v3.1.0
Published
A markdown-it plugin that renders math with Typst, falls back to KaTeX, and hides on failure.
Downloads
763
Maintainers
Readme
markdown-it-typstex
一个基于 markdown-it 的数学公式工具包,可以:
- 作为 Typst + LaTeX 回退 插件使用:优先 Typst,失败后回退到 KaTeX / MathJax;
- 也可以作为一个精简的 纯 LaTeX 插件 使用(仅 KaTeX / MathJax,不依赖 Typst)。
Typst → KaTeX/MathJax → 隐藏
一层层回退,保证页面在任何情况下都不会被一坨报错信息搞乱。
✨ 特性(Features)
- ✅ 支持常见数学语法:
- 行内公式:
$ ... $ - 行间公式:
$$ ... $$ - fenced 代码块:
math ...
- 行内公式:
- ✅ 优先使用 Typst 渲染为 SVG,显示效果精细、可缩放
- ✅ Typst 渲染失败时自动回退到 KaTeX(LaTeX) 或 MathJax v4(SVG) 渲染(默认使用 KaTeX)
- ✅ LaTeX 引擎解析也失败时,自动隐藏 该公式,不破坏页面布局
- ✅ 可选支持在 HTML 块中解析
$...$/$$...$$ - ✅ 提供
typstInjection选项,可以在每次 Typst 编译时注入全局配置(字体、#show等) - ✅ 只依赖
markdown-it,可用于 VitePress、VuePress 或任何使用 markdown-it 的渲染流程
📦 安装(Installation)
# 使用 npm
npm install @jxpeng98/markdown-it-typstex
# 使用 pnpm
pnpm add @jxpeng98/markdown-it-typstex
# 使用 yarn
yarn add @jxpeng98/markdown-it-typstex本包将较重的渲染引擎声明为 peer 依赖,你需要在自己的项目中按需安装:
- 必需:
markdown-it
- 可选(按你的使用场景选择):
@myriaddreamin/typst-ts-node-compiler(Typst 渲染,主要用于 Node/SSR)katex(作为 LaTeX 回退引擎时需要)@mathjax/src和@mathjax/mathjax-modern-font(使用 MathJax v4 作为 LaTeX 回退时需要)
如果某个引擎未安装,那么对应的渲染路径会不可用:
例如未安装 Typst 编译器时,会直接走 LaTeX 回退;未安装 KaTeX/MathJax 时,相应的回退也无法工作。
由于这些是 peerDependencies,本包不会自动为你安装它们,需要你在自己的项目里显式添加到 dependencies 或 devDependencies 中。例如:
使用 Typst + KaTeX:
npm install @jxpeng98/markdown-it-typstex markdown-it @myriaddreamin/typst-ts-node-compiler katex使用 Typst + MathJax:
npm install @jxpeng98/markdown-it-typstex markdown-it @myriaddreamin/typst-ts-node-compiler @mathjax/src @mathjax/mathjax-modern-font
🔧 基本用法:Typst + LaTeX 回退(plain markdown-it)
import MarkdownIt from 'markdown-it'
import typstex from '@jxpeng98/markdown-it-typstex'
import '@jxpeng98/markdown-it-typstex/styles.css'
const md = new MarkdownIt()
md.use(typstex, {
enableFencedBlocks: true,
enableMathInlineInHtml: true,
enableMathBlockInHtml: true,
// typstInjection: '#set text(font: "New Computer Modern")',
// katexOptions: { macros: { '\\RR': '\\mathbb{R}' } },
// latexEngine: 'mathjax', // 默认是 'katex'
})
const html = md.render(`
这是一个行内公式:$L = 1/2 rho v^2 S C_L$。
$$
\\int_a^b f(x)\\,dx
$$
\`\`\`math
L = 1/2 rho v^2 S C_L
\`\`\`
`)🔧 Typst + 单一回退引擎(更小体积)
如果你希望减少 bundle 体积、避免同时打包 KaTeX 和 MathJax,可以使用专门的 Typst + KaTeX 或 Typst + MathJax 入口。每个入口只引入一个 LaTeX 引擎。
1. Typst + KaTeX 回退
import MarkdownIt from 'markdown-it'
import typstexKatex from '@jxpeng98/markdown-it-typstex/typst-katex'
import '@jxpeng98/markdown-it-typstex/styles.css'
import 'katex/dist/katex.min.css'
const md = new MarkdownIt()
md.use(typstexKatex, {
enableFencedBlocks: true,
enableMathInlineInHtml: true,
enableMathBlockInHtml: true,
// typstInjection: '#set text(size: 13pt)',
// katexOptions: { throwOnError: false },
})该插件:
- 优先使用 Typst 渲染;
- Typst 不可用或失败时回退到 KaTeX;
- 不会 引入任何 MathJax 相关代码。
2. Typst + MathJax 回退
import MarkdownIt from 'markdown-it'
import typstexMathJax from '@jxpeng98/markdown-it-typstex/typst-mathjax'
import '@jxpeng98/markdown-it-typstex/styles.css'
const md = new MarkdownIt()
md.use(typstexMathJax, {
enableFencedBlocks: true,
enableMathInlineInHtml: true,
enableMathBlockInHtml: true,
// typstInjection: '#set text(size: 13pt)',
})该插件:
- 优先使用 Typst 渲染;
- Typst 不可用或失败时回退到 MathJax v4(SVG);
- 不会 引入任何 KaTeX 相关代码。
📘 在 VitePress 中使用(Usage with VitePress)
VitePress 内部使用的是
markdown-it,集成方式就是在markdown.config中挂插件。
.vitepress/config.ts:
import { defineConfig } from 'vitepress'
import typstex from '@jxpeng98/markdown-it-typstex'
export default defineConfig({
markdown: {
config(md) {
// 兼容 CJS / ESM 的导出方式
const plugin = (typstex as any).default ?? typstex
md.use(plugin, {
enableFencedBlocks: true,
enableMathInlineInHtml: true,
enableMathBlockInHtml: true,
})
},
},
})主题入口中需要引入插件样式。
如果你使用 KaTeX 作为回退引擎(默认),还需要额外引入 KaTeX 的样式,例如 .vitepress/theme/index.ts:
import DefaultTheme from 'vitepress/theme'
import '@jxpeng98/markdown-it-typstex/styles.css'
// 可选:仅在使用 KaTeX 回退时需要
import 'katex/dist/katex.min.css'
export default {
...DefaultTheme,
}🧩 支持的语法(Supported Syntax)
1. 行内公式(inline math)
升力 $L$ 可以通过升力系数 $C_L$ 按如下公式计算。渲染流程:
- 尝试用 Typst 渲染
$L$; - Typst 失败 → 使用 KaTeX 渲染
L; - KaTeX 也失败 → 返回空字符串(该段公式被隐藏)。
2. 行间公式(display math)
$$
L = 1/2 rho v^2 S C_L
$$渲染为一个居中显示的块级公式,同样走 Typst → KaTeX → 隐藏 的回退链路。
3. fenced 代码块:```math
```math
L = 1/2 rho v^2 S C_L
当 `enableFencedBlocks: true` 时,所有 language 为 `math` 的 fenced 块都会被当作数学公式处理,而不是普通代码块。
---
### 4. HTML 中的数学(math in HTML blocks)
如果你的内容中包含原始 HTML 块,并且希望在其中识别 `$...$` / `$$...$$`,可以开启:
```ts
md.use(typstex, {
enableMathInlineInHtml: true, // 识别 HTML 中的 $...$
enableMathBlockInHtml: true, // 识别 HTML 中的 $$...$$
})插件会在 html_block token 中拆分文本,将匹配到的部分转换成 math_inline / math_block 再参与渲染。
⚙️ 配置项(Options)
插件接受一个 TypstMathFallbackOptions 对象:
md.use(typstex, {
enableMathBlockInHtml?: boolean
enableMathInlineInHtml?: boolean
enableFencedBlocks?: boolean
typstInjection?: string
katexOptions?: katex.KatexOptions
latexEngine?: 'katex' | 'mathjax'
})enableMathBlockInHtml(默认:false)
是否在 HTML 块中解析 $$...$$ 为行间公式。
示例:
<div>
$$ L = 1/2 rho v^2 S C_L $$
</div>enableMathInlineInHtml(默认:false)
是否在 HTML 块中解析 $...$ 为行内公式。
示例:
<p>升力 $L$ 可以通过 $C_L$ 计算</p>enableFencedBlocks(默认:true)
是否启用 fenced 代码块 math ... 的处理。
关闭后,```math 只会被当作普通代码块。
typstInjection(默认:undefined)
每次调用 Typst 渲染时,会将这段 Typst 代码注入到文档顶部。
可用于设置字体、全局 #set、#show 等配置,例如:
md.use(typstex, {
typstInjection: `
#set text(font: "New Computer Modern")
#show math.equation: it => box(it, inset: 0.5em)
`,
})你也可以利用这一配置项来整体放大或缩小 Typst 渲染的公式,使其与 LaTeX 回退引擎(KaTeX / MathJax)或正文字号更匹配,例如:
md.use(typstex, {
typstInjection: `
#set text(size: 13pt)
`,
})katexOptions(默认:{ throwOnError: true })
传递给 katex.renderToString 的配置对象。
可以用于定义 LaTeX 宏、控制错误行为等,例如:
md.use(typstex, {
katexOptions: {
macros: {
'\\RR': '\\mathbb{R}',
},
},
})latexEngine(默认:'katex')
用于 Typst 渲染失败时的 LaTeX 回退引擎:
'katex':使用 KaTeX 进行 LaTeX 回退(原有行为)。'mathjax':使用 MathJax v3(SVG 输出)进行 LaTeX 回退。
说明:
- MathJax 通过
mathjax-full在 Node 侧渲染,直接生成独立的 SVG 片段。 - 一般不需要额外的 MathJax CSS,但你仍然可以根据需要为外层容器添加样式。
🧠 设计思路(Plugin Idea)
这个插件的核心设计思路是:
将 Typst 作为首选数学引擎
- 使用
@myriaddreamin/typst-ts-node-compiler在 Node 环境中编译一段包含$ <code> $的 Typst 文档; - 使用
NodeCompiler.svg(...)得到 SVG 输出; - 根据 Typst 生成的
data-width/data-height将尺寸转换为em,并为行内 / 行间公式设置合适的样式。
- 使用
Typst 失败时不把错误直接展示给用户
- Typst 语法不兼容、拼写错误、编译失败等情况,插件会捕获异常;
- 而不是把 Typst 的错误文本渲染到 HTML 中。
自动回退到 KaTeX(LaTeX 引擎)
- 当 Typst 渲染失败时,用 KaTeX 将同一段字符串作为 LaTeX 数学表达式渲染;
- 对大部分“正常的 LaTeX 数学语法”来说,这一步可以平滑兜底。
KaTeX 再失败则静默隐藏
- 如果 KaTeX 也抛错(语法错误、宏未定义且
throwOnError: true等),插件返回空字符串; - 保证页面不会出现任何“渲染错误文本”或奇怪的占位元素。
- 如果 KaTeX 也抛错(语法错误、宏未定义且
因此,这个插件特别适用于:
- 希望逐步从 LaTeX 数学迁移到 Typst,但暂时无法一次性重写所有公式;
- 文档中可能混有 Typst 不支持的写法,需要自动回退到 LaTeX;
- 对页面整体观感有较高要求,希望即使公式渲染失败也不要破坏排版。
⚠️ 限制(Limitations)
需要 Node 环境
Typst 渲染依赖@myriaddreamin/typst-ts-node-compiler,目前主要用于 Node 侧(构建阶段 / SSR),无法直接在纯浏览器环境中运行。Typst / LaTeX 语法差异
- 大部分基础数学语法在 Typst 和 LaTeX 之间是兼容的;
- 但 Typst 专有特性和 LaTeX 宏包的高级特性并不完全一致,可能触发回退逻辑。
性能注意
Typst 渲染公式需要一定的计算资源,大量公式时建议结合缓存或合理的构建策略使用。
📄 License
MIT
