Honkitで書いたMarkdownのドキュメントをDockerコマンド一発でPDFに出力する

# HonkitをPDFで出力したい
Honkit、便利ですよね。簡単にPDFで出力できたらもっと便利ですよね。

# それ、Dockerですぐにできます
Honkitのディレクトリで、以下のコマンドを実行するだけでoutput.pdfが生成されるんです！
```bash
docker run --rm -v .:/honkit nishidemasami/markdown-docs:v1.2.1 npx honkit pdf ./ ./output.pdf
```

# TL;DR

以下のリポジトリで実践しています。これを見れば一目でわかります。

https://github.com/nishidemasami/honkit-document-sample

# ドキュメントをHonkitで作ってPDFに出力する
とりあえず最小構成で動かしてみます。と言っても白紙が出てもちゃんと動いているかよくわからないので、今回は試しにPlantUMLでAWSのサンプルのAWS構成図を書いてみます。
## ファイル構成
まずは4つのファイルを作成します。
```plantuml
@startuml
title ディレクトリ構成図
skinparam TitleFontSize 0

salt

{
  {T
    + ルートディレクトリ
      ++ book.json | Honkitの設定ファイル
      ++ README.md | READMEページ(このページが無いとダメっぽい？)
      ++ SUMMARY.md | 目次ページ
      ++ plantuml.md | PlantUMLサンプルページ
  }
}

@enduml
```
内容は以下の通りです。

### Honkitの設定ファイル
Honkitの設定ファイルです。

:::note
さらに詳しい設定をしたい場合は以下サイトから設定値を確認してください。PDFの余白の幅とかも変えられますよ！
https://honkit.netlify.app/config.html
:::

```json:book.json
{
    "plugins": [
        "uml"
    ],
    "uml": {
      "charset" : "UTF-8"
    },
    "language": "ja"
}
```

### READMEページ
````md:README.md
# Honkitで書いたドキュメントをDockerでPDFに変換する
このコマンドでできます
```bash
docker run --rm -v .:/honkit nishidemasami/markdown-docs:v1.2.1 npx honkit pdf ./ ./output.pdf
```
````

### 目次ページ
```md:SUMMARY.md
# 目次

* [Honkitで書いたドキュメントをDockerでPDFに変換する](README.md)

* [PlantUmlテスト](plantuml.md)
```

### PlantUMLサンプルページ
````md:plantuml.md
# PlantUmlテスト

```uml
@startuml
'Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
'SPDX-License-Identifier: MIT (For details, see https://github.com/awslabs/aws-icons-for-plantuml/blob/master/LICENSE)

!define AWSPuml https://raw.githubusercontent.com/awslabs/aws-icons-for-plantuml/v14.0/dist
!include AWSPuml/AWSCommon.puml
!include AWSPuml/Groups/all.puml
!include AWSPuml/Compute/LambdaLambdaFunction.puml
!include AWSPuml/General/Documents.puml
!include AWSPuml/General/Multimedia.puml
!include AWSPuml/General/Tapestorage.puml
!include AWSPuml/General/User.puml
!include AWSPuml/MediaServices/ElementalMediaConvert.puml
!include AWSPuml/MachineLearning/Transcribe.puml
!include AWSPuml/Storage/SimpleStorageService.puml
skinparam shadowing false
' define custom group for Amazon S3 bucket
AWSGroupColoring(S3BucketGroup, #FFFFFF, AWS_COLOR_GREEN, plain)
!define S3BucketGroup(g_alias, g_label="Amazon S3 bucket") AWSGroupEntity(g_alias, g_label, AWS_COLOR_GREEN, SimpleStorageService, S3BucketGroup)

!procedure $stepnum($number) 
<back:black><color:white><b>$number</b></color></back>
!endprocedure

' Groups are rectangles with a custom style using stereotype - need to hide
hide stereotype
skinparam linetype ortho
skinparam rectangle {
    BackgroundColor AWS_BG_COLOR
    BorderColor transparent
}

rectangle "$UserIMG()\nUser" as user
AWSCloudGroup(cloud){
  RegionGroup(region) {
    S3BucketGroup(s3) {
      rectangle "$MultimediaIMG()\n\tvideo\t" as video
      rectangle "$TapestorageIMG()\n\taudio\t" as audio
      rectangle "$DocumentsIMG()\n\ttranscript\t" as transcript

      user -r-> video: $stepnum("1")\lupload
      video -r-> audio
      audio -r-> transcript
    }

    rectangle "$LambdaLambdaFunctionIMG()\nObjectCreated\nevent handler" as e1
    rectangle "$ElementalMediaConvertIMG()\nAWS Elemental\nMediaConvert" as mediaconvert
    rectangle "$TranscribeIMG()\nAmazon Transcribe\n" as transcribe
    
    video -d-> e1: $stepnum("2")
    e1 -[hidden]r-> mediaconvert
    mediaconvert -[hidden]r-> transcribe
    mediaconvert -u-> audio: $stepnum("3")
    transcribe -u-> transcript: $stepnum("4") 
    
    StepFunctionsWorkflowGroup(sfw) {
      rectangle "$LambdaLambdaFunctionIMG()\nextract audio" as sfw1
      rectangle "$LambdaLambdaFunctionIMG()\ntranscribe audio" as sfw2

      e1 -r-> sfw1: Start\nExecution
      sfw1 -r-> sfw2
      sfw1 -u-> mediaconvert
      sfw2 -u-> transcribe
    }
  }
}

@enduml
```
````
そしてこのコマンドを実行します。
```bash
docker run --rm -v .:/honkit nishidemasami/markdown-docs:v1.2.1 npx honkit pdf ./ ./output.pdf
```
めでたくoutput.pdfファイルに、3枚ペラのPDFファイルが出力されました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92146/35a53cbc-c78e-535d-3cbd-d0d52442110f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92146/01a3ed59-f947-6dac-3fa4-6f6802f124c5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92146/bf30bd00-167d-8547-df48-d87f13325829.png)

