この記事は、フラー株式会社 Advent Calendar 2024 の 7 日目の記事です。6 日目は su8 のサポート終了間近 しがない 30 代エンジニアの本棚(2024 年版)でした。
はじめに
unified(remark、rehype)を使って Markdown を HTML へ変換する人は多いでしょう。unified は Gatsby や Nuxt.js、Astro など、多くのフレームワークで利用されています。
unified で数式を扱う場合、Markdown 中の $f(x)=ax+b$
のような TeX(LaTeX)数式を remark-math
で見つけ、rehype-mathjax
や rehype-katex
で MathJax や KaTeX により表示できる形式に変換するのが一般的です。
ブラウザで数式を表示するために、HTML に MathML を記述する方法があります。KaTeX は数式表示のための HTML に変換するだけでなく、MathML への変換もサポートしています。しかし、KaTeX は少し TeX 数式のカバレッジが低く、純粋な MathML 以外も出力されるなど、いくつかの不満がありました。
そんなとき、カバレッジが優れ、軽量な MathML を出力する Temml というライブラリを見つけました。Temml を使って MathML に変換したいと思い、@daiji256/rehype-mathml
を作成しました。
rehype-mathml
で出来ること
このような Markdown から MathML を含む HTML に変換できます。
本文中や $f(x)=ax+b$、別行立てで、
$$
\begin{align}
f(x) &= ax + b\\
g(x) &= cx^{2} + dx + e
\end{align}
$$
MathML による数式表示が可能です。
See the Pen MathML Sample by Daiji (@Daiji256) on CodePen.
MathML
MathML について簡単に説明します。
MathML(Mathematical Markup Language)とは XML/HTML5 で数式を記述するためのマークアップ言語です。Can I use によると、現在ではメジャーなブラウザが MathML をサポートしているそうです。
ブラウザで数式を表示する方法として、MathML の他に、MathJax や KaTeX があります。これらは JavaScript の処理や画像の読み込み、HTML の肥大化などによりパフォーマンスが優れないです。一方で MathML は標準機能で数式を扱い非常に軽量です。さらに、MathML は数式の表示だけでなく、そのコードに数式としての意味を持たせるため、スクリーンリーダーなどでも扱うことができます1。
しかし、MathML はコンピューターが認識しやすいように設計されたものであり、人間が直接扱うのは難しいです。そのため、MathML 専用のエディタなどを使うのが一般的です。
MathML による数式記述例
例えば二次方程式の解の公式
$$
x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a}
$$
は MathML で記述すると次のようになる。
<math>
<mrow>
<mi>x</mi>
<mo>=</mo>
<mfrac>
<mrow>
<mo>−</mo>
<mi>b</mi>
<mo>±</mo>
<msqrt>
<mrow>
<msup>
<mi>b</mi>
<mn>2</mn>
</msup>
<mo>−</mo>
<mn>4</mn>
<mi>a</mi>
<mi>c</mi>
</mrow>
</msqrt>
</mrow>
<mrow>
<mn>2</mn>
<mi>a</mi>
</mrow>
</mfrac>
</mrow>
</math>
rehype-mathml
の使い方
rehype-mathjax
や rehype-katex
をすでに使っている場合、その部分を @daiji256/rehype-mathml
に置き換えるだけで完了します。詳しくは rehype-mathml/README.md に書いてあります。
インストール
npm の場合、
npm install @daiji256/rehype-mathml
でインストールできます。
remark-math
— rehype-mathml
remark-math
と rehype-mathml
を以下のようにして使うことができます。
import { unified } from 'unified';
import rehypeParse from 'rehype-parse';
import rehypeStringify from 'rehype-stringify';
import remarkRehype from 'remark-rehype'
import remarkMath from 'remark-math';
import rehypeMathML from '@daiji256/rehype-mathml';
import { read, write } from 'to-vfile';
const file = await unified()
.use(remarkParse)
.use(remarkMath)
.use(remarkRehype)
.use(rehypeMathML)
.use(rehypeStringify)
.process(await read('input.html'));
file.basename = 'output.html';
await write(file);
文献
rehype-mathml
(GitHub)rehype-mathml
(npm)- unified
- remark-math
- W3C Math Home
- "MathML" | Can I use
-
rehype-mathml
: TeX数式をMathMLにするrehypeプラグイン2