Python-Markdown Extensions

初回公開:2018/01/01
最終更新:2018/01/13

Python-MarkdownにはExtensions APIというMarkdown機能を拡張するためのAPIが用意されている。
Extensions APIを使ってプログラミングする事で独自にMarkdownの機能を追加,拡張する事ができる。

Python-Markdownには標準で利用できるExtensionsライブラリが存在する。
更にサードパーティ製のExtensionsライブラリもいろいろと...

【 目次 】

利用可能なExtensions

標準で利用できるExtensionsのドキュメント。

これらのドキュメントは英語、
勉強のため私のつたない語学力で翻訳してみた。

Python-Markdown Extra <- PHP Markdown Extra

標準のExtensionsにはPHP Markdown Extraを利用するためのPython-Markdown Extraも含まれている。

py-gfm

PHP Markdown Extraの他にもGFM(GitHub Flavored Markdown)という良く知られたmarkdownの方言が存在する。

詳しくは

サードパーティによるExtensions

py-gfm以外にもサードパーティによって提供されているExtensionsが。

Extensionsのサンプル

ここでは、 「MarkdownでHTMLを簡単に - Sublime Tex 編 」で述べた,- Table of Contents(目次),subscript(下付きテキスト),superscript(上付きテキスト),Attribute ListsTables Extension — Python Markdownを利用する例を紹介しよう。

extensionsサンプル(extensions.py)

import markdown

makedown_text = u'''
# python markdown extensionsサンプル

## 【toc】 - 目次を表示

[TOC]

## 【subscript,superscript】 - 下付き・上付きテキストの表示

H~2~O

2^10^ = 1024

## 【attr_list】 - id属性やclass属性などの属性を指定する

Le Site
{ .main .shine #the-site lang=fr}

[リンク](http://ichitcltk.hustle.ne.jp/gudon2/index.php){: target="_blank"}


文字列を*赤色*{: style="font-style:normal; color: red;"}で表示させます

## 表組み(Tables)


| aaa | bbb | ccc |
|-----|-----|-----|
| ddd | eee | fff |
| ggg | hhh | iii |

'''

extensions=["toc", "subscript","superscript","attr_list","tables"]
md= markdown.Markdown(extensions=extensions)
print md.convert(makedown_text)

extensionを利用するには、上記のコードのようにキーワード付き引数extensionsに利用するextensionのリスト指定して、markdownに渡す。

ところがこのコードを実行してみると以下のようなエラーとなってしまった。

Traceback (most recent call last):
...
ImportError: Failed loading extension 'subscript' from 'subscript', 'markdown.extensions.subscript' or 'mdx_subscript'

どうやら、subscriptのextensionパッケージがインストールされていないという事でエラーになってしまったようだ。
python-markdownには標準ではsubscriptパッケージ含まれていない。
別途、subscriptのextensionパッケージのインストールをおこなう必要がある。

という事で、

よりサードパーティから提供されているExtensionsより「Subscriptパッケージを探してみると、 「Subscript (PyPI) Subscripts text between ~ symbols」が見つかるので

上記のリンクより、「Clone or download」ボタンを押してZIPファイルをダウンロード。
ZIPファイルを解凍、解凍先のデレクトリに移動して、pipを実行してインストール。

python -m pip install MarkdownSubscript

以下のように表示されてインストールが完了。

Downloading/unpacking MarkdownSubscript
  Downloading MarkdownSubscript-2.0.0-py2.py3-none-any.whl
Requirement already satisfied (use --upgrade to upgrade): Markdown>=2.5,<2.7 in
c:\python27\lib\site-packages (from MarkdownSubscript)
Installing collected packages: MarkdownSubscript
Successfully installed MarkdownSubscript
Cleaning up...

同様に、Superscriptsのextensionパッケージもインストール。

subscriptやsuperscriptのextensionには、他にもmarkdown-simplechemというものも存在するようだ。

subscriptとsuperscriptのextensionパッケージもインストール後に再度、前述のextensionsサンプル(extensions.py)を実行。

