Bookdownによる技術系同人誌執筆

C95でPhotorealismというパストレーシングの理論と実装を扱う技術同人誌を執筆しました。


その時の組版環境としてBookdownというものを利用してとても便利だったのですが、日本語環境では様々な問題にぶつかったのと、同人誌入稿の制限(トンボ、ノンブル、奥付)などで苦労したのでその知見をまとめてみました。


Bookdownについて

Bookdownは統計プログラミング言語Rを用いて本の組版を行えるRパッケージです。R Markdownという、MarkdownにRのコードを混ぜてレポートなどを執筆することができるパッケージを拡張し、本の組版に便利な機能を追加したものになっています。

Markdownを利用して本の執筆を行うことができ、GFM記法やLaTeXの数式環境、コードのシンタックスハイライトも利用することができます。HackmdやQiitaといったサービスで書いたMarkdownをそのまま持ってくることができるので便利です。

出力形式はHTML、PDF、EPUBの三種類あり、一つの原稿から三つの出力形式を得ることができます。今回コミケの入稿で利用したのはPDF形式です。


技術本執筆で必要な要素

技術本を描く上で個人的に必要だなと思う要素が
  1. 簡単に文章構造を指定できる
  2. 図表を簡単に扱える(番号も付けられる)
  3. LaTeXの数式が扱える
  4. シンタックスハイライトが利用できる
の4点です。1に関してはMarkdownが優れていると思っています。2, 3はLaTeXを最初から使えば良いのですが、文章全体を簡単に書けないという問題点があります。4はGFMのようなものが理想でした。

これらの点を全てを満たすのがBookdownです。Markdownを利用して簡単に執筆が行え、しかも図表のキャプション・番号付け機能、数式・シンタックスハイライトが簡単に扱えます。こうして私はBookdownで執筆することに決めました。


Bookdown執筆の環境構築

Bookdownを利用するためにはRを利用できる環境を整える必要があります。Rの公式サイトから必要なものをインストールします。

次にRのIDEであるRStudioをインストールします。Bookdownで執筆を行うためには必要です。

次にここのチュートリアルに従ってBookdownをインストールします。RStudioを開いて下に現れるコンソールに
install.packages("bookdown")
と入力するとインストールが始まります。

PDF出力を利用するためにはLaTeXの環境が必要です。環境構築の方法は人によって分かれると思いますが、texliveが必要なものが全部入っているのでおすすめです。


Bookdownで執筆

RStudioを開き、New ProjectからNew Bookdown Projectを選択すると、デフォルトのテンプレートが入った状態でBookdownのプロジェクトが作成されます。

プロジェクトには様々なファイルがありますが
  • index.Rmd 本全体の設定をここで行う
  • _output.yaml 3種類の出力形式の設定をここに記述する
  • _bookdown.yaml 出力先とかの設定
  • 01-06.Rmd それぞれの章の内容
  • preamble.tex PDF出力の場合のLaTeXのプリアンブル
という構成になっています。

index.Rmdの先頭にあるYAML形式の部分は本全体の設定になっています。本のタイトルや寸法、シンタックスハイライトの色など指定できます。

本の内容はindex.Rmdと01-06.RmdにRMarkdownで記述していきます。RMarkdownについてはこちらのページでよくまとめられています。RMarkdownが普通のMarkdownと決定的に違うところは
```{r}
plot(cars)
```
というように書くことでRのコードをMarkdown中で実行できるところです。この場合plot(cars)はcarsというデータをグラフにする命令なので、Markdown中にコード例とともにグラフが挿入されることになります。何かデータを読み込んでグラフとして表示する必要がある場合は、Rの素晴らしい機能をそのまま利用できるので便利だと思います。

コード例を消したい場合は
```{r echo=FALSE}
plot(cars)
```
のように記述します。

01-***.Rmdの後ろにある名前は適当な名前で大丈夫です。ファイル名の先頭に数字があることで、それが第$n$章に対応しているとBookdownが勝手に認識してくれます。

本の組版結果を見るにはエディターにあるknitrボタンを押します。すると内部ブラウザーが立ち上がり、HTML形式で出力された結果を見ることができます。

PDF形式で出力するにはエディタの下にあるコンソールで
bookdown::render_book("index.Rmd", output_format = "bookdown::pdf_book")
とRのコードを実行することでPDFのレンダリングが始まります。texliveの導入がうまくいっていれば動くと思います。内部的にはMarkdownをPDFに変換するのにPandocを使用しているのが分かります。index.RmdのYAML部分でpandocの設定も自由にいじることができます。

PDFは_bookフォルダの中に出力されます。documentclassにbookを指定しているので、目次がついて本っぽく出力されます。

目次

生成されたPDF



日本語を使う

BookdownではLaTeXのエンジンとして
  • pdflatex
  • xelatex
  • lualatex
の3種類が利用できます。このうち日本語が利用できるのはxelatexとlualatexです。xelatexはlualatexより高速に動きます。

