Vuepress 之 KaTeX 插件配置
Vuepress 之 KaTeX 插件配置
基本使用
在vuepress@v2中,如果想要内置的 markdown-it 支持数学公式的显示,只需要使用 mathjax、katex 等对应的插件即可,katex 相比 mathjax,公式渲染速度要快很多,因此这里选择使用 katex 插件。
安装 markdown-it-katex
这里的 katex 插件指的是 markdown-it-katex,其安装方式很简单,只需要在项目中使用 yarn、npm 之类的包管理工具就行了
yarn add markdown-it-katex
配置
很快就能完成,接下来在config.ts
中配置:
import { defineUserConfig, DefaultThemeOptions } from "vuepress";
import markdownItKatex from "markdown-it-katex";
export default defineUserConfig<DefaultThemeOptions>({
// ...
extendsMarkdown: (md) => {
md.use(markdownItKatex);
},
});
提示
配置文件 config.ts
或者 config.js
在 docs/.vuepress
目录下,两者配置方式有部分不同,详见官网的说明,本人倾向于使用 typescript
,因为它有更好的类型提示,本文之后也是使用 ts
格式的配置文件。
已经成功引入的 katex 插件,除此之外,还需要引入 css 文件,同样在配置文件中加入:
head: [
// something else ...
[
"link",
{
rel: "stylesheet",
href: "https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.5.1/katex.min.css",
},
],
];
此外,如果你是用的是默认的 markdown-it 解析器,作者还推荐使用 github stylesheet:
[
"link",
{
rel: "stylesheet",
href: "https://cdn.jsdelivr.net/github-markdown-css/2.2.1/github-markdown.css",
},
];
使用
至此,已经可以在 md 文件中使用公式并渲染了。
输入:
$\sin \theta \cos \theta =\frac 1 2 \sin 2\theta$
$$\lim_{x\to 0} \frac 1x \int_0^x f(t) \mathrm{d} t$$
输出:
查看结果
更多支持的符号可以查看 katex 官网说明.
注意事项
在 dev 模式下,会发现控制台有一些警告,例如:
[Vue warn]:
Failed to resolve component: math
If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.
查看官网的文档,了解到是因为 Katex 在 HTML 中渲染这些公式会使用非标准标签。
非标准的 HTML 标签不会被 Vue 模板编译器识别成原生 HTML 标签。相反,Vue 会尝试将这些标签解析为 Vue 组件,而显然这些组件通常是不存在的。 例如:
如果你无论如何都要使用这些标签的话,可以尝试下面两种方法之一:
- 添加一个 v-pre 指令来跳过这个元素和它的子元素的编译过程。注意所有的模板语法也都会失效。
- 设置 compilerOptions.isCustomElement 来告诉 Vue 模板编译器不要尝试作为组件来解析它们。
- 对于
@bundler-webpack
,设置 vue.compilerOptions- 对于
@bundler-vite
,设置 vuePluginOptions.template.compilerOptions
显然选择第二种方式更好。本人使用的是vite
,以下也是基于vite
的配置.
// config.ts
import { defineUserConfig } from "vuepress";
import type { DefaultThemeOptions, ViteBundlerOptions } from "vuepress";
export default defineUserConfig<DefaultThemeOptions, ViteBundlerOptions>({
bundlerConfig: {
vuePluginOptions: {
template: {
compilerOptions: {
isCustomElement: (tag) => customElement.includes(tag),
},
},
},
},
});
const customElement = [
"math",
"annotation",
"semantics",
"mtext",
"mn",
"mo",
"mi",
"mspace",
"mover",
"munder",
"munderover",
"msup",
"msub",
"msubsup",
"mfrac",
"mroot",
"msqrt",
"mtable",
"mtr",
"mtd",
"mlabeledtr",
"mrow",
"menclose",
"mstyle",
"mpadded",
"mphantom",
"mglyph",
];
其中customElement
中的元素可以通过查看Katex 源码找到。
提示
实际使用时发现以上customElement
数组并不完全包括 Katex 所使用的标签,还有"eq"
, "eqn"
等标签。
至此,在markdown-it
中引入 katex 的工作已经基本完毕。
参考:
响应式公式块
当屏幕比较小时,比较长的公式可能显示怪异,此问题可以通过 css 解决,以下设置当公式长度超过屏幕宽度时,会通过左右滑动显示:
/* 浏览器可视区域宽度 < 825px */
@media screen and (max-width: 825px) {
.katex-display > .katex {
max-width: 100%;
}
.katex-display > .katex > .katex-html {
max-width: 100%;
overflow-x: auto;
overflow-y: hidden;
}
/* 滚动条样式 */
.katex ::-webkit-scrollbar {
width: 4px;
height: 4px;
}
.katex ::-webkit-scrollbar-track {
background-color: #e4e5e6e7;
border-radius: 2px;
}
.katex ::-webkit-scrollbar-thumb {
background-color: #778899ff;
border-radius: 2px;
}
/* 滚动条向下偏移 */
.katex .base {
margin-bottom: 4px;
}
}
宏相关配置
提示
如果你不需要宏相关的配置,这块内容可以忽略。
更换插件
如果需要使用自定义宏(macro),需要 Katex 版本在 0.7.0 以上,而现在的markdown-it-katex 使用的 katex 版本为 0.5.1。本人在 npmjs 上搜索了一番,浏览之后发现以下库应该都是可用的:
- markdown-it-texmath 需要先安装 katex,因此新版 katex 都是可以的,版本更新较频繁
- @littlefattie/markdown-it-katex 对原有同名插件的改善,使用
katex@0.15.1
,支持 TypeScript - @iktakahiro/markdown-it-katex 使用
katex@0.11.1
这里我选择了 texmath,直接安装即可
yarn add katex markdown-it-texmath
安装完成后,在 config.ts
中加入:
import { defineUserConfig, DefaultThemeOptions } from "vuepress";
import markdownItTex from "markdown-it-texmath";
export default defineUserConfig<DefaultThemeOptions>({
head: [
// something else...
[
"link",
{
rel: "stylesheet",
href: "https://cdn.jsdelivr.net/npm/katex/dist/katex.min.css",
},
],
],
extendsMarkdown: (md) => {
md.use(markdownItTex, {
// katexOptions: {...} macros配置可以不放在里面
macros: {
"\\ds": "\\displaystyle",
"\\ts": "\\textstyle",
},
});
},
});
相关信息
官方的说明还推荐引入 texmath.min.css,但是实测发现引入后样式异常。
引用和跳转
katex
本身是不支持 \label
和 \ref
等命令的(见 support table),这个问题可以通过自定义宏结合 html
得以实现。
该小节参考 Support \eqref and \label。
添加 katex options
:
katexOptions: {
macros: {
"\\eqref": "\\href{##tag-#1}{(\\text{#1})}",
"\\ref": "\\href{##tag-#1}{\\text{#1}}",
"\\label": "\\htmlId{tag-#1}{}"
},
trust: (context) => ['\\htmlId', '\\href'].includes(context.command)
}
在 markdown
中使用:
$$
I_1=\int_0^p{\frac{\arctan x}{x^2+p(C+1)x+C}\text{d}x} \label{I1}
$$
$$
\arctan x+\arctan \frac{p-x}{1+px}=\arctan p \tag{1}\label{1}
$$
利用换元 $x\mapsto\frac{p-x}{1+px}$ 以及 $\eqref{1}$ 式可知,形如 $\href{#tag-I1}{I_1}$ 的式子可化为
% 当然也可以用 markdown 语法:[$I_1$](#tag-I1) 但 markdownlint 等可能会有警告
$$
\frac{\arctan p}{2}\int_0^p{\frac{1}{x^2+Bx+C}\text{d}x}
$$
查看效果
利用换元 以及 式可知,形如 的式子可化为
需要注意的是,跳转之后的内容可能会被默认主题的 header
挡住,此问题可以通过 css
解决:
/* 调整引用公式跳转后的顶部距离 */
/* 浏览器可视区域宽度 < 825px */
@media screen and (max-width: 825px) {
.base > span.enclosing {
padding-top: 4em;
margin-top: -4em;
}
}
/* 浏览器可视区域宽度 >= 826px */
@media (min-width: 826px) {
/* PC 浏览器可通过 scroll-margin-top 属性修改 */
.base > span.enclosing {
scroll-margin-top: 4em;
}
}
其中的 4em
和 header
的高度相近。