<h1 id="python-markdown-extensions">python markdown extensionsサンプル</h1>
<h2 id="toc-">【toc】 - 目次を表示</h2>
<div class="toc">
<ul>
<li><a href="#python-markdown-extensions">python markdown extensionsサンプル</a><ul>
<li><a href="#toc-">【toc】 - 目次を表示</a></li>
<li><a href="#subscriptsuperscript-">【subscript,superscript】 - 下付き・上付きテキストの表示</a></li>
<li><a href="#attr_list-idclass">【attr_list】 - id属性やclass属性などの属性を指定する</a></li>
<li><a href="#tables">表組み(Tables)</a></li>
</ul>
</li>
</ul>
</div>
<h2 id="subscriptsuperscript-">【subscript,superscript】 - 下付き・上付きテキストの表示</h2>
<p>H<sub>2</sub>O</p>
<p>2<sup>10</sup> = 1024</p>
<h2 id="attr_list-idclass">【attr_list】 - id属性やclass属性などの属性を指定する</h2>
<p class="main shine" id="the-site" lang="fr">Le Site</p>
<p><a href="http://ichitcltk.hustle.ne.jp/gudon2/index.php" target="_blank">リンク</a></p>
<p>文字列を<em style="font-style:normal; color: red;">赤色</em>で表示させます</p>
<h2 id="tables">表組み(Tables)</h2>
<table>
<thead>
<tr>
<th>aaa</th>
<th>bbb</th>
<th>ccc</th>
</tr>
</thead>
<tbody>
<tr>
<td>ddd</td>
<td>eee</td>
<td>fff</td>
</tr>
<tr>
<td>ggg</td>
<td>hhh</td>
<td>iii</td>
</tr>
</tbody>
</table>

今度は無事にhtmlコードに変換されたようだ。

ソースのコードのシンタックスハイライト - Fenced Code BlockscodehiliteそしてPygments

CodeHiliteというextensionを利用するとコードブロックのシンタックスハイライトしてHTML出力する事ができる。

このCodeHiliteのextensionを機能させるには、別途、Pygmentsというパッケージをインストールする必要がある。

Pygmentsの概略

Pygmentsはpython-markdownだけでは無くさまざまな局面で使われている。 Pygmentsのもっと詳しい内容については後で述べる事として、ここではpython-markdownでコードハイライトをおこなうために必要と思われる事柄についてのみ述べる事にする。

シンタックスハイライトの表示色等は、cssクラスで指定されてHTML出力されるため、このcssクラスに対してstyleの指定をする必要がある。

Pygmentsにはpygmentizeというコマンドラインツールが用意されている。
これを使って、Pygmentsにあらかじめ組み込まれている幾つかのスタイルシートのコードを生成することができる。

以下のようにpygmentizeをコマンドラインより実行するとdefaultのスタイルのcssコードを吐き出してくれる。

pygmentize -S default -f html -a .codehilite > styles.css

生成されたファイルstyles.cssの内容

