報告書をMarkdownで書いてpdfにしたいと思っていたところPandocを使うと良さそうだと知りました
Pandocはインストールが難しいらしいので、安易にdockerで構築しようと思い立って苦労しました。。。
LaTexは名前は知っていたのですが、学生時代はMSWordで論文を書いたため、ほぼゼロ知識だったのですが今回の構築を通して少し学べました
githubにまとめました
できること
MarkdownからPandocを用いて1コマンドで良い感じのPDFを生成すること
できたもの
pandoc-latex/content.pdf at main · atooshi-note/pandoc-latex
特徴
- Dockerで構築
- pdf-defaults.yaml,header.texに設定を記載
- pandoc-crossrefにより図表番号を自動入力(相互参照)
- 目次のリンク機能
- 章番号自動付与
defaults.yamlはpandoc2.8以降の機能です
環境
- Windows10,11 macOS 12.6.8
- Docker Desktop
Docker
> docker -v
Docker version 24.0.2, build cb74dfc
Pandoc
> docker run -it --entrypoint=/bin/sh --volume "$(pwd):/data" manned2665/pandoclatex311
/data # pandoc -v
pandoc 3.1.1
Features: +server +lua
Scripting engine: Lua 5.4
User data directory: /root/.local/share/pandoc
Copyright (C) 2006-2023 John MacFarlane. Web: https://pandoc.org
This is free software; see the source for copying conditions. There is no
warranty, not even for merchantability or fitness for a particular purpose.
Pandoc-crossref
/data # pandoc-crossref -v
pandoc-crossref v0.3.15.1 git commit 6bc8fa67a4e1ada4787fa0ccd720a19e8e3c818e (HEAD) built with Pandoc v3.1.1, pandoc-types v1.23 and GHC 9.0.1
LuaLaTex
/data # lualatex -v
This is LuaHBTeX, Version 1.15.0 (TeX Live 2022)
Development id: 7509
Execute 'luahbtex --credits' for credits and version details.
There is NO warranty. Redistribution of this software is covered by
the terms of the GNU General Public License, version 2 or (at your option)
any later version. For more information about these matters, see the file
named COPYING and the LuaTeX source.
LuaTeX is Copyright 2022 Taco Hoekwater and the LuaTeX Team.
TexLive 2022
/data # tlmgr version
tlmgr revision 63068 (2022-04-18 07:58:07 +0200)
tlmgr using installation: /opt/texlive/texdir
TeX Live (https://tug.org/texlive) version 2022
「tlmgr」とは「TeX Live Manager」の略
Linux : alpine 3.16.4
/data # cat /etc/alpine-release
3.16.4
ファイルのエンコード
Markdownファイルなど,全てUTF-8とします
shift-jisではエラーになります
Docker image
使用するにはまず、Docker imageを用意します
それには、Dockerfileをビルドするか,docker hubからイメージをpullします
両方同じなのでどちらでも良いです
DockerfileでベースにしたDocker imageは以下です
pandoc/latex - Docker Image | Docker Hub
pandoc/latexは2023年8月時点で最新のpandoc/latex:3.1.1をベースにして、日本語関係をインストールしています(tlmgr install collection-langjapanese
)
pandoc-crossrefはPandocとバージョンを合わせる必要がありますが、pandoc/latex:3.1.1にはpandoc-crossrefが含まれているので新たにインストールは不要です
Dockerfileをビルド
Dockerfileがあるディレクトリにて,以下コマンドを実行します
Dockerfileはgithubにあげています
以下は例として
DockerfileがあるディレクトリはC:\Users
イメージ名 mypandoc
でビルドした場合です
docker build -t mypandoc .
Dockerfileのビルドは初回のみ
次回以降は実行だけで良いです
docker hubからイメージをpull
実行するディレクトリはどこでも良いです
docker pull manned2665/pandoclatex311
PDF生成
docker pull manned2665/pandoclatex311
したとして記載します
Docker Desktopを起動しておき,pdfにしたいmdファイルがあるディレクトリに移動して,以下を実行するとpdfが同じディレクトリに生成されます
(※Docker Desktopが未起動だとエラーになります)
ディレクトリはC:\Users
と仮定します
docker run -it --rm --volume "$(pwd):/data" manned2665/pandoclatex311 -d pdf-defaults.yaml -M listings
- インプットファイル名 content.md
- アウトプットファイル名 content.pdf
インプット,アウトプットファイル名はpdf-defaults.yamlに記載してあります
もしくはコンテナを作成して起動して入ってシェルで実行します
pandoc/latex:3.1.1では、entrypointがpandocコマンドになっています
pandocコマンド以外を使いたい場合、シェル上で操作するためにentrypointを/bin/sh
に上書きをします
なお、参考サイトで使用しているpandoc/latex:2.9.2.1はデフォルトでentrypointがshの様なので、上書きの操作は不要でした
> docker run -it --entrypoint=/bin/sh --volume "$(pwd):/data" manned2665/pandoclatex311
/data # pandoc -d pdf-defaults.yaml -M listings
フォント
フォントはフォントファイルを用意して、任意の場所に置き、pdf-defaults.yamlで指定することで適用できます
欧文フォントは以下で指定できます
- mainfont
- sansfont
- monofont
和文フォントは以下で指定できます
- CJKmainfont
CJK = Chinese Japanese Korean
当然ですが、フォントファイルに斜体,太字斜体が無ければ当然そうはなりません
例えばメイリオなら斜体,太字斜体は無いため,出力されたPDFでもそうはなりません
和文フォントには斜体、太字斜体があるものが少ないためコメントアウトしています
# pdf-defaults.yaml
variables:
mainfont: times.ttf
mainfontoptions:
- Path=./fonts/
- BoldFont=OpenSans-Bold.ttf
- ItalicFont=timesi.ttf
- BoldItalicFont=timesbi.ttf
sansfont: FiraCode-Regular.ttf
sansfontoptions:
- Path=./fonts/
monofont: Quicksand-Regular.ttf
monofontoptions:
- Path=./fonts/
CJKmainfont: meiryo001.ttf
CJKoptions:
- Path=./fonts/
- BoldFont=meiryob001_bold.ttf
#- ItalicFont=meiryo002_ita.ttf
#- BoldItalicFont=meiryob002_bold_ita.ttf
フォントはコンテナ内に入れる必要はありません
フォントの拡張子は以下が使えることを確認しています
- .ttf(.ttcではない)
- .otf
ttcはttfに分解して配置する必要あります
mdファイルと同じディレクトリに置くときの書き方は
# pdf-defaults.yaml
sansfont: FiraCode-Regular.ttf
でokです
./fontsにある場合は
# pdf-defaults.yaml
sansfont: FiraCode-Regular.ttf
sansfontoptions:
- Path=./fonts/
和文フォントについてその他
CJKmainfontで指定する以外にluatexjapresetoptions:
で指定する方法があります(これのほうが一般的かも??)
これにはコンテナ内にフォントがインストールされている必要がありますが、tlmgr install collection-langjapanese
しているので、大方の日本語フォントはインストールされていますCJKmainfont
で指定している場合はCJKmainfont
が優先される模様(これはpdf-defaults.yamlの記載順のせいかもしれないし、よく分かっていないです)
ゴシック体を使いたかったのですが,デフォルトは(私の環境では)luatexjapresetoptions: haranoaji
とすると原ノ味明朝体が本文に適用されており、ゴシック体を指定する方法はわかりませんでした
このためluatexjapresetoptions:
は使用していませんCJKmainfont
で原ノ味(例えば,HaranoAjiGothic-Regular.otf)を指定するなら、luatexjapresetoptions: haranoaji
はコメントアウトして良いです
以下は原ノ味(haranoaji)を指定している例
# pdf-defaults.yaml
# テンプレート変数
variables:
lang: ja
documentclass: ltjsarticle
luatexjapresetoptions: haranoaji
原ノ味については以下
GitHub - trueroad/HaranoAjiFonts: 原ノ味フォント / Harano Aji Fonts
TeXLive2019には,haranoajiが入っていなかったので,
tlmgr install collection-langjapanese
でインストールが必要でした
TexLive2022には最初から入っているようです
フォント関連の参考
- xetex - Pandoc xelatex font-family with relative path - TeX - LaTeX Stack Exchange
- Pandoc + TexLive (LuaTex)によるPDF生成と和文フォント - Chienomi
- メモ: Pandoc+LaTeXで気軽に日本語PDFを出力する -方法2-1: luatexjapresetoptions変数を使う方法 - Qiita
- TeX Liveガイド 2023 p.17
日本語組版を行うためには原則として日本語コレクション(collection-langjapanese)を追加する必要があります)。
コードブロックでのあれこれ
コードブロックでうまくいかなかった事と解決策を記載します
コードブロックにlistings環境を適用するとエラーが発生する
エラー発生なし
{ .python .numberLines startFrom="10" caption="test.py"}
print("Hello World")
エラー発生
{ .python #lst:code .numberLines startFrom="10" caption="test.py"}
print("Hello World")
エラー内容
> docker run -it --rm --volume "$(pwd):/data" manned2665/pandoclatex311 -d pdf-defaults.yaml
Error producing PDF.
! LaTeX Error: Environment codelisting undefined.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.234 \begin{codelisting}
原因
カスタムテンプレート
filterにpandoc-crossrefを使用しており、listingsと干渉しているため
Captions for code listings produce \begin{codelisting} which is not in the listings package · Issue #47 · lierdakil/pandoc-crossref · GitHub
解決方法
header-includesを使わない or -M listings
を追加する
docker run -it --rm --volume "$(pwd):/data" manned2665/pandoclatex311 -d pdf-defaults.yaml -M listings
# pdf-defaults.yaml
# テンプレート変数
variables:
# 採番接頭辞・接尾辞の追加
header-includes:
- \renewcommand{\thesection}{第\arabic{section}章}
- \renewcommand{\thesubsection}{第\arabic{subsection}節}
- \renewcommand{\thesubsubsection}{第\arabic{subsubsection}項}
コードブロックで折り返しが効かず右に突き抜ける
PDF出力時にソースコードが長く、量が多い場合はdefaultでは折返しが効かず右を突き抜けてしまいます。また、下にはみだします
defaultは、 verbatimであり、listings を使うと自動折返しが可能です(ですがcontent.pdfを見ていただくとわかりますが、完全ではありません。未解決です。)
このためlistingsを使用したいのですが、上記した通りpandoc-crossref と listings は干渉して以下のエラーが発生します
同様に-M listings
をつけるとエラーを回避できます
verbatim でのコードブロック
\begin{verbatim}
code code code code code code code code
\end{verbatim}
listings でのコードブロック
\begin{lstlisting}
code code code code code code code code
\end{lstlisting}
エラー内容
> docker run -it --rm --volume "$(pwd):/data" manned2665/pandoclatex311 -d pdf-defaults.yaml
Error producing PDF.
! LaTeX Error: Environment lstlisting undefined.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.133 \begin{lstlisting}
listingsの設定
自動折返しの設定などを含む細かい設定はheader.texに記載します
コマンドラインに -H header.tex
をつける
か、default.yamlで呼び出します
-H header.tex
をつけたパターン
docker run -it --rm --volume "$(pwd):/data" manned2665/pandoclatex311 -d pdf-defaults.yaml -M listings -H header.tex
default.yamlでheader.texをインクルードしたパターン
(コマンドラインに-H header.tex
は不要です)
# pdf-defaults.yaml
# ヘッダーファイルをインクルード
include-in-header:
- header.tex
listings: true
docker run -it --rm --volume "$(pwd):/data" manned2665/pandoclatex311 -d pdf-defaults.yaml -M listings
デバッグについて
pdf出力は時間がかかります
このため、texに一旦出力して、変更点が反映されたかチェックしてからpdfにしたほうが早いです(tex出力は早い)
PandocでMarkdown+Latexからpdfを出力する話 - Qiita
もし、Latexまわりでエラーが出た場合はdefaults.yaml内のoutput-file:desc.texに変え、standalone: trueを追加するとtexファイルが生成されるためエラー箇所が見つけやすいと思います。
# 出力ファイル (単一アイテムで指定)
output-file: content.tex
参考
- Can’t run shell · Issue #47 · pandoc/dockerfiles · GitHub
- 楽にDockerで日本語Pandocする - Qiita
- Pandoc+Dockerでドキュメント作成環境を整備する - 日々是好日
- pandoc-crossrefとEisvogelを併用する - みつきんのメモ
- Inner Journeys: PandocとLuaLaTeXを使ったPDF出力でコードブロックをきれいに表示する
- Pandocを使ってMarkdownでレポートを書いてみる - 屋根裏
- 自分が普段使ってるpandocの設定ファイルをさらす
- Dockerを使用して比較的新しいpandoc環境を簡単に構築する - みつきんのメモ