【技術書著者必見】Word地獄からの脱却!Markdownで電子書籍・紙を同時生成する「Quarto」最適ワークフロー

導入:WordでのKDP出版が「新しい地獄」になる理由

KDP(Kindle Direct Publishing)で技術書を出版する際、多くの方がまずWordを使います。私もそうでした。しかし、Wordは柔軟性が高すぎるがゆえに、以下のような問題を引き起こしがちです。

  • 電子書籍(EPUB)の質が低い: Wordで作成したものをそのまま電子書籍にすると、「紙の書籍のPDF」のような固定レイアウトになり、フォントサイズ変更や端末最適化といった電子書籍本来の利点(リフロー機能)が損なわれてしまいます。
  • 紙(ペーパーバック)と電子の「二重メンテ」: 紙版の美しいレイアウト(PDF)を作るためのWord調整と、電子版(EPUB)のための調整が完全に別作業になり、改訂のたびに膨大な手間がかかります。
  • 技術書特有のレイアウト崩れ: コードブロックのシンタックスハイライト、図表の自動番号、長いコードの自動折り返しなど、技術書に必要な機能の管理がWordでは煩雑になりがちです。

「ツール移行が単なる時間の浪費ではないか?」「さっさと執筆しろよ」という本質的な問題(ツッコミ)もあるのですが、とうとう「Wordの持つ非効率性を根本から解決する」ツールを見つけました。それがQuartoです。

結論:技術書出版の最適解は「Quarto」

Quartoは、RStudioによって開発された、エンジニア向けの技術文書作成・出版ツールです。Markdownで執筆するだけで、電子書籍(EPUB)と紙(KDP対応PDF)をワンコマンドで同時生成できる、まさに技術書のための特効薬です。

Quartoが最適解である3つの理由

  1. エンジニア向け機能の標準装備
    • Markdown形式での執筆に特化しているため、コードブロックシンタックスハイライト(言語に応じた色付け)が簡単に実装できます。
    • 図表や相互参照の管理も容易で、Wordで苦労していた技術書特有のレイアウト問題を一掃します。
  2. KDPの複雑な制約を自動処理
    • KDPペーパーバックには、「6×9インチサイズ強制」「コードの自動折り返し必須」「フォント埋め込み必須」など、多くの厳しい制約があります。
    • Quartoは、カスタム設定ファイル(_quarto.yml)を用意することで、これらのPDF生成の地獄を自動で処理します。
  3. ワンソース・マルチアウトプット
    • 同じMarkdownファイルから、リフロー型EPUB(電子書籍向け)と固定レイアウトPDF(ペーパーバック印刷向け)を同時に出力します。
    • これにより、「紙と電子のレイアウト調整」という最も非効率だった作業が不要になります。

Quartoワークフロー:具体的なアクションプラン

Wordからの移行は決して「新しい地獄」ではありません。Quartoを使えば、Markdownを書き慣れたエンジニアにとって、出版はむしろ執筆の一部になります。

Step 1: 環境構築とテンプレートの利用(所要30分)

  1. Quartoのインストール: 公式サイトからOS(macOS/Linux/Windows)に応じたインストーラーをダウンロードし、インストールします。
  2. KDP対応テンプレートの取得: ゼロから設定ファイルを書く必要はありません。KDP出版用に最適化されたテンプレートを利用するのが最速です。
  3. 設定ファイルの調整: _quarto.yml 内のタイトル、著者名、出力フォーマットなどを書籍に合わせて微調整します。

Quatroのインストール
ダウンロードしたインストーラーを起動してインストール

ターミナルを起動してPDFの作成準備のため以下のコマンドを実行しておきます。

quarto install tinytex
Bash

次に、https://cloud.r-project.org より、Rをインストールしておきます。インストールしたらターミナルを開き、以下のパッケージをインストールしておいてください。

