Edited at

Markdownから楽してフォーマット変換する方法

More than 3 years have passed since last update.

O'Reilly Atlasの簡易版みたいな仕組みで製品マニュアルを作って欲しいと言われました。

マニュアル作成にはAsciidoctorを使いたいのでAsciiDoc形式で記述することが決まったのですが、Markdown形式のほうが慣れてて楽とのことだったので、Markdown形式からAsciiDoc形式へ変換しなければならなくなりました。

pandocを使えば余裕!と思っていたのですが、意図した通りの変換ができませんでした。


調べたこと

pandocを使うならHaskellを勉強して直せばいいんだろうけども、時間がないのでPythonのMarkdownパーサーライブラリ使って変換プログラム作れないかな?と思って調べてみました。

表でまとめると以下の通り。

評価項目
Python-Markdown
Misaka
Mistune

URL
https://github.com/waylan/Python-Markdown
https://github.com/FSX/misaka
https://github.com/lepture/mistune

ライセンス
BSD
MIT
BSD

実装
python
python + C
python

対応バージョン
Python 2.7, 3.3+ and PyPy
Python 2.7, 3.2+ and PyPy 2.6
Python 2.6+, Python 3.3+ and PyPy

出力のカスタム
×

備考

Hoedownに依存

Python-Markdownは出力をカスタムできないのでパス。Misakaは枯れてて良さそうなんだけども、Hoedownに依存している点が微妙だからパス。

消去法でMistuneに決定したので、これを使って実装してみます。


簡単な使いかた


インストール

Python2.6以上で動くそうなので、2.7.11で動作確認しました。

pip install mistune

簡単ですね!


MarkdownからHTMLへ変換

以下のMarkdown形式のファイルとHTML変換用のソースを用意しました。ほぼ公式のBasic Usageに書いてある内容と一緒です。


test.md

# サンプルドキュメント

## 第XX章
### 第XXX節


convert.py

import mistune

with open('test.md', 'r') as test_file:
markdown = mistune.Markdown()
print markdown(test_file.read())


で、実行します。

python convert.py

すると、出力結果は以下のようになりました。


output

<h1>サンプルドキュメント</h1>

<h2>第XX章</h2>
<h3>第XXX節</h3>

部分的に適用されているので、HTMLの定義などは別でテンプレートを用意しておいて、Bodyの内容だけを書き換えるような感じで作れば良さそうです。


Markdownから自由な形式へ変換

さて本題です。

mistuneはRendererクラスを継承して、出力したい項目(メソッド)をオーバーライドすればよいそうです。

今回は見出しタグをAsciiDoc形式のセクションに置き換えたいので、以下のように作りました。


custom_render.py

import mistune

class CustomRenderer(mistune.Renderer):
def header(self, text, level, raw=None):
section = '=' * level
return '{0} {1}\n'.format(section, text)

if __name__ == '__main__':
custom_renderer = CustomRenderer()
with open('test.md', 'r') as test_file:
markdown = mistune.Markdown(renderer=custom_renderer)
print markdown(test_file.read())


実行します。

python custom_render.py

以下のような結果になりました。


output

= サンプルドキュメント

== 第XX章
=== 第XXX節

想定していた結果が得られました!

あとは、必要な構文からメソッドをオーバーライドしていって、出力形式を整えればフォーマット変換ができますね。