Github Pages で数式を ～ MathJax v3 設定のポイント

# はじめに

Github Pages で数式を使うには MathJax を組み込めばよいですが、できるだけ簡単に設定してみます。MathJax version 2 と、つい最近リリースされた MathJax version 3 を使ってみます。

なお、version 3 を使うにはすこし[コツ](https://qiita.com/memakura/items/e4d2de379f98ad7be498#%E8%A3%9C%E8%B6%B3-%E3%83%90%E3%83%BC%E3%82%B8%E3%83%A7%E3%83%B33%E3%81%A7%E3%81%AE-renderactions-%E3%81%AE%E6%8C%87%E5%AE%9A%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)が必要です。最後にその補足をします。


ここでは以下のように「Github Pages のもろもろの設定は Github におまかせにしている」ことを想定します。

- Github リポジトリの Settings > Github Pages > Source の None を master branch に変えただけ
    - テーマは、リポジトリの Settings で設定したか，もしくはデフォルトのまま
    - テーマのリポジトリを fork/clone して独自にカスタマイズしたりはしていない
- 各MarkdownファイルにはYAMLフロントマター（冒頭に --- で挟んで入れる設定情報）を書いていない

もちろん一番単純には、数式を使いたいMarkdownファイルに

```js:version2
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.6/MathJax.js?config=TeX-AMS_CHTML"></script>
```

もしくは

```js:version3
<script async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js" id="MathJax-script"></script>
```

を埋め込んでおけばよいだけですが、行内 (inline) で`$...$`を使うなど、MathJaxのオプション設定もいろいろしたいので、それぞれのMarkdownファイルにべた書きするのは（特に数式を使いたい Markdownファイルが複数あるのであれば）手間です。

そこで以下の手順で設定します。

## 手順のまとめ

1. MathJax読み込みとオプション設定をまとめた htmlファイルを  _includes/ に用意
2. 使用中のテーマの _layouts/default.html を[そのテーマのリポジトリ](https://github.com/pages-themes/)からコピーし、1 を読み込むように編集

必ずしも default.html である必要はないですが、どのテーマにもこれはあるはずなので、以下では default.html をカスタマイズすることにします。


## まとめのサンプル

- [Github 上のリポジトリ（デフォルトテーマ）](https://github.com/memakura/mathjax-test)
- [上記リポジトリの Github Pages](https://memakura.github.io/mathjax-test/)

以下、詳しく見ていきます。

# 1. MathJax の読み込みとオプション設定をまとめておく

リポジトリに `_includes/` というフォルダを作り、そこに MathJax の読み込みとオプション設定をまとめて htmlファイルとして保存しておきます。



## バージョン2

バージョン2 用には以下のような `mathjax-v2.html` を用意します（設定内容はあくまで例です）。

```html:mathjax-v2.html
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    tex2jax: {
      inlineMath: [['$','$'], ['\\(','\\)']],
      processEscapes: true
    },
    CommonHTML: { matchFontHeight: false },
    displayAlign: "left",
    displayIndent: "2em",
    TeX: {
      equationNumbers: { autoNumber: "AMS" },
    }
  });
</script>
<script async src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.6/MathJax.js?config=TeX-AMS_CHTML"></script>

```

## バージョン3

続いてバージョン3ですが、こちらは以下のような `mathjax-v3.html` を用意します。MathJax v3 のオプション設定は、バージョン2から大幅に変わりましたが、[こちらに変換ツール](https://mathjax.github.io/MathJax-demos-web/convert-configuration/convert-configuration.html)が用意されています。あとはドキュメントを読む感じでしょうか。

- http://docs.mathjax.org/en/latest/web/configuration.html#converting-your-v2-configuration-to-v3
- https://github.com/mathjax/MathJax-demos-web#converting-from-version-2

以下は自動生成された設定スクリプトを、さらに改変したものです。

```html:mathjax-v3.html
<script>
    MathJax = {
      tex: {
        inlineMath: [['$','$'], ['\\(','\\)']],
        processEscapes: true,
        tags: "ams",
        autoload: {
          color: [],
          colorV2: ['color']
        },
        packages: {'[+]': ['noerrors']}
      },
      chtml: {
        matchFontHeight: false,
        displayAlign: "left",
        displayIndent: "2em"
      },
      options: {
        renderActions: {
          /* add a new named action to render <script type="math/tex"> */
          find_script_mathtex: [10, function (doc) {
            for (const node of document.querySelectorAll('script[type^="math/tex"]')) {
              const display = !!node.type.match(/; *mode=display/);
              const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display);
              const text = document.createTextNode('');
              node.parentNode.replaceChild(text, node);
              math.start = {node: text, delim: '', n: 0};
              math.end = {node: text, delim: '', n: 0};
              doc.math.push(math);
            }
          }, '']
        }
      },
      loader: {
        load: ['[tex]/noerrors']
      }
    };
</script>
<script async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js" id="MathJax-script"></script>
```

MathJax の読み込み時に `async` を入れました。`ignoreHtmlClass` や `processHtmlClass` もデフォルト値なので削除。`options` の `renderActions` が非常に重要ですが、これは後で説明します。

それぞれのオプションの意味は、以下のページに詳細な説明があります。

- `tex`（入力関係）: http://docs.mathjax.org/en/latest/options/input/tex.html
- `chtml`（出力関係）: http://docs.mathjax.org/en/latest/options/output/chtml.html
- `options`（解析処理関係）: http://docs.mathjax.org/en/latest/options/document.html
- `loader`（コンポーネント読み込み関係）: http://docs.mathjax.org/en/latest/options/startup/loader.html
- その他ここにはないものもいろいろあります（[ドキュメント](http://docs.mathjax.org/en/latest/options/index.html)を参照してください）。


# 2. _includesに用意したhtmlを読み込むよう設定する

Github のヘルプにある[「Customizing your theme's HTML layout」](https://help.github.com/en/articles/adding-a-theme-to-your-github-pages-site-using-jekyll#customizing-your-themes-html-layout)を参考に、_layouts/default.html だけ自前のリポジトリに用意して[オーバライド](https://jekyllrb.com/docs/themes/#overriding-theme-defaults)します。

1. 使用している Github Pages のテーマを確認する。
2. 以下のページから使用テーマに対応するリポジトリを見つける。
    - https://github.com/pages-themes/ （デフォルトのテーマは `primer`）
3. 2のリポジトリをたどって `_layouts/default.html` をコピーする（rawで表示するとコピーしやすい）。
4. 自分のリポジトリに `_layouts/default.html` を新規作成し、3の内容を貼り付ける。
5. 4 で作成した default.html の `<head>...</head>` の中に `{% include mathjax-v3.html %}` を追加する。（バージョン2ならば `mathjax-v2.html`を指定）

   ```html:default.html
   ...
       {% include mathjax-v3.html %}
   </head>
   ...
   ```

あとは適当に数式を書いたMarkdownファイルを用意しておき，push すると（少し待てば）数式が表示されるようになります。


# 補足: バージョン3での renderActions の指定について

options に renderActions を指定しています。これがないと、`$$...$$` で囲った数式が表示されません。理由は次の通りです。

- MathJax バージョン2 では、いったんプリプロセッサが、ドキュメント内の数式を `<script type="math/tex">数式</script>` のような中間表現に置き換え、次の段階でその中身を処理していた。
    - Markdown や Wiki などの MathJax 外部の各種自動変換プログラムでも、`<script type="math/tex">` を直接出力することが推奨されていた。
        - https://docs.mathjax.org/en/v2.7-latest/advanced/model.html#how-mathematics-is-stored-in-the-page
    - そういう理由もあってか、Jekyll (Kramdown) も、MathJax の変換に先立って  `$$...$$` を `<script type="math/tex; mode=display">...</script>` に変換していた。
- しかし、バージョン3は処理方法ががらっと変わって `<script type="math/tex">` の中間表現は使われなくなった。結果、元から中間表現で挟まれている数式が処理対象外に！（そういう仕様とのことでした）
    - https://github.com/mathjax/MathJax/issues/2220
- したがって、少なくとも現時点では、明示的に `script type="math/tex"` も処理対象であることを指定する必要がある。
    - http://docs.mathjax.org/en/latest/upgrading/v2.html#changes-in-the-mathjax-api （この最後の項目）
    - http://docs.mathjax.org/en/latest/options/document.html#document-renderactions
    - もちろん `\\[...\\]` だけを使うという選択肢もあり。この場合は `renderActions` の設定は不要。


`<script type="math/tex">` の形式を出力するプログラムは他にもあるだろうから、今後もう少し簡単に設定できるようになることを期待・・・