# このDockerの中ではなにをやっているの？

この`nishidemasami/markdown-docs:v1.2.1`コンテナではなにをやっているのでしょうか？

https://github.com/nishidemasami/markdown-docs-dockerfile

詳細は上記のリポジトリで公開していますが、中身はこれだけです。
```dockerfile
FROM debian:12-slim

ENV DEBIAN_FRONTEND=noninteractive

RUN apt update && \
	apt install calibre openjdk-17-jre-headless nodejs npm graphviz fonts-noto-cjk -y && \
	groupadd -g 1000 honkit && useradd -m -d /home/honkit -s /bin/bash -u 1000 -g 1000 honkit

USER honkit
RUN mkdir ~/.npm-global && \
	npm config set prefix '~/.npm-global' && \
	echo export PATH=~/.npm-global/bin:$PATH >> ~/.profile && \
	. ~/.profile && \
	npm install -g honkit gitbook-plugin-uml

WORKDIR /honkit
```
いろいろ入れているのは、主にhonkitを動かすためのnpmとnodejs、PDFを変換するためのcalibreと、PlantUMLを実行するためのJDKとgraphviz、それから日本語フォントです。
それからhonkitユーザでhonkitをグローバルインストールしています。

:::note
ちなみに以前はCalibreのバージョンが古くて公式サイトからわざわざ取得してこないといけませんでしたが、Debian12ではcalibreのバージョンが6.26.0に上がっているので、そのまま使えます。感謝。
:::

おわかりの通り、gitbook-pluginがgitbook-plugin-umlしか入っていないので、他に必要なプラグインがあればnpm installして各自入れてください。

# mainブランチにpushされるたびにGitHub ActionsでPDFとHTMLを生成してReleaseしてGitHub Pagesで見れるようにする
応用として、mainブランチにpushされるたびにDockerでPDFを生成してReleaseするGitHub Actionsを作ってみます。
GitHub Pagesで見れるようにHTMLも生成しています。
```yml:.github/workflows/release-docs.yml
name: Release PDF and Public GitHub Pages

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    timeout-minutes: 30

    steps:
    - name: Checkout
      uses: actions/checkout@v3

    - name: chmod for github actions docker
      run: chmod -R 777 .

    - name: Generate PDF
      run: docker run --rm -v .:/honkit nishidemasami/markdown-docs:v1.2.1 npx honkit pdf ./ ./output.pdf

    - name: Upload PDF
      uses: actions/upload-artifact@v3
      with:
        name: documents
        path: ./output.pdf

    - name: Release
      uses: softprops/action-gh-release@v1
      with:
        name: PDF Release
        tag_name: pdf_relrase
        generate_release_notes: true
        files: ./output.pdf

    - name: Generate pages
      run: docker run --rm -v .:/honkit nishidemasami/markdown-docs:v1.2.1 npx honkit build

    - name: Push to gh-pages
      uses: peaceiris/actions-gh-pages@v3
      with:
        github_token: ${{ secrets.GITHUB_TOKEN }}
        publish_branch: gh-pages
        publish_dir: _book/
```
これで、GitHubでドキュメントを管理して、いつでもPDFやGitHub Pagesで見れるようになりました！

# まとめ
便利すぎるものを便利すぎるもので動かした結果、あまりにも便利すぎることになった