お問い合わせ

技術コラム

キレイなWordファイルをMarkdownからつくる ― PandocによるWord簡易組版

投稿日:2024年12月21日|最終更新日:2025年1月8日

WordとMarkdownのいいとこどり

今回、Markdownから生成するWordファイル

文章を外部に提出する場合、それなりに整った見た目がほしくなります。しかし、どのソフトで見た目を制御するのか、選択肢は意外と多く悩ましいものです。

  • Word docxファイル/Excel xlsxファイル/PowerPoint pptxファイル
  • InDesign/Illustrator
  • HTML
  • TeXからPDF

ここではMarkdownからPandoc経由でWordファイルを生成し、必要に応じてそれをPDFにする方向で進めます。ポイントとなるのは、Markdownの時点で内容を固めてしまい、Wordでの作業は最低限にすることです。

なんで、そんな回りくどいことをするのか、それは、次のメリットがあるからです。

  • 執筆はMarkdownなので、最低限のタグ付けのみで内容に集中できる
  • Word上でのスタイル適用は大変面倒だしミスしがち。Pandocで機械的に実行してくれるとすごくラク
  • オリジナルはMarkdownなので、Gitなどのバージョン管理ソフトなどと相性が良く、差分をみながら管理できる
  • Wordであればたいていの人が編集可能
  • PDFにフォントを埋め込めば、使用できるフォントの制限がなくなる

それではさっそく、試してみましょう。

サンプル

今回は、ChatGPTにMarkdown文章のサンプルを書いてもらいました。

「複数レベルの見出し、箇条書きやプログラムコード、図や表など、できるだけ多くの要素を入れたMarkdown形式の読み物として面白いサンプル文章を書いて」と頼んだら出てきたのがこちら。まさかのファンタジー作品。

# 不思議な図書館と魔法の書

ある日、私はふと立ち寄った街角の古い図書館で、不思議な本を見つけた。表紙には何も書かれておらず、ただ一枚の古びた画像が貼られているだけだった。

![不思議な図書館](./images/book-image.webp){width=500}

その画像は、どこか見覚えのある場所だったが、どこで見たのかは思い出せない。好奇心に駆られた私は、ページをめくり始めた。


## 1. 魔法の呪文

本の最初のページには、呪文のような数式が書かれていた。

### 1.1 数式の登場

$\Phi(x) = \int_{-\infty}^{x} \frac{1}{\sqrt{2\pi}} e^{-\frac{t^2}{2}} dt$
(以下略)

今回はこれをきれいなWordファイルに変換するためがんばります。

Wordテンプレートの出力と調整

先述のように、MarkdownからWordへの変換ではPandocというコマンドラインツールを使用します。Pandocのインストールについて、公式ページは こちら。日本語情報としては、こちら などを参照ください。
まず、PandocのデフォルトのWordスタイルをテンプレートとして出力します。

$ pandoc -o custom-reference.docx --print-default-data-file reference.docx

こんな感じのWordファイルが出力されるので、このファイルに含まれるスタイルを変更していきます。

図のように、右側にスタイルペインを出しておくと、左側のカーソル位置にあたっているスタイルが「現在のスタイル」として表示されるので、スタイル名の右の[▼]をクリックして、「スタイルの変更」を選ぶと、各要素にあたっているスタイルの見た目が変えられます。

注意が必要なのは、次の点です。

  • 最初にほぼすべてのスタイルの元になっている「標準」スタイルを変更する(日本語フォントだけでなく英語フォントも忘れずに)
  • Pandocが生成するWord文章では、「本文」スタイルとは別に「First Paragraph」がある。これは、「本文」スタイルから派生したスタイルで、見出しなどの直後にくる文章に適用される。「本文」とフォント指定などが違うとおかしなことになる
  • CSSでいうところのmarginは設定できるがpaddingはない。網かけ余白が必要なときは「スタイルの変更」→「罫線と網かけ」→「罫線」で網と同じ色の線を入れるしか方法がない(と思う)

  • 罫線と網掛けに隙間が入るときは、[スタイルの変更]→「罫線と網かけ」→「罫線」で「オプション」をクリックして、隙間が入る場所の数値を「0」ptにする。

  • テンプレートとして出力されたdocxにはSource Codeスタイルが存在しないが、Pandocでソースコードを変換すると、この名称のスタイルが当てられる。したがって、ソースコードに当たるスタイルを変更したいときは、自分でこの名前のスタイルをつくる必要がある
  • ヘッダー、フッターなども変更できるが、表、箇条書き、数字付き箇条書きスタイルは変更できない(テンプレート側の変更が生成したdocxに反映されない)。方法があるのなら、誰か教えてほしい

