# ポイント

  • pandocを用いてmarkdownを(tex経由の)pdfにコンパイルするdocker imageを作る

    • documentclassはltjsbookがいいな
    • 自前のテンプレートを使って様々な体裁に対応
    • bibliographyファイルを用意すれば、参考文献も載せられる
  • 上記imageを用いて、自動コンパイル+そのままgit pushするgithub actionsを作る

# 動機

レポートや論文をmarkdownで書きたい。texで消耗もしないし、テキストファイルで書ければ差分管理も楽ちんなので。

ただし、markdownで書いたままの落書きでは人様に見せられないので、体裁を整えて然るべき拡張子のファイルにする必要がある。

pandocでmd->tex->pdfとコンパイルすることにした。
で、これをやってくれるdocker imageがある。(今回はbibliographyを載せたいので、このイメージをちょっといじるけどね)

実際使ってみたが
md書く->pdfにコンパイル->git push
↑この工程のうち、毎回コンパイル挟むのが面倒になってきた。(すぐ面倒臭がる)

なのでpandocによるコンパイルをgit push後に自動でやってもらう事にした。←今回の本題

# pandocを乗っけたdocker image

基本は以下の記事を読んでください。

まだまだ Word で消耗してるの? 大学のレポートを Markdown で書こう (Docker 編)

ただ、上記イメージにはbibliographyを挿入するのに必要なpandoc-citeprocが入っていなかったので、入れ直すついでにpandocのバージョンも上げた。

pandoc入れ直すDockerfile
FROM kumassy/alpine-pandoc-ja

WORKDIR /src

COPY ./ /src

RUN ls -la

RUN apk update && \
  apk upgrade && \
  apk add --no-cache git

RUN wget https://github.com/jgm/pandoc/releases/download/2.9.1.1/pandoc-2.9.1.1-linux-amd64.tar.gz
RUN tar xvfz pandoc-2.9.1.1-linux-amd64.tar.gz
RUN cp pandoc-2.9.1.1/bin/* /usr/local/bin/

RUN rm -r /usr/bin/pandoc-crossref \
  && wget https://github.com/lierdakil/pandoc-crossref/releases/download/v0.3.6.1a/linux-pandoc_2_9_1.tar.gz -q -O - | tar xz \
  && mv pandoc-crossref /usr/bin/

これをbuildして、

# イメージ名my-pandoc-jaとしてビルド
$ docker build ./ -t my-pandoc-ja

こんな感じで使うとコンパイルできる。

# input.mdにreferences.bibを付け足してoutput.pdfに書き出す
$ docker run -it --rm -v `pwd`:/src my-pandoc-ja pandoc -F pandoc-crossref input.md -o output.pdf --pdf-engine=lualatex --template mytemplate.tex -N --top-level-division=chapter  --bibliography=references.bib

テンプレートは自前のものを用意するか、以下のようにデフォルトのテンプレートを吐き出して使うかする。

$ docker run -it --rm -v `pwd`:/src my-pandoc-ja pandoc -D latex > mytemplate.tex

おそらく目次以前のページに関するレイアウトをいじることになると思う。(表紙とか概要とか)
自分は標準テンプレートのmaketitle部分をいじって、表紙にいろんな情報を載せられるようにした。

# github actionsで自動コンパイル

基本は以下リンクを参照。

ワークフローを設定する - GitHub ヘルプ

pushされたらworkflowを起動させたいので、on: push を指定。

# 自前imageつかってコンパイルする

各stepのusesメンバにDockerfileが置いてあるディレクトリを指定することで、そのDockerfileをもとにしたイメージをビルドする。

with.argsはビルドしたイメージでrunしたいコマンドを指定する。

今回の場合は上記イメージにpandocによるコンパイルを任せたいので、

    - name: pdf compile
      uses: ./path/to/image/
      with:
        args: pandoc -F pandoc-crossref input.md -o output.pdf --pdf-engine=lualatex --template mytemplate.tex -N --top-level-division=chapter  --bibliography=references.bib

こんな感じになる。

# コンパイル結果をgit pushする

このままではただコンパイルしただけになってしまうので、結果をどこかに上げるなりしないといけない。

今回はそのままgit pushすることにした。
(gitに無闇にバイナリを乗せるのもどうかと思うので、多分クラウドストレージにアップロードするなりした方がいい。)

gitにログインして変更をpushするコマンド
# gitユーザー設定
git config --global user.name "your-git-username"
git config --global user.email "your-git-email"

# 追跡
git remote set-url origin https://your-git-username:${GITHUB_TOKEN}@github.com/your-repository.git

git checkout -b master

#
#  なんやかんややる
#

# git push
git status
git add .
git commit -m '[updater] update.'
git push origin HEAD

# 2つをまとめる

まとめて以下のようなshを作った。

# gitユーザー設定
echo "set git config."
git config --global user.name "your-git-username"
git config --global user.email "your-git-email"

# 追跡
git remote set-url origin https://your-git-username:${GITHUB_TOKEN}@github.com/your-repository.git

git checkout -b master

# pandocでpdfコンパイル
echo "build pdf."
pandoc -F pandoc-crossref input.md -o output.pdf --pdf-engine=lualatex --template mytemplate.tex -N --top-level-division=chapter -B abstract.tex --bibliography=references.bib

# git push
echo "git push."
git status
git add output.tex
git commit -m '[updater] update pdf.'
git push origin HEAD

やっていることは、

  1. gitにログイン
  2. git追跡開始
  3. pdfコンパイル
  4. コンパイル結果のcommit, push

該当stepのwith.argsに、このshを実行するようにコマンドを渡せばok.

    - name: git update step
      uses: ./.github/images/
      with:
        args: sh ./lib/update.sh

# 環境変数

出力結果などのファイル名を変えるのが面倒なので、envメンバに然るべき環境変数を置くことで出力ファイル名などの管理を簡単にする。

# できた

このリポジトリに完成版があります。

各人のリポジトリで試してみてください。
pushしたら勝手に後追いでコンパイルしたpdfがpushされるはずです。

# future works

コンパイル結果をgitにpushするのではなく、適当なクラウドストレージにアップロードしたい。google driveでいいかな

また、workflow自体はイメージを毎回ビルドするので遅い。早くするには

  • イメージを軽くしてパッケージレポジトリに上げる(多分texのみ入っているalpineイメージでも事足りるはず)
  • キャッシュを使う(イメージのキャッシュってどうすればいいんだろう)

といいと思います(投げやり)

遅いなら遅いで、コンパイルできたら通知するようにしてもいいかも (slack連携なら秒でできるはず)