DjangoやBottleでウェブアプリの開発をしていると、入力されたテキストに対してPythonでMarkdownのレンダリングをしたくなることがあります。そこで今回はmistuneというOSSのパッケージを利用して、Python側でHTMLに変換することを試してみます。
シンプルな使い方
mistuneのREADMEに書かれているサンプル通り動かすと、以下のようになります。ポイントとしては、通常のテキストの場合は段落ごとに<p>
タグで囲われており、その中で強調表示や斜体などが展開されます。リスト表記などの場合は、対応するタグで囲われるという感じです。
In [1]: import mistune
In [2]: mistune.markdown('I am using **mistune markdown parser**')
Out[2]: '<p>I am using <strong>mistune markdown parser</strong></p>\n'
In [3]: txt = """段落1
...:
...: 段落2"""
In [4]: mistune.markdown(txt)
Out[4]: '<p>段落1</p>\n<p>段落2</p>\n'
In [5]: txt = """- リスト1
...: - リスト2
...: - リスト3"""
In [6]: mistune.markdown(txt)
Out[6]: '<ul>\n<li>リスト1</li>\n<li>リスト2</li>\n<li>リスト3</li>\n</ul>\n'
またオプションとして、入力されたHTMLタグをエスケープするかどうかのescape
(デフォルトではTrue)や、空白行を入れない改行の際に<br/>
タグを含めるhard_wrap
というものがあります(デフォルトではFalse)。
自作のLexerとRenderを使う
さて、mistuneでは一通りのmarkdownの仕様に従った変換はデフォルトで提供されていますが、加えて独自の表記や記号に対してもルールを指定してHTML変換する機能もあります。
mistuneでは標準でhttp/httpsのリンク付与機能を提供していますが、他のftpやsmbなどのプロトコルには対応していません。ここでは例として、リンクに自動でaタグを付与する機能を追加してみます。
方法としては、Lexerに独自ルールの記載して、Rendererに対応する変換方法を指定するというものです。ここでは、LexerでftpやsmbのプロトコルのURLを正規表現で抜き出して、Rendererで前後に<a>
タグを付与するということをしています。
import re
from mistune import Renderer, InlineLexer
class DocumentLinkRenderer(Renderer):
def document_link(self, link):
return '<a href="{l}">{l}</a>'.format(l=link)
class DocumentLinkInlineLexer(InlineLexer):
def enable_document_link(self):
self.rules.document_link = re.compile(r'''^((https?|smb|ftp|file):\/\/[^\s<]+[^<.,:;"')\]\s])''')
self.default_rules.insert(3, 'document_link')
def output_document_link(self, m):
text = m.group(1)
return self.renderer.document_link(text)
使い方としては、mistune.Markdown()
にカスタムのRendererとInlineLexerを指定します。
renderer = DocumentLinkRenderer()
inline = DocumentLinkInlineLexer(renderer)
inline.enable_document_link()
markdown = mistune.Markdown(renderer, inline=inline)
markdown("markdown text")
実際に利用してみると、以下のようにftpのURLに対しても自動でリンクが作成されていることがわかります。
In [20]: markdown("ftp://path/to/file")
Out[20]: '<p><a href="ftp://path/to/file">ftp://path/to/file</a></p>\n'
この機能を使えば、はてなキーワードみたいに特定の単語にリンクを貼ったり、RedmineやBacklogのチケットのように記事のIDとURLの紐付けを行うことができます。