bookの日本語版としてjsbookドキュメントクラスがあるのでそれを利用します。xelatexを使う場合、documentclassにbxjsbook、lualatexの場合はltjsbookを指定します。この記事ではxelatexを使うことにします。


documentclass: bxjsbook
また、_output.yamlのbookdown::pdf_bookの項にlatex_engineとしてxelatexを指定します。
bookdown::pdf_book:
  includes:
    in_header: preamble.tex
  latex_engine: xelatex
  citation_package: natbib
  keep_tex: yes

本文中に日本語を入れてPDF出力してみましょう。どのような結果が得られるでしょうか。

0.1には日本語が入っているはず・・・
日本語の部分はすべて空白になってしまっています。これはフォントが日本語に対応していないためです。これを防ぐためにはクラスオプションで以下のものを指定するようにします。
classoption: xelatex,ja=standard
これでPDFを生成すると以下のようになります。
日本語にした
見てみると幾つか問題があります。まず章の番号の頭に0がついていて変です。さらに章ごとに改ページが入っていないので、これをそのまま原稿として使うことはできません。

! LaTeX Error: Option clash for package geometryと出る場合

このエラーはgeometryパッケージを重複して呼び出してしまうために起きるようです。Bookdownではtexファイルを生成する際にデフォルトのテンプレートを含めるようにしているのですが、そこでgeometryパッケージが読み込まれるようになっています。これがdocumentclassやusepackageで読み込んだ追加パッケージの設定と衝突することでエラーが起きています。そこでデフォルトのテンプレートを書き換えてgeometryパッケージを読み込まないようにします。

デフォルトのテンプレートの位置はPDFをレンダリングした際にコンソールに表示される、pandocの--template引数に書いてあります。これを開きgeometryを読み込んでいる部分をコメントアウトします。

$if(geometry)$
%\usepackage[$for(geometry)$$geometry$$sep$,$endfor$]{geometry}
$endif$


章の番号と改ページを直す方法

pandocを用いて生成されたtexファイルを見てみましょう。
\section{あいうえお}

あいうえおあいうえお
\sectionが使われていますが、jsbookにおいては\chapterが章立てのコマンドになります。そのため\renewcommandを用いて\sectionを\chapterに置き換えます。さらに\sectionの下に存在する\subsectionを\sectionを置き換える必要があります。必要なところまでこれを繰り返します。
\let\asdf\section
\renewcommand{\section}{\chapter}
\let\asdff\subsection
\renewcommand{\subsection}{\asdf}
\let\asdfff\subsubsection
\renewcommand{\subsubsection}{\asdff}
これでPDFを出力しなおすと以下のようになります。
修正後
章立てが直って、各節の番号も正しく割り振られています。さらに章ごとの改ページも有効になりました。


本のサイズ指定

本のサイズを指定するにはクラスオプションにb5paperを指定します。

classoption: xelatex,ja=standard, b5paper
実行すると
こんな感じで出力されます。サイズは182mm x 257mmでちゃんとB5サイズになっています。


デザインの統一

目次や章の始まりのページを他のページと同じデザインにする場合、プリアンブルに次のコマンドを書き込みます。

\makeatletter
\renewcommand{\chapter}{%
  \if@openright\cleardoublepage\else\clearpage\fi
  \global\@topnum\z@
  \secdef\@chapter\@schapter}
\makeatother

章の始まりが同じデザインになる
ここら辺の話はこちらにまとまっています。他にも余白を調整する方法など色々なことが書いてあります。


フォントの指定

好きなフォントを指定する場合、プリアンブルに次のように書きます。

% 英語本文のフォント
\setmainfont{MigMix 1P}
% 日本語本文のフォント
\setjamainfont{MigMix 1P}
% 英語コードのフォント
\setmonofont{Lucida Console}
生成されるPDFは次のようになります。
フォント指定後

目次から出力されるようにする

PDFの最初のページを目次からにするには、index.Rmdでtitle, author, dateをなくすことで可能です。

トンボをつける

同人誌入稿で必要なトンボはgentombowパッケージを利用することで付けることができます。プリアンブルでこれを読み込みます。


\usepackage[pdfbox]{gentombow}
これでPDFを出力してみると以下のようになります。
用紙全体がずれている
用紙全体が右下にずれてしまっています。gentombowは本のレイアウトがB5のとき、用紙サイズは自動的にA4になるようになっています。しかし出力されたPDFのサイズを確認してみるとB5のままになっています。ズレが起きるのは用紙サイズが小さいままだからです。

そこで出力の用紙サイズを明示的に指定することにします。bxpapersizeパッケージを利用するとこれが可能です。

\usepackage[pdfbox]{gentombow}
\usepackage[size=a4paper]{bxpapersize}
これでPDFを出力すると以下のようになります。
トンボが正しく付いた状態

ノンブルを付ける

同人誌入稿ではノンブル(ページ番号)が全てのページに付いていることが必要です。これは改ページ後の空白ページも含まれます。

しかし、今までの出力されたPDFを見てみると空白ページには何も書いていないことが分かります。これをどうにかしないといけません。

