はじめに
誰もが一度はマークダウン(Markdown)の処理系の自作を考えると思います。
最近、私も例に漏れずひそかに制作に着手しました1。
普段なんとなく使っている記法でも、よくよく考えてみるとどうやって処理すればよいか、なかなか思いつかないこともあるでしょう。そんな時は、既存の処理系がマークダウンの記述をどう解釈しているか調べてみると、参考になるかもしれません。
ということで、今回は強調記法( *
とか **
で囲むやつ)のGitHubのマークダウンにおける解釈を調べてみました。
マークダウンの強調記法について
改めて書く必要はないかもしれませんが、念のため。
- 強調
-
*
で囲まれた箇所は emタグで囲まれた部分に変換されます。 - emタグで囲まれた部分はブラウザでは 斜体 で表示されます。
-
- 強い強調
-
**
で囲まれた箇所はstrongタグで囲まれた部分に変換されます。 - strongタグで囲まれた部分はブラウザでは 太字 で表示されます。
-
- em + strong
-
***
で囲まれた箇所はemタグとstrongタグの両方で囲まれた部分に変換されます。
-
GitHubのマークダウンにおける強調記法の解釈
変換前
ケース1: *a*
ケース2: **a**
ケース3: ***a***
ケース4: ***a**a*
ケース5: ***a*a**
ケース6: **a*a*
ケース7: ***a*a*a*
ケース8: ****a*a*a*a*
ケース9: *a*a*a***
ケース10: ****a**a**
ケース11: ******a**a**a**
ケース12: ********a**a**a**a**
ケース13: **a**a**a******
変換後
<p>ケース1: <em>a</em></p>
<p>ケース2: <strong>a</strong></p>
<p>ケース3: <em><strong>a</strong></em></p>
<p>ケース4: <em><strong>a</strong>a</em></p>
<p>ケース5: <strong><em>a</em>a</strong></p>
<p>ケース6: **a<em>a</em></p>
<p>ケース7: <em><em><em>a</em>a</em>a</em></p>
<p>ケース8: <em><em><em><em>a</em>a</em>a</em>a</em></p>
<p>ケース9: <em>a</em>a<em>a</em>**</p>
<p>ケース10: ****a<strong>a</strong></p>
<p>ケース11: <strong><strong><strong>a</strong>a</strong>a</strong></p>
<p>ケース12: <strong><strong><strong><strong>a</strong>a</strong>a</strong>a</strong></p>
<p>ケース13: <strong>a</strong>a<strong>a</strong>****</p>
考察
ケース1~3は通常の使い方での強調記法です。
ケース3を見ると、emタグの内側にstrongタグという順番になっています。
ケース4,5を見ると、 同じ ***
で始まるケースでも、後ろの書き方次第でemタグとstrongタグの順番が入れ替わっていることがわかります。
ケース6~8を見ると、emタグの入れ子は2重の時はうまく変換できないようです。3重、4重はうまく変換できています。
ケース9はケース7を逆順で書いたものですが、これはうまく変換できないようです。
ケース10~13はケース6~9をstrongタグが使われるように書き換えたものです。結果はemタグの時と同じでした。
処理系を困らせるような書き方はいくらでも思いつきそうですが、今日のところはこの辺にしておきましょう。
まとめ
GitHubのマークダウンの強調の解釈について挙動を調べました。
どう実装されているか知るには、ソースコードを見るのが一番の近道だと思いますが、自力でどこまでできるか試したいので、今回は挙動を調べるだけにとどめておきます。
記法をどう解釈するかや、どこまで記法に対応するかなど作者依存なことろもあるので、この調子で 私の考える最強のマークダウン処理系 を作っていこうと思います1。
ちなみに、上で示したケースをQiitaに書くと次のようになります。
GitHubと全然違いますよね。
ケース1: a
ケース2: a
ケース3: a
ケース4: aa
ケース5: aa
ケース6: **aa
ケース7: aaa
ケース8: aaaa
ケース9: aaa**
ケース10: ****aa
ケース11: aaa
ケース12: aaaa
ケース13: aaa****