Re: SphinxCon JP 2017

38度の熱が出たので、楽しみにしていた SphinxCon JP 2017 を休むことになってしまいました。
おかげで、Sphinx の魔改造の話HTML テンプレートへの提案など、興味深い発表を聞きそびれてしまったのは非常に残念です。
資料は公開されているので、それぞれ噛み締めながら何度か読み返そうと思っています。

さて、今回の SphinxCon では僕はトーク枠を持っていなかったのですが、実はイベントに合わせて作っていたものがあります。
LT でお披露目しようかと思っていたのですが、間に合わなかった上に風邪でダウンしてしまったので、代わりにここで紹介しようと思います。
作ったのは pycmark というパッケージです。
github.com

まだ README すら置いていないので、なにものかがわかりづらいのですが、docutils 向けの CommonMark パーサです*1
現状では、ひととおりの記法をサポートしているので、触ってもらえるレベルにはなったかと思います。
TAB やコントロール文字類、特殊文字類の対応が済んでいないので、もう少し開発を続けるつもりです。
もう少し進めて一段落したら、一度リリースするつもりです。

使ってみる

未リリースなので、リポジトリから直接入れます。

$ pip install git+https://github.com/tk0miya/pycmark

ちなみに Python3.x 専用です。いまのところ 3.6 でしか動作確認していません。
いまのところ遡ってサポートする気はないので、使いたい人は Python のバージョンを上げてください。

Sphinx 拡張としての作り込みはしていない*2ので、conf.py に setup 関数を書き足し、直接 pycmark を有効にします。

html_experimental_html5_writer = True


def setup(app):
    from pycmark import CommonMarkParser
    app.add_source_parser('.md', CommonMarkParser)

ついでに、HTML5 writer を有効にしておきます。標準で利用される HTML4 writer では正しく動作しません。

設定はこれで完了です。あとは .md ファイルを置いて、ビルドするだけです。

pycmark のゴール

さて、Sphinx では recommonmark が CommonMark パーサとして知られています。
それなのに、敢えて新しい CommonMark パーサを開発したのはわけがあります。

recommonmark がベースにしている CommonMark-py はコア部分がモノリシックなモジュールとして実装されています。これはシンプルで正しい設計なのですが、残念ながら拡張性がありません。
CommonMark の生まれた経緯などを考えると、パーサは拡張可能である必要はないのです。しかし、実際には gfm 然り、kibe.la 然り、新し目の Markdown の派生言語は CommonMark をベースとしています。つまり、これらのパーサを用意するには CommonMark パーサをさらに拡張する必要があります。こうしたときに CommonMark-py では都合が悪いのです。

pycmark はプラガブルな構造になっており、個々の記法を個別に無効化したり、新たな記法を追加できます。
現時点では、CommonMark の範囲の実装しか提供していませんが、いずれ gfm などのよく使われている記法のプラグインを用意する予定です。

まとめ

pycmark という CommonMark パーサを作っています。
現在の pycmark CommonMark パーサとしてはおおよそ完成しているものの、未熟なところが多くまだ使用に耐えません。
しかし、いずれは gfm などの記法も解釈できる CommonMark サブセットパーサにまで実装を進める予定です。

そこまでたどり着くと、これまでの markdown 資産が活かせ、Sphinx が使える範囲が更に広まるのではないかと考えています。

はてさて、これが夢物語で終わるのか、ちゃんと実装が完了するのかはお楽しみにお待ちください。
なお、pycmark はいつでもバグレポートと PR をお待ちしております :-)

ひとまずファーストリリースを近いうちに (年内に?) やりたいところですね。

*1:Python の CommonMark パーサだから pycmark です。いい名前が思いつかなければ、このままリリースされます。

*2:現時点では、あくまで docutils の parser モジュールとしてだけ動きます