同人小説を初めてEPUBにした時の覚書

この記事は、自分の試行錯誤の垂れ流しなので、いつも以上に突っ込み歓迎です

過去発行していた同人小説のEPUB版を作ることにしました

EPUBを選んだ理由は縦書きにしたい固定レイアウトにする必要はない内容なのでリフロー版にしたいだったので、EPUBでも3.0.1か3.1が対象になります

その上で、今回参照した本がEPUB3を対象としており、これに従ってEPUBを作ったらValidatorからEPUB3.0.1と認定されたので下記は3.0.1 (としてValidatorを通過できるファイル) を作る作業記録になります

仕様 (邦訳) とか参考文献とか資料とかツールとか

サンプルEPUBを作ってみる

EPUBファイルは特定のディレクトリィ構造、ファイルを持つZIPファイルです

今回作るSample EPUBの構成は以下の通りです (下記の ContentSampleEpubNavigation は任意の名称)

mimetype
META-INF/container.xml
Content/SampleEpub.opf
Content/SampleEpub.xhtml
Content/Navigation.xhtml

ファイル名、フォルダ名

EPUBの内容となるファイルのファイル名、フォルダ名は基本的に任意ですが、複数OS間での互換性の為や、予約されているファイル名などもありますので、以下を参照してください

雑に言えばファイル名は大文字小文字を区別した上でUTF-8で表現可能かつ記号は避け、またMETA-INFフォルダ配下には所定のファイル (今回の例示では container.xml) のみみしておけば大丈夫っぽいです

mimetype

4.3 OCF ZIP Container Media Type Identification - EPUB Open Container Format (OCF) 3.1

mimetypeファイルは application/epub+zip のみを内容物として持つファイルで文字コードはUS-ASCIIです

META-INF/container.xml

META-INF/container.xml は以下の通りです

フォルダ名の META-INF ファイル名の container.xml 共に名称は固定です

<?xml version='1.0' encoding='utf-8'?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
  <rootfiles>
    <rootfile full-path="Content/SampleEpub.opf" media-type="application/oebps-package+xml" />
  </rootfiles>
</container>

rootfile 要素の full-path 属性の値は、実際のopfファイルの相対パスになり、それ以外の内容は固定になります

Content/SampleEpub.opf

Content/SampleEpub.opf (フォルダ名、ファイル名は container.xml で指定した任意の物) は以下の通りです

フォルダ名の Content ファイル名の SampleEpub は任意の名称になりますが、拡張子の '.opf' は多分固定です (あるいは変えない方が無難です)

<?xml version='1.0' encoding='utf-8'?>
<package unique-identifier="BookId" version="3.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns="http://www.idpf.org/2007/opf">
  <metadata>
    <dc:title>Sample Epub</dc:title>
    <dc:language>ja</dc:language>
    <dc:identifier id="BookId">tag:example.com,2018-09-11:BookId/Sample Epub</dc:identifier>
    <meta property="dcterms:modified">2018-09-11T00:00:00Z</meta>
  </metadata>
  <manifest>
    <item id="Navigation" href="Navigation.xhtml" media-type="application/xhtml+xml" properties="nav" />
    <item id="SampleEpub" href="SampleEpub.xhtml" media-type="application/xhtml+xml" />
  </manifest>
  <spine>
    <itemref idref="Navigation" />
    <itemref idref="SampleEpub" />
  </spine>
</package>

opfファイルはXMLファイルで、document要素は package 要素となります

package 要素の unique-identifier 属性の値は任意のIDとなる値です

package 要素の子要素は metadatamanifestspine の3要素となり、それぞれについて説明します

metadata 要素

metadata 要素は要素名の通りEPUBファイルのメタデータ (書誌情報) を格納する要素です

dc名前空間の子要素として最低限 titlelanguageidentifier を記述します

title 要素は文字通りの本のタイトルを記述し、language 要素はIETF言語タグ (RFC 4646 および RFC 4647) で日本語の場合は ja または ja-JP を記述します

identifier要素は id 属性に document 要素の package 要素の unique-identifier 属性の値と同一の値を設定し、子要素としてIDREF (XML)のTextNodeを記述します

この identifier 要素の内容となる IDREF は、 property 属性に dcterms:modified を持つ meta 要素の日付と合わせて同一の書籍の同一性と異なる版の判別に使われます

