Help us understand the problem. What is going on with this article?

R MarkdownでKatexを使って数式表示

More than 3 years have passed since last update.

タイトルのまんまです。気が向いたのでやってみた。

Katexとは

Katexとはtexライクな数式コードをブラウザ上でレンダリングするためのJavaScriptライブラリです。同様のJavaScriptとしてはmathjaxが筆頭としてよく利用されており,R Markdownでも標準でmathjaxを利用するようになっています。

ただ最近「mathjaxよりKatexを使わないかい?」という意見を見るようになり,選択肢が多いほうがいいと思い実装してみました。

実装

まず以下のようなhtmlファイルを準備します:

include_katex.html
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.css" integrity="sha384-wITovz90syo1dJWVh32uuETPVEtGigN07tkttEqPv+uR2SE/mbQcG7ATL28aI9H0" crossorigin="anonymous">
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.js" integrity="sha384-/y1Nn9+QQAipbNQWU65krzJralCnuOasHncUFXGkdwntGeSvQicrYkiUBwsgUqc1" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/contrib/auto-render.min.js" integrity="sha384-dq1/gEHSxPZQ7DdrM82ID4YVol9BYyU7GbWlIwnwyPzotpoc57wDw/guX8EaYGPx" crossorigin="anonymous"></script>
<script>
  document.addEventListener("DOMContentLoaded", function() {
    renderMathInElement(document.body, {delimiters: [
      {left: "$$", right: "$$", display: true},
      {left: "$", right: "$", display: false}]
    });
  });
</script>

これをRmdのyaml-front-matter(冒頭のyaml部分)でin_headerにて読みこむように指定します:

---
title: "R MarkdownでKatexを使って数式表示"
output:
  html_document:
    includes:
      in_header: include_katex.html
    mathjax: NULL
    self_contained: false
---

以下テスト。

$$
f(x)= \sum_{k=0}^{\infty} \frac{ f^{(k)}(x_0)}{n!} \left( x-x_0 \right)^k 
$$

文中の数式$y = f(x)$のテスト。

これでOKです。以下のような感じになります:

3453333.png

解説

mathjaxの解除

katexを使うのでmathjaxを解除する必要があります。これは上述の例のようにyaml-front-matterでmathjax: NULLとすればOKです。

Katexの読み込み

要するにkatex.min.jskatex.min.cssのファイル,及びauto-renderのためのauto-render.min.jsをheadに読み込むような<script>タグを仕込めばいいだけです。これについては公式サイトを参照してもらえればと:

CDNへのパスについては,必ず公式サイトをチェックしてから,必要に応じて変更してください

Katexの設定

色々設定ポイントがあるのですが,詳しくは上記公式サイトを参照してください。今回はmathjaxからの移行とR Markdownでの利便性を考え,以下のように設定しました:

document.addEventListener("DOMContentLoaded", function() {
  renderMathInElement(document.body, {delimiters: [
    {left: "$$", right: "$$", display: true},
    {left: "$", right: "$", display: false}]
  });
});

これで$$で挟んだものはブロック要素として,$で挟んだものはインライン要素(行内)でレンダリングされるようになります。これについては以下のサイトを参考にさせていただきました:

留意事項

地雷というか気になる点がいくつかありました。

self_containedについて

上記例ではself_contained: falseと指定しています。つまりhtmlファイル内にbase64-encしないようにしてます。この場合オンラインでないと表示されません。ですがCDNで読み込むようにしているので速度は(回線が貧弱でなければ)十分でしょう。

なおself_contained: trueでも動作しますが,正直オススメしません。理由は以下の2点です:

rmarkdown::renderにかなり時間がかかる

katexをまるっとDLしてbase64encして差し込むので,その変換の分時間がかなりかかります。またファイルサイズがかなり大きくなります。これだとkatexを利用するメリットほぼなし,です。

CDN読み込みの<script>および<link>タグ内属性について

検証中に気付いたのですが,self_contained: trueにするなら以下のようにしないとうまく表示されませんでした:

  • CDNから読み込む(今回の)<script>タグ内属性はsrc属性のみ
  • CDNから読み込む(今回の)<link>タグ内属性はrel属性とhref属性のみ

公式サイトでは,CDNとの整合性チェックのためIntegrity属性を指定したコードが表示されています。これはセキュリティ上大切だと思うし,そうすべきだと思います。でもそれが入っているとどうも動作しません…。ダメダメです。

RStudio DesktopとRStudio Serverの違い

環境にもよるかもしれませんが,手元(Ubuntu)で検証したところViewerでの表示速度に大きな差がでます。おそらくRStudioに組み込まれているブラウザの問題で,Desktop版だとものすごく遅くなります(ビジーになる)。なおRStudio Serverでrenderすると瞬時に表示されます。「katex速い」が実感できるはずです。てことでできるだけRStudio Server版でやりましょう

Katexとmathjaxは完全互換ではない

大体のことは大丈夫なのですが,多少違います。この辺りは省略しますので,ご自身で調べてみてください。

結論

こうなりました:

  • in_headerでスクリプトを読み込ませる
  • self_contained: falseを超推奨
  • RStudio Server環境を推奨

これらが揃えば,きっとmathjaxにはない数式レンダリング速度を体験できるでしょう。

Enjoy!

kazutan
ただの残念なぞうさんです。同名のTwitterアカウントでほそぼそと。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away