入力漏れを防ぐ!EPUBのファイル作り方、目次・表紙付きファイル

原稿、目次、表紙から一つのEPUBファイルを作るアイキャッチ

EPUBのファイルを一章・目次・表紙付きで作るなら、最初に「入力」と「生成物内部の参照」を一枚の契約表へ置くのが答えです。入力はchapter原稿とcover.png。生成物ではnav.xhtml、content.opf、cover.xhtml、chapter.xhtml、colophon.xhtml、container.xml、mimetype、格納後のcover.pngを互いに結びます。ファイルがあるだけでは足りず、OPFのIDとhref、spineのidref、目次の本文href、表紙ページの画像srcまで解決できれば、入力漏れを場所ごとに切り分けられます。

この記事は一章+目次+表紙の「パッケージ契約」を作る記事です。Rune Studioの6ページのEPUBウィザードで三章を選び、画面を進めて生成する操作は別の実践として切り分けます。ここでは生成物の中に何が必要で、どの参照が切れてはいけないかへ集中します。

入力二件を先に固定する

作り始める前に、次の二件を入力票へ記録します。

入力ID 正本パス 検査する内容
CHAPTER-01 source/chapter.md 章見出し、本文、文字コード、章ID
COVER-01 source/cover.png 採用画像、ファイル形式、正本パス

作品名、著者、言語、識別子、更新日時も同じ票に書きます。ファイル名だけを作品情報の代わりにしません。chapter原稿の章見出しは、後でnav.xhtmlのラベルと移動先を照合する基準になります。cover.pngは候補を複数混ぜず、採用した一件をCOVER-01として固定します。

パッケージの八実体を配置する

一章、目次、表紙、奥付を持つ標本は、次の八実体へ固定します。

番号 EPUB内のパス 役割
1 mimetype EPUBの媒体型を示す
2 META-INF/container.xml package文書の場所を示す
3 OEBPS/content.opf 書誌、資源登録、読む順を定義する
4 OEBPS/nav.xhtml 読者用の目次ナビゲーション
5 OEBPS/Text/cover.xhtml 表紙画像を表示するページ
6 OEBPS/Text/chapter.xhtml CHAPTER-01から作る本文一章
7 OEBPS/Text/colophon.xhtml 著者・発行情報を示す奥付
8 OEBPS/Images/cover.png COVER-01から格納する表紙画像

入力票の二件と、格納後の八実体は別の表です。source/cover.pngがあることと、EPUB内のOEBPS/Images/cover.pngがOPFと表紙ページから参照されることを混同しません。

chapter、cover、奥付のXHTMLを作る

chapter.mdを整形式のOEBPS/Text/chapter.xhtmlへ変換します。XML名前空間、head、title、bodyを持つ完全なXHTMLにし、本文見出しへid="c01"を付けます。navのhrefはこのIDまで含めてText/chapter.xhtml#c01へ向けます。

OEBPS/Text/cover.xhtmlには、../Images/cover.pngを参照するimgを一件置きます。画像の実パスとsrcの大文字小文字まで一致させます。奥付はOEBPS/Text/colophon.xhtmlへ分け、著者、発行者、発行日など、入力票で採用した情報を記載します。

nav.xhtmlをEPUB 3の目次にする

nav.xhtmlは、単にリンクを置いたXHTMLではありません。OPFのmanifestでnav資源を正確に一件登録し、そのitemへproperties="nav"を付けます。さらにnav.xhtml側ではepub名前空間を宣言し、正確に一件のnav epub:type="toc"を置きます。

目次本体は順序付きリストにし、一章の項目をText/chapter.xhtml#c01へ結びます。合格条件は次の三点です。

  1. OPFにproperties="nav"を持つnav itemが一件ある
  2. nav.xhtmlにepub:type="toc"を持つnavが一件ある
  3. toc内のhrefがchapter.xhtmlのc01へ解決し、表示ラベルが章見出しと一致する

