コードは、Markdownドキュメントが画面上では問題なく見えるのに、紙の上で崩れることが最も多い部分です。ワイドモニターに収まる行が、A4ページの右マージンを越えてしまうことがあります。フェンス付きブロックがページの下端に置かれ、2行だけが前のページに残り、残りが次のページへ送られることもあります。言語タグのないブロックは、隣のブロックと異なる表示になることがあります。
md2pdfはフェンス付きコードを印刷レイアウト内の整形済みテキストとしてレンダリングします。シンタックスハイライトは追加せず、ページに収めるためにソースコードを折り返すこともありません。これは意図的な制限です。コードを収めるために変更すると、意味が変わってしまう可能性があるからです。実践的なアプローチは、変換なしでも印刷されたブロックが読めるようにソースを整えておくことです。
本ガイドでは、フェンス付きブロック、言語タグ、行の長さ、テーマ、そしてPDFを送る前に問題を見つけるための確認項目を扱います。エンドツーエンドの流れについては、GitHubのREADMEをPDFに変換する方法から始めてください。
コンバーターがフェンスに何をするか
GitHub Flavored Markdownは、3つ以上のバッククォートまたはチルダで区切られたフェンス付きコードブロックをサポートします。md2pdfはそのフェンスを解析し、テキストをそのまま保持して、<pre><code>要素内にレンダリングします。開始フェンスの後の言語タグはクラス名として保持されますが、現在のレンダラーはシンタックスハイライトのテーマを適用しません。
つまり、次の2つのことになります。
- インデント、空行、句読点はそのまま残る。
- 見た目は、テーマのコード背景と枠線を持つ等幅テキストであり、色付きのトークンにはならない。
差分を色で説明しているドキュメントでは、短いキャプションを追加するか、ソース内で+と-のマーカーを使ってください。印刷されたコピーで読者が緑と赤を見分けられると仮定してはいけません。
インデントではなくフェンス付きブロックを使う
4つのスペースによるインデントもMarkdownではコードブロックになりますが、フェンスのほうが制御しやすいです。開始と終了が明示され、言語タグをサポートし、ブロック内の行がたまたまインデントされていても壊れません。
シンプルなフェンス付きブロックの例です。
npm install
npm run build
npm test
コンテンツ内に現れるバッククォートの連続より長いフェンスを使ってください。コードに3連バッククォートが含まれる場合は、4つで開いて閉じます。これはMarkdown自体についてのドキュメントで特に重要です。フェンスが例の一部になっていることがあるからです。
ブロック内でタブとスペースを混在させないでください。レンダラーは書いたとおりを保持するため、コードが正しくても不揃いなインデントはバグのように見えます。
ハイライトがなくても言語タグを付ける
シンタックスハイライトがなくても、言語タグは役に立ちます。意図した言語を記録し、エディターやリンターの助けになり、翻訳者にそのブロックを翻訳してはいけないという明確な信号を与えます。ソースの検索もしやすくなります。
一般的なタグはbash、js、ts、json、yaml、python、html、css、sql、textです。出力、ログ、ディレクトリツリー、プログラミング言語でないものにはtextを使ってください。短いスニペットならタグなしのプレーンなフェンスでもかまいませんが、読者がコピーする可能性があるものにはタグを付けるほうがよいです。
ハイライターが認識するという理由だけで言語タグを付けないでください。コンテンツが実際に何であるかをタグにします。プロンプトと出力を含むシェルの記録は、プロンプトがコマンドの一部でない限り、bashではなくtextです。
行を印刷可能な幅に収める
最もよくある印刷時の失敗は、ページより幅の広いコード行です。ブラウザのプレビューでは、ブロックが横スクロールするかもしれません。紙にはスクロールバーがないため、行が切り取られるか、ブロック全体が縮小されます。
すべてのフォントとページサイズに当てはまる単一の文字数制限はありませんが、A4やLetterの実用的な目安は80~90文字程度です。これがクラシックなターミナル幅に近いのには理由があります。等幅テキストを快適に読める幅だからです。
行が長すぎる場合は、印刷倍率ではなくソースを変更してください。
const message = buildMessage({ owner, repo, branch, path });
この行は読めます。オブジェクトにさらに8つのプロパティがあるなら、複数行に分割します。
const message = buildMessage({
owner,
repo,
branch,
path,
});
シェルコマンドなら、バックスラッシュによる継続か変数を使います。長いURLは、URLを単独の行に置くか、リンク参照を使います。JSONはフォーマッターにオブジェクトを折り返させます。どの場合も目的は同じです。横スクロールに依存する行をなくすことです。
出力とログの扱いを決める
ログやコマンド出力は、ソースコードより幅が広いことがよくあります。また、テキストを変えずに折り返すことのできないタイムスタンプ、パス、識別子を含んでいます。
印刷で有効な選択肢は次のとおりです。
- 出力を削る。 関連する行だけを示し、省略記号はコードブロックの中ではなく本文に置きます。
- 記録を分割する。 コマンドを1つのブロックに、重要な出力を別のブロックに置き、その間に文を挟みます。
- 構造化された出力には表を使う。 出力が本当に行と列なら、等幅ブロックより表のほうがきれいに印刷できることがあります。
- フォントサイズの縮小は最後の手段にする。 テーマの変更はドキュメント全体に影響し、小さなコードは短い例より読みにくくなります。
ログがドキュメントそのものでない限り、200行のログをPDFに貼り付けないでください。完全なログが必要な読者はリポジトリを参照できます。PDFは要点を示すべきです。
コードの扱いをテーマに合わせる
4つの印刷テーマはコードをそれぞれ異なる方法で扱います。Cleanは明るいコード背景と中立な書体を使います。Businessはセリフ本文と対比する暗めのコードブロックを使います。Academicはコードを明るく保ち、本文に対して二次的な存在にします。Darkは画面優先のテーマで、印刷用スタイルシートが明るいインクと明るいコード背景を強制します。
実用上の結果は2つです。
- 実際のテーマでコントラストを確認する。 Cleanで問題なく見えるコードブロックも、Businessでは重く感じられ、Academicでは薄すぎると感じられるかもしれません。
- 印刷時に背景グラフィックを有効にする。 有効にしないとコード背景が消え、ブロックは枠線だけに頼ることになります。テキストは読めますが、視覚的な分離は弱くなります。
ドキュメントの大半がコードなら、通常はCleanが最も安全な選択です。いくつかのスニペットを含むレポートならBusinessも機能しますが、スニペットは短く保ってください。完全な比較はClean vs Business vs Academic vs Darkをご覧ください。
印刷されたページをレビューする
保存したPDFを開き、最初のブロックだけでなく、すべてのコードブロックを確認してください。注目する点は次のとおりです。
- 切り取られた行。 右端をズームしてください。トークンの途中で終わる行は、ブロックが広すぎる兆候です。
- 孤立したフェンス。 ブロックがページ下端の1行から始まってはいけません。そうなっている場合は、前に文を追加するか、周囲のコンテンツを調整します。
- 壊れたインデント。 タブとスペースは一貫して見えるべきです。インデントが混在したコピーされたブロックは、レンダラーではなくソースの問題です。
- 失われた空行。 ブロック内の空行には意味があります。PDFがそれを保持しているか確認してください。
- 読めないコントラスト。 ドキュメントがコピーされる可能性があるなら、ページをグレースケールで印刷してみてください。
- キャプション内の言語タグ。 タグが読者にとって重要なら、本文で言語に言及してください。タグ自体はラベルとして表示されません。
ドキュメントを広く配布する場合は、別のブラウザでの最終確認が有効です。HTMLが同じでも、印刷エンジンによって改ページや背景グラフィックの扱いが異なります。
コードブロックは、Markdownドキュメントのなかで最も他のツールへコピーされやすい部分です。短く、正確に、そしてページ内に収めてください。PDFはIDEを再現する必要はありません。読者がスニペットを理解し、再利用できるようにする必要があります。変換中に何がローカルに留まるかについては、ブラウザだけで完結するMarkdownからPDFへの変換をご覧ください。
自分だけのREADME PDFを作る
無料、ログイン不要、そしてすべてクライアントサイド。