これは「Markdown Advent Caleandar 2020」の12日目の記事です。
gfm spec のドキュメント、Version 0.28-gfm (2017-08-01) って書いてある割には 0.28 以降の (2018年以降の) CommonMark の修正も取り込んであるし、記述に矛盾があるし、https://t.co/2xhuSngbJK とも動作が違うし、本当に信頼できないものだという思いを強めております。
— tk0miya (@tk0miya) March 27, 2019
どうやら、某Markdownソムリエ氏の情報によると、GitHub Flavored Markdown(GFM)の仕様には**「矛盾」が含まれている**ようです。
GFMが矛盾しているかもしれない話
GFMに潜む「矛盾」については、以下のQiita記事で詳しく論じられています。それによると、「自動リンク」に関する規定に問題があるとのことです。
- GitHub Flavored Markdown は何であって何でないか(Qiita/tk0miya)
GFMの「自動リンク」が矛盾しているかもしれない
CommonMarkとGFMの規格では、「自動リンク(autolink)」の規定について次のような差異があります。
- 段落に
http://example.com
のような“単独のURL”だけが書かれている場合、CommonMarkではそれは自動リンクにはならない。 - しかし、GFMでは“単独のURL”の記述も
http://
で始まる場合は自動リンクになる。
この差異は「細かい機能追加」といえるものであり、それ自体は特に問題になるものではありません1。問題になっているのは、この規定に関する、GFMの規格の記述です。
- 6.8節“Autolinks”はCommonMarkの規格の6.7節を変更なしにそのまま引き写している。そしてそこでは“単独のURL”は自動リンクにならないことが明記されている。
-
6.9節“Autolinks (extension)”はGFM規格で独自に追加された節で、そこでは
http://
で始まる“単独のURL”が自動リンクになると規定されている。
つまり、独自追加の節がどれかは読者には明示的に示されているものの、6.8節と6.9節は**「同列で並んでいる」ため、結局のところ、「単一の規格の中で矛盾した記述が併存する」事態になってしまうわけです。これを受けて、某ソムリエ氏は次のように述べて、これが「矛盾」である**と指摘しています。
順序や成り立ちを考えると、前者の仕様は破棄され GFM としては後者の仕様を採用したという理解となるのですが、仕様書の中で矛盾が起きているのは非常に厄介です。
GFMの「自動リンク」が矛盾していないかもしれない
この議論は一見して妥当そうです。しかし、私が実際にGFMの規格の6.9節を読んでみると、割と印象が異なるように感じました。
GFM enables the
autolink
extension, where autolinks will be recognised in a greater number of conditions.
(GFMではautolink
拡張が有効である。そこでは、より広い条件に当てはまるものが自動リンクと見なされる。)
つまり、本文において明確に「この節の内容は“autolink拡張”の規定である」と述べています。つまり、GFMにおいて「拡張(extension)」という概念は参考情報(informative)ではなく規定の一部をなす(normative)であると解釈すべきでしょう。そう考えると、6.8節の内容は「GFMの“基礎”の規定」であり、6.9節の内容は「GFMの“autolink拡張”の規定」である、ということになり、両者は**「同列に並んでいる」とはいえず**、従って、必ずしも矛盾しているとはいえないことになります。
もちろん「“基礎”と“拡張”の規定の関係性についての規定が不明瞭」という問題はあるのですが、そもそも**「GFMの規定は『かっちりして』いない」**(これは異論のないところでしょう)わけなので、不明瞭であるからといって「だから同列であると見なされるので、矛盾がある」と結論づけるのはやはり無理があると思いました。
GFMがやっぱり矛盾している話
というわけで、GFMの「自動リンク」の規定に矛盾があるかどうかは怪しい、ということになってしまいました。GFMは矛盾していないのでしょうか?
「GFM specの内部の矛盾」を見つけた。でも、「Markdown アドベントカレンダー」のネタとしてとっておくことにしよう🙃🙃🙃#markdown #gfm
— 某ZR(ざんねん🙃) (@zr_tex8r) November 7, 2020
どうやら某ZR氏(非Markdownソムリエ)によると、GFMの「打消しテキスト」の規定に矛盾があるらしいです。
GFMの「打消しテキスト」が矛盾しているはず
GFMの「打消しテキスト(strikethrough text)」の機能は、strikethrough
というextensionとして規定されています。規定のある個所は6.5節“Strikethrough (extension)”です。
GFM enables the strikethrough extension, where an additional emphasis type is available.
(GFMではstrikethrough
拡張が有効である。そこでは、新たなタイプの強調記法が使える。)Strikethrough text is any text wrapped in two tildes (
~
).
(打消しテキストは、2つのチルダで囲われた任意のテキストである。)
本文はこれだけです(この後に例が続く)。ぱっと見て気になる点は、「優先順位に関する記述がない」ということです。ここでいう「優先順位」というのは、例えば次の例のように「複数の種類のマークアップが互いに干渉する状態にあるときにどれを有効とするのか」という規定を指します。
Here is a ~~strike *emph through~~ asis* text.
もしここで打ち消しテキスト~~…~~
と強調*…*
の両方を有効と見なすと、これをHTMLで表したときに次のようになってしまいます。
<p>Here is a <s>strike <em>emph through</s> asis</em> text.
しかしHTMLではこのような「2つの要素が部分的に重なっている状態」は認められていません。
例によって、「かっちりしている」CommonMarkにおいては、互いに干渉する可能性のあるインライン要素について、明確に優先順位が規定されています。例えば、CommonMarkにおける強調の規定(6.4節“Emphasis and strong emphasis”)では次のように書かれていて「リンク記法と干渉する場合には*…*
は強調にならない」ことが明確に規定されています。
Inline code spans, links, images, and HTML tags group more tightly than emphasis.
So, when there is a choice between an interpretation that contains one of these elements and one that does not, the former always wins.
Thus, for example,*[foo*](bar)
is parsed as*<a href="bar">foo*</a>
rather than as<em>[foo</em>](bar)
.
GFMの「打ち消しテキスト」に優先順位が決められていないのは、ある意味「GFMらしい」わけですが、この件については単に「かっちりしていない」だけでなく、もっと重大な結果を引き起こします。なぜなら、「優先順位がない」ということは即ち「strikethrough
拡張機能が『打消しテキスト』以外の規定に対して変更を加えるための根拠をもたない」ことを意味するからです。
もう一度、先に挙げた「干渉している例」がどう解釈されるべきかを考えてみましょう。
Here is a ~~strike *emph through~~ asis* text.
- 6.4節“Emphasis and strong emphasis”はCommonMarkの規格の6.4節を変更なしにそのまま引き写している。先述の通り、この節の解釈が変更される根拠はこの節の外にも存在しない。ということは、CommonMarkで強調と解釈される記述はGFMでも必ず強調と解釈される。
- 従って、先の例の
*emph through~~ asis*
は強調である。 - 一方で、6.5節では、「2つのチルダで囲われた任意のテキスト」が打消しテキストと解釈されると規定している。
- 従って、先の例の
~~strike *emph through~~
は打消しテキストである。
結局、優先順位がないために、「HTMLとして不正な構造」になってしまうのを避けられません。
一方で、GFMの規格の1.4節(CommonMark規格の1.3節の引き写し)では「この規格文書ではMarkdown文書の構造をHTMLで表現する」としていて、ここでは「Markdownの文書の構造はHTMLで表せる」ことが前提になっています。従って、「HTMLで表せないMarkdownのコードの存在」は矛盾であるといっていいでしょう。
まとめ
*「なんだ、結局、ソムリエ氏と同じことをやってるじゃん」
ZR「えっ」
*「だって、『かっちりしていない』GFMに対して厳密な議論を適用するのがまず無理じゃない」
ZR「えっえっ」
*「実際には何か優先順位があることになってるんじゃないの?」
ZR「えっえっえっ」
~おしまい~
-
GFM規格の6.11節にある「一部の生HTML記法の適用除外」は「機能の削除」に相当するため、「GFMはCommonMarkの厳密な上位互換である(GFM is a strict superset of CommonMark.)」と称するのは問題がありそうですが……。 ↩