みつきんのメモ

組み込みエンジニアです。Interface誌で「My オリジナルLinuxの作り方」連載中

pandocのdockerでEisvogelを使用する

はじめに

pandocが提供しているDockerコンテナpandoc/latexをベースにEisvogelを使用できる環境を作成する。

目指すゴールは下記が全て機能すること。

  • PlantUMLが使用できる
  • Eisvogelを使用してきれいなPDFを出力できる
  • pandoc-crossrefが使用できる

[2022/4/9 追記]
成果物をgithubに置いた

PlantUMLを使用できる環境の作成

pandoc/coreをベースにPlantUMLを使用できる環境はDockerを使用して比較的新しいpandoc環境を簡単に構築するで構築した。

pandoc/coreは標準でpandoc-crossrefが使用可能となっている。

今回使用するpandoc/latexはpandoc/coreをベースにしているため、pandoc/coreを使用して実現できた機能はそのまま転用することができる。

Eisvogelを使用できる環境の作成

TeX関連のパッケージの追加

執筆時点のpandoc/latexではTexLive 2021をベースとしLaTeX環境が構築されているため、tlmgrでLaTeX用のパッケージをインストールできる環境が整っている。

Eisvogelのサイトで案内されている手動でのインストールが必要があるパッケージは下記のようになっている。

adjustbox babel-german background bidi collectbox csquotes everypage filehook
footmisc footnotebackref framed fvextra letltxmacro ly1 mdframed mweights
needspace pagecolor sourcecodepro sourcesanspro titling ucharcat ulem
unicode-math upquote xecjk xurl zref

これらをDockerイメージに追加する必要がある。

また、日本語を取り扱う必要があるので、この辺りのパッケージも必要になる気がする。

babel-japanese luatexja haranoaji

Eisvigolがbabel-germanを使用しているのでbabel-japanese。pandocのpdfengineにlualatexを指定する際に日本語を取り扱うためluatexja。

日本語のフォントであるharanoajiを追加する。

scrartcl.clsのエラー

環境構築後にEisvigolを使用してpandocを実行すると下記のようなエラーが発生した。