Sample EpubのIDについて

例では RFC 4151のThe 'tag' URI Scheme をIDとして使っています

Examples of tag URIs are:
     tag:timothy@hpl.hp.com,2001:web/externalHome
     tag:sandro@w3.org,2004-05:Sandro
     tag:my-ids.com,2001-09-15:TimKindberg:presentations:UBath2004-05-19
     tag:blogger.com,1999:blog-555
     tag:yaml.org,2002:int

2.1. Tag Syntax and Examples - The 'tag' URI Scheme

manifest 要素

manifest 要素には子要素として順不同でEPUB内に格納しているコンテンツを item 要素として記載します

XHTML内から参照される画像や直接コンテンツとはならないstyle sheetなどもEPUBを構成するファイルは item 要素となります

item 要素

item 要素には id 属性、href 属性、media-type 属性を記載します

id属性は任意のid、href属性にはopfファイルから見た相対パスmedia-typeにはMINEの値を記載します

なお参照するファイルがXHTMLの場合、拡張子は.xhtmlMIMEapplication/xhtml+xmlとします

また、カバー絵となる画像を参照する item 要素には properties 属性でcover-image を設定し、目次となるXHTMLを参照する itme要素には同じくproperties 属性で nav" を記述します

spine 要素

spine 要素には子要素としてEPUBの内容を昇順で itemref 要素として記述します

itemref 要素

itemref要素にはidref属性で各リソースのIDを記述します

このidは manifest 要素の子要素の item 要素の id 属性の値になります

目次を記述する

XHTMLで目次を記述します

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE html>
<html xml:lang="ja" lang="ja" xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
  <head>
    <meta charset="utf-8" />
    <title>Sample Epub</title>
  </head>
  <body>
    <nav epub:type="toc">
      <h1>Sample Epub - 目次</h1>
      <ol>
        <li><a href="Sample Epub.xhtml">Sample Epub</a></li>
      </ol>
    </nav>
  </body>
</html>

EPUBの目次は opf ファイルの item 要素には properties 属性で properties 属性で nav" を記述した上で、XHTML文書内ではnav要素を使ってマークアップし、更に nav 要素には http://www.idpf.org/2007/ops 名前空間type 属性として toc を記述します

ZIP化してみる

Windows上でEPUBファイルとなるZIPファイルを作ろうとしたがどうしてもうまくいかなかったので、今回は EPUB で電子書籍を作成するEPUB ファイルを ZIP アーカイブとしてバンドルする を参考にbashでコマンドを叩くことにしました

以下、bashでZIPファイルを作ったときの作業

  1. 身近なbashWindows 10上のWindows Subsystem for LinuxUbuntu 18.04のbashだったのでそれを起動
  2. WSLにZIPがインストールされていなかったので $ sudo apt install zip unzip でZIPをインストール
  3. Windows上のドライブはrootの mnt ディレクトリィにマウントされているので $ cd /mnt/c/users/(以下略) でEpupファイルを作りたいディレクトリィに移動
  4. 最初に mimetype ファイルを非圧縮でzipに追加するために $ zip -0Xq SampleEpub.epub mimetype を実行
  5. 続いてmimetype以外のファイルをZIPに追加するために$ zip -Xr9Dq SampleEpub.epub *

EPUBファイルの名称

互換性の問題でEPUBの拡張子はすべて小文字で .epub とするのが良いそうです

チェッカーで確認してみる

EPUB Validator (beta) を使ってチェックしてみます

ここでエラーやワーニングが出たらGoogle翻訳先生に聞きながら直します

色々弄ったら、3.0.1 のファイルとして合格しました

右綴じ、縦書きのEPUBファイルにする

右綴じのEPUBの場合、opfファイルのspine要素に page-progression-direction 属性として rtl を記述します

縦書きの場合、各XHTMLファイルにCSSwriting-mode: vertical-rl; を適用することで縦書きになります

なお、筆者が不勉強のため各ビュワーの対応状況などについて把握していないのですが、-webkit- プレフィックス-epub- プレフィックスを付けた writing-mode プロパティも併せて記述した方が良いようです (-webkit- の方は問題がないことを確認したら外したい)

writing-mode: vertical-rl;
-webkit-writing-mode: vertical-rl;
-epub-writing-mode: vertical-rl;

現時点ではざっくりこんな感じで