.codehilite .hll { background-color: #ffffcc }
.codehilite  { background: #f8f8f8; }
.codehilite .c { color: #408080; font-style: italic } /* Comment */
/* 途中を省略*/
.codehilite .il { color: #666666 } /* Literal.Number.Integer.Long */

-aオプションにはcssのクラス属性を指定するが、単純なcssクラスを指定するのではなくCSSセレクタを指定してみても面白いかも?

上記のコマンドではdefaultのスタイルのcssコードを吐き出してくれるが、他にもいろいろなスタイルが定義されている。
どのような、スタイルが定義されているかは以下のpygmentizeコマンドを使ってリスト出力,確認する事ができる。

pygmentize -L styles

また、以下のpythonのコードを実行する事で、定義されているスタイルのリストを得ることができる。

listup_pygments_styles.py

from pygments.styles import STYLE_MAP
print STYLE_MAP.keys()

私の環境では以下のように表示された。

実行結果

['manni', 'igor', 'lovelace', 'xcode', 'vim', 'autumn', 'abap', 'vs', 'rrt', 'native', 'perldoc', 'borland', 'arduino', 'tango', 'emacs', 'friendly', 'monokai', 'paraiso-dark', 'colorful', 'murphy', 'bw', 'pastie', 'rainbow_dash', 'algol_nu', 'paraiso-light', 'trac', 'default', 'algol', 'fruity']

CodeHilite Extensionのコード

以下はcodehiliteのコードの例とその実行結果である。

import markdown

makedown_text = u'''
```python
def func(my_name):
    class MyCls(object):
        def __init__():
            self.my_name = my_name
    return MyCls()

my_inst=func("abc")
print my_inst.my_name
```
'''

md= markdown.Markdown(extensions=["fenced_code", "codehilite"])
print(md.convert(makedown_text))

実行結果

<div class="codehilite"><pre><span></span><span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="n">my_name</span><span class="p">):</span>
    <span class="k">class</span> <span class="nc">MyCls</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
        <span class="k">def</span> <span class="fm">__init__</span><span class="p">():</span>
            <span class="bp">self</span><span class="o">.</span><span class="n">my_name</span> <span class="o">=</span> <span class="n">my_name</span>
    <span class="k">return</span> <span class="n">MyCls</span><span class="p">()</span>

<span class="n">my_inst</span><span class="o">=</span><span class="n">func</span><span class="p">(</span><span class="s2">&quot;abc&quot;</span><span class="p">)</span>
<span class="k">print</span> <span class="n">my_inst</span><span class="o">.</span><span class="n">my_name</span>
</pre></div>

ハイライト表示がcssのクラス名で指定されているのがわかる。

Fenced Code Blocks

CodeHilite Extensionでハイライトさせるコードブロックをどの言語の構文として解釈させるかはFenced Code Blocksの書式を使って指定する。

例えば、pythonの構文であれば

~~~~{.python}
# python code
~~~~

```python
# more python code
```

等と指定することになる。

このため、python-markdownでCodeHilite Extensionを使うには以下のようにextensions引数にFenced Code Blocksの指定も必要になる。

md= markdown.Markdown(extensions=["fenced_code", "codehilite"])

指定行のハイライト表示

指定行したハイライト表示にするには以下のようにhl_linesを指定する。

```python hl_lines="1 3"
# This line is emphasized
# This line isn't
# This line is emphasized
```

CodeHiliteにはオプションを指定する事ができる。 例えば行番号とCSSクラス名を指定するにはextensions引数を使って以下のように指定する。

```python md= markdown.Markdown(extensions=["fenced_code", "codehilite(linenums=True,css_class=highlight_class)"])

Extensionsを指定する複数の方法

Extensionsを指定するには複数を方法があるようで、

  • 名前で指定する場合'denden_extension'とクラスで指定する場合'DenDenExtension()'の違いを調べる · Issue #12 · muranamihdk/denden_extension · GitHub

    extensionをextensionsキーワードに指定する際、3つの方法がある。

    1.extensionクラスのインスタンスを渡す
    2.extensionモジュール名を文字列で渡す
    3.extensionクラス名を文字列で渡す
    1が推奨される方法である。
    オプション値はインスタンス生成時の引数として渡す。

    extensions=[MyExtension(option='value')]
    extensionクラスを直接インポートできない場合に2を使う。オプション値はextension_configsキーワードを使って渡す。
    モジュール名はドット記法によって特定されたパッケージ内モジュールでもよい。モジュールもしくはパッケージはモジュールサーチパス上にある必要がある。

    extensions=['markdown.extensions.extra']
    extensionモジュールがクラス定義を複数持つ場合に3の方法を使う。 モジュール名とコロンにクラス名を続ける。それ以外は2と同じ。ただしひとつしかクラス定義がない場合に3を使ってもパーサーの動作に影響はない。

    extensions=['path.to.module:SomeExtensionClass']
    extensionsキーワードに複数のextensionを渡す場合、そのリスト内で1〜3の方法は混在できる。

    extensions=[MyExtension(), 'path.to.my.ext']

MarkdownをPythonライブラリとして使用する」も参照

ページのトップへ戻る