現在の最新版は8/25リリースのv3.1
らしいぞ!
MathJax公式ドキュメント
何かあったらこ↑こ↓を読んでくれよな〜頼むよ〜
注意
ちょっと頑張って和訳したり実験したりしているだけです,あんまり本気でアテにするなよ…?
前提
(特には)ないです.
MathJaxの導入
最も基本の型
こ↑こ↓にある通りだと
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js">
</script>
を<head></head>
にぶち込めばおk.
ちなこのcdn.jsdelivr
はこのままだと強制的に最新版を読み込ませてくるので,それが嫌なら
<script id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3.x.y/es5/tex-mml-chtml.js">
</script>
のように,指定したいバージョンを@3.x.y
みたいにフル記述してやればおk.
これでもうバージョン管理は…完璧やな!
概念として
「html本文を読み取った内容を読める数式として出力する」という性質上,html本文に記述する入力とページに表示される出力のそれぞれに,方式が2つずつ存在する.
入力ならば
- TeX
- みなさんお馴染みのまさしくアレ
- MML
- XMLとしてXHTMLにぶち込まれる
,出力ならば
- chtml
- どうやらこれはCSS+HTMLを意味するらしい,決してCompact HTMLではない
- svg
- どんだけ拡大しても品質が劣化しないヤツ,これを生成して直に埋め込むらしい
,これをどう設定するかによって最初の話からがらりと変わってくる…のだが,俺はTeXとsvgが好きだからよ,折角だしTeX入力・svg出力を選ぶぜ!
用途ごとの使い分け
じゃあさっきの例だとtex-mml-chtml.js
を呼び出すということだ,そしてこれは「tex型の入力もmml型の入力も受け入れてchtmlで出力する」ということ,他のパターンならこ↑こ↓にある通り
- tex-chtml
- tex-chtml-full
- tex-svg
- tex-svg-full
- tex-mml-chtml
- tex-mml-svg
- mml-chtml
- mml-svg
なんか-full
って付いてあるのが強そうだな!じゃあ俺は
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg-full.js">
</script>
を<head></head>
にぶち込んでやればいいんだな!
☝️-full
ってなんだよ
こ↑こ↓によると,TeXの入力の処理に使うライブラリを事前に全てロードさせるオプションらしい.
更なるオプションについて
実は最初のロードの時点で使うライブラリやその動作の設定自由自在にできたりする,TeXのオプションだったりMathMLのオプションだったりAsciiMathのオプションがある,その上でTeXにはこれだけのライブラリを個別に使い分けられるだからこれほどまでにTeXを勧めているという節もある.
じゃあ試しに書いてみるか,さっきのinput/tex-full
のとこには
This is the most complete TeX input component. It includes the main TeX/LaTeX input parser, along with all the TeX extensions, and is configured to enable all of them other than physics and colorv2. You can add these two to the packages array in the tex section of your MathJax configuration, though you should remove the color extension if you add the colorv2 extension, and should remove the braket extension if you enable the physics package.
これは最も完全なTeX入力コンポーネントです。 これには、メインのTeX / LaTeX入力パーサーとすべてのTeX拡張機能が含まれており、物理学とcolorv2以外のすべてを有効にするように構成されています。 これら2つをMathJax構成のtexセクションのpackages配列に追加できますが、colorv2拡張機能を追加する場合はcolor拡張機能を削除し、physicsパッケージを有効にする場合はbracket拡張機能を削除する必要があります。
って書いてある,つまり-full
した上で更にcolor
とbracket
を減らしてcolorv2
とphysics
を入れることができる(そしたらコマンドの重複がなく安全に動作する)らしいな?
こ↑こ↓の全体像とこ↑こ↓の説明
This array lists the names of the packages that should be initialized by the TeX input processor. The input/tex and input/tex-full components automatically add to this list the packages that they load. If you explicitly load addition tex extensions, you should add them to this list. For example:
この配列は、TeX入力プロセッサによって初期化される必要があるパッケージの名前をリストします。 input / texおよびinput / tex-fullコンポーネントは、ロードするパッケージをこのリストに自動的に追加します。 追加のtex拡張機能を明示的にロードする場合は、それらをこのリストに追加する必要があります。
そしてこ↑こ↓の例文を見る限りだと,なんだか
MathJax = {
loader: {load: ['[tex]/colorv2', '[tex]/physics']},
tex: {
packages: {
'[+]': ['colorv2', 'physics'],
'[-]': ['color', 'bracket']
}
}
};
というような形が推奨されているように思うなぁ…
urlとライブラリの対応関係
-
input/tex-base
-
base
のみ-
require
もautoload
も入ってないので,本文中のTeX記法からの拡張が不可能になる
-
-
-
input/tex
base
ams
newcommand
require
autoload
configmacros
noundefined
- 管轄外のコマンドを呼び出すと,
physics
・colorv2
以外なら勝手にrequire
する- ちなみに自分で
require
で明示的に呼び出した方が整理しやすいらしいよ
- ちなみに自分で
-
input/tex-full
-
physics
・colorv2
以外の全て- その2つは
bracket
・color
と差し替えできる
- その2つは
-
以上からわかる通り,別にTeX専用のライブラリに限らずとも,そもそもInputのコンポーネントもOutputのコンポーネントも同じくライブラリの扱いであり,単に指定しなければsrcの先のurlに-full
があるか否かでロードする中身を勝手に決めているだけである.
require
とautoload
require
の出来る仕事は本家TeX並みに強く,説明ページには
The require extension defines the non-standard \require macro that allows you to load extensions from within a math expression in a web page.
require拡張機能は、Webページの数式内から拡張機能をロードできるようにする非標準の\ requireマクロを定義します。
とあり,つまりコイツさえ入れれば各ページでrequire
することで逐次にロードできる.
他方でautoload
はTeXコマンドとロードするライブラリとの対応関係を事前に定義するものであり,そのTeXコマンドをWebページの本文に打っておくと最初にロードされる.
説明ページを見てもrequire
とは準備や挙動が全く異なることがわかるが,TeX本家にはなさげな見慣れない機能なので,試しに動作する例を示すと
MathJax = {
loader: {
load: ['input/tex-base', 'output/svg', '[tex]/autoload']
},
tex: {
packages: {
'[+]': ['base', 'autoload']
},
autoload: {
boldsymbol: ['boldsymbol']
}
}
}
↓
後述するloader: {load: []}
やtex: {packages: {}}
とは無関係にロードを行うことができる,という点はrequire
と共通している
最小構成のやり方について
ん?先に挙げた最小構成オプションの選択肢に対応するようなURLがこ↑こ↓のリストに載ってないやん!と思う方も中にはいるかもしれない.
だがしかし,そもそもこのMathJax
オブジェクトの中のloader: {}
(の中のload: []
)こそが,ページがロードする中身を事前に決め打ちできるレシピのような存在なのである.早い話が例えば
MathJax = {
loader: {load: ['input/tex-base', 'output/svg']},
tex: {
packages: {
'[+]': ['base']
}
}
};
とすれば,取り合えずは(使えるかどうかは置いといて)最小構成となる.
更にrequire
とautoload
を含めて柔軟性を高めた最小構成であれば
MathJax = {
loader: {load: ['input/tex-base', 'output/svg', '[tex]/require', '[tex]/autoload']},
tex: {
packages: {
'[+]': ['base', 'require', 'autoload']
}
}
};
と設定してやるのが妥当であろう.
しかしそう設定したところで,srcの先のurlを
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
</script>
やら
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg-full.js">
</script>
やらとやってしまって良いのだろうか?いや,やっぱりそれはよくない(反語).
後述するstartup
を用いなければMathJaxの指定通りのロードは完璧にはできない.
そしてドキュメントには仕様が載っていなかったので,自分でやって比較してみた…
下の方が指定通りのロードをしていそうなことがわかる.
よって突き詰めるのであれば
<script type="text/javascript" id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/startup.js">
</script>
を選択することが正しいと考えられる.でもurlを打てば一括でロードできちゃうのは楽なんよ
まだまだあるよ!ライブラリ
別にライブラリがあるのはTeXに限った話ではないし,面白い機能もあったりする.
アクセシビリティ
さっきのload: []
に入れると使えるらしい.
-
a11y/semantic-enrich
- 数式に読み仮名を振る,読み上げ機能がある端末に対応できる
-
a11y/complexity
- 複雑すぎる式を折り畳んでくれる,クリックすれば元に戻る
-
a11y/explorer
- Tab(↹)とかを押してWebページの中で数式を移動できる
-
a11y/complexity
と組み合わせられる
-
- Tab(↹)とかを押してWebページの中で数式を移動できる
-
a11y/assistive-mml
- MathMLを利用する読み上げ機能がある端末に対応できる
-
a11y/semantic-enrich
が必要
-
- MathMLを利用する読み上げ機能がある端末に対応できる
ここまでを全部載せすると…?
<script type="text/javascript" id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg-full.js">
</script>
MathJax = {
loader: {load: ['[tex]/colorv2', '[tex]/physics', 'a11y/semantic-enrich', 'a11y/complexity', 'a11y/explorer', 'a11y/assistive-mml']},
tex: {
packages: {
'[+]': ['colorv2', 'physics'],
'[-]': ['color', 'bracket']
}
}
};
tex: {packages: {}}
が設定するのはTeXのタイプセット処理にどのライブラリを用いるかのみであり,アクセシビリティのライブラリはそれとは無関係なので,loader: {load: []}
の中に記載するだけでおk.
その他
-
startup
- 先にある通り,srcの先のurlの末尾を
startup
にすると,loader: {load: []}
で指定したライブラリを決め打ちでロードできる - 同時にライブラリとしても存在し,
loader
を動かしてロードさせた後にタイプセットまでを行う - オプションでロードやタイプセットに関する挙動を制御できる
- 先にある通り,srcの先のurlの末尾を
-
ui/safe
- ユーザーがWebページ上に入力する際に,変なコードが紛れて走らないように防御できる
- 基本的にhtmlコードに関してであり,オプションで制限する内容をカスタマイズできる
-
ui/menu
- 数式を右クリックすると出現するメニューを追加する
- 先のアクセシビリティの注意書きには「機能が被っているので別々に読み込まなくても良い」って書いてる
- つまりアクセシビリティを突っ込んだからコレと同じものが勝手に読み込まれるらしい
- ただしコレ単体でもソースコードを表示したり拡大縮小したりchtmlとsvgを切り替えたりはできる
- あと「自動で折り畳まれる機能は
v3.x.y
にはまだない」って書いてある - オプションで表示や機能の設定をカスタマイズできる
-
adaptors/liteDOM
- ブラウザのDOMに対して直接のアクセスができないもの(nodeのアプリとか)でMathJaxのタイプセット等を実行するために,ブラウザのDOMの代替品を実装させる
- …というものらしいが使ったことがない
-
core
- その他の機能の全てを含む,基本的には勝手に操作されるので弄らなくてもいい
-
loader
-
startup
が自動で持ってくるライブラリで,追加のライブラリをロードする - オプションでロードするライブラリの中身やロードの設定をカスタマイズできる
-
loader: {load: []}
はその内の1つ
-
-
loader
のオプション
オプション自体はこ↑こ↓が公式ドキュメント,機能の一覧を見ると割と使いそうなものも…?
MathJax = {
loader: {
paths: {mathjax: Loader.getRoot()}, // the path prefixes for use in specifying components
source: {}, // the URLs for components, when defaults aren't right
dependencies: {}, // arrays of dependencies for each component
provides: {}, // components provided by each component
load: [], // array of components to load
ready: Loader.defaultReady.bind(Loader), // function to call when everything is loaded
failed: function (error) { // function to call if a component fails to load
console.log(`MathJax(${error.package || '?'}): ${error.message}`);
},
require: null // function to use for loading components
}
};
loader: {load: []}
今まで何度も出たしもういいよね…
loader: {paths: {}}
[xxx]/yyy
ってなんだ?
loader: {paths: {}}
が関係する,例えばxxx
のソースのurlが
MathJax = {
loader: {
paths: {xxx: 'https://example.com/xxx'},
}
};
と定義されれば,その下のyyy
を
MathJax = {
loader: {
load: ['[xxx]/yyy']
}
};
でロードできる,更に数珠つなぎにしてしまえば
MathJax = {
loader: {
paths: {
xxx: 'https://example.com/xxx',
yyy: '[xxx]/yyy'
},
load: ['[yyy]/zzz']
}
};
となる,すなわちTeX系のライブラリにおいては
MathJax = {
loader: {
paths: {
tex: '何かしらのurl',
},
load: ['[tex]/何かしらのライブラリ']
}
};
みたいな構造になっていると推測される.
ちなみにさっきの最小構成においてloader: {load: []}
を以下のように改変すると…
MathJax = {
loader: {load: ['input/tex-base', 'output/svg', 'tex']},
tex: {
packages: {
'[+]': ['base']
}
}
};
↓
MathJax = {
loader: {load: ['input/tex-base', 'output/svg', '[tex]']},
tex: {
packages: {
'[+]': ['base']
}
}
};
↓
要するに最終的に末端で確実にファイルが手に入るようなurlにならないとCDNに突き返される,こんな横着みたいな一括ロードはできないそりゃそうじゃ
更に,
MathJax = {
loader: {load: ['input/tex-base', 'output/svg', '[tex]/boldsymbol.js']},
tex: {
packages: {
'[+]': ['base', 'boldsymbol']
}
}
};
↓
MathJax = {
loader: {load: ['input/tex-base', 'output/svg', '[tex]/boldsymbol.js']},
tex: {
packages: {
'[+]': ['base', 'boldsymbol.js']
}
}
};
↓
tex: {packages: {}}
にはちゃんとライブラリの名前を表記しなきゃいけない割にはloader: {load: []}
はurlの体を成してさえいればおkらしい…
loader: {source: {}}
xxx/yyy
ってなんだ?
絶対urlを設置できるloader: {source: {}}
が関係する,例えば
MathJax = {
loader: {
source: {
'xxx/yyy': 'https://example.com/xxx/yyy.js'
},
load: ['xxx/yyy']
}
};
となる,すなわちアクセシビリティ系のライブラリにおいては
MathJax = {
loader: {
source: {
'何かしらのライブラリ': '何かしらのurl',
},
load: ['何かしらのライブラリ']
}
};
みたいな構造になっていると推測される.
見ての通りで1対1構造の決め打ち方式であり,loader: {paths: {}}
のような拡張性はない.
dependencies: {}
とprovides: {}
dependencies: {}
はライブラリ間の依存関係を記憶するリストであり,startup
はload: []'
の依頼に基づきdependencies: {}
を使って必要な(ロードするべき)ライブラリを考えprovides: {}
に列挙していく.
すなわち最終的にロードされるライブラリの実態はprovides: {}
に現れる,先に述べたurlとライブラリの対応関係はこれで実現されているとも言える,ドキュメントにも
loader: {
provides: {
'input/tex': [
'input/tex-base',
'[tex]/ams',
'[tex]/newcommand',
'[tex]/noundefined',
'[tex]/require',
'[tex]/autoload',
'[tex]/configmacros'
]
}
}
みたいな例が載っているし多分そう.
また基本的なライブラリであればdependencies: {}
は既に完全に整備されている.
そもそも普通にMathJaxを使うだけなら(コピー品や独自品を自前のサーバーから配信したいとか出ない限り),loader
にわざわざ手を加える場所は何もなさそうだけど…
その他のオプション
投げられる関数だったりエラーの処理だったり色々とあるけど,もういいよね…
startup
のオプション
オプション自体はこ↑こ↓が公式ドキュメント,ロードとタイプセットの挙動を弄るのはもう完全に動的なサービスを作りたい人くらいだと思うので,パスさせていただきますね…
それにタイプセット自体のお話はまた後述…