今回は、それなりの美しさと組版の自由度を確保しつつ、環境を選ばず使用できるように、オープンソースかつフォントウェイトが豊富なフォント源ノ角ゴシックを中心に使用しました。導入方法などはこちらなど。

なお、テンプレートファイルのスタイル以外の部分は何が書いてあっても無視されるので、スタイルの微調整時は、Wordで変換する実際の文章などを入れてみて確認するのがおすすめです。

正直、今回のネタで一番面倒なのはこの調整作業です。

Wordの直感的とはいえないスタイル指定、数々のつかみきれない挙動と闘いながら、次項のPandocでの変換とWordでのスタイル調整をひたすら繰り返し、なんとか体裁を整えたテンプレートファイルがこちら。

custom-reference-1.docx

だいぶがんばりました。いろいろ気に入らないところもありますが、さらなる美しさを求めるのならば、正直InDesignなどの専用ソフトを使うと良いと思います。

PandocによるWordファイルへの変換

では、さっそくPandocにスタイルテンプレートを指定して実行し、Markdownで書かれた原稿をWordファイルに変換してみましょう。

コマンドは次のとおり。

$ pandoc sample.md --reference-doc=custom-reference-1.docx -o sample2.docx

作成したWordファイルを開いてみましょう。

Markdownから自動生成したことを考えれば、比較的きれいに組めているのではないでしょうか。

特に数式がちゃんとWordの数式スタイルになる点や、ソースコードの色分け(シンタックスハイライト)がちゃんと適用される点は魅力的です。

sample2.docx

応用編 改行、改ページをコントロールする

組版としての美しさを考えた場合、改行位置や改ページ位置をコントロールしたくなることがあります。

たとえばこの状態。1ページ目の見出し「1. 魔法の呪文」は次ページに送りたくなりませんか?

もしかして改行については<br>タグが使えるのでは?と思って試してみましたが、次のように表示され、使用できません。

[INFO] Not rendering RawInline (Format "html") "<br>"

仕方がないので作成したのが、次のLuaフィルターです。
●pagebreak.lua

-- pagebreak.lua
function RawBlock(el)
  -- 改ページの処理
  if el.text == "\\newpage"  then
    return pandoc.RawBlock('openxml', '<w:p><w:r><w:br w:type="page"/></w:r></w:p>')
  end
end
function RawInline(el)
  if el.text == "<linebreak>" then
    return pandoc.RawInline('openxml', '<w:br/>')
  end
end

docxファイルをzip解凍して、中身を覗いた経験がある方ならわかると思いますが、Wordの中身のXMLファイルに直接タグ追加しております。ワイルドですね。

これを利用するには、Markdown中に\newpage(改ページ)、<linebreak>(改行)タグを入れます。

その画像は、どこか見覚えのある場所だったが、どこで見たのかは思い出せない。好奇心に駆られた私は、ページをめくり始めた。

\newpage

## 1. 魔法の呪文

本の最初のページには、<linebreak>呪文のような数式が書かれていた。

\newpageのTeX風コマンドと、<linebreak>のHTML風コマンド、混ざってるの気持ち悪いですね…。

ですが、残念ながら、RawBlock側では<newpage>のようなHTMLっぽいタグ、RawInline側では/linebreakのようなTeXっぽいタグは使えません。Pandocの解釈が失敗します。

この状態で、Pandoc変換時に--lua-filter=pagebreak.luaとしてこのファイルを指定すると、改ページ、改行が制御できます。

$ pandoc sample.md --reference-doc=custom-reference.docx --lua-filter=pagebreak.lua -o sample2.docx

結果は次のとおり。

意図した通りに改ページ、改行されています。

まとめ

以上の手順で、Markdownからかなり意図通りのWordファイルが出力できるはずです。

元ファイルはMarkdownなので、バージョン管理との親和性も高くなります。WordファイルからPDFにすれば、外部に配布するときにもフォントの問題が発生しません。

今回は表スタイルについては諦めてしまい、デフォルトの状態で出力していますが、luaフィルターを使ってがんばれば、そちらも制御可能だと思います。

ぜひ、みなさまも色々と試してみて、レイアウトソフトとしてのWordを使いこなしてください。

(R&D かつの)