跳至主要內容

Vuepress 之 KaTeX 插件配置

zedo2022年1月26日VuePressKaTeXlatexkatexvuepress大约 6 分钟约 1781 字

Vuepress 之 KaTeX 插件配置

提示

本文内容基于 vuepress2 的默认主题。

更建议使用 Hopeopen in new window 主题作者维护的 Markdown 增强插件open in new window

基本使用

vuepress@v2open in new window中,如果想要内置的 markdown-it 支持数学公式的显示,只需要使用 mathjax、katex 等对应的插件即可,katex 相比 mathjax,公式渲染速度要快很多,因此这里选择使用 katex 插件。

安装 markdown-it-katex

这里的 katex 插件指的是 markdown-it-katexopen in new window,其安装方式很简单,只需要在项目中使用 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.jsdocs/.vuepress 目录下,两者配置方式有部分不同,详见官网的说明open in new window,本人倾向于使用 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 stylesheetopen in new window

[
    "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 官网说明open in new window.

注意事项

在 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.

查看官网的文档open in new window,了解到是因为 Katex 在 HTML 中渲染这些公式会使用非标准标签。

非标准的 HTML 标签不会被 Vue 模板编译器识别成原生 HTML 标签。相反,Vue 会尝试将这些标签解析为 Vue 组件,而显然这些组件通常是不存在的。 例如:

如果你无论如何都要使用这些标签的话,可以尝试下面两种方法之一:

显然选择第二种方式更好。本人使用的是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 源码open in new window找到。

提示

实际使用时发现以上customElement数组并不完全包括 Katex 所使用的标签,还有"eq", "eqn"等标签。

至此,在markdown-it中引入 katex 的工作已经基本完毕。

参考:

  1. KaTeX Optionsopen in new window

  2. vuepress-next issuesopen in new window

响应式公式块

当屏幕比较小时,比较长的公式可能显示怪异,此问题可以通过 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;
    }
}

参考 KaTeX issues: 327open in new window

宏相关配置

提示

如果你不需要宏相关的配置,这块内容可以忽略。

更换插件

如果需要使用自定义宏(macro),需要 Katex 版本在 0.7.0open in new window 以上,而现在的markdown-it-katexopen in new window 使用的 katex 版本为 0.5.1。本人在 npmjsopen in new window 上搜索了一番,浏览之后发现以下库应该都是可用的:

这里我选择了 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.cssopen in new window,但是实测发现引入后样式异常。

引用和跳转

katex 本身是不支持 \label\ref 等命令的(见 support tableopen in new window),这个问题可以通过自定义宏结合 html 得以实现。

该小节参考 Support \eqref and \labelopen in new window

添加 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;
    }
}

其中的 4emheader 的高度相近。

2023-9-14 更新
重启 search-pro,css 样式调整