在 Gatsby 中与 MDX 一起使用 KaTeX

December 24, 2021 · 1 min read

前言

一开始,我跟据网上的教程为我的使用了 MDX 的 Gatsby 站点添加了 KaTeX\KaTeX 支持,比如使用 gatsby-remark-katex, 但是遇到了很多问题,很多都是版本的兼容性问题。

尽管很多情况下,把各种依赖项降级就能解决问题,但是我本人并不喜欢降级依赖项,旧版本的依赖项一般具有更多的 Bug 和安全问题。(然而我还是使用了旧版的 remark-math 😂)

解决方案

首先,直接使用 KaTeX\KaTeX 相关的 remark/rehype 底层插件,而不是通过 gatsby-remark-katex 这样的封装过的插件。

下面是我的站点的 package.json 的一部分,其中高亮出来的是和配置 KaTeX\KaTeX 相关的依赖项。

{
    ...
  "dependencies": {
      ...
      "@mdx-js/mdx": "^1.6.22",
      "@mdx-js/react": "^1.6.22",
      "bulma": "^0.9.3",
      "gatsby-source-filesystem": "^4.2.0",
      "esm": "^3.2.25",      "gatsby-plugin-mdx": "^3.3.0",      "katex": "^0.15.1",      "rehype-katex": "^6.0.2",      "remark-math": "^3.0.0",    }
    ...
}

注意,因为在我撰写本文的时候,gatsby-plugin-mdx 的使用 mdx.js v2.0 的版本还没有发布,所以 gatsby-plugin-mdx 内部使用的是第一代 mdx, 这导致 gatsby-plugin-mdx 使用的 remark 版本比较低(^10.0.1),而 remark 在 v13.0 中作出了重大改动(micromark),因此很多新版本插件和新插件只兼容 v13 及以上的版本,无法和 gatsby-plugin-mdx 一起使用,我们用到的 remark-math 就是其中之一。

gatsby-plugin-mdx@^3.3.0:
  version "3.3.0"
  resolved "https://registry.npmjs.org/gatsby-plugin-mdx/-/gatsby-plugin-mdx-3.3.0.tgz#18b3f5d2eab02e5bdd8264560c850473ce772039"
  integrity sha512-4uYcNXVLnx0jgfjp3iyrGjVJr/D5gItfZxrUgVKtrsy2LhtR9gtQgLFZgGONnqDoPn+26kAlBsqTOORN3m88bQ==
  dependencies:
  	...
    remark "^10.0.1"    remark-retext "^3.1.3"

另外,JavaScript 有了标准的模块实现(ESM), 很多 remark 插件不再与 CommonJS 的模块兼容,我们在加载这些使用 ESM 的插件时需要使用来自 gatsby-oi-wikiesmRequire. (在此向 gatsby-oi-wiki 致谢)

使用你最喜欢的 JavaScript 包管理器安装好依赖之后,我们来修改一下 gatsby-config.js:

esmRequire = require("./esm-require")

module.exports = {
  ...
  plugins: [
    ...
    {
      resolve: `gatsby-plugin-mdx`,
      options: {
        ...
        remarkPlugins: [          require("remark-math"),        ],        rehypePlugins: [          esmRequire("rehype-katex").default        ],        ...
      }
    }
  ]
  ...
}

其中,remark-math 解析Markdown的数学语法,rehype-katex 负责将 <span class=math-inline><div class=math-display> 这样的标签用 KaTeX\KaTeX 渲染出来.

然后,我们在博客的模板文件 src/templates/blog-post.js 里面引入 KaTeX\KaTeX 的 css 就大功告成了!

下面是数学公式的示例:

A2+B2=C2xRA^2 + B^2 = C^2\\ x \in \R\\