エフアンダーバー

個人開発の記録

はてなブログで数式(Markdown)

前回の記事を書くにあたり、 はてなブログでの数式の書き方を調べたのですが、どうにも納得のいく方法が見つからなかったのでいろいろ試してみました。

はてな記法で数式

そもそも、はてなブログにはもとからLaTeXの数式を書く機能があります。

[tex: (LaTexの数式)]

内部的にはMathJaxというライブラリを用いているらしく、 少し表示に時間はかかりますが、HTMLとしても正しい数式を出力してくれる優れものです。

しかし、このはてな記法はMarkdownと組み合わせると、どうにもうまく動かないのです。

Markdownと数式

はてなブログにはいくつかの編集モードがありますが、 そのうちMarkdownモードは他のツールでも多く採用されている記法であり、 特にプログラマな方々にはお馴染みかと思います。

しかし、Markdownモードではてな記法の数式を書くと正しく表示されないケースがあることが知られています。
ここがわかりやすくまとまっているので引用させていただくと、

  • 指数が表示されない
  • 2回繰り返すと表示されない
  • 中括弧{}、大括弧[]が表示されない
  • 等号揃えができない

・・・思いっきり、数式がMarkdownとして解釈されてますね。

  • 指数が表示されない → ^ が上付き文字と解釈されて<sup>タグに
  • 2回繰り返すと表示されない → _ で挟まれた文字が強調と解釈されて<em>タグに
  • 中括弧{}、大括弧[]が表示されない → \ が1つだとMarkdownのエスケープとみなされて消去
  • 等号揃えができない → & が &amp; にHTMLエンコード

さらには内部に変なタグが入ると、はてな記法とすらみなされないのか、texがキーワードリンクされる始末。

なんでだよ!!とツッコミを入れたくなるような仕様ですが、そうなっているものは仕方ない。 この制限のもとで如何に楽に書くかを考えます。

<pre>タグと<div>タグ

この話題で調べて出てきた解決策はおおまかに四つ。

  • Markdown以外の編集モードを使う
  • 自分でMathJaxを入れてそれを使う
  • しっかりとエスケープする
  • <pre>タグで数式を囲む

このうち、自分の感覚で一番楽そうなのはこちらで紹介されている<pre>タグを使う方法。

<pre>[tex: y = a^x]</pre>