Error producing PDF.
! LaTeX Error: File `scrartcl.cls' not found.

Type X to quit or <RETURN> to proceed,
or enter new name. (Default extension: cls)

Enter file name: 
! Emergency stop.
<read *> 
         
l.54 \usepackage

Where to find scrartcl.cls ? #238に、koma-scriptパッケージを追加すると良さそうなことが書いてあるので、tlmgrでkoma-scriptを追加する。

Eisvogelのインストール

github上のソースコードにraw指定してhttps://raw.githubusercontent.com/Wandmalfarbe/pandoc-latex-template/master/eisvogel.texのようなURLからファイルを取得するようなサイトをいくつか見かけたが、ここはお行儀よくきちんとリリース物を取得するようにしておく。

/opt/pandoc/templates以下にpandoc-latex-template本体となるファイルを配置する。

mkdir -p /opt/pandoc/templates
wget -O - https://github.com/Wandmalfarbe/pandoc-latex-template/releases/download/v2.0.0/Eisvogel-2.0.0.tar.gz | tar zxvf - -C /opt/pandoc/templates

pandoc-crossrefを使用できる環境を作成

pandoc/coreをベースとしているpandoc/latexの環境ではpandoc-crossrefを使用すること自体はできる。 ただし、Eisvogelと併用しようとすると、いろいろとバッドノウハウが必要になる。

筆者が遭遇した問題を挙げると下記のような問題の対処が必要となる。

  • pandoc-crossref使用時にlistingを有効化するとエラーになる
  • リストのキャプションが「Listing」に固定される

pandoc-crossref使用時にlistingを有効化するとエラーになるの対処

pandoc-crossref使用時にlistingを有効化すると下記のようなエラーになる。

Error producing PDF.
! LaTeX Error: Environment lstlisting undefined.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...

l.456 \begin{lstlisting}

この辺はpandoc-crossrefとEisvogelを併用するにも回避方法を記載している。

最終的にはpandoc実行時に-M listingsとしてメタデータを定義してやると回避できる。

リストのキャプションが「Listing」に固定されることを回避する

pandoc-crossrefでは、図表番号のキャプションにつくprefixをyamlで定義することができる。このファイルはcrossref_config.yamlとして作成しておく。

figureTitle: "図 "
tableTitle: "表 "
listingTitle: "リスト "
figPrefix: "図"
eqnPrefix: "式"
tblPrefix: "表"
lstPrefix: "リスト"

しかし、listingを有効化すると、リストのキャプションのprefixがListingで固定されてしまう。 せっかくpandoc-crossrefを使用するのでyamlで定義したものと一致させたい。

これを変更するにはheader-includesで下記のようにしてLaTeXの変数を上書きする必要がある。詳しいやり方は大学のレポートをMARKDOWNで爆速で書く話を参照。

header-includes:
- \renewcommand{\lstlistingname}{Source Code}

しかし、マークダウンに毎回yamlヘッダで指定するのは嫌なので、下記の様にtexファイルを作成しpandoc実行時に-Hオプションで指定する。このファイルはheader.texとして作成しておく。

\renewcommand{\lstlistingname}{リスト}

環境構築

ここまでの内容を踏まえてDockerfileを作成し、そのコンテナを使用してpandocを実行するためのコマンドラインを考える。

Dockerfile

Dockerfileは下記のようになった。

FROM pandoc/latex

# Eisvogel latex-template
RUN tlmgr install \
    adjustbox \
    babel-german \
    background \
    bidi \
    collectbox \
    csquotes \
    everypage \
    filehook \
    footmisc \
    footnotebackref \
    framed \
    fvextra \
    letltxmacro \
    ly1 \
    mdframed \
    mweights \
    needspace \
    pagecolor \
    sourcecodepro \
    sourcesanspro \ 
    titling \
    ucharcat \
    ulem unicode-math \
    upquote \
    xecjk \
    xurl \
    zref \
    koma-script

# Japanese
RUN tlmgr install \
    babel-japanese \
    luatexja \
    haranoaji

# Eisvogel
RUN mkdir -p /opt/pandoc/templates && \
    wget -O - https://github.com/Wandmalfarbe/pandoc-latex-template/releases/download/v2.0.0/Eisvogel-2.0.0.tar.gz | \
    tar zxvf - -C /opt/pandoc/templates

RUN apk add --no-cache \
    graphviz \
    openjdk11 \
    python3 \
    py3-pip \
    ttf-droid \
    ttf-droid-nonlatin

RUN apk add --no-cache \
    wkhtmltopdf

ARG plantuml_version="1.2022.2"
RUN wget https://github.com/plantuml/plantuml/releases/download/v${plantuml_version}/plantuml-${plantuml_version}.jar -O /opt/plantuml.jar

RUN pip3 install --upgrade pip
RUN pip3 install pandoc-plantuml-filter

ENV PLANTUML_BIN="java -jar /opt/plantuml.jar"

ENTRYPOINT [ "/usr/local/bin/pandoc" ]

これを下記のようにビルドしてイメージを作成する。

$ docker build -t pandoc-eisvogel .

dockerコンテナを利用してpandocでPDFを生成する

pandoc-eisvogelというタグでイメージを作成したので、これを利用してコンテナを実行する。

マークダウンファイル

対象となるマークダウンファイルをREADME.mdとして作成する。

---
title: 使用例
subtitle: サブタイトル
date: 2022-04-03
author: jhon doo
---

# 概要

概要の本文

## 見出し2

見出し2の本文


# PlantUML

```{#fig:uml .plantuml caption="クラス図"}
サブクラス -|> 親クラス
```

# コード

ハローを @lst:hello に示す。


```{#lst:hello .cpp caption="ハローワールド"}
#include <iostream>

int main() { //ハロー
std::cout << "hello world" << std::endl;
return 0;
}
```

# 表

@tbl:table のサンプル


| No | 項目   |
|----|--------|
| 1  | りんご |
| 2  | みかん |
: フルーツ {#tbl:table}

# 結論

おしまい

下記のようなコマンドでPDFを生成する。

docker run --rm \
       --volume "$(pwd):/data" \
       --user $(id -u):$(id -g) \
       pandoc-eisvogel \
       ./README.md \
       --filter pandoc-plantuml \
       --filter pandoc-crossref \
       --metadata-file="./crossref_config.yaml" \
       --standalone \
       --data-dir=/opt/pandoc \
       --template eisvogel \
       --pdf-engine lualatex \
       -V lang=ja \
       -V luatexjapresetoptions=haranoaji \
       -V CJKmainfont=HaranoAjiGothic \
       -V caption-justification=centering \
       -N \
       --toc \
       -M listings \
       --listings \
       -H ./header.tex \
       -V linkcolor=blue \
       -V table-use-row-colors=true \
       -V titlepage=true \
       -V toc-own-page=true \
       -V toc-title="目次" \
       -o README.pdf

出力結果

f:id:mickey_happygolucky:20220407170925p:plain

f:id:mickey_happygolucky:20220407170955p:plain

f:id:mickey_happygolucky:20220407171100p:plain

f:id:mickey_happygolucky:20220407171119p:plain

まとめ

下記の機能は実現できた。

  • PlantUMLが使用できる
  • Eisvogelを使用してきれいなPDFを出力できる
  • pandoc-crossrefが使用できる

Eisvotelを使用すると簡単で非常にきれいなPDFが作成できるので、これを使う例はネット上ではよく見つかるが、 カスタマイズは結構面倒なので自分が使いたい機能を全て使えるようにするような記事は見つからなかった。

これで自分のやりたいことができる環境が作れたと思う。