デフォルトで改ページのpagestyleがemptyになっているのが原因なので、これをデフォルトのheadingsに書き換えます。プリアンブルで次のように記述します。


\makeatletter
\def\emptypage@emptypage{%
    \hbox{}%
    \thispagestyle{headings}%
    \newpage%    
}%
\def\cleardoublepage{%
        \clearpage%
        \if@twoside%
            \ifodd\c@page%
                % do nothing
            \else%
                \emptypage@emptypage%
            \fi%
        \fi%
    }%
\makeatother
これでPDFを出力すると以下のようになります。
空白ページにもヘッダーがついた
ヘッダーのデザインを変える場合はfancyhdrパッケージを読み込んで色々設定することでできます。詳しくはfancyhdrの公式のPDFを参照してください。

目次のページ番号を3ページから始めるようにする場合、_output.yamlにbefore_bodyを設定することで本文が始まる前にtexファイルを読み込ませて、\setcounter{page}{3}を利用することで変えられます。
bookdown::pdf_book:
  includes:
    in_header: preamble.tex
    before_body: before.tex
\setcounter{page}{3}

奥付をつける

奥付の付け方はこちらの記事を参考にさせていただきました。

_output.yamlにおいてafter_bodyを指定すると、本文が終わった後(参考文献の後ろ)にtexファイルを読み込ませることができます。

bookdown::pdf_book:
  includes:
    in_header: preamble.tex
    before_body: before.tex
    after_body: after.tex
after.texに奥付を作るコードを書きます。
\clearpage
\vspace*{\stretch{1}}
\begin{flushright}
\begin{minipage}{0.5\hsize}
\begin{description}
  \item{著者:} ASDF
  \item{表紙:} ASDF
  \item{発行:} 2019年1月1日
  \item{サークル名:} ASDF
  \item{連絡先:} ASDF
  \item{印刷:} ASDF
\end{description}
\end{minipage}
\end{flushright}
\clearpage
すると一番最後のページに奥付がつきます。

参考文献をつける

参考文献はafter.texに記述することでつけることができます。

\begin{thebibliography}{9}
  \bibitem{PBRT} Matt Pharr, Wenzel Jakob, Greg Humphreys "Physically Based Rendering" 3rd Edition (Morgan Kaufmann, 2017) ISBN-13:978-0128006450
  \bibitem{veach} Eric Veach, "Robust Monte Carlo Methods for Light Transport Simulation" Ph.D. dissertation, Stanford University, December 1997  
  \bibitem{BB} Henrik Wann Jensen(著), 苗村 健(翻訳) "フォトンマッピング―実写に迫るコンピュータグラフィックス" (オーム社, 2002) ISBN-13:978-4274079504 
\end{thebibliography}
これをそのまま動かすと! Package natbib Error: Bibliography not compatible with author-year citations.というエラーが出てしまいます。natbibを使わないようにすれば良いので、_output.yamlでcitation_packageの部分をコメントアウトします。
bookdown::pdf_book:
  includes:
    in_header: preamble.tex
    before_body: before.tex
    after_body: after.tex
  latex_engine: xelatex
  #citation_package: natbib
  keep_tex: yes
PDFを出力すると以下のようになります。
参考文献

図の挿入

図を挿入するには次のようにします。
# Vec3クラス
Vec3クラスはベクトルを表現するクラスです。ベクトルの演算を演算子オーバーロードを用いて定義することで、プログラム中でベクトルの演算を容易に書けるようにします。

```{r echo=FALSE, fig.cap="Cornell Box", fig.align="center", out.width="100%"}
knitr::include_graphics("img/cornell_box.png")
```
fig.capでキャプション、fig.alignで画像のアラインメント、out.widthで大きさを指定することができます。PDFを出力すると以下のようになります。
LaTeX特有の図がずれずれ問題が発生

図の位置がずれてコードの間に入り込んでしまっています。これはLaTeXを使っているとよく起きる問題で解決策は色々ありますが、ここではfloatパッケージを使った方法を紹介します。プリアンブルに次を記述します。

\usepackage{float}
\floatplacement{figure}{H}
実行すると次のようになります。
図が正しい位置に挿入された

他の細かい設定など

全ての印刷所が同じ入稿形式になっているわけではないので、今まで紹介してきたこと以外にも設定が必要になる項目があると思います。このページで紹介したbxjsbookやfancyhdrパッケージなどには多くのオプションが指定できるので、細かいところはそういうオプションをプリアンブルで指定して対応していくことになります。


Bookdownで執筆してみた感想

序盤は多くのエラーと遭遇してろくにPDFが出力できなくて大変でした。どうにか対応してPDFが出るようになった後も、レイアウトが崩れたり、トンボが出てこなかったり色々なエラーに遭遇しました。しかし一回環境を整えてしまえば、RMarkdownという非常に強力なツールを用いて執筆が行えるので、そこまでの苦労を乗り越えれば大変快適な執筆環境でした。しばらくはこれを使い続けていきたいと思っています。私と似たようなエラーに遭遇している人がこの記事を読んで無事解決に結びつけば幸いです。

Comments