在 Astro 中使用 KaTeX 渲染数学公式

/

TL;DR

npm install remark-math rehype-katex katex
// astro.config.mjs
import remarkMath from 'remark-math';
import rehypeKatex from 'rehype-katex';

export default defineConfig({
  markdown: {
    remarkPlugins: [remarkMath],
    rehypePlugins: [rehypeKatex]
  },
});
// *.astro
---
import "/node_modules/katex/dist/katex.min.css";
---

安装依赖

这一步没什么好说的,直接在命令行中运行这一行命令,安装 remark-math rehype-katex katex 即可。

npm install remark-math rehype-katex katex

编辑 Astro 配置

现在,插件已经安装好了,但是 Astro 并不会去用它们。编辑 Astro 的配置文件 astro.config.mjs,告诉 Astro 应该使用这些插件,两个省略号之间的是要添加的内容:

// astro.config.mjs
import remarkMath from 'remark-math';
import rehypeKatex from 'rehype-katex';

export default defineConfig({
  markdown: {
    remarkPlugins: [remarkMath],
    rehypePlugins: [rehypeKatex]
  },
});

在完成以上步骤后,你可以运行 npm run dev 来看看现在是什么样的。在你的网站中找一篇带有数学公式的网页,你会发现公式看起来很奇怪;查看页面源代码。你会发现数学公式都被 <span> 包裹了起来。这说明 Astro 已经能够正确处理数学公式了,但是由于缺少 KaTeX 的样式,公式看起来非常丑陋。

编辑页面模板

为了告诉浏览器如何该如何渲染数学公式,我们需要引入 katex.csskatex.min.css,这里以 katex.min.css 为例,不过使用 katex.css 也是没有问题的,因为 Astro 会自动压缩 CSS(仅限于本地托管,不适用于 jsDelivr 第三方托管的方法)。

本地托管

如果你和我一样使用了 Astro 的 Blog 模板,那你可以在打开 src/components/BaseHead.astro,在 Frontmatter(也就是文件顶部用“---”包裹起来的部分)中添加一行:

---
import "/node_modules/katex/dist/katex.min.css";
---

这行代码不一定要添加到 BaseHead.astro 的 Frontmatter 中,理论上任意一个 .astro 文件都行,只要这个 .astro 文件参与到了含有数学公式的网页的生成即可。例如 src/layouts/BlogPost.astro 等。这种方法是最简便的,Astro 会自动处理 CSS 和字体文件。

还有一种方式也可以在本地托管 KaTeX:

<link rel="stylesheet" href="/node_modules/katex/dist/katex.min.css">

Astro 同样会自动处理 CSS 和字体文件。不过这种方式意义不大,不如第一种方便,就不详细讲了,步骤和下面 👇 使用 jdDelivr 的那个方法一样,有需要的可以参考。

当然还有一种更加鸡肋的本地托管方法,大致就是将 CSS 和字体文件都复制到 public 文件夹下,然后手动引入 katex.min.css。这种方法默认情况下会找不到字体,还要手动修改 katex.min.css 中的字体链接。由于实在鸡肋,就不展开了。有需要的可以自己去试试。

第三方(jdDelivr)托管

如果你不希望自己托管 CSS 和字体文件,也可以使用 jdDelivr。只需要将以下代码复制到负责生成 <head> 部分的 .astro 文件中,例如 BaseHead.astro。注意这段代码应复制到正文部分,而不是 Frontmatter。

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.9/dist/katex.min.css" integrity="sha384-n8MVd4RsNIU0tAv4ct0nTaAbDJwPJzDEaqSD1odI+WdtXRGWt2kTvGFasHpSy3SV" crossorigin="anonymous">

完成!

使用 npm run dev 命令运行本地服务器,然后在浏览器中打开 localhost:4321。使用你喜欢的编辑器打开你的一篇博客,然后添加以下内容:

$$E = MC^2$$

回到浏览器,你就可以看到正确渲染后的公式了!

Astro 3.0 与 remark-math 6.0.0、rehype-katex 7.0.0 的兼容性问题

在这个时间点(2023 年 10 月),你大概率会遇到多行公式渲染报错的 bug,可见 remark-math throws an error on multiline math。你可以在这个 issue 中找到解决方案,也可以翻到这篇文章的最后。

现在(2023 年 12 月),Astro 4.0 已经发布,上述 bug 已经被修复,你可以直接使用最新版本的 remark-mathrehype-katex。请忽略下述步骤,除非你还在使用 Astro 3.0

你可能习惯在公式块中换行:

$$
E = MC^2
$$

保存之后回到浏览器,就会发现 报!错!啦! 满屏密密麻麻的文字,头都要大了!

总之,如果你安装了最新的 remark-mathrehype-katex,并且在 $$ … $$ 中使用了换行,就会报错。似乎官方人员对于这个 bug 也做不了什么,直接把相关的 issue 给 close 了。

但是,要(暂时)解决这个问题也很简单,只需回退旧版本即可。打开 package.json,找到:

{
  "rehype-katex": "^7.0.0",
  "remark-math": "^6.0.0"
}

把它修改成:

{
  "rehype-katex": "^6.0.3",
  "remark-math": "^5.1.1"
}

然后运行一下 npm install,就好了!这个问题困扰了我很久,希望它没有对你造成什么麻烦~