次にQuartoの執筆環境を整えていきましょう。今回はVS Codeを使いたいと思います。すでにVS Codeはインストール済みです。

機能拡張からQuarto機能拡張をインストールします。

KDP対応テンプレートの取得

b-rodrigues/kdp_quarto」は、Bruno Rodrigues(ブルーノ・ロドリゲス)氏が作成し、GitHubで公開しているQuartoのプロジェクトテンプレートです。

これは、技術書をKDP (Kindle Direct Publishing) で出版したい著者のために、Quartoの設定ファイル(_quarto.yml)や関連ファイルを、KDPの厳しい要件を満たすように事前に構成したものです。

テンプレートの主な目的と特徴

  1. KDP要件への自動対応:
    • PDF出力: KDPペーパーバックが要求する特定の用紙サイズ(例:6×9インチ)やマージン設定など、PDF(LaTeX)の複雑な設定を自動で処理します。
    • コードの折り返し: 技術書で問題になりやすい、長いコード行がPDFからはみ出さないように、自動で折り返すための設定(LaTeXのfvextraパッケージなど)が含まれています。これはKDPの審査落ちを防ぐために非常に重要です。
  2. マルチフォーマット出力:
    • EPUB (電子書籍): リフロー対応の高品質なEPUBを生成し、Kindle電子書籍として最適化します。
    • PDF (ペーパーバック): KDP印刷に適した固定レイアウトのPDFを生成します。
    • Webサイト(オプション): おまけとして、書籍の内容をそのまま公開できるWebサイトも生成できます。
  3. 効率的な執筆環境:
    • Markdown形式で執筆するだけで、複雑な出力形式の設定を気にせず、執筆に集中できる環境を提供します。

このテンプレートは、Quartoを導入する際にゼロからKDP対応の設定を行う手間を省き、「すぐにKDP出版に向けた執筆を始められる」ように設計された、非常に実用的なスターターキット(雛形)です。

これをgit cloneするだけでKDP対応ができるわけです。

git clone https://github.com/b-rodrigues/kdp_quarto
cd kdp_quarto
quarto render  # 初期ビルド確認
Bash

KDP対応テンプレートは、https://github.com/b-rodrigues/kdp_quarto にあります。取得して、 quarto render を実行するとEPUBファイル、HTMLファイルが生成されることを確認しましょう。

次にVS Codeでフォルダを開いてみましょう。.qmdファイルがあるフォルダを開いて、.qmdファイルを開きます。

_quarto.yml ファイル

Quartoプロジェクトの設定ファイルです。詳しい説明が以下に記載されているので、これを見ながら修正していきます。

39  Quarto:YAMLの基礎 – R入門

lang:ja に設定すると、「AUTHOR」や、PUBLISHEDといった表記が「作者」、「公開」と日本語で表示されるようになります。

chapters: の最初は index.qmd である必要があります。それ以外は自由にフォルダを切って配置することが可能です。

chapters:
  - index.qmd # ここは固定
  - chapters/chapter_01.qmd # 以降はフォルダを切って配置してもOK
YAML

※index.qmdは_quarto.ymlと同じ場所に置きます

注意:lang: はPDFなどの言語設定を変更するものではありません。

これで、HTML出力(作業時のプレビュー用として使う)と、EPUB(電子書籍用)が準備できました。しかしPDF(ペーパバック用)の出力がうまくいきません。日本語が出力されていないのです。そこで、次のテンプレートを参考に、PDFが日本語で出力できるように修正していきます。

GitHub - PureHertz/QuartoTemplates: できるだけプレーンに近いMarkdownファイルから、それなりの見た目の日本語PDFを作るQuarto用テンプレート
できるだけプレーンに近いMarkdownファイルから、それなりの見た目の日本語PDFを作るQuarto用テンプレート - PureHertz/QuartoTemplates

最終的に、_quarto.ymlは次のように修正しました。

