pandoc + markdownでいい感じの執筆環境を作る

何番煎じ感はありますが、markdownを入力としていい感じの組版をしたいと思いました。


# 実現したこと

- markdownをPDFに出力する
- ディレクトリ横断して1ファイルに出力する
- 任意のCSSを適用する
- コードブロックに任意のキャプションを表示する(Qiitaで ```python:test.pyって書くようなやつ)
- 任意の箇所で改ページする

# markdownをPDFに出力する

PDFの出力にはpandocを利用しました

## pandocのインストール

筆者の環境はMacなのでhomebrew経由でインストールしました

```shell

brew install pandoc
```

また、pandocでPDFを出力するためにwkhtmltopdfを追加でインストールしています

```sh
brew cask install wkhtmltopdf
```

これで準備は完了です

## pandocでmarkdownをPDFに出力する

適当なマークダウンを用意します

<pre>
これは00.mdのテストです

- foo
- bar

```python
import zen 

def __name__ == "=__main__":
    print('これはテストです')
```
</pre>


コマンドを実行します
後にCSSを適用したいので、-tでhtmlを経由しているのがポイントです

```shell
pandoc src/00.md -f markdown -t html5 -o ./output.pdf
```

出力結果

<img width="1259" alt="スクリーンショット 2020-04-11 14.07.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67790/384cdea0-24ba-4c77-06a6-8aed117b353d.png">

いい感じです

# ディレクトリ横断して1ファイルに出力する

まとまった文章を書くときは章立てして書くことが多いと思います。そこで1ファイル1章を想定してそれぞれにファイルを分割し、けれども出力は1ファイルのような構成を考えてみます。

先程のファイルをコピーして、構成は以下のようにしてみました。

```shell
tree
.
└─── src
    ├── 00
    │   ├── 00.md
    │   └── 01.md
    └── 01
        └── 00.md
```

markdownで章の表現は`#`なので、先程のファイルの先頭行に`#`の行をそれぞれ追加します。

<pre>
# テスト
これは00/00.mdのテストです

- foo
- bar

```python
import zen 

def __name__ == "=__main__":
    print('これはテストです')
```
</pre>

pandocでは入力のファイルをglobで指定できるので以下のコマンドで1ファイルに出力できます

```shell
pandoc src/**/*.md -f markdown -t html5 -o ./output.pdf
```

さらに章番号を表示する-Nオプションを付与します

```shell
pandoc src/**/*.md -f markdown -t html5 -o ./output.pdf -N
```

<img width="867" alt="スクリーンショット 2020-04-11 14.17.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67790/ec233a1e-d540-506c-9c7c-b4fc0961fe20.png">


# 見た目の調整

これで最低限出力は出来ました。
ここからは見た目の調整や改ページの制御をします。

## コードブロックの背景色を変更する

ハイライトのスタイルをtangoに変更すると背景色が変わります。オプションに--highlight-style=tangoを付与します。

```shell
pandoc src/**/*.md -f markdown -t html5 -o ./output.pdf -N --highlight-style=tango
```

 <img width="918" alt="スクリーンショット 2020-04-11 14.41.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67790/0925dee9-a3f6-7eb8-850c-cff918063c36.png">

## 独自のCSSを当てる

よくmarkdownは表現力が弱いと言われますが、その点については独自にCSSを当てることで解消できます。

markdown内でhtmlタグを書いてしまえばclassを付与できるので、ここからはHTML + CSSの世界で整形できます。

ここでは適当にborderで囲っています

```md:src/00/00.md
<div class="question">
以下のpythonコードの出力を答えよ
</div>
```

```css:style.css
.question {
    border: 1px solid black;
    border-radius: 4px;
    padding: 4px;
}
```

コマンド実行時にCSSを指定します

```shell
pandoc src/**/*.md -f markdown -t html5 -c style.css -o ./output.pdf -N --highlight-style=tango
```

<img width="879" alt="スクリーンショット 2020-04-11 14.50.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67790/8fc9c760-4c65-6b18-96fc-07efc7343206.png">

## コードブロックに任意のキャプションを表示する

Qiitaではコードブロックで
\```md:src/00/00/md
のように書くとキャプションを付与できます。

<img width="429" alt="スクリーンショット 2020-04-11 14.53.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67790/2dd0b6d3-75ca-6bd3-ecbb-8945d85bcb7d.png">

便利なのでこれを実現してみます。

pandocでは`{}` で様々なことができますが、その中の一つにhtmlに属性を付与する機能があります。

以下のように書いた場合、コードブロックの言語はpython、コードブロックのdata-caption属性に'test.py'を付与するようになります。

<pre>
```{.python caption="test.py"}
import math 

def __name__ == "=__main__":
    print('これはテストです')
```
</pre>

また、pandocではコードブロックの言語を指定したとき.sourceCodeクラスを付与します。
これを活用してCSSでdata-caption属性を表示すると以下のようになります。

```css:style.css

.sourceCode:before{
    font-size: small;
	content:attr(data-caption);
    color: #eee;
    padding: 2px;
    background-color: #999;
}
```

<img width="889" alt="スクリーンショット 2020-04-11 15.06.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67790/940042c8-291f-e73c-ddaa-eebed4810b26.png">

## コードブロックに行数を表示する

これも `{}` で設定可能です。
.numberLines、startFromを活用します。

<pre>
``` { .python .numberLines caption="test.py"}
import math 

def __name__ == "=__main__":
    print('これはテストです')
```

4行目だけ表示します

``` { .python .numberLines startFrom='4'}
    print('これはテストです')
```
</pre>

<img width="878" alt="スクリーンショット 2020-04-11 15.12.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67790/6e9f68eb-a988-aeb3-e02e-e40bc4c9124f.png">

## 任意の箇所で改ページする

これもCSSで表現可能です。

空のdivタグを任意の改ページしたい箇所に挿入します

```md
<div class="page-break"></div>
```

```css:style.css
.page-break {
	page-break-before:always;
}
```

## fontを変える

繰り返しですがCSSで表現可能な値は調整可能です

```css:style.css
body {
    font-family: -apple-system, BlinkMacSystemFont, Roboto, "Segoe UI", "Helvetica Neue", HelveticaNeue, "游ゴシック体", YuGothic, "游ゴシック Medium", "Yu Gothic Medium", "游ゴシック", "Yu Gothic", Verdana, "メイリオ", Meiryo, sans-serif;
}
```

<img width="921" alt="スクリーンショット 2020-04-14 12.59.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67790/dd021e81-4521-c017-c8fe-e463794fb7db.png">


---

### 所感
ややCSSでのマークアップ知識は必要ですが、CSSを適用できると技術書の執筆だけに留まらないのかと思いました（e.g. 学校のテスト問題など）

ちょっと触っただけでもpandocの多機能さ = オプションの多いことがわかりました。やりたいことがあるときはまずオプションを漁ってみるのがいいと思います。

# 参考

[多様なフォーマットに対応！ドキュメント変換ツールPandocを知ろう \- Qiita](https://qiita.com/sky_y/items/80bcd0f353ef5b8980ee#pandoc%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)
[Pandoc ユーザーズガイド 日本語版 \- Japanese Pandoc User's Association](http://sky-y.github.io/site-pandoc-jp/users-guide/)
[Inner Journeys: PandocのHTML出力でGFMとカスタムテンプレートを使う](https://babooshka-innerjourneys.blogspot.com/2015/05/pandochtmlgfm.html)
[Pandoc Markdown のあまり知られていない書法 \- Chienomi](https://chienomi.org/archives/digi/software/1697)
[【 content:attr\(\) 】CSSでタグのdata属性やtitle属性を取得して表示する \| 8bit モノづくりブログ｜Web制作、Webサービスに関するコラム｜東京都渋谷区のWeb制作会社 株式会社8bit](https://blog.8bit.co.jp/?p=14553)
[VScodeのMarkdownからPDF変換時に改ページを挿入 \- Qiita](https://qiita.com/0xmks/items/4fec4116bb42120f5180)
[Markdownをgithub\-markdown\.cssを充てつつwkhtmltopdfでpdfに変換 \- Qiita](https://qiita.com/mitsuaki1229/items/c9acf1937e5c529385cc)
[markdown \+ pandoc で、1問1答の小テストプリントを作る \- adbird（広告鳥） 備忘録](https://adbird.hatenablog.com/entry/2017/01/04/205338)