Honkit でつくられたドキュメント群を PDF で書き出すメモです。
Honkit で教材を作っていた
こちらの授業資料をHonkit で教材を作っていました。
こんなかんじです。
公式の PDF 化のナレッジはあるにはあるがうまくいかない
eBook and PDF · HonKit Documentation
こちらに公式の資料もあって PDF 化できそうなんですが、2021年11月現在 Windows だとバージョンの違いなのか PDF 化のコアとなる Calibre に対して連携できなくて、うまく PDF にすることができませんでした。
HonKitでMarkdown から PDFを作成する – Secret Ninja Blog
WSL で頑張れなくはなさそうなんですが、やっぱりバージョンが良くないなどエラーがめちゃくちゃ出るので、この路線は断念。
全ドキュメントを1ページにまとめて Honkit で書き出して PDF 印刷してしまおう
はい。できるだけシンプルに出来ないかなということで、こういう着地になりました。
- 全ドキュメントを目次ページである SUMMARY.md から結合する Markdown ファイル群を取得
- 全ドキュメントを1ページにまとめて Honkit で書き出し
- その1ページを PDF 印刷
でやってみます。
下準備
まず、今までのドキュメントは壊したくないので pdf というフォルダを作って、基本的な構造を移植します。
- layout.html
- website.css
- book.json
- SUMMARY.md
を持ってきます。README.md はひとまず空ファイルで。
SUMMARY.md
# Summary - [README](README.md)
SUMMARY.md は書き出し後の README.md だけなのでこのように記述しました。
元ネタの SUMMARY.md から全ドキュメントを 1 ページにまとめる Node.js のコード
こんな app.js を書きました。
const fs = require('fs').promises; const path = require('path'); async function main (){ // SUMMARY.md から結合する Markdown ファイル群を取得 const filepath = path.resolve(__dirname , './base/SUMMARY.md'); const message = await fs.readFile(filepath, {encoding: 'utf-8'}); // Markdown のリンク記法の配列で入ってくる let resultMarkdownLinkList = message.match(/\[(.*)\]\((.*)\)/gm); console.log(resultMarkdownLinkList); // 大量に取得してしまうと確認がしにくいので、いったん取得後に数件に限定する処理 // チューニング用 /* resultMarkdownLinkList = [ resultMarkdownLinkList[0], resultMarkdownLinkList[1], resultMarkdownLinkList[2] ] */ // ファイルを結合して README.md 1ファイルに集約 let targetContent = ""; let targetContentAll = ""; for(let i = 0; i < resultMarkdownLinkList.length; i++){ const targetMatchResult = resultMarkdownLinkList[i]; // Markdown のリンク記法からリンクタイトルとファイルパスを抽出 const regexp = /\[(.*)\]\((.*)\)/gm; const match = regexp.exec(targetMatchResult); // console.log(match[1],match[2]); const targetSummaryTitle = match[1]; const targetResolveFilepath = match[2]; // 相対パス化 const targetFilepath = path.resolve(__dirname , './base/' , targetResolveFilepath); // 非同期でコンテンツ読み込み targetContent = await fs.readFile(targetFilepath, {encoding: 'utf-8'}); console.log('----'); console.log(targetContent.substr(0,100)); // コンテンツ連結 targetContentAll += targetContent; } console.log('----'); console.log('コンテンツ書き込み'); console.log('----'); // pdf というフォルダに格納する // この pdf フォルダを honkit で書き出し const filepathMainContent = path.resolve(__dirname , './pdf/' , 'README.md'); // コンテンツ書き込み await fs.writeFile(filepathMainContent,targetContentAll); } main();
イレギュラーな状態をあまり想定していないですが、私の場合 base フォルダに全ドキュメントの Markdown があります。
その元ネタの SUMMARY.md から結合する Markdown ファイル群を Markdown のリンク記法で取得したあと、Markdown のリンク記法からリンクタイトルとファイルパスを抽出し、pdf/README.md にガシガシつなげました。
website.css の調整
印刷用の CSS として調整しました。
ページのサイズは A4 縦を上下左右 10 mmくらいマージンとったものです。body タグでは、それより少し小さく収まるサイズにしています。
.page-inner
だけは、通常のレイアウトだと 60% が効いていて印刷時には変に狭く出てしまったので、このように調整しています。
/* 印刷用 */ @media print { @page { size: 190mm 277mm; margin: 0; } body{ /*A4縦 210mm x 297mm*/ width: 186mm; height: 270mm; } .page-inner { width: 100% !important; } }
book.json の調整
book.json も印刷レイアウト時に邪魔するプラグインを減らしました。
{ "title": "デジタルハリウッド大学院大学 2021 プロダクトプロトタイピングII 授業資料", "description": "2021 授業資料", "language": "ja", "plugins": [ "anchors", "hide-published-with", "intopic-toc" ], "styles": { "website": "styles/website.css" } }
こちらです。
"plugins": [ "anchors", "hide-published-with", "copy-code-button", "intopic-toc", "back-to-top-button" ]
copy-code-button
は印刷時には必要なかったのと、back-to-top-button
は印刷後の全ページの右下にトップに戻るボタンが出てしまったので無くしました。
いざ書き出し
"scripts": { "serve-pdf": "honkit serve pdf src-pdf", "serve": "honkit serve base src", "build": "honkit build base docs",
package.json に serve-pdf
という、今回の pdf フォルダの内容を src-pdf に HTML で書き出すコマンドを作って書き出しました。
npm run serve-pdf
実行。
無事書き出されて http://localhost:4000/
で見ることができました。
PDF 印刷
あとは Chrome ブラウザから PDF で印刷を選択しましょう。
今回は 500 ページ越えなので、取得に時間がかかりました!
無事出てきたので印刷します!
PDF 保存できました!
無事、生徒の希望にも応えれた
生徒の反応も上々な様子。
私も「どこかでまとめなきゃなー」と思っていた作業だったのがうまくいって良かったです。
今後、余裕があれば
- 改ページが読みづらい切られ方をするケースもあるのでできれば調整
- 印刷用 CSS をより良い感じに出来ないか模索
- Puppeteer やヘッドレス Chrome ブラウザで印刷自体を自動化
などなど、良くしていきたいなと思いました!