最近、Markdownからpdfを作る機会がありました。
pdf化を都度行うのは手間だったため、何か良い方法がないかを探したところ、 Markdown > Re:VIEW > pdf という経路でpdfを作成できそうでした。
ただ、手動でpdfを生成するのが手間だったため、GitLab CIを使って、push後にMarkdownをtextlintしてからpdf化するCI環境を作ってみました。
目次
環境
| 項目 | 内容 |
|---|---|
| CI環境 | GitLab.comのCI |
| Lintツール | textlint |
| Lint辞書 | 自作 |
| Markdownからpdf化の方法 | Markdown > Re:VIEW > pdf |
| MarkdownからRe:VIEWへの変換 | md2review |
| Re:VIEWからpdfの変換 | review-pdfmaker |
| pdfのレイアウト調整 | Re:VIEWなどに詳しくないため、今回は行わない |
pdf化する対象のMarkdownは target.md です。それ以外のファイルについては後述します。
$ tree
.
└── docs
├── catalog.yml
├── config.yml
├── prh.yml
├── sty
│ ├── README.md
│ ├── gentombow.sty
│ ├── jsbook.cls
│ ├── jumoline.sty
│ ├── plistings.sty
│ ├── review-base.sty
│ ├── review-custom.sty
│ ├── review-jsbook.cls
│ ├── review-style.sty
│ ├── reviewmacro.sty
│ └── techbooster-doujin-base.sty
├── style-web.css
├── style-web.scss
├── style.css
├── style.scss
└── target.md
また、対象のMarkdownファイル target.md は以下のような感じです。
(Pythonコードについては、実際はトリプルバッククォートで囲みましたが、はてなブログに貼り付ける都合上、トリプルシングルクォートにしてあります)
# タイトル
Pythonコードを書きます。
'''
print('Hello world')
'''
## りんごの時期
以下の表を参照のこと。
|項目|時期|
|---|---|
|夏あかり|お盆過ぎ|
|シナノドルチェ|9月中頃|
|シナノゴールド|10月過ぎ|
GitLab CIの設定ファイル .gitlab-ci.yml の作成
GitLabでCIを動かすために .gitlab-ci.yml が必要なので作成します。
今回は、以下のようなPipelineを作成します。
| No | 対象ブランチ | 条件 | ジョブの内容 |
|---|---|---|---|
| 1 | 全ブランチ | GitLabへpush時 | 対象のMarkdownにtextlintを実行 |
| 2 | 指定ブランチ | No.1成功時 | Markdownをpdf化 |
ステージを定義
ジョブを順番に実行するため、ステージを2つ定義します (lint と build)。
stages: - lint - build
ジョブを定義
2つのジョブ markdown_lint と pdf_build を定義します。
また、ジョブの stage にて、各ジョブがどのステージで動作するかを指定します。
markdown_lint: stage: lint pdf_build: stage: build
ジョブ「対象のMarkdownにtextlintを実行」の詳細を定義
ジョブ markdown_lint は、対象のMarkdownにtextlintを実行します。
以下を参考に、今回は textlint と textlint-rule-prh を使うことにします。
textlint + prhで表記ゆれを検出する | Web Scratch
textlintはNode.jsがあれば動作するようなので、Dockerの公式リポジトリから一番軽そうなイメージ node:11.12.0-alpine を使います。
before_script でtextlintのインストールを行い、 script でtextlintを実行します。
ジョブの全体は以下の通りです。
markdown_lint: image: node:11.12.0-alpine stage: lint before_script: - npm install -g textlint textlint-rule-prh script: - cd docs - textlint target.md
ジョブ「Markdownをpdf化する」の詳細を定義
ジョブ pdf_build は、Markdownファイルをpdf化します。
今回、Markdown > Re:VIEW > pdfの変換では、以下のツールを使います。
Dockerイメージは、必要なファイルがすべて含まれている vvakame/review を使います。ありがとうございます。
https://github.com/vvakame/docker-review
あとは、 before_script にて必要なものをインストールし、 script にて変換を行います。
pdf_build: image: vvakame/review stage: build before_script: - apt-get update -y - apt-get -y install build-essential ruby-dev - gem install md2review script: - cd docs - md2review target.md > target.re - review-pdfmaker config.yml
なお、変換後のpdfをダウンロードできるようにするため、 artifacts を定義します。
今回は、中間でできる target.re ファイルやpdfなど、Git管理外ファイルをダウンロードするため、 untracked: true とします。
artifacts: untracked: true
また、pdfをビルドするブランチを master と feature/* に制限するため、 only も定義しておきます。
only: - master - /^feature\/.*$/
設定ファイル .gitlab-ci.yml の全体は以下の通りです。
stages: - lint - build markdown_lint: image: node:11.12.0-alpine stage: lint before_script: - npm install -g textlint textlint-rule-prh script: - cd docs - textlint target.md pdf_build: image: vvakame/review stage: build before_script: - apt-get update -y - apt-get -y install build-essential ruby-dev - gem install md2review script: - cd docs - md2review target.md > target.re - review-pdfmaker config.yml artifacts: untracked: true only: - master - /^feature\/.*$/
textlint向けの定義
以下を参考に、textlint向けの定義を行います。
textlint + prhで表記ゆれを検出する | Web Scratch
今回は、 doc ディレクトリの中に、 prh.yml と textlintrc を作成します。
prh.yml
まずは prh.yml に、textlintでチェックする内容を記載します。
今回は「Python」という単語の表記ゆれはエラーとなるように設定します。
version: 1 rules: - expected: Python specs: - from: python to: Python - from: PYTHON to: Python
.textlintrc
textlint実行時に prh.yml を参照するよう設定します。
{ "rules": { "prh": { "rulePaths": [ "./prh.yml" ] } } }
review-pdfmaker向けの設定
review-pdfmaker向けの設定については、以下のリポジトリを参考にしました。また、一部ファイルはそのまま利用させていただきました。ありがとうございました。
https://github.com/TechBooster/ReVIEW-Template
config.ymlの設定
review-pdfmaker を実行する時の定義ファイル config.yml を doc ディレクトリの中に作成します。
ReVIEW-Templateを元に、以下の内容を記載します。
# この設定ファイルでサポートするRe:VIEWのバージョン番号。 # major versionが違うときにはエラーを出す。 review_version: 3.0 # ブック名(ファイル名になるもの。ASCII範囲の文字を使用) bookname: my_sample_book # 記述言語。省略した場合はja language: ja # 書名 booktitle: {name: "サンプル本", file-as: "sample book"} # 著者名。「, 」で区切って複数指定できる aut: [{name: "thinkAmi", file-as: "thinkAmi"}] # 以下はオプション # a-edt, edt: 編集者 edt: ["my editor"] # a-pbl, pbl: 出版社(発行所) pbl: thinkami_pub. # 刊行日(省略した場合は実行時の日付) date: 2019-3-24 # 発行年月。YYYY-MM-DD形式による配列指定。省略した場合はdateを使用する # 複数指定する場合は次のように記述する # [["初版第1刷の日付", "初版第2刷の日付"], ["第2版第1刷の日付"]] # 日付の後ろを空白文字で区切り、任意の文字列を置くことも可能。 history: [["2019-3-24 v0.0.1"]] # 権利表記(配列で複数指定可) # rights: (C) 2016 Re:VIEW Developers rights: (C) 2019 thinkAmi # デバッグフラグ。nullでないときには一時ファイルをカレントディレクトリに作成し、削除もしない debug: null # HTMLファイルの拡張子(省略した場合はhtml) htmlext: html # # CSSファイル(配列で複数指定可、yamlファイルおよびRe:VIEWファイルを置いたディレクトリにあること) stylesheet: ["style.css"] # ePUBのバージョン (2か3) epubversion: 3 # # HTMLのバージョン (4か5。epubversionを3にしたときには5にする) htmlversion: 5 # 目次として抽出する見出しレベル toclevel: 3 # 採番の設定。採番させたくない見出しには「==[nonum]」のようにnonum指定をする # # 本文でセクション番号を表示する見出しレベル secnolevel: 3 # 本文中に目次ページを作成するか。省略した場合はnull (作成しない) toc: true # 表紙の後に大扉ページを作成するか。省略した場合はnull (作成しない) titlepage: true # 奥付を作成するか。デフォルトでは作成されない。trueを指定するとデフォルトの奥付、ファイル名を指定するとそれがcolophon.htmlとしてコピーされる colophon: true # EPUBにおけるページ送りの送り方向、page-progression-directionの値("ltr"|"rtl"|"default") direction: "ltr" epubmaker: # HTMLファイルの拡張子 htmlext: xhtml stylesheet: ["style.css","epub_style.css"] # LaTeX用のスタイルファイル(styディレクトリ以下に置くこと) texstyle: ["reviewmacro"] # B5の設定(10pt 40文字×35行) - 紙版 texdocumentclass: ["review-jsbook", "media=print,paper=b5,serial_pagination=true,hiddenfolio=nikko-pc,openany,fontsize=10pt,baselineskip=15.4pt,line_length=40zw,number_of_lines=35,head_space=30mm,headsep=10mm,headheight=5mm,footskip=10mm"] pdfmaker: # 奥付を作成するか。trueを指定するとデフォルトの奥付、ファイル名を指定するとそれがcolophon.htmlとしてコピーされる colophon: true webmaker: stylesheet: ["style.css","style-web.css"]
pdf化するコンテンツの設定 (catalog.yml)
pdfに含まれるコンテンツの設定を行います。
本文部分のRe:VIEWファイルは、 target.md が変換された target.re になります。そのため、 target.re を CHAPS に指定します。
PREDEF: CHAPS: - target.re APPENDIX: POSTDEF:
デザインまわりのファイルのコピー
今回デザインまわりは何も修正しないため、リポジトリ TechBooster/ReVIEW-Template のものをそのままコピーしました。
コピーするのは以下です。
以上で準備が終わりました。
動作確認
masterブランチ
今までの作業を master ブランチにコミットし、GitLabにpushします。
すると、以下の画像のように、Lintとpdfの生成ができました。
右側にあるダウンロードボタンを押すことで、Re:VIEWとpdfのファイルがzip化されたものがダウンロードできます。

featureブランチ
次に、Lintエラーが出るように以下を追加した target.md をfeatureブランチにcommitします。
- python - PYTHON
GitLabにpushしてCIを確認すると、Lintチェックエラーになりました。

また、後続のpdf作成ジョブは実行されていませんでした。
lint-onlyブランチ
最後に、Lintエラーが出るように以下を追加した target.md を lint-only ブランチにcommitします。
- Lintだけします - python
GitLabにpushしてCIを確認すると、Lintチェックエラーになりました。

また、今までと異なり、後続ジョブ pdf_build がありません。
以上で、GitLab CI + docker-reviewを使って、Markdownをtextlintしてからpdf化するCI環境ができました。