Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
17
Help us understand the problem. What is going on with this article?
@pashango2

markdown-preview-enhancedのマークダウンを取り込むSphinxフィルタ

More than 3 years have passed since last update.

みなさん、ドキュメントを書いていますでしょうか?
私は最近はAtommarkdown-preview-enhancedを使ってドキュメントを書いています。

markdown-preview-enhancedの記事は以下のものがわかり易いと思います。

mermaid.jsPlantUMLをリアルタイムに確認しながらドキュメント書けるので、とにかくドキュメントを早く書けます。

ただ辛い部分もあって、ある程度長いドキュメントになってくるとページ分けをしたくなってきます。
やはりある程度、分量があるドキュメントはSphinxのように章分けしてくれるツールのほうが読みやすいです。

ですので、markdown-preview-enhancedで書いたマークダウンをSphinxにそのまま取り込めるsphinxcontrib-pandoc-markdownというSphinxフィルターを作りました。

sphinxcontrib-pandoc-markdown

インストールはpipで簡単に行なえます。

$ pip install -U sphinxcontrib-pandoc-markdown

conf.pyに以下の記述を追加します。

from sphinxcontrib.pandoc_markdown import MarkdownParser

source_suffix = ['.rst', '.md']
source_parsers = {
   '.md': MarkdownParser,
}

これでSphinxで.mdファイルを読み込み可能になります。

依存ソフトウェア

markdown-preview-enhancedという名前の通りpandocに依存しています、依存ソフトウェアは以下の通りです。

実装済みのmarkdown-preview-enhanced機能

CodeChunkやスライド能は実装していません。

Sphinx独自の機能

markdown-preview-enhancedに実装されている機能の他にSphinx固有の記法も実装しています。

reStructuredTextの埋め込み

recommonmarkと同様にeval_rstreStructuredTextを埋め込むことができます。

`` ` eval_rst
* This is a bulleted list.
* It has two items, the second
  item uses two lines.
`` `

これでマークダウンで書きながら、reStructuredTextできめ細かい制御を行うという書き方もできます。

ノート、警告、参照

`` `note
This is note.
`` `

`` `warning
This is warning.
`` `

`` `seealso
This is seealso
`` `

TODO

`` `todo
This is todo.
`` `

TODOリスト

`` `todolist
`` `

TODOを使用するにはconf.pyに以下の記述を追加してください。

extensions += ['sphinx.ext.todo']

todo_include_todos=True

pull-quote、highlights

`` `pull-quote
This is pull-quote
`` `
`` `highlights
This is highlights
`` `

epigraph

`` `epigraph
考えるな、感じろ ”Don't think. Feel!”

-- 映画「ドラゴン怒りの鉄拳」より
`` `

mermaid.js

`` `mermaid
graph TD;
    A-->B;
    A-->C;
    B-->D;
    C-->D;
`` `

注意

mermaid.jsの現バージョン(7.0.0)ではCssの設定の関係で画面が半透明になる問題があります。
すでにイシューは投げられていますが、次バージョンあたりで修正されると思います。
現状ではpng形式で出力した方がよいでしょう。

mermaid.jsを使用するには、Sphinx拡張のsphinxcontrib-mermaidをインストールする必要があります。

$ pip install sphinxcontrib-mermaid

また、pngやsvgなどの出力形式に対応したい場合はmermaid-cliが必要です。

$ npm install -g mermaid-cli

conf.pyに以下の記述を追加してください。

extensions += ['sphinxcontrib.mermaid']
mermaid_output_format = "png"

Graphviz

Graphvizはグラフ構造をテキストベースで記述できるツールです。

`` `viz
digraph G {

    subgraph cluster_0 {
        style=filled;
        color=lightgrey;
        node [style=filled,color=white];
        a0 -> a1 -> a2 -> a3;
        label = "process #1";
    }

    subgraph cluster_1 {
        node [style=filled];
        b0 -> b1 -> b2 -> b3;
        label = "process #2";
        color=blue
    }
    start -> a0;
    start -> b0;
    a1 -> b3;
    b2 -> a3;
    a3 -> a0;
    a3 -> end;
    b3 -> end;

    start [shape=Mdiamond];
    end [shape=Msquare];
}
`` `

Graphvizを使用するには、conf.pyに以下のコードを追加する必要があります。

extensions += ['sphinx.ext.graphviz']

Wavedrom

`` `wavedrom
{ assign:[
  ["out",
    ["|",
      ["&", ["~", "a"], "b"],
      ["&", ["~", "b"], "a"]
    ]
  ]
]}
`` `

Wavedromを使用するには、Sphinx拡張のsphinxcontrib-wavedromをインストールする必要があります。

$ pip install sphinxcontrib-wavedrom

conf.pyに以下の記述を追加してください。

extensions += ['sphinxcontrib.wavedrom']

技術解説

ここはQiitaなので技術解説をします。
とはいえ、pandocが難しい事をほとんどやってくれているので難しい事はほとんどありません。

処理の流れ

マークダウン -> プリプロセス -> pandocフィルタ -> reStructuredText -> ポストプロセス

プリプロセス

@import記法をプリプロセス部分で置き換えします、多分、本家の処理もプリプロセスで処理していると思います。

pandocフィルタ

pandocでマークダウンからreStructuredTextに変換しているのですが、フィルタを作成して画像のキャプションを除去しています。
フィルタは以下の通りです。

from pandocfilters import toJSONFilter, Image


def remove_caption_filter(key, value, format_, meta):
    if key == 'Image':
        """
        markdown:
            ![alt](path "title")

        json:
            [[u'', [], []], [{u'c': u'alt', u't': u'Str'}], [u'path', u'fig:title']]
        """
        try:
            alt = value[1][0].get("c")
        except IndexError:
            alt = None

        value[1] = []

        if alt:
            value[2][1] = u"fig:{}".format(alt)
        return Image(*value)


if __name__ == "__main__":
    toJSONFilter(remove_caption_filter)

ポストプロセス

変換されたreStructuredTextをパースしてコードブロックの置換処理をします。

こんなコードを

.. codeblock:: note

    This is Note.

こんなふうに変換しているだけです。

.. note::

    This is Note.

reStructuredTextはルールが単純なのでパースしやすいですね。

まとめ

markdown-preview-enhancedマークダウン->HTMLと直接変換なのに対して、こちらはマークダウン->reStructuredText->HTMLとしているので、どうしてもdocutilsの仕様にひっぱられたりします。

何か問題や欲しい機能がありましたら、GitHubのイシューに投げてください。

17
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
e-zero1
映像制作の企画・開発、モバイルアプリの制作を行っています。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
17
Help us understand the problem. What is going on with this article?