この三点のどれかが欠ければ、見た目にリンクがあっても目次契約は不合格です。

content.opfでcover・manifest・spineを結ぶ

content.opfのmetadataには作品名、識別子、言語、著者、更新日時を一度だけ定義します。表紙画像はmanifestのitemへproperties="cover-image"を付けて登録します。古い読み手との互換情報を持たせる構成では、metadataのcover指定も同じ表紙画像IDへ向け、別IDへ分岐させません。

manifestでは最低でも次の五資源を登録します。

spineは表示する読む単位をcover-page、chapter、colophonの順に参照します。cover画像そのものをspineへ入れるのではなく、cover画像を表示するcover.xhtmlを入れます。各itemrefのidrefからmanifestのIDへ進み、そのhrefが実ファイルへ解決するところまでたどってください。

container.xmlとmimetypeで入口を作る

META-INF/container.xmlのrootfileはOEBPS/content.opfを指すようにします。OPFが存在していてもfull-pathが別の場所なら、入口からパッケージへ到達できません。

ルートのmimetypeにはapplication/epub+zipだけを入れます。EPUBへ固めるときはmimetypeを最初のZIPエントリーとして無圧縮で格納し、その後にMETA-INFとOEBPSを追加します。拡張子を.epubへ変えただけでは、この入口条件は成立しません。

四本の参照鎖で入力漏れを探す

ZIP化後は、見た目ではなく次の順に検査します。

  1. container.xml → OEBPS/content.opf
  2. OPF manifest → nav、cover-image、cover-page、chapter、colophonの各実体
  3. OPF spine → cover-page → chapter → colophon
  4. nav toc href → chapter.xhtml#c01、cover.xhtml img src → Images/cover.png

合わせてmimetypeの内容、ZIP内の先頭位置、無圧縮格納を確認します。エラーは「開かなかった」でまとめず、入口、登録、読む順、目次移動先、表紙参照のどこで切れたかを記録します。そうすれば、chapter原稿の変換漏れとcover.pngの格納漏れを別々に直せます。

参照が切れたときは、生成物へファイルを足す前に契約表へ戻ります。containerからOPFへ届かないなら入口、OPFに項目がないなら登録、idrefが解決しないなら読む順、画像srcだけ切れるなら表紙参照の問題です。該当する一段を直した後も四本すべてを先頭から再確認し、修正で別のhrefやIDを壊していないことまで確認します。

Rune Studioの確認済み範囲を混ぜない

実際の画像なしEPUBでは、mimetype、META-INF、OEBPS、XHTML、nav、NCX、content.opfのmetadata・manifest・spine、奥付を確認し、パッケージ検査を通過しました。

表紙を含む別のEPUBでは、ZIP内部のOEBPS/Images/cover.png、OPF manifest、cover.xhtmlから表紙画像への参照は実在しました。一方、検査結果は実在する画像を欠落扱いしています。したがって「表紙ファイルと参照は確認済み」ですが、「表紙入りEPUBの検査合格」は判断待ちです。画像が無かったとも、完成検査に通ったとも書けません。

作品名・組み方向・ページ順・出力ファイル名・発行日が一覧で並ぶRune StudioのEPUB出力確認画面
EPUB作成の確認画面。作品情報、組み方向、ページ順、出力ファイル名、発行日、表紙の有無が出力前に一覧で見えます。生成物の構造検査はこの画面とは別に行います。

入力票と参照契約を残してから生成する

EPUBのファイル作り方で入力漏れを防ぐには、chapter原稿とcover.pngを固定し、八実体の配置を決め、navのproperties="nav"とtoc nav、OPFのcover・manifest・spine、container、mimetype、奥付を一つずつ結ぶことが重要です。

一章の内部契約が通った後に、Rune Studioの6ページのEPUBウィザードで三章を選び、生成した三つの目次ラベルと移動先を試す段階へ進みます。現行Mac版の製品範囲は、Rune Studioの商品ページで確認できます。