format:
  pdf:
    pdf-engine: lualatex
    documentclass: bxjsbook
    classoption: [lualatex, ja=standard, 10pt, openany]
    pagestyle: headings
    number-sections: true  # 見出しに番号を付ける
    number-depth: 2  # subsectionまで見出し番号を付ける
    include-in-header:
      - file: _preamble_book.tex  # プリアンブルの設定
    toc: true  # 目次を生成
    toc-depth: 2  # 目次の深さ(sectionまで)
    toc-title: 目次  # 目次のタイトル
    highlight-style: tango  # コードブロックのシンタックスハイライトのスタイル
    # keep-tex: true  # デバッグ用に.texファイルを残す
  epub:
    toc:
      true
    lang:
      ja
    date:
      today
    css:
      epub.css
  html:
    theme:
      light: flatly
      dark: solar
    css:
      epub.css
YAML

_preamble_book.texは、LaTeX ドキュメントの「前置き」ファイルです。PDF生成時に自動的に読み込まれ、以下の設定を一括管理します:

パッケージの読み込み、フォントの設定、ページのレイアウト設定、見出しのフォーマットなど。

_preamble_book.texは次のよう設定しました。

% Packages

\usepackage{array} % tabular環境を拡張、セルの幅を設定できる
\usepackage{multirow} % 表のセルを縦方向に結合
\usepackage{siunitx} % 数字と単位の書式設定
\sisetup{mode = match}  % モード(数式/本文)に合わせて、数字や単位の書式を切替
\usepackage[dvipsnames]{xcolor}  % 色の設定
\usepackage{here}  % {fig-pos="H"}で図をソースコードの位置に強制的に配置
\usepackage{pdfpages}  % 外部で作成したPDF(図面、別章、付録など)をそのまま挿入
\usepackage[hidelinks]{hyperref}  % PDFにハイパーリンク機能を追加
\usepackage{appendix}  % 付録の章番号を設定
\usepackage{quotchap} % 章見出しのデザインを変更

% Font

\usepackage[no-math]{fontspec}  % LuaLaTeXでOpenType/TrueTypeフォントを直接指定する、数式フォントの設定は無効化
\usepackage{amsmath,amssymb}  % 数式で\align環境などを使えるようにする、追加の数学記号を使えるようにする
\usepackage[noto-jp,deluxe,expert,bold]{luatexja-preset}  % 日本語フォントにプリセットを使う
\ltjsetparameter{ jacharrange = {-2} }  % リテラルなギリシャ文字を欧文扱いする(ギリシャ文字に欧文フォントをそのまま使う)
\setmainfont[Ligatures=TeX]{Noto Serif}  % 英数字メインフォントを設定
\setsansfont[Ligatures=TeX]{Noto Sans}  % 英数字サンセリフフォントを設定
\setmainjfont{Noto Serif JP}  % 日本語メインフォントを設定
\setsansjfont{Noto Sans JP}  % 日本語サンセリフフォントを設定
\setmathfont[Scale=1.0]{texgyrepagella-math.otf}  % 数式用フォントを設定
\setmonofont{PlemolJP}  % 英数字等角フォントを設定
\setmonojfont{PlemolJP}  % 日本語等角フォントを設定

% geometryはここで一度だけ指定する
\makeatletter
\@ifpackageloaded{geometry}{
  % geometryが既に読み込まれている場合はオプションを上書き設定
  \geometry{
    paperwidth=155.2mm, % 152 + 裁ち落とし
    paperheight=224.4mm,  % 218 + 裁ち落とし
    % paperwidth=210mm,  % A4サイズ
    % paperheight=297mm,  % A4サイズ
    top=14mm,
    bottom=14mm,
    inner=12mm,
    outer=12mm
  }
}{
  % 未読み込みならここで一度だけ読み込む
  \usepackage[
    paperwidth=155.2mm, % 152 + 裁ち落とし
    paperheight=224.4mm,  % 218 + 裁ち落とし
    % paperwidth=210mm,  % A4サイズ
    % paperheight=297mm,  % A4サイズ
    top=14mm, % 上余白
    bottom=14mm, % 下余白
    inner=12mm, % 内側の余白
    outer=12mm % 外側の余白
  ]{geometry}
}
\makeatother

