Markdown からいい感じの PDF を作る


やりたいこと

  • Markdown を PDF にしたい
  • 文章は日本語で書きたい
  • 自動で表紙を生成したい
  • 見出しから自動で目次を生成したい
  • 見出しを自動で採番したい
  • コードブロックをそれなりの見た目で表示したい
  • PlantUML を画像に変換して埋め込みたい
  • 環境構築が楽な方法が良い
  • 最終的に CI に組み込みたい

方法

変換自体はいくつかの手段がありそうでしたが、表紙や目次を自動生成するとなると Pandoc が良さそうです。
ただ、上記のような要求を満たそうとすると環境構築がそれなりに面倒そう (+ CI に組み込むのが難しそう) だったので、必要なものを突っ込んだ Docker イメージ を作りました。

作成した Docker イメージ

frozenbonito/pandoc-eisvogel-ja

特徴

ベースイメージ

公式の pandoc/latex イメージをベースにしています。alpine ベースなので比較的軽量です。

テンプレート

デフォルトで Eisvogel template を使うようになっています。
Markdown → PDF or LaTex 変換のために作られたテンプレートで、かなりいい感じのスタイルにしてくれます。
豊富な カスタムテンプレート変数 が用意されているのである程度カスタマイズも可能です。

日本語フォント

次のフォントに対応しています。

デフォルトは原ノ味フォントです。

PlantUML 対応

plantuml tag には timofurrer/pandoc-plantuml-filter が入っています。
デフォルトでフィルターが有効になっているので特に意識せずに使用することができます。
PlantUML 対応のために Java や Graphviz、Python が必要となりイメージが肥大化してしまうので、別の tag にしています。PlantUML サポートが必要ない場合は軽量な latest tag などを使用する想定です。

pandoc-crossref

一応、pandoc-crossref も入っています。こちらはデフォルトで有効になっていないのでオプションから有効にする必要があります。

PlantUML と組み合わせる方法はなさそうです…。

使い方

基本

pandoc コマンドが ENTRYPOINT になっています。
次のコマンドでカレントディレクトリの doc.md を doc.pdf に変換できます。

$ docker run --rm -v $(pwd):/data frozenbonito/pandoc-eisvogel-ja -o doc.pdf doc.md

日本語フォントの指定

デフォルトの原ノ味フォントから変更したい場合は luatexjapresetoptions 変数を使います。
luatexjapresetoptions については こちらの記事 が非常に参考になります(Eisvogel も対応しているようです)。

IPAex に変更する場合は以下のようにします。

$ docker run --rm -v $(pwd):/data frozenbonito/pandoc-eisvogel-ja \
    -V luatexjapresetoptions=ipaex \
    -o doc.pdf \
    doc.md

PlantUML

PlantUML を使う場合は plantuml tag を指定します。

$ docker run --rm -v $(pwd):/data frozenbonito/pandoc-eisvogel-ja:plantuml -o doc.pdf doc.md

使用例

こちらの Markdown を PDF に変換してみます。

「やりたいこと」 に記載した要求を満たすためいくつかオプションをつけて実行します。

docker run --rm -v $(pwd -W):/data frozenbonito/pandoc-eisvogel-ja:plantuml \
    --listings \
    -N \
    --toc \
    -V linkcolor=blue \
    -V table-use-row-colors=true \
    -V titlepage=true \
    -V toc-own-page=true \
    -V toc-title="目次" \
    -o doc.pdf \
    example-pandoc-eisvogel-ja.md

結果は次のような感じになります。



与えたオプションの意味は次の通りです。

  • --listings
    • コードブロックの有効化 (LaTex の listings パッケージの有効化)
  • -N
    • 見出しの自動採番を有効化
  • --toc
    • 目次の自動生成を有効化
  • -V linkcolor=blue
    • Eisvogel 用の変数定義
    • リンクテキストの色を青に変更
  • -V table-use-row-colors=true
    • Eisvogel 用の変数定義
    • テーブルの行の色を行ごとに変えるようにする
  • -V titlepage=true
    • Eisvogel 用の変数定義
    • 表紙の生成を有効化
      • 表紙は Markdown 冒頭に記載した yaml 形式のメタデータを参照して生成される
  • -V toc-own-page=true
    • Eisvogel 用の変数定義
    • 目次の後に改ページを入れる
  • -V toc-title="目次"
    • Eisvogel 用の変数定義
    • 目次のタイトルを「目次」に変更
      • デフォルトは 「Contents」

オプションが多すぎて指定が面倒な場合は設定ファイルを作成して読み込むこともできます。

config.yaml
listings: true
number-sections: true # -N と同等
table-of-contents: true # --toc と同等
variables: # -V と同等
  linkcolor: blue
  table-use-row-colors: true
  titlepage: true
  toc-own-page: true
  toc-title: 目次
docker run --rm -v $(pwd -W):/data frozenbonito/pandoc-eisvogel-ja:plantuml \
    -d config.yaml \
    -o doc.pdf \
    example-pandoc-eisvogel-ja.md

その他のオプションについては Pandoc User's GuideEisvogel の README を参照してください。