MathMLのすすめ

<details><summary>更新履歴</summary>
2025/04/02: Firefoxの自動改行について追記
</details>


皆さんMathMLは使っていますか?
使っていないからMathML4の記事が無いんですね（MathMLタグのフォロワー4…）．しかもQiitaに埋め込むと存在を消されます．~~（ブラウザのデフォルトでいいから使わせろ．）~~
ということで，今後の変更を恐れず[草案段階のMathML4](https://www.w3.org/TR/mathml4/)を前提に，MathMLについての紹介をします．

まあ大体[Mozillaの記事](https://developer.mozilla.org/ja/docs/Web/MathML)を読めばわかりますが…

## MathMLタグ一覧
### `<math>`
全ての数式は`math`タグで囲みます．
デフォルトは`display="inline"`で，`display="block"`では独立した一行で書いてくれます．

### トークン要素`<mi>`，`<mo>`，`<mn>`，`<mtext>`，`<ms>`（，`<mspace>`）
#### `<mo>`
演算子，括弧，セパレータ，アクセントに使います．
演算子は`<mo>+</mo>`や`<mo>∑</mo>`などで **函数名は含みません**
括弧は括弧です．~~`<mfenced>`は非推奨になりました~~
セパレータは`<mo>,</mo>`などを意味してる見たいです．
アクセントは上線`<mo>‾</mo>`などで，後述の`<mover>`などの中で使います．

:::note
MathMLでしか使わないであろう不可視のUnicode文字をめちゃくちゃ使うので紹介します．
<dl>
    <dt>U+2061（函数適用）<code>&af;</code></dt>
    <dd>$𝑓(𝑥)$の𝑓と()の間とかに置くやつです．</dd>
    <dt>U+2062（不可視の積）<code>&it;</code></dt>
    <dd>$2𝑥$とかの2と𝑥の間に置きます．</dd>
    <dt>U+2063（不可視の,） <code>&ic;</code></dt>
    <dd>「,」を省略したもので，Kroneckerのデルタ$𝛿_{𝑖𝑗}$でいう𝑖と𝑗の間に置きます．ぶっちゃけ「,」書けばいい話．
    </dd>
</dl>
（一応帯分数用の不可視の+（U+2064）もあります．）

LaTeXからの変換最大の敵…というか完璧にやるのはほぼ不可能だと思いますが，サボると文字の間隔がおかしくなったるのでつけた方がいいです．
:::
:::note
負記号はハイフンマイナス`-`（U+002D）ではなく`−`（U+2212）を使いましょう．
普通のハイフンも圏論で使ってますが，そのときは`‐`（U+2010）を使うべきかもしれません．
:::

`<mo>`専用の属性として`form`があり，一番最初の子要素が自動的に`"prefix"`，最後の子要素が`"postfix"`，それ以外は`"infix"`となります．使い道は`<mrow>`で紹介します．

#### 数値リテラル`<mn>`
`<mn>0</mn>`などの「数字」に使います．

#### テキスト`<mtext>`
`<mtext>s. t.</mtext>`などの「任意のテキスト」に使います．

#### String Literal`<ms>`
プログラミング言語などの文字列を扱うためのものらしいです．
[Mozilla](https://developer.mozilla.org/en-US/docs/Web/MathML/Element/ms)では`<ms>Hello World!</ms>`を例に挙げてます．自分は使ったことがないですが，使う人もいるのかもしれません．

:::note warn
あくまでプログラミング言語などのためであり，基本は`<mtext>`，`<mo>`，および次の`<mi>`です．
:::

#### 識別子`<mi>`
最も基本となる「識別子」ですが，使い方は「上記以外」です．
とはいえ`<mi>𝑥</mi>`などの変数と`<mi>sin</mi>`などの函数名がほとんどでしょう．

`<mi>x</mi>`のように中身が一文字の場合，（Google Chrome以外は）立体でなく斜体で表示されます．
そのため立体にするときは専用の属性で`mathvariant = "normal"`とします．
しかしそもそも斜体の𝑥は`<mi>𝑥</mi>`（U+1D465）を使うべきで，`"normal"`以外の値は非推奨ということで，この属性の存在自体が負の遺産です．
ちなみにGoogle Chromeにいたっては対応すらしていません．

#### スペース`<mspace>`
一応LaTeXでいう`\quad`などが扱える要素が存在しています．
適切なスペースなんて人それぞれでしょうし，`class`（もしくは後述のMathML専用属性`intent`）を適切に設定し，CSSでどうにかすべきでは?

### グループ化，空要素`<mrow>`
横並びになるトークンを等価にするためのものです．例えば$𝑓{({{𝑥+𝑦},𝑧})}$なら
```html
<math>
	<mi>𝑓</mi>
	<mo>&af;</mo>
	<mrow>
		<mo>(</mo>
		<mrow>
			<mrow>
				<mi>𝑥</mi>
				<mo>+</mo>
				<mi>𝑦</mi>
			</mrow>
			<mo>,</mo>
			<mi>𝑧</mi>
		</mrow>
		<mo>)</mo>
	</mrow>
</math>
```
となります．LaTeXで{}で囲んでいる部分（これから分数や添字も出てきます）には当然必須です．また，$()$のまわりを囲むまないと，$()$の`form`の値が`"infix"`となってしまい，大きさが自動調整され **ないので** 実質ここにも必須です．LaTeXでいう`\left`と`\right`に近いものがあります（もちろん全ての演算子に適用されるのでそれ以上に汎用のものですが）．

それ以外の$()$の中身や$𝑥+𝑦$をグループ化しているのはもはやただなマナーかもしれませんが…（自分はちゃんとやってます）

また，引数が必要だが空要素にしたいときに`<mrow />`として使えます．~~`<none />`は非推奨になりました~~

### 一般レイアウトスキーム`<mfrac>`，`<msqrt>`，`<mroot>`，`<mstyle>`，`<merror>`，`<mpadded>`，`<mphantom>`

#### 分数`<mfrac>`
$\frac{1}{2}$は
```html
<math>
    <mfrac>
        <mn>1</mn>
        <mn>2</mn>
    </mfrac>
</math>
```

### 平方根`<msqrt>`
$\sqrt{2𝑥}$は
```html
<math>
    <msqrt>
    	<mn>2</mn>
        <mo>&it;</mo>
        <mi>𝑥</mi>
    </msqrt>
</math>
```
:::note
#### inferred `<mrow>`
子要素が1個であるべきものは上の例のように`<mrow>`を省略できます．
該当するのが`<math>`，`<msqrt>`や後述の`<mtd>`などで，無意識に使っているでしょうが念の為．
:::

#### 根号`<mroot>`
底が先で，例えば$\sqrt[3]{x}$は
```html
<math>
    <mroot>
    	<mi>𝑥</mi>
    	<mn>3</mn>
    </mroot>
</math>
```

#### スタイル変更`mstyle`
`class`と`intent`などの属性設定で十分じゃない?

#### エラー`merror`
エラーメッセージ用です．構文エラーを教える機能にどう? だそうです ~~いらない~~

#### 位置ずらし`mpadded`
こんなことしなくても適切な位置になるようにすべきですし，そもそも`class`と`intent`で（略）

#### ファントム`mphantom`
文字の大きさだけ確保して，何も表示しないものです．
行揃え（LaTeXでいう`\align`）は後述の`<mtable>`でやるので，ほぼ出番は`<mfrac>`だけかと思います．例えば
```math
\frac{𝑥+𝑦+𝑧}{𝑥\quad \ \ \ +𝑧}
```
と表示するためには
```html
<math>
	<mfrac>
		<mrow>
			<mi>𝑥</mi>
			<mo>+</mo>
			<mi>𝑦</mi>
			<mo>+</mo>
			<mi>𝑧</mi>
		</mrow>
		<mrow>
			<mi>𝑥</mi>
			<mphantom>
				<mo form="infix">+</mo>
				<mi>𝑦</mi>
			<mphantom>
			<mo>+</mo>
			<mi>𝑧</mi>
		</mrow>
	</mfrac>
</math>
```
とする，などです．ちなみに$+$の`form="infix"`は，そのままだと`form="prefix"`になってしまうからですね． ~~サボっても大した問題は起きないけど~~

### 添字 `<msup>`，`<msub>`，`<msubsup>`，`<munder>`，`<mover>`，`<munderover>`，`<mmultiscripts>`，`<mprescripts>`

#### 右上・右下付き添字`<msup>`，`<msub>`，`<msubsup>`
底の後に添字で，`<msubsup>`はその名と通り下付き添字が先です．$𝑎_𝑛^𝑘$は
```html
<math>
    <msubsup>
    	<mi>𝑎</mi>
    	<mi>𝑛</mi>
        <mi>𝑘</mi>
    </msubsup>
</math>
```

#### 真上・真下付き添字`<munder>`，`<mover>`，`<munderover>`
同じく底の後に添字で，`<munderover>`はその名と通り下付き添字が先です．
```math
\sum_{𝑘=0}^𝑛
```
は
```html
<math display="block">
	<munderover intent=":largeop">
		<mo>∑</mo>
		<mrow>
			<mi>𝑘</mi>
			<mo>=</mo>
			<mn>0</mn>
		</mrow>
		<mi>𝑛</mi>
	</munderover>
</math>
```
:::note
インライン形式のデフォルトは`displaystyle="false"`となっており，CSSが`math-style: comact`に設定されることで，`<msubsup>`のように，右上・右下付きの添字のように表記されます．
:::

#### テンソル`<mmultiscripts>`，`<mprescripts>`
同じく底の後に添字で，(右一列目の下付き添字，上付き添字)…と書きます．
添字は各列上下セットが必須なので，空白の部分は`<mrow />`を入れておきましょう．
左にも添字を書きたいときは，`<mprescripts>`を書いてから，(左一列目の下付き添字，上付き添字)…と書きます．内側からではないです．例えば${}^𝑛{}^𝑚𝐶^𝑘$は
```html
<math>
	<mmultiscripts>
		<mi>𝐶</mi>
		<mi>𝑘</mi> <mrow/>
		<mprescripts />
		<mi>𝑛</mi> <mrow />
		<mi>𝑚</mi> <mrow />
	</mmultiscripts>
</math>
```

### 表`<mtable>`，`<mtr>`，`<mtd>`
HTMLの`<table>`，`<tr>`，`<td>`と一緒で，まず`<table>`で囲み，各行を`<tr>`で囲んで，各成分を`<td>`で囲みます．
[intentの例](https://w3c.github.io/mathml-docs/intent-core-properties/#Table)にあるように，単なる表，行列，場合分け，連立方程式，式変形などに使います．~~`<maligngroup>`と`<malignmark>`は非推奨になりました~~

:::note
ちなみに式の途中で改行する用途も想定されていますが，横幅が任意なのに適切な改行位置なんか事前に知りようがないので，流石に代替案が出るのではないかと負われます．
:::

## MathMLに使える属性
どのMathML要素にも使えるのは，大体は当然備わっているべき`class`や`id`などです．注意すべきなのは，なぜか`color`などが`mathcolor`になっていることぐらいでしょう．リストは[MathML Core](https://www.w3.org/TR/mathml-core/#global-attributes)を参照してください．

また，Coreではないようですが，数式の一部に`href`を入れることもでき，定義を参照したりといった使い方ができそうです．

### intent
その名の通り，要素の役割を示すものです．

:::note warn
MathML4から追加されたものです．MathML4がそもそも草稿段階ということで，これから激しい変更がある可能性があります．
:::
`<mtable>`なら
- 行列`intent=":matrix"`
- 連立方程式`intent=":system-of-equations"`，式変形`intent=":lines"`
などがあり，
- 前者は全て中央揃え
- 後者は最初の子要素（=の前）を右揃え，最後の子要素（=の後）を左揃え
にすることが多いと思うので，CSS用に`class`を設定するかわりにこの`intent`を設定することになります．

これらは，`<img>`の代替テキスト`alt`のようにスクリーンリーダー用のものらしいので，スタイル変更の有無にかかわらず基本は設定すべきです．

取り得る値は[Intent Lists](https://w3c.github.io/mathml-docs/#intent-lists)の通りです．上のように`:`をつけるintent propertyの他，intent conceptというものがあります．

ただ，intent conceptの方，流石にもう少し簡略化される気がするので，自分はしばらく使わない予定です．例えば行列の転置は$𝐴^\mathrm{T}$
```html
<math>
    <msup intent='transpose:function($arg)'>
        <mi arg='arg'>𝐴</mi>
        <mi intent='transpose' mathvariant='normal'>T</mi>
    </msup>
</math>
```
となります．このようにtransposeと2回書いたり，`<msup>`の中にある時点でどっちが行列で，どっちが転置を表す作用素かなんて自明なのに`arg`という属性を要求したりと無駄が多い感じで，さすがに変更を受けると思って待っています．

もちろん本来は書くべきですし，簡略化できても全て省略されることはほぼないでしょうから，今から書いておいてもいいとは思いますが（消すのは簡単）．

## その他MathMLの困難
`mathvariant`，`intent`の他にも微妙な点がいくつかあります．
一つは自動改行がほとんど無いこと．上述のように`<mtable>`を用いた手動の改行は可能ですが，横幅が可変である以上，使い勝手が悪すぎます．ほんと何で無いんだ．（2025/4/2追記: Firefoxでは、`math`タグの直接の子要素のみ自動改行が可能なようです．これでも全くもって不十分ですが…）
もう一つは数式中にSVGなどの図が埋め込めないことです．圏論の普遍性の図式くらいなら（見た目はともかく）`<mtable>`で無理矢理書けますが，自然変換などを含めるときに曲線が描きたくなったり，フュージョンダイアグラムのように線どうしを繋げたいときはどうしようもありません．

HTMLで数式を扱うならば，ここら辺の需要に対応しないはずはないと思われるので，まあとりあえず待つことにします．

今すぐ使いたいんですがね…