Sphinx + Recommonmarkの環境ではリンクの箇条書きはtoctreeになることを失念してトラブルに見舞われた話
こんにちは。サービスグループの武田です。
みなさんドキュメント書いてますか?その際どのようなツールを使っていますか?今回はSphinxを採用していたプロダクトで(主に筆者の不理解で招いた)トラブルに見舞われ、その解決策の備忘録となります。
発生した問題
SphinxはreStructuredTextというマークアップ言語を採用しています。ただ新しく覚えるモチベーションが湧かないというのと、使い慣れているMarkdownで書きたい!という要求からRecommonmarkを利用してMarkdownで書いていました。そこで次のようなリンクの箇条書きを記載しました。
参考サイト。 - [Classmethod](https://classmethod.jp) - [Developers.IO](https://dev.classmethod.jp)
そしてsinglehtml
やlatexpdf
でビルドしたら、このリンクがきれいさっぱり消えてしまったのでした(html
でビルドする分には問題ないように見える)。
原因と対応
まず原因ですが、今回書いたようなリンクの箇条書きはRecommonmarkによってtoctreeとして解釈されます(設定によります、後述)。完全にこの仕様は頭から抜けていたのですが、問題の調査をしている中でドキュメントにある記載を見つけました。
AutoStructify Component — Recommonmark 0.6.0 documentation
toctreeとして認識された結果、singlehtml
やlatexpdf
ではリンク先を記載箇所に差し込もうとしていたわけです。ただ外部リンクのため差し込めずリンクそのものが消失しました(内部リンクでも意図しない差し込みが起きて変な構成になります)。
enable_auto_toc_tree
という設定項目が提供されており、これを切ることで問題は解決できました。
def setup(app): app.add_config_value('recommonmark_config', { 'enable_auto_toc_tree': False, }, 'env') app.add_transform(AutoStructify)
問題の再現手順
上記の設定で問題は解決できましたので、ここからは再現する手順を記載します。解決策さえわかれば十分という方には蛇足になります。
検証環境
次のような環境で検証しています。
$ sw_vers ProductName: Mac OS X ProductVersion: 10.15.3 BuildVersion: 19D76 $ pipenv --version pipenv, version 2018.11.26 $ pipenv run python -V Python 3.7.6 $ pipenv run python -m pip list | grep -E 'Sphinx|recommonmark' recommonmark 0.6.0 Sphinx 2.4.4
ドキュメントの作成
まずはさくっとドキュメントのひな型を作成しましょう。sphinx-quickstart
を実行するといくつか質問をされますが、基本的にはデフォルト設定で十分です。
$ cd /path/to/working $ cat > Pipfile <<EOS [source] name = "pypi" url = "https://pypi.org/simple" verify_ssl = true [dev-packages] [packages] sphinx = "*" recommonmark = "*" [requires] python_version = "3.7" EOS $ pipenv install $ pipenv run sphinx-quickstart
これで環境が作成できました。試しにドキュメントをビルドしてみましょう。
$ pipenv run make html singlehtml $ open _build/html/index.html _build/singlehtml/index.html
シンプルな画面ですが、問題なく生成できたことが確認できます。
Recommonmarkの設定を追加
続いてSphinxのドキュメントをMarkdownで書くための設定をconf.py
に追加します。
@@ -14,6 +14,7 @@ # import sys # sys.path.insert(0, os.path.abspath('.')) +from recommonmark.transform import AutoStructify # -- Project information ----------------------------------------------------- @@ -28,8 +29,18 @@ author = 'test' # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ + 'recommonmark' ] +source_suffix = { + '.rst': 'restructuredtext', + '.txt': 'restructuredtext', + '.md': 'markdown', +} + +def setup(app): + app.add_transform(AutoStructify) + # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates']
設定はこれだけです。実際にMarkdownのファイルを追加してみましょう。
# hello これは**Markdown**で書いています。 ```eval_rst - `Classmethod <https://classmethod.jp>`_ ``` - [Developers.IO](https://dev.classmethod.jp)
toctreeに追加します。
@@ -10,6 +10,7 @@ Welcome to test's documentation! :maxdepth: 2 :caption: Contents: + hello Indices and tables
あらためてドキュメントをビルドします。
$ pipenv run make clean html singlehtml $ open _build/html/hello.html _build/singlehtml/index.html
こちらがhtml
のドキュメント。リンクは健在です。
こちらがsinglehtml
のドキュメント。リンクが消失しました……。
なお、実際には他の箇所にも影響は出ているのですが、テーマなどに依存するため今回の問題に焦点を当てています。
auto_toc_treeの設定を追加して解決
実は今回の問題は、解決策が2個あります(他にもあったら教えてください)。1個目は上述したenable_auto_toc_tree
を設定する方法。2個目はauto_toc_tree_section
を設定する方法です。
enable_auto_toc_tree
はtoctreeの生成を完全にOFFにできます。
def setup(app): app.add_config_value('recommonmark_config', { 'enable_auto_toc_tree': False, }, 'env') app.add_transform(AutoStructify)
もうひとつの方法であるauto_toc_tree_section
はtoctreeを生成するセクションを限定できます。
def setup(app): app.add_config_value('recommonmark_config', { 'auto_toc_tree_section': 'Welcome', }, 'env') app.add_transform(AutoStructify)
いずれかの設定をしてドキュメントをビルドします。
$ pipenv run make clean html singlehtml $ open _build/html/hello.html _build/singlehtml/index.html
こちらがhtml
のドキュメント。リンクは健在です。
こちらがsinglehtml
のドキュメント。リンクが復活しました!
まとめ
始めはビルド環境の問題なのか、Sphinxのバグなのか、など問題の切り分け自体に難航しました。一時的にはeval_rst
で解消できたのですが、根本解決をするためにドキュメントを眺めたりしていたところ今回の解決に至りました。ドキュメントはちゃんと読もう!(戒め)