Markdown 文書を manupulate したい。
Pythonでそのようなものを調べてみたら、 Markdown を変換して HTML にするものが一般的なようだ。そうではなくて Markdown フォーマットの文書を操作したいとなると AST 的なものを使えるようにしならなければならない。そのものずばりは無かったので、改造のベースとして使えそうなものを探してみた。
基礎知識
Markdown 文書の manupulate は大変。
例えば以下のようなコメントを文中に書くと特定のテンプレートが挿入されるというオレオレ拡張(nanbuwks拡張)を作りたいとします。
[](nanbuwks:template)
Makrdown テキストを対象に、単純に文字列検索/置換でできるかな?
- いやいやコードブロックにこの行が含まれていた場合は無視しないといけないですね。
- コードブロックの開始/終了は 「 ``` 」 ですが、 では「 ``` 」が出てきたら無視するようにしないといけないですね。
- でも「 ``` 」 が []() の中にあったら無視しないといけないですね。
- []() は埋め込みHTML中にあった場合は無視しないといけないですね・・・
など、結局markdownの文書構造をパースしてrawなテキストとしてみなせるかどうかを判定し、その上で文字列検索/置換しなければなりません。
これはオレオレ拡張に限らず、画像パスの変更、Headingのレベル変更、自動整形などをする場合も同様です。
・・・markdownの文書構造をパースするには?
一般的なパーサ
一般的には Markdown を HTMLに出力するものとなるようだ。
Markdown → トーカナイザー → 文書構造データ → レンダラー → HTMLに出力
となる。以下は想像。
トーカナイザー
こんな感じ?
- markdown には ブロックレベルとスパンレベルがある
- トークンとしてブロックトークンとスパントークンがある
- 最初に、文書全体を1ブロックとする
- 一行ずつ検査
- ブロックトークンを再帰で適合するか調べる
- 余ったテキストにスパントークンが適合するか調べる
文書構造データ
トーカナイザーで調べた文書構造を内部データに格納
文書構造データーはツリー構造となる
レンダラー
文書構造データに基づきタグをつけたり制御テキストをつけたりして文書を再構築する。
一般的にはここでHTMLにするものが多い。
求めるもの
生 Markdown を操作できるもの
文書構造データを元の Markdown のテキスト構造にひもづけて取得できれば、文書構造を参照しながら操作できますね。
でもそのものずばりは見当たりませんでした。
では既存のものに手を加えようとしてそういうものを作りたかったけれど結構手間がかかりそうなので今回は断念。
抽象データからMarkdownを作ることができるもの
文書構造データとコンテキストから、Markdown を再生成できる。けれども抽象データを元にするので元文書は完全には再現できない。それでもいいからそういったものは無いかな? → 無さそうでした。
抽象データを出力できるもの
AST的なものが得ることができるかな? コードに手を加えずに出力が得られそうなものは無さそう。
(2020/1/4追記 あとで探したら Markdown から JSONに変換するものがいくつかありました。詳細は調べていませんが要件を満たしていたかも知れません。)
抽象データからMarkdownを作れそうなもの
既存のコードに手を加えて、Markdown が出力できそうなもの。それができれば更に機能を追加するのは簡単かな?
調査
以下の要件で調査
- Python3
- HTMLだけではなく、複数の他のフォーマットにも変換できているのが望ましい。
- 今後生Markdownの操作に発展できそうなもの
Python-Markdown
https://github.com/Python-Markdown/markdown
標準的ライブラリという感じ。
プラグインが沢山ある。しかしHTML以外にコンバートするものではない感じ。例えば Markdown-LaTeX も、MarkdownにインラインMarkdown-LaTeXTEX表記のものをHTMLにコンバートするもののようだ。
求めるものと勝手が違うようなので断念。
commonmark.py
commonmarkのPythonへのポート。
commonmarkはMarkdownの標準規格的な考えで作られているもの。リファレンス実装が以下にある。
https://github.com/commonmark/commonmark.js
リファレンス的なところを重視して、応用的な方向に向いてなさそうなので諦める。
mistune
処理が高速らしい
Version2が2019/12に出ているが、2019/1/1現在、Ubuntu の pip3 では 0.8.4 がインストールされる。
最新版をインストールするために以下のようにした。
$ sudo pip3 install git+https://github.com/lepture/mistune.git
ドキュメントが不足していてあきらめる
mistletoe
mistletoe は標準で HTML以外にLaTeXへの出力がある。
- LaTeX
- JIRA
- Scheme ?
使いやすそうなのでこれを元に作ってみることにする。
調査後にわかったもの
上記4つを調べて mistletoe で作った後に出てきた良さそうなもの。
ちゃんと調べてないけどまたの機会に改めて。
pycmark
「拡張性を持っているためGFM (GitHub Flavored Markdown)の対応や独自の記法の追加など、柔軟なパースが可能です」という記述がある
https://www.papercall.io/speakers/tk0miya/speaker_talks/78833-markdown
marko
Among all implementations of Python's markdown parser, it is a common issue that user can't easily extend it to add his own features.
とある。