sphinx
2022年現在では、VivlioStyleを用いた同人誌作成をやっています。
すぐ書き出すためのテンプレートリポジ トリも作成しました。詳細は下記記事にて。
gensobunya-tech.hatenablog.com
電子書籍 も紙書籍もキッチリ作りたい!
幻想サイクルの活動では、完全オリジナルであることを活かして現物の同人誌頒布だけでなく、電子媒体での配信も意欲的に行ってきました。
Booth でのPDF版の頒布を皮切りに、Amazon kindle 、BookWalker(現在は停止)で配信をはじめ、今ではKindle Unlimitedでも読めるようになっています。
実績から言うと、人気は「紙媒体>>>Kindle =Kindle Unlimited>>>>>>>>>その他」となっています。思ったよりで電子版の配信が好評で驚いています。
しかし…実は、現在配信している同人誌には文字情報がありません。Illustrator で作成している都合上、文字情報を維持したままepub ファイル(電子書籍 形式)を作成することが手持ちのソフトでは困難だったためです。Boothで配信しているPDFは文字情報を維持できているので、コンテンツの質としてはKindle 版より上なのですが利便性はそれに優るようです。
※PDFでもKindle モバイルアプリで読むことは可能です
実用寄りの本を書いていることもあり、せっかくなら文字検索ができる状態の本を出してもらおうとしたのがC95の新刊「泥輪事情」です 。
技術書典が公表を博していることもあり、1ソースから印刷用のファイルと電子書籍 用のファイルを出し分けることに関するノウハウがいくらか溜まっていることは把握していたので、ITを仕事にしているものの端くれとして興味が昂ぶっていたこともあり、原稿ファイルから複数の入稿ファイルをビルドするスタイルに挑戦しました。
以下、検討から出力までかなりの長文が続きますが、最終的に下記のツールでPDFの出力まで持ち込みました。
conf.py
が含まれたリポジトリ は下記のとおりです。ビルド方法はREADME参照のこと。
Github : gentksb/md2doujin_sphinx
https://github.com/gentksb/md2doujin_sphinx
プランニング
入稿要件
印刷用の原稿は、同人活動 開始以来お世話になっている、ラック出版 様の入稿ファイルを要件として設定します。移動体通信 事業者のプランがかわいく見える印刷所の料金体系の中で、非常に明快な印刷メニューと割引メニューを準備している素晴らしい印刷所です!(ダイレクトマーケティング )
入稿はPDF形式です。要件はこちらのページ に記載されている通り、大きく下記の3点です。
フォントは全て埋め込み
PDF/X-1a形式
ページ設定---原寸
出力時に上記を満たしている必要があります。epub は出力してくれればなんとかなる(中身はHTML)なので対して問題にならないだろうと割愛。
技術系同人誌はA5が多いですが、評論かつ弊サークルの前例に従いB5サイズを作成するものとします。
Wordじゃだめなの?
ドキュメントビルドのフレームワーク を使うことで、ノンブルの設定や目次の自動生成などの細かいあれこれから開放されるためです。
Wordでもできる?こまけえこたあいいんだよ!あと自宅PCはずいぶん前にGoogle に入信したためOfficeが一切入っていません。あと出先でChromebook を使って執筆したいのでOfficeは(個人的には)一切使いません。
今回のメインとなるお題です。パッと見た限り、情報と実績が豊富なのは下記の手段。
ソースは使い慣れているMarkdown をメインで使うことを前提としています。このサイトもブログもMarkdown なので、生産性という名前の慣れは抜群。
Pandoc
Sphinx + RecommonMark
Re:View + md2review
ここで、最終的に「LateX を使ってPDFを出力する」という点は逃れられないことに気が付きます。若干の不安を抱えつつもネイティブにMarkdown を扱えるPandocがいいなとこの時点では考えていました。どうしてもMarkdown 記法で解決できない問題が出てきた際に、Sphinx はReST、Re:View もRe:View 記法を新たに理解する必要があるからです。
新しい記法を覚えるくらいなら原稿に力を注ぎたいので、まずはPandocの参考になる情報を漁り、下記のページに行き当たります。
情報をあさっている間、並行してMarkdown で構造に気を使いつつ原稿を書いていきます。
Pandoc + LaTeX で markdownからA5・縦書・2段組の小説本のPDFを作成
http://adbird.hatenablog.com/entry/2017/01/15/010459
バッチリドンピシャやんけ!!!!!!!
こちらの記事を参考に、章ごとに分割した.md
ファイルを準備してビルド!と思うもよく見るとTeX のテンプレートファイルを使ってそこに流し込んでいる=TeX の知識がないと細かいことができない、という点に気が付き候補から脱落。素のビルド内容でも試してみましたが、後述するSphinx に比べあまりにも味気ないので、作り込みの時間をとっていないこともあって残念ながら却下となります。
Re:view はかなり版組み向けの言語でしたが、それゆえに原稿の可読性が著しく落ちているのでやめておきました。
Sphinx +RecommonMarkでオフセ本に耐えるPDFを出力する
ようやく本題です。Sphinx は優しいのでsphinx-quickstart
を実行するだけでいい感じにディレクト リを作ってくれます。
こちらは脱稿時のリポジトリ です。
リポジトリ 構成
nn_題名.md
が各章の原稿、index.rst
がビルドの開始地点です。残りの設定はすべてconf.py
の中。conf_lua.py
はpLateX ではなくluaLateXで出力しようとして失敗したときの名残です。
本来、index.rst
の内部でファイルのインポート順を決定できるため、.md
ファイルにプレフィックス 番号は不要なのですがPandoc用に原稿を作成した名残です。
まずはSphinx でMarkdown を使えるようにします。
RecommonMarkとAutoStructifyをインポートしてググって出てきた内容を追加します。
下記の内容をconf.py
に追記・編集していきます。
import recommonmark
from recommonmark.parser import CommonMarkParser
from recommonmark.transform import AutoStructify
github_doc_root = 'https://github.com/rtfd/recommonmark/tree/master/doc/'
def setup (app):
app.add_config_value('recommonmark_config' , {
'url_resolver' : lambda url: github_doc_root + url,
'auto_toc_tree_section' : 'Contents' ,
}, True )
app.add_transform(AutoStructify)
次に、.mdファイルを原稿ファイルと認識させます。
source_suffix = ['.rst' , '.md' ]
source_parsers = {
'.md' : 'recommonmark.parser.CommonMarkParser'
}
この時点で、ビルドコマンドを打って.md
ファイルが原稿で使えるようになりました。
PowerShell だとディレクト リ内に実行ファイルがあっても明示的にパスを指定する必要があるのでめんどいです。
.\make clean
.\make latexpdf
ここで原稿を見ているとあることに気が付きます。テーブルが出力されていません 。
RecommonMarkはCommonMarkという標準Markdown のみをサポートしているため、みんな大好きGithub Flavored Markdown でサポートされている表組は対応していません。
残念ですがReST記法を用いたテーブル に書き直す必要がありました。
前節のAutoStructifyは、.md
ファイルの中でReST記法を使えるようにしてくれます。下記のようにeval_rst
で囲ったコードブロック内をReSTで解釈してくれます。
```eval_rst
============ ==========
出走内容 昇格内容
============ ==========
6人未満 昇格無し
6人以上で1勝 昇格できる
6人以上で2勝 昇格は必須
============ ==========
```
conf.py
でimportするだけでなく、定義も宣言しないと動作しないので注意。
github_doc_root = 'https://github.com/rtfd/recommonmark/tree/master/doc/'
def setup (app):
app.add_config_value('recommonmark_config' , {
'url_resolver' : lambda url: github_doc_root + url,
'auto_toc_tree_section' : 'Contents' ,
}, True )
app.add_transform(AutoStructify)
原稿の見た目はできた、出力形式が問題だ
残念ながら、ここからLateX の設定 と格闘することになります。conf_py
でlatex_elements
の設定内にメタデータ をJSON ライクに書いていくのですが、大半の設定はpreamble
というLateX の設定を直書きできる箇所でレイアウトを指定します。
文字サイズ、開き方向、原稿サイズ以外はほぼLateX です。B5サイズを使っている人がなかなか居なかったのですが、'papersize': 'b5j'
を指定すれば、LateX の設定抜きでB5サイズで出力できます。
なお、最新版のSphinx ではlatex_documents
にmanual
を指定した場合自動的にLatex のレイアウトがjsbook形式で出力されるので、インターネッツ の海に浮かんでいるmanualとjsbookをマッピング させる設定は不要です。
'extraclassoptions': 'openany,twoside'
は本っぽく中央の余白を大きく取るための設定となります。
latex_engine = 'platex'
latex_elements = {
'pointsize' : '10pt' ,
'papersize' : 'b5j' ,
'extraclassoptions' : 'openany,twoside' ,
'babel' : r'''
\usepackage[japanese]{babel}
''' ,
'tableofcontents' : r'''
%normalで目次ページを出力しつつSphinxスタイルをやめさせる
\tableofcontents
''' ,
'preamble' : r'''
%フォント
%TexLive側コマンドで制御kanji-config-updmap-user [kozka|kozuka-pr6n|ipaex|yu-win10|status|他]
%luatexで
%\usepackage[kozuka-pr6n]{luatexja-preset}
%pdf/x使うための設定
%\usepackage[x-1a1]{pdfx}
%レイアウト
\renewcommand{\plainifnotempty}{\thispagestyle{plain}}
\setlength{\textheight}{\paperheight}
\setlength{\topmargin}{-5.4truemm}
\addtolength{\topmargin}{-\headheight}
\addtolength{\topmargin}{-\headsep}
\addtolength{\textheight}{-40truemm}
\setlength{\textwidth}{\paperwidth}
\setlength{\oddsidemargin}{-5.4truemm}
\setlength{\evensidemargin}{-5.4truemm}
\addtolength{\textwidth}{-40truemm}
% ハイパーリンクモノクロ
\hypersetup{colorlinks=false}
% 字下げ
%\setlength\parindent{1zw}
% パラグラフ間空白
%\setlength{\parskip}{0pt}
% タイトル装飾
\usepackage{titlesec}
\usepackage{picture}
% chapter
\titleformat{\chapter}[block]
{}{}{0pt}{
\fontsize{30pt}{30pt}\selectfont\filleft
}[
\hrule \Large{\filleft 第 \thechapter 章}
]
% section
\titleformat{\section}[block]
{}{}{0pt}
{
\hspace{0pt}
\normalfont \Large\bfseries{ \thesection }
\hspace{-4pt}
}
% subsection
\titleformat{\subsection}[block]
{}{}{0pt}
{
\hspace{0pt}
\normalfont \large\bfseries{ \thesubsection }
\hspace{-4pt}
}
''' ,
}
latex_documents = [
('index' , 'c95.tex' , '泥輪事情' ,
'ゲン' , 'manual' ),
]
セクションの装飾を入れたところ、目次が「第0章」となってしまいますが消し方がわからないので許容しました。
入稿要件の満たし方
ようやく見た目の整ったPDFが出力されるようになりました。次は入稿ファイルの要件を満たしていきます。
(2020.09)
下記に自分がやったことを記載していますが、今はPDFを変換するツールを公開している方がいるので、楽々変換できます!
github.com
フォント埋め込み
TeX Live2018を使用した場合、デフォルトでPDFにフォントが埋め込まれます。 フォント埋め込みに難航している情報が大量に検索に出てきましたが、古い情報です。
IPAフォント をデフォルトで使用していますが、埋め込みフォントはkanji-config-updmap-user
というコマンドを利用することで、フォントセットを簡単に切り替えることができます。
これもフォント変更に難航している情報が大量に浮かんでいますが、このコマンドで一発解決します。使えるフォントセットはこちら を参考に。游ゴシック体 やモリサワ 、Adobe でお馴染みの小塚フォントもインストールされていれば使うことができます。
ページごとのPDF、ノンブル開始番号
実はラック出版では本文全体のPDFではなく、ページごとのPDFを03.pdf
の用に単ページごとに入稿する必要があります。が、もちろんSphinx で素直にビルドすると全体のPDFが出てきます。
本文ページは3ページからスタートするため、目次ページのノンブルは3、本文は4ページ目からスタートしますが、Sphinx はデフォルトで目次と本文のノンブルを別物でカウントしていたためこの2つの課題を解決する必要があります。
なぜかconf.pyのpreambleに設定しても動かないため、index.rst
に設定を書き込みます。
.. raw:: latex
%目次は3ページ目から
\setcounter{page}{3}
.. raw:: latex
はこれまたLateX 記法をrstに組み込むためのrst記法です。組版 を刷る限りLateX からは逃れられないようです。
ページごとのPDF出力には、Sphinx の裏のLateX の裏で動いているdvipdfmx を使います。
そもそも、pLateX によるPDF出力は.tex
→.dvi
→.pdf
という変換順になっており、副産物としてDVIファイルが生まれています。こいつを横取りして1ページづつビルドし直します。
こんなコマンドをプロジェクトの/_build/latex/
で打っていきます。コマンドの大量生成はGoogle スプレッドシート でやりました。
mkdir .\build\latex\indv\
cd .\build\latex\
dvipdfmx -c -V 3 -s 2 - 2 -o './indv/03.pdf' 'c95.dvi'
dvipdfmx -c -V 3 -s 3 - 3 -o './indv/04.pdf' 'c95.dvi'
...
これで見た目はフォントが埋め込まれたページごとのPDFが生成されました。
最後の砦、PDF-X形式
入稿にはPDF-X形式が基本です。カラーやらリンクが埋め込まれていないPDFファイルで、印刷の段階で事故が起きないようにするための形式らしい。RGBではなくCMYK になってます。
PDF/X-1a形式で出力するためとりあえずTeX Wiki へ。
dvipdfmx には出力結果が PDF/X 準拠かどうか検証したり,準拠するように適切に処理したりする機能はありません。
…
……………………………
LuaLatexはdvildfmxを使わずにPDFを出力でき、\usepackage[x-1a1]{pdfx}
をプリアンブルに入れることでpdf-x/a1形式を出力できます。(この際に試行錯誤したときの設定ファイルがconf_lua.py
です)
しかし、Sphinx で出力したtex ファイルをLualatexに食わせてPDF出力したところ、思いっきり画像周りのレイアウトが崩れました。
しかもフォントの埋め込み方法が変わってしまいます。
この時点でゲームオーバーと判断。最終的にはdvipdfmxで出力したモノクロPDF(埋め込み画像は予めグレースケール化済み)をラック出版さんに確認出してOKもらった上で入稿しました。オンデマンド印刷なら場合によっては問題ありませんし、コピ本ならなおさら問題なく発行できます。
よく考えたらフォントも小塚を使ったのでAdobe の呪縛からも逃れられていませんでした。Adobe さんChrome OS でも使えるようにLinux 版イラレ を出してくれ。
結論
最も簡単なソリューションはインデザに課金することです。一人で本を作るならビルド環境よりコンテンツに力を注ぎましょう。
でも夏コミまでにかっこよくLuaLatexで出力したいから誰かナイスなPRをください