ただし、元記事でも述べられているようにこの方法にはいくつか欠点があります。 ひとつは、<pre>タグにデフォルトで枠や背景といったプロパティが設定されている可能性があること。 そして致命的なもうひとつは、```*1を<pre>タグ以降で使用するとtexがなぜかキーワードリンクされ、 はてな記法とみなされなくなってしまうことです。

ここで、そもそもなぜ数式の表示がうまくいかなかったのかを考えてみます。 表示がおかしい原因は数式がMarkdownとして解釈されていたことでした。 それならば、数式部分がMarkdownと解釈されないのであれば、<pre>タグでなくてもうまくいく可能性があります。

というわけで、この手の状況にもっとも適している<div>タグで試してみます。

<div>[tex: y = a^x]</div>
 y = a^x

表示されました!!

<div>タグなのでデフォルトでプロパティが設定されていることもありませんし、 エスケープやHTMLエンコードは無効でも解析はされる<pre>タグと違い、<div>タグ内は解析すらされないようでキーワードリンクもされません *2

というわけで、ここからはこの<div>タグをベースに実際にどう書いていくべきかを考えていきます。

ブロック要素としての数式

<div>タグ自体がブロック要素なので、ブロック要素としての数式は簡単です。

<div style="margin-left: 2em">
[tex: \displaystyle
  \sum_{n=0}^{\infty} \frac{f^{(n)}(a)}{n!} (x-a)^{n}
]
</div>
 \displaystyle
  \sum_{n=0}^{\infty} \cfrac{f^{(n)}(a)}{n!} (x-a)^{n}

余白の設定等はお好みで。

\displaystyleはディスプレイスタイルで表示するためのTeXのコマンドです。 通常、TeXで文書を書く場合にはコンテキストに応じて自動設定されるらしいのですが、 はてなブログではコンテキストがわからないので明示的に指定する必要があります。 ブロック要素としてはディスプレイスタイルが適当なので、 この形で覚えてしまうのがいいと思います。

ちなみに外すとこうなります(多分テキストスタイル)。


  \sum_{n=0}^{\infty} \cfrac{f^{(n)}(a)}{n!} (x-a)^{n}

インライン要素としての数式

結論から言うと、インライン要素としての数式はあまりいい方法が思いつきませんでした。

<div>タグでブロック要素ができるのだから、 <span>タグでインライン要素ができるかというとそうではありません。 <span>タグでは囲った部分が依然としてMarkdownとして解釈されてしまうためです。

ならば、と書いてみたのが以下のコード。

<div style="display: inline">[tex: y = a^x]</div>
 y = a^x

<div>をインライン要素として扱うように設定しています。 一見、うまく動作しているようにも見えますが、 前後に文字を入れると儚くも崩れ去ります。

前のテキスト<div style="display: inline">[tex: y = a^x]</div>後のテキスト

前のテキスト

[tex: y = ax]
後のテキスト

おかしな場所に改行が入った上に、数式もまともに表示されていません。

HTMLを見てみると以下のようになっています。

...
<p>前のテキスト</p>
<div style="display: inline">
  [<a class="keyword" href="(略)">tex</a>: y = a<sup>x</sup>]
</div>
後のテキスト
<p></p>
...

これはひどい・・・

そもそも<div>タグが文章中に入ってくることが想定されていないようで、段落の解析が完全に壊れています。 そして、単独で書いた場合にはMarkdownと解釈されなかった<div>タグ内にも解析が入り、 ^が<sup>タグに置き換えられたことで数式が崩壊しています。 ちなみに改行されているように見えたのは、ブロック要素である<p>タグの終端タグが挿入されたためのようです。

Webに明るくない私としてはこれ以上の手が思いつかないので、 ここからはうまく妥協しつつなんとか記述できないかと考えてみます。

段落すべてに責任を持つ

<div>タグは単独で書いた場合には内部を解析されることがないようです。 そこで、考えられるひとつめの手段として、 数式を含む段落についてはすべて自分で書くという方法があります。

つまり、こういうことです。

<div style="display: inline">
  <p>
   ベクトル [tex: v = \[ \: v_x \; v_y \; v_z \: \]^{T}] に対して・・・
  </p>
</div>

ベクトル  v = [ \: v_x \; v_y \; v_z \: ]^{T} に対して・・・

ブロック要素の数式の合間に挟むような単文の段落などの場合には、 Markdownの恩恵よりも数式を手軽に書ける恩恵のほうが大きいためこの方法がいいと思います。

全力でエスケープする

ふたつめの手段は普通にはてな記法で数式を書いて、 問題になりそうな文字を頑張ってエスケープすることです。

注意すべきなのは文字によって必要な\(バックスラッシュ)の数が違うことです。 Markdownでのみエスケープすべき文字は1つ、 LaTeXでのみエスケープすべき文字とLaTeXのコマンドは2つ、 両方でエスケープすべき文字は3つ、 バックスラッシュ自体を表示したいときには4つのバックスラッシュが必要です。

ベクトル [tex: v = \\\[ \\: v\_x \\; v\_y \\; v\_z \\: \\\]\^\{T\}] に対して・・・

ベクトル  v = [ \: v_x \; v_y \; v_z \: ]^{T} に対して・・・

\\mboxコマンド → [tex: x \\quad : \\mbox\{数式中に文字を書くには\\\\mboxコマンド\}]

\mboxコマンド →  x \quad : \mbox{数式中に文字を書くには\\mboxコマンド}

長い文章の中で  x_i のように変数を書く必要がある場合にはこちらの方が手軽でいいと思います。

ただし、&や<,>などHTMLエンコードされてしまうものに対しては使えないので注意。

まとめ

ブロック要素

<div style="padding-left: 2em">
[tex: \displaystyle
  P(t) =
    \begin{bmatrix} 1 & t & t^2 & t^3 \end{bmatrix}
    \begin{bmatrix}
       1 &  0 &  0 &  0 \\
      -3 &  3 &  0 &  0 \\
       3 & -6 &  3 &  0 \\
      -1 &  3 & -3 &  1
    \end{bmatrix}
    \begin{bmatrix} P_0 \\ P_1 \\ P_2 \\ P_3 \end{bmatrix}
]
</div>
 \displaystyle
  P(t) =
    \begin{bmatrix} 1 & t & t^2 & t^3 \end{bmatrix}
    \begin{bmatrix}
       1 &  0 &  0 &  0 \\
      -3 &  3 &  0 &  0 \\
       3 & -6 &  3 &  0 \\
      -1 &  3 & -3 &  1
    \end{bmatrix}
    \begin{bmatrix} P_0 \\ P_1 \\ P_2 \\ P_3 \end{bmatrix}

複雑な数式を含むインライン要素

<div style="display: inline">
  <p>
    オイラーの公式 [tex: e^{i\theta} = \cos\theta + i\sin\theta] より・・・
  </p>
</div>

オイラーの公式  e^{i\theta} = \cos\theta + i\sin\theta より・・・

単純な数式や変数・関数のみのインライン要素

変数 [tex: x\_0, \\ldots, x\_n] について・・・

変数  x_0, \ldots, x_n について・・・

おわりに

結局、なんとなくは書けるようになりましたが、すごく便利といえるほどの方法も見つかりませんでした。 CSSとかJavaScriptとかの知識がもっとあれば、 もう少しどうにかなったのかもしれませんがそのへんは他の人に任せます。

というかこの記事、はてなブログ側が少し変換処理を書きなおせばまったく必要ない話なんですよね。 そこそこ頑張って記事書いただけに数か月後とかに試してみたら直ってそうで怖い・・・

*1:正確にはdata-unlink属性のついた<pre>タグっぽい

*2:はてな記法が解釈されている以上なんらかの解析はされてるか・・・