\setpagelayout{hmargin=12mm} % 左右の余白を12mmに設定
\setlength{\textheight}{0.80\paperheight} % 本文部分の高さ
\addtolength\topmargin{-0.2in} % 上余白の微調整
\setlength{\headsep}{20pt} % ヘッダーと本文の間隔を20ptに設定

\usepackage{titlesec} % セクション見出しのフォーマットを変更するためのパッケージ
\usepackage{tikz} % LaTeXで図や図形を描くための描画パッケージ

% Title

\usepackage{titling}  % タイトルのフォーマットを変更するためのパッケージ
\makeatletter
\newcommand{\subtitle}[1]{\def\@subtitle{#1}}
\newcommand{\@subtitle}{}  % 初期値は空
\pretitle{\begin{center}\gt\sf\bfseries\huge}
\posttitle{
  \par\end{center}
  \ifx\@subtitle\@empty
  \else{
    \begin{center}\gt\sf\large\@subtitle\par\end{center}
  }
  \vskip 2em  % タイトルの後に空白を追加
}
\preauthor{\begin{center}\gt\sf\large}
\postauthor{\par\end{center}\vskip 1em}  % 著者の後に空白を追加
\predate{\begin{center}\gt\sf\large}
\postdate{\par\end{center}}
\makeatother

% description list

\usepackage{enumitem}
\setlist[description]{%
  font=\sffamily\bfseries,  % ラベルをサンセリフ体の太字に
  style=nextline,           % ラベルの後に改行
  leftmargin=1em            % 本文の左マージン
}

% inline code block
\definecolor{codebg}{RGB}{234,234,234}  % 明るいグレーの背景色
\let\oldtexttt\texttt
\renewcommand{\texttt}[1]{  % \textttの再定義
  \colorbox{codebg}{  % 背景色
    \textcolor{Maroon}{  % 文字色
      \small  % 文字サイズ
      \oldtexttt{#1}
    }
  }
}

% code block
\usepackage{fvextra}    % fancyvrbの拡張
\setlength{\fboxrule}{6pt}  % 枠の太さを太くする
\fvset{
  bgcolor = codebg,
  frame = single,
  framesep = 0pt,        % 枠と内容の間の余白
  rulecolor = \color{codebg},
  fontsize = \footnotesize,
  breaklines = true,
  breakanywhere = true,  % 単語の途中でも改行する
  commandchars = \\\{\},  % Pandocの構文ハイライトマクロに必要
}
\usepackage{framed} % <- Shaded は framed の shaded/snugshade を使う
\definecolor{shadecolor}{RGB}{255,255,255} % 外枠の Shaded を白に

% Headings

% --- Chapter ---
\titleformat
{\chapter} % command
[display] % shape
{\color{NavyBlue}\gt\sf\bfseries} % format
{%
\titlerule[3pt]%
\huge 第\thechapter 章%
} % label
{-10pt} % sep
{\huge} % before-code
[{\titlerule[3pt]}] % after-code

\titlespacing*{\chapter}{0pt}{0pt}{40pt}

% --- Section ---
\titleformat
{\section} % command
[block] % shape
{\color{NavyBlue}\gt\sf\bfseries\Large} % format
{
  \definecolor{teal}{gray}{0.30}
  \begin{picture}(-11,0)
    \put(-11,-5){
      \color{NavyBlue}
      \line(1,0){\hsize}
    }
  \end{picture}
  \Large%
  \hspace{-4pt}
  \thesection .
  \hspace{0pt}
} % label
{0pt} % sep
{} % before-code


% --- Section (.unnumbered) ---
\titleformat
{name=\section,numberless} % command
[block] % shape
{\color{NavyBlue}\gt\sf\bfseries\Large} % format
{} % label
{0pt} % sep
{
  \definecolor{teal}{gray}{0.30}
  \begin{picture}(-11,0)
    % \put(-10,-5){
    %   \begin{tikzpicture}
    %     \fill[teal] (0pt,0pt) rectangle (5pt,19pt);
    %   \end{tikzpicture}
    % }
    \put(-11,-5){
      \color{NavyBlue}
      \line(1,0){\hsize}
    }
  \end{picture}
} % before-code

% --- Subsection ---
\titleformat
{\subsection} % command
[block] % shape
{\color{NavyBlue}\gt\sf\bfseries\large} % format
{\thesubsection .} % label
{8pt} % sep
{} % before-code

% --- Subsubsection ---
\titleformat
{\subsubsection} % command
[block] % shape
{\color{NavyBlue}\gt\sf\bfseries} % format
{} % label
{} % sep
{} % before-code

% --- Paragraph ---
\titleformat
{\paragraph} % command
[runin] % shape
{\normalsize\gt\sf\bfseries} % format
{} % label
{} % sep
{} % befor-code
% スペーシングの調整
\titlespacing*{\paragraph}{0pt}{3.25ex plus 1ex minus .2ex}{1em}

YAML

Step 2: 執筆開始(即日)

markdown形式で記述していきます。

  • chapters/ ディレクトリ配下にMarkdownファイルを作成し、執筆を進めます。
  • コードは、通常のMarkdownの記法である \“言語名` で囲むだけで、自動的にシンタックスハイライトが適用されます。

references.bib

references.bib ファイルには参考文献をbibtex形式で記載していきます。Google Scholarから取得して貼り付けると良いでしょう。

https://scholar.google.co.jp Google Scholarを開き文献を検索、bibtexを取得します。

Google Scholarに掲載がない場合、例えばAmazonで売られているような商業誌の場合は次のようにbibtexを作成します。

@book{kaneda_hajimete_android_2020,
  author    = {金田浩明},
  title     = {はじめてのAndroidプログラミング 第5版},
  year      = {2020},
  publisher = {SBクリエイティブ},
  address   = {東京},
  isbn      = {978-4-8156-0796-8},
  note      = {日本語},
  url       = {https://www.amazon.co.jp/dp/4815607966},
  urldate   = {2025-11-16}
}
YAML

ドキュメント本文で参照したい箇所に、references.bib内で定義されている引用キー(この場合 kaneda_hajimete_android_2020 )の前に @ を付けて記述します。

Android入門としては「はじめてのAndroid入門」, @kaneda_hajimete_android_2020 が参考になる
YAML

レンダリング結果は次のように、著者(年) となります。

PDFとEPUBで段組みを実現する

.columnsを使って書いていたのですが、HTMLでは2段組が実現できるものの、EPUB,PDFでは段組みにならず、上下に並んでしまします。そこで次のように書いたところEPUB,PDFどちらも2段組を表現することができました。

::: {layout="[0.5, 0.5]"}
::: {#firstcol}
Fist column content.
:::

::: {#secondcol}
Second column content.
:::
:::
LaTeX
カスタム相互参照

図や表、数式はfig-,tbl-,eq-を頭につけて定義することでひょうげんすることができますが、今回はソースコードに対して連番をつけて管理、相互参照をしたいと思いますので、「コード」という図表番号を新たに追加したいと思います。この場合crossref: custom:を定義することで新しい図表番号(相互参照)を追加できます。図表番号は通常コンテンツの下に表示されますが、caption-location: topと指定することで、コンテンツの上に表示することができます。

crossref:
  custom:
    - kind: float
      reference-prefix: "コード"
      caption-location: top
      key: code
      latex-env: lstlisting
LaTeX

このように作成したカスタム図表番号は #code-任意の文字列 とすることで使用することができます。

::: {#code-define-variable layout="[0.5, 0.5]"}
::: {#firstcol}
```kotlin
var a: Int = 100
```
:::

::: {#secondcol}
```markdown
a: 100
```
:::
型を明示する“aaaaaaあ」あああああああああ”
:::
LaTeX

Step 3: KDP提出準備

執筆完了後、以下のコマンドを実行するだけで、提出ファイルが生成されます。

quarto render
Bash

提出ファイル格納場所KDPへの用途特徴
EPUBファイル_book/book.epub電子書籍リフロー対応、高い読みやすさ
PDFファイル_book/book.pdfペーパーバック制約をクリア

あとは、別途用意したカバー画像とともに、これらのファイルをKDPにアップロードするだけです。

まとめ:Quartoへの移行は「執筆に集中する」ための投資

検討したツール評価採用しなかった理由
手動HTML + Sigil最大の制御力過剰エンジニアリング。生産性ゼロ、PDF生成が別途必要。
Pandoc + Markdown汎用性が高いKDP用PDFのLaTeXテンプレート調整(コード折り返し等)が面倒。
Quarto技術書出版の最適解エンジニア向けに全て自動化されており、学習コストが最も低い。

技術書の価値は、ツールではなく中身です。これまでWordのレイアウト調整に時間を溶けていましたが、Quartoを使ってセットアップを爆速で終わらせ、価値ある執筆に集中し、素早く書籍をリリースしていきたいものです。

Quarto機能拡張の使い方

Command+Shift+Pでコマンドパレットを開きます。

Quarto: Render Project】を選択すると、プレビューで表示することができます。

フォーマットを選択します。Render epub bookを選択すると、epub形式で作成されます。 _bookフォルダ内に.epubファイルができます。

Quarto: Preview】を選択すると、プレビュー表示できます。

カスタムクラスを追加

最低限の文字装飾として、強調したい箇所の文字色を変更したいと思います。今回、文字列をえんじ色(赤紫)で表示するためのカスタムクラスを追加し、これにより色変更を実現します。

カスタムクラスはLuaフィルタでSpan関数として用意します。

function Span(el)
  if el.classes:includes("enji") then
    if FORMAT:match "html" then
      return pandoc.RawInline("html", '<span style="color: #B22652;">' .. 
             pandoc.utils.stringify(el.content) .. '</span>')
    elseif FORMAT:match("latex") then
      -- LaTeX 出力用:プリアンブルで \enjiText を定義している想定
      return pandoc.RawInline("latex", '\\enjiText{' .. pandoc.utils.stringify(el.content) .. '}')             
    elseif FORMAT:match "epub" then
      return pandoc.RawInline("html", '<span style="color: #B22652;">' .. 
             pandoc.utils.stringify(el.content) .. '</span>')
    end
  end
  return el
end
Lua

このLuaフィルタは、Quartoのレンダリングプロセスに介入し、特定のクラスを持つSpan要素を変換します。

実際の使用方法

この機能は[非常に重要]{.enji}です。

このようにすることで、PDF出力時も、HTML出力時も、EPUB出力時も、「非常に重要」がえんじ色で表示されます。

VSCodeのスニペットで効率化

今回、enjiというカスタムクラスを追加しました。これをVSCodeのスニペットに登録して、簡単に選択範囲をえんじ色設定できるようにしておきます。

.vscode/add_color.code-snippetsを作成します。

{
	"enji": {
		"scope": "Markdown,Quarto",
		"prefix": "enji",
		"body": [
			"console.log('$TM_SELECTED_TEXT');"
		],
		"description": "Add enji class to the previous line"
	}
}
JSON

キーボードショートカットで「editor.action.insertSnippet」のキーバインドを設定します。ここではCmd+K,Cmd+Eに設定しました。

コメント

タイトルとURLをコピーしました