Logo lkw123's Blog
为 AstroPaper 主题添加 KaTeX 支持

为 AstroPaper 主题添加 KaTeX 支持

February 23, 2024
3 min read
Table of Contents

AstroPaper 主题并不支持 KaTeX,因此我们需要手动添加 KaTeX 支持。

安装相关依赖项

首先,我们通过个人喜好的包管理器安装以下依赖项:

  • remark-math:用于解析 Markdown 中的数学公式;
  • rehype-katex:用于将数学公式渲染为 HTML。
pnpm add remark-math rehype-katex

修改博客 astro.config.mjs

astro.config.mjs 中新增 remark-mathrehype-katex 的引入:

import remarkMath from 'remark-math'
import rehypeKatex from 'rehype-katex'

并在配置文件中的 markdown 部分添加相关定义,相关文档参见 Astro Configuration Reference

astro.config.mjs
export default defineConfig({
  ...
  markdown: {
    remarkPlugins: [
      remarkMath,
      ...
    ],
    rehypePlugins: [[rehypeKatex, { strict: false }]],
    ...
  },
});

PS:KaTeX 的这个套件的 strict 参数的预设值为 warn,也就是在进行转换的过程中,如果遇到汉字等不符合规范的字符,则会发出警告。

strict 参数设置为 false,可以消除这些警告。

添加 KaTeX 样式表引入

为引入 KaTeX 的 stylesheet,需在 Layout.astro 中在 Header 部分添加:

src/layouts/Layout.astro
<!-- KaTeX -->
<link
  rel="stylesheet"
  href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css"
  integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+"
  crossorigin="anonymous"
/>

更改暗色主题相关 CSS

然而,根据 issue #150 中的讨论,AstroPaper 主题的暗色模式下 KaTeX 渲染效果不佳,会出现如下图所示的情形:

AstroPaper 主题暗色模式下 KaTeX 渲染效果

因此,我们需要手动在 PostDetails.astro 中新增相关 CSS 的处理:

src/layouts/PostDetails.astro
/* Fix the dim color of KaTeX in dark mode */
.prose {
  color: var(--color-text-base);
}

至此,AstroPaper 博客主题已支持 KaTeX 渲染。

可选:给博文新增 KaTeX Frontmatter 开关

经过以上的步骤,KaTeX 的 JavaScript 静态文件会全局引入,出现在几乎所有页面的 Header 中,这意味着打开博客的任意一篇文章都会加载 KaTeX 的相关资源,这显然是可以进一步优化的。

我们可以通过在博文的 Frontmatter 中新增 katex 开关,来控制是否加载 KaTeX 的相关资源:

  1. config.ts 中新增 katex 的配置项:
src/content/config.ts
import { SITE } from "@config";
import { defineCollection, z } from "astro:content";
 
const blog = defineCollection({
  type: "content",
  schema: ({ image }) =>
    z.object({
      author: z.string().default(SITE.author),
      ......
      canonicalURL: z.string().optional(),
      katex: z.boolean().default(false), 
    }),
});
 
export const collections = { blog };
  1. PostDetails.astro 中给文章添加 katex 属性,并赋给 layoutProps,最终传给 Layout.astro 组件以控制是否加载 KaTeX 的相关资源:
src/layouts/PostDetails.astro
---
const { post } = Astro.props
 
const {
  title,
  // ......
  tags,
  katex,
} = post.data
 
const layoutProps = {
  title: `${title} | ${SITE.title}`,
  // ......
  scrollSmooth: true,
  katex,
}
---
  1. Layout.astro 中根据 katex 属性的值来决定是否加载 KaTeX 的相关资源:
src/layouts/Layout.astro
<!-- KaTeX -->{
  katex && (
    <link
      rel="stylesheet"
      href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css"
      integrity="sha384-nB0miv6/jRmo5UMMR1wu3Gz6NLsoTkbqJghGIsx//Rlm+ZU03BU6SQNC66uf4l5+"
      crossorigin="anonymous"
    />
  )
}
  1. 可选。修改 astro-paper.code-snippets,在 VS Code 中新增 KaTeX Frontmatter Snippet:
.vscode/astro-paper.code-snippets
{
  "Frontmatter": {
    "scope": "markdown",
    "prefix": "frontmatter",
    "body": [
      "---",
      "author: $1",
      // ......
      "tags:",
      "  - $7",
      "description: $8",
      "katex: ${9|false,true|}",
      "---"
    ],
    "description": "Adds the frontmatter block for the AstroPaper Blog post"
  }
  // ......
}