2012年1月17日火曜日

SphinxでHTMLでもPDFでも見やすい文書を一発で作る

昨年の秋位から Sphinx を本格的に使ってきたので色々メモした事、やった事をまとめて見る。Whyの部分は後で拡充するかも。

後これは俺が買って考えた事なので、これよりいい方法とか知ってる方いたら是非に教えてください。マジで。ホントに。
尚Sphinxを使える用にして、PDFまで出力出来る様にする方法は Sphinxとrst2pdfの「domains」がないよエラー を参照してください。


■やらないといけない事
取り敢えずやらないといけない要件は以下の通り。
  1. HTMLはHTMLで見やすく。PDFはPDFで見やすく。
  2. PDFは各章に通し番号を振る。HTMLは振らない。
  3. PDFは見出し必須。しかし見出しに載せる深さは2番目まで
  4. 内容的に同一の文書を使い回す場所がある。
これに加えて、HTMLとPDFの両方を作る場合以下の問題もあった。(今はもう Sphinx とか rst2pdf 側で対応してるかもだけど。)
  • HTMLを重視する場合、toctreeを使えば1ページに見出しだけが全てそろうので目的のページを探しやすく移動しやすい
  • PDFの場合、toctree を使って書くと章の番号を振るのがおかしくなる。
  • toctree はリンクになってしまいリンク先のページは個別で評価、変換されるっぽいのでPDFの場合だと章段落の程度がおかしくなる
  • include を使えば多数のファイルをマージして(1ファイルにして)から評価変換される用なので章段落の程度がおかしくならない。しかしHTMLだと一個のHTMLが巨大化してしまい死ぬほど見にくい。
つまり toctree は HTML と相性が良く、include は PDF と相性が良い。


■HTMLとPDFとを分けて考える
という事で「HTML用のRootドキュメントとPDF用のRootドキュメントを分ければいいんじゃね?」と考えて、調べてみたら出来るっぽい。Sphinxの conf.py の以下の場所の「indexPdf」の部分を変更する。
pdf_documents = [ ('indexPdf', 'Manualタイトル', u'Manualタイトル', u'Author', 'manual'), ]
初期値だとHTMLのと同じ奴に設定されてるけど、ここを変更するとPDFを作成する際はここで指定されたファイルをRootドキュメントにして作成してくれるようになる。こうしておけば make html pdf って一個のコマンドで違う構成ファイルを元にしたHTMLとPDFとが同時に作れる様になる。


■RSTファイルの構成
次に実際に利用するRSTファイル群は以下の様な構成に成っている。
  • index.rst ・・・ HTML用のドキュメント構成。ページ構成のRSTファイルを toctree で記述。
  • indexPdf.rst ・・・ PDF用のドキュメント構成ページ構成のRSTファイルを include で記述。
  • page.rst ・・・ 章構成。実コンテンツの本体。基本的に重複のない文書を書く。HTML用もPDF用も共通。 paragraph.rst を全て include で記述。 
  • paragraph.rst ・・・ 各パラグラフ。使い回す可能性のある文書はここに書いている。HTML用もPDF用も共通
index.rstは以下の通り
########
各章タイトル
########


.. toctree::
:maxdepth: 1


hoge
fuga
pugya
homu
indexPdf.rstは以下の通り。PDFの場合、各章の頭に数字を振りたいのでそのコマンドを先頭に入れておく。
.. section-numbering::


########
各章タイトル
########


.. include:: hoge.rst
.. include:: fuga.rst
.. include:: pugya.rst
.. include:: homu.rst
Sphinx公式のセクション管理 にSphinxでのセクション管理の例が載っているけど、私は以下の様なルールでセクションを利用している。
ただしpage.rstに関してはかなり流動的。使い回す可能性のない説明であれば、一番したのパラグラフまで使う事もある。
  • # 部: オーバーライン付き ・・・ index.rst/indexPdf .rst で使用
  • * 章: オーバーライン付き ・・・ page .rst で使用
  • =, セクション  ・・・ page .rst、 paragraph.rst で使用
  • -, サブセクション  ・・・   paragraph .rst で使用
  • ^, サブサブセクション  ・・・   paragraph.rst で使用
  • ", パラグラフ  ・・・   paragraph.rst で使用


■ PDFでの改ページ処理
一応rst2pdfには自動改ページ設定機能があるがこれが結構微妙。ルール一辺倒なのでいやここは・・・って所でも改ページしてしまう。なのでこれを使わず、面倒だけど自分で改ページを指定する事にした。

まずconf.pyの以下の設定をコメントアウトして自動改ページを無効にする。
#pdf_break_level = 2
で代わりの改ページ指定は、改ページしたい所に以下の記述を加えておく。これを入れておくとHTMLの方では何も出力されない。だけどPDFを出力する時のみ改ページ処理が行われる。
.. raw:: pdf


PageBreak
なお私が作ったドキュメントではこのPDF用改ページコマンドをpage.rstに末尾に必ず追加している。


■DPFの目次管理
次にPDFでのページ管理。toctreeを使うと目次っぽいのが勝手に出来るけど、includeを使うとそれが生成されない。なので rst2pdf の機能を使って目次を生成する。
また目次を設定する際、上から2番目(1.1 インストール方法)までを目次に載せるように設定する。これを指定しないと全てのセクションが目次に載ってしまう。(例えば 1.2.3.4.5 注意 とか)。
その為に conf.py に以下の設定を追加する。
pdf_use_toc = True
pdf_toc_depth = 2
目次に載せるセクションの深さは数字で自由に変更出来ます。


■ただ一つの欠点
これでHTMLとPDFの両方が見やすくなったと思う。
ただ唯一新しい章を追加する際にindex、indexPdfの2つに記述しないといけない事が面倒だけど。

参考になるURL

コメントを投稿