AsciiDoc から A4 の PDF を出す、最小構成
前回は「仕様書をコードと同じ土俵に載せる」という原則を立てました。原則だけでは何も動かないので、今回は手を動かします。AsciiDoc 形式のファイル(拡張子は .adoc)を1つ書いて、A4 の PDF が1本出るところまでを進めます。
バージョンについて この連載のコマンドとオプションは、記事中に明記したバージョンで動作を確認したものです。Asciidoctor も Vivliostyle も、メジャーバージョンが変わるとオプションの名前や意味が変わることがあります。しかも変わったことに気づけず、エラーも出ないまま結果だけが違う、という形で現れる場合があります。手元のバージョンが記事と違うときは、
--helpの出力を確認してから進めてください。
作るもの
到達点は「テキストファイル1枚から A4 の PDF が出る」状態です。編集するファイルは index.adoc ひとつ、出力は dest/index.html と PDF の2つだけです。
図の埋め込み、表紙、目次、章ごとの改ページは、すべて後回しです。最初から全部載せると、どこで壊れたのか分からなくなります。まず「1本出る」を確保してから足していきます。

上は実際に出力した PDF の1ページ目です。この記事で書く index.adoc をそのまま変換したもので、タイトルと章立て、本文だけが A4 の紙面に組まれています。
前提: Node.js があること
必要な前提はこれだけです。検証時の環境は Node.js v24.15.0、npm 11.9.0、OS は Windows 11 Pro(シェルは Git Bash)でした。Asciidoctor は Ruby 実装が有名ですが、ここで使うのは JavaScript 版なので Node.js だけで完結します。作業用のディレクトリを1つ作り、npm init -y を実行しておいてください。
パッケージを入れる
インストールするのは次の3つです。
npm install asciidoctor @vivliostyle/cli asciidoctor-kroki
このとき解決されたバージョンは以下でした(npm ls --depth=0 の出力)。
├── @vivliostyle/[email protected]
├── [email protected]
└── [email protected]
この記事と同じ挙動を再現したい場合は、バージョンを固定してください。
npm install [email protected] @vivliostyle/[email protected] [email protected]
検証時に実際に走らせたのは前者の無指定形で、この固定形はそのとき解決されたバージョンをそのまま書き出したものです。
3つ目の asciidoctor-kroki は、今回は使いません。図を扱う次回で必要になるので、まとめて入れておきます。ただし拡張の登録のしかたには注意点があるので、そちらは実際に図を出すときに触れます。
なお、PDF 化で使うテーマ @vivliostyle/theme-techbook はこの一覧にありません。テーマを使わないわけではなく、Vivliostyle が必要になった時点で自分で取得するので、あらかじめ入れておかなくても動くからです。仕組みと、そのぶんの注意点は、PDF を作るところで説明します。
AsciiDoc を1枚書く
作業ディレクトリに index.adoc を作ります。検証で使ったものをそのまま載せます。
= サンプル仕様書
:projectname: サンプルプロジェクト
:author: WEELWORKS
:revnumber: 1.0
:revdate: 2026-08-02
:toc: macro
:toclevels: 3
:sectnums:
== はじめに
本書は連載記事のサンプルです。
== システム構成
システムの構成を示します。
先頭の = が文書タイトル、== が章です。タイトル直後に続く :名前: 値 の並びが文書ヘッダーの属性です。
:projectname:は独自定義の属性で、本文中に{projectname}と書けば展開されます。製品名を1か所で管理するための仕組みです。:author::revnumber::revdate:は著者と版数・版日付です。版の情報を本文の外に持たせておくと、改版のたびに本文を触らずに済みます。:toc: macroは目次の指定です。macroの場合、目次は本文中にtoc::[]と書いた位置にだけ出力されます。今回は書いていないので目次は出ません。:toclevels: 3は目次に載せる見出しの深さ、:sectnums:は章番号の自動採番です。並べ替えても番号を振り直す必要がありません。
HTML にする
まず HTML を作ります。PDF は HTML から組むので、これが中間成果物になります。
npx asciidoctor -b html5 -o dest/index.html index.adoc
-b html5 は使うバックエンド(出力形式)の指定、-o dest/index.html は出力先で、dest/ が無ければ作られます。最後の index.adoc が入力ファイルです。
生成された dest/index.html はブラウザでそのまま開けます。執筆中の確認はこれで十分です。
PDF にする
HTML ができたら、Vivliostyle で組版します。
npx vivliostyle build dest/index.html --theme @vivliostyle/theme-techbook --size A4 -o dest/sample.pdf
--size A4 が用紙サイズの指定です。HTML にはページという概念がないので、どこで紙面を区切るかをここで初めて決めます。--theme は組版に使うスタイルの指定で、@vivliostyle/theme-techbook は技術書向けの既定テーマです。見出しの階層や行間、余白があらかじめ整えられています。
先ほど保留した話がここに関わります。テーマを入れていないのに動くのは、--theme を指定すると Vivliostyle がビルド時に npm から取得してくれるからです。
手軽ですが、そのぶんビルドがネットワークに依存します。オフラインでビルドしたいときや、CI で再現性を確保したいときは、テーマも依存関係に入れておくほうが安全です。
これで dest/sample.pdf ができます。1枚の .adoc から A4 の PDF が出る、今回の到達点です。
日本語が出ない・字が欠けるとき
最初に正直に書いておきます。この問題は今回の検証環境では再現しませんでした。 Windows 11 上の Node.js v24.15.0 と @vivliostyle/theme-techbook の初期設定のまま、日本語は見出し・本文とも正常に描画されています。以下は「環境によっては起こりうる事象と、その場合に試す価値のある対処」であって、対処法自体を実地で検証できてはいません。
環境によっては、日本語の箇所が白紙になったり、いわゆる豆腐(□)に置き換わったりすることがあります。組版エンジンが参照するフォントに日本語のグリフが無い場合に起きる、フォント側の問題です。一般的な対処は、CSS でフォントファミリーを上書きすることです。Vivliostyle は --vs-font-family というカスタムプロパティで本文フォントを制御します。
:root {
--vs-font-family: "Noto Sans JP", "Yu Gothic", sans-serif;
}
このファイルを style.css として保存し、ビルド時に --style style.css で渡します。フォント名は、実際にその環境に入っているものに読み替えてください。
もうひとつ、確認手段のほうを疑う視点も持っておくと安全です。pdftotext で PDF からテキストを抽出して日本語が化けて見えても、-enc UTF-8 を付けていなければ化けるのはツール側の都合で、PDF 自体は正常なことがあります。
pdftotext -enc UTF-8 dest/sample.pdf -
PDF が壊れているのか、確認に使ったツールの設定が足りないだけなのか。切り分けを先にやると、無駄な深追いを避けられます。
ここまでで、テキスト1枚から PDF が出る土台ができました。ただし今の状態で図を書こうとしても、PlantUML のソースがそのままコードブロックとして印字されるだけです。次はここに手を入れて、図を本文と同じソースから生成できるようにします。
この回で使ったツール
- AsciiDoc — 技術文書向けの軽量マークアップ言語
- Asciidoctor — AsciiDoc を HTML や PDF に変換する処理系(JavaScript 版のドキュメント)
- Vivliostyle — CSS で組版して PDF を生成するツール(CLI のリポジトリ)
- Node.js — JavaScript の実行環境