AstroでKaTeXを使いたいぞという話
はじめに
Webで数式組版をしたい場合、MathJaxを使うというのが常識でしたが、前回のhugoブログを作った時点でKaTeXの方が早くて良いぞという話になっていました。 今回のAstroブログでもどうにか数式を表示したいということで、さくっと調べてみたのですが、あまり情勢は変わってないようだったので、KaTeXを導入することにします。
Remark / Rehype
AstroはMarkdownをHTMLにレンダリングする際、Remark/Rehypeを利用しているようです。(ref: MarkdownとMDXの設定)
Remark/Rehypeの関係は掴み辛いですが、「Introduction to unified」や「Remark で広げる Markdown の世界」が分かりやすかったので紹介します。
こんな感じの理解をしてます。
unistというASTがあり、それの特化としてmdastやhast、nlcst(なぜtastにしなかった。。) がある。*-parseでunistに変換する。*-stringifyでunistをそのフォーマットの文字列に変換する。
さらに
unistからunistに変換するtransformを挟むことができ、ここにプラグインを刺すunist同士の変換をremark-rehypeやrehype-remarkで行う

この一連の流れが unified エコシステムで整理されています。
うーん。きれいですね。すばらしい。
remark-math / rehype-katexの導入
remark-mathとrehype-katexを導入します。
remark-math がマークダウン中の $C_L$ のような数式をmdast上で変換し、
rehype-katex がhast上でKaTeXを使うように変換します。
Astroでは書き下しませんが、READMEの例が分かりやすかったので引用します。
import {read} from 'to-vfile'import {unified} from 'unified'import remarkParse from 'remark-parse'import remarkMath from 'remark-math'import remarkRehype from 'remark-rehype'import rehypeKatex from 'rehype-katex'import rehypeStringify from 'rehype-stringify'
const file = await unified() .use(remarkParse) .use(remarkMath) .use(remarkRehype) .use(rehypeKatex) .use(rehypeStringify) .process(await read('example.md'))
console.log(String(file))マークダウンの文字列をmdastに変換して、mdastでmathを変換して、hastに変換して、hastでkatexを変換して、htmlに変換しているのが分かります。
Astroでの設定
astro.config.mjsに追加
Astroから使えるようにするには astro.config.mjs に以下のように設定します。
import { defineConfig } from 'astro/config';import mdx from '@astrojs/mdx';import sitemap from '@astrojs/sitemap';import remarkMath from 'remark-math';import rehypeKatex from 'rehype-katex';
import react from "@astrojs/react";
export default defineConfig({ site: 'https://a.conao3.com', integrations: [mdx(), sitemap(), react()], markdown: { remarkPlugins: [remarkMath], rehypePlugins: [rehypeKatex], }});CSSの追加
KaTeXのページからCSSのタグをコピーして良い感じのところに貼り付けます。
私はいろいろ面倒だったので、 src/component/BaseHeader.astro に貼り付けて全ページで読み込まれるようにしました。
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.4/dist/katex.min.css" integrity="sha384-vKruj+a13U8yHIkAyGgK1J3ArTLzrFGBbBc0tDp4ad/EyewESeXE/Iv67Aj8gKZ0" crossorigin="anonymous">動作確認
$C_L$ は のようにレンダリングされます。
ブロックスタイルはこんな感じ。
$$\frac{1}{\pi} = \frac{2\sqrt{2}}{99^2} \sum_{n=0}^\infty \frac{(4n)!}{(4^n n!)^4} \frac{1103 + 26390n}{99^{4n}}$$ちゃんと動いてそう。すばら。
まとめ
想像以上に簡単にできた。remark/rehypeというプロジェクトを知れたのも良かった。どんどん使っていきたい。
記事ごとレイアウトを指定すると良いという記事もあったが、多分それは記事のタイトルとか記事の抜粋で 別のページに出たときに壊れる気がするので、今回は全ページで読み込むようにした。
rehype-katexが にレンダリングしているので、おそらくその時だけCSSを追加するようにできると最適化されて良さそう。