epub3.2仕様を読んで手作業epub作りメモ

# はじめに

- 既存のコンバータでepubを作ったら汚かった
- epub仕様を把握して自分でepubドキュメントを作ろうと思った
- 昔自炊した連番JPGをepubにまとめたいので、epub仕様書から必須項目だけ集めてみた
- 最小サンプルセット https://github.com/positrium/create-epub-with-my-hand
    - 画像をカバーで１枚、ページで１枚。ただそれだけのセット。
- rubyで連番JPGをepubにするスクリプトを書いてみた
    - https://github.com/positrium/img2epub.rb

# epubコンテナ

```
.
├── mimetype
├── META-INF/
│   └── container.xml
└── EPUB/
    ├── images/
    │   ├── cover.jpg
    │   ├── chap1.jpg
    │   └── chap2.jpg
    ├── nav.xhtml
    ├── chap1.xhtml
    ├── chap2.xhtml
    └── book.opf
```

- ファイル拡張子 .epub の ZIPアーカイブ準拠
- 例: https://imagedrive.github.io/Submission/epub32/epub-ocf.html#example


### mimetype

```:mimetype
application/epub+zip
```

#### ZIPファイル仕様

mimetypeはZIPファイルの先頭になければならない。

```shell
# mimetypeのみ書き込む
zip -X0 ../test_epub.epub mimetype

# mimetypeを除いてそれ以外を追加書き込みする
zip -r9 ../test_epub.epub * -x mimetype -x .*
```

- **ERROR(PKG-005) mimetypeファイルに長さ28の拡張フィールドがあります. mimetypeファイルでZIPフォーマットの拡張フィールド属性を使うことは許可されていません.**
    - 対策： `-X` 指定ファイル属性を除外する。
- **ERROR(PKG-007): mimetypeファイルは文字列 'application/epub+zip' だけを含み、また圧縮してはいけません.**
    - 対策： `-0` 非圧縮に設定する。
    - 補足： 非圧縮にしてもepubcheckはPKG-007を吐くが、iBookは改行を含んでいた場合もエラーなしで読み込むことが出来る。
    - epubcheckのバグ？　ERROR回避方法があれば教えて欲しい。
- **ERROR(PKG-006): mimetypeファイルエントリが存在しないか、アーカイブの先頭以外の場所に存在しています.**
    - 対策： `-x` 指定名を除外する。


### META-INF/container.xml

opfの位置を指定する。

```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="EPUB/book.opf" media-type="application/oebps-package+xml" />
    </rootfiles>
</container>
```

- container#version=1.0はcontainer.xmlスキーマ由来
    - 補足： https://github.com/w3c/epubcheck/blob/master/src/main/resources/com/adobe/epubcheck/schema/30/ocf-container-30.rnc 
- EPUB/book.opfは後述のパッケージドキュメントのファイル名と一致する 


# ドキュメント構成

https://imagedrive.github.io/Submission/epub32/epub-packages.html

- パッケージドキュメント
    - マニフェスト（出版物リソース）
- EPUBナビゲーションドキュメント
- コンテンツドキュメント

## パッケージドキュメント

```xml:EPUB/book.opf
<?xml version="1.0" encoding="UTF-8"?>
<package unique-identifier="pub-id" version="3.0" xmlns="http://www.idpf.org/2007/opf">
    <metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
        <dc:identifier id="pub-id">urn:uuid:14109e67-1e75-4360-acc2-1bd5644ecedb</dc:identifier>
        <dc:title>MINIMUM SAMPLE</dc:title>
        <dc:language>ja-JP</dc:language>
        <meta property="dcterms:modified">2019-08-07T00:49:06Z</meta>
    </metadata>

    <manifest>
        <item id="nav" href="./nav.xhtml" properties="nav" media-type="application/xhtml+xml" />
        <item id="cover" href="./images/cover.jpg" properties="cover-image" media-type="image/jpeg" />

        <item id="chap2" href="./chap2.xhtml" media-type="application/xhtml+xml" />
        <item id="chap1" href="./chap1.xhtml" media-type="application/xhtml+xml" />
        <item id="imgChap1" href="./images/chap1.jpg" media-type="image/jpeg" />
        <item id="imgChap2" href="./images/chap2.jpg" media-type="image/jpeg" />
    </manifest>
    
    <spine page-progression-direction="rtl">
        <itemref idref="chap1" />
        <itemref idref="chap2" />
    </spine>
</package>
```

- `package.version`は3.0にしなければならないと記述があるので3.2ではいけない。
- `package#unique-identifier`に指定する中身はドキュメントユニークであれば何でも良い。
- `package.metadata.meta#property`の中身
    - 補足： https://imagedrive.github.io/Submission/epub32/epub-packages.html#sec-property-datatype に定義されている。
- `package.manifest.item`は順序を保証しない。順序はspine(脊椎)で保証する。
- `package.manifest.item#media-type`の中身
    - 補足： https://imagedrive.github.io/Submission/epub32/epub-spec.html#sec-cmt-supported に定義されている。(jpg -> `image/jpeg`)
- `package.manifest.item#properties="nav"`とし、EPUBナビゲーションドキュメントを記述しなければならないらしい。
- `package.spine.itemref#linear="no"`の用途は、本文ではない注釈向け。
- 拡張子opf であれば良い。
- book.opf中で相対パスを書いているが、これも正しい。
- `package.spine.itemref`には`image/jpeg`なid参照は出来なかった。 
- `package.manifest.item`にはコンテナ内のリソースをすべて書き込まなければならないので画像用のエントリを追記。

(*) Online UUID Generator: https://www.uuidgenerator.net/version4


## EPUBナビゲーションドキュメント

目次に相当。

```xml:nav.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops">
  <head>
    <title>nav</title>
  </head>
  <body>
    <nav epub:type="toc">
      <ol>
        <li><a href="chap1.xhtml">chapter 1</a></li>
        <li><a href="chap2.xhtml">chapter 2</a></li>
      </ol>
    </nav>
  </body>
</html>
```

- `nav#epub:type`が指定されている場合にのみ有効とあるが、必須項目だった。
- `nav#epub:type`は、 https://imagedrive.github.io/Submission/epub32/epub-packages.html#sec-package-nav-def-types に定義されている。
- chapter, section, subsectionなどはHTMLのol-liの構造と同じ。ol > li > ol > li と掘っていく。
- 拡張子xhtmlのファイル。package.manifest.item#id="nav"ではnav.xhtmlとして参照してる。

## コンテンツドキュメント

本文に相当。

```xml:chap1.xhtml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>chapter 1</title>
  </head>
  <body>
    <img src="./images/chap1.jpg"/>
  </body>
</html>
```

https://imagedrive.github.io/Submission/epub32/epub-contentdocs.html

- html5ドキュメントで良い。 
    - 補足： https://www.slideshare.net/lost_and_found/iipabu-11542571
- chap2.xhtmlも同様。

# 付録 : macでepub作成シェルスクリプト

epubcheckを利用。

```sh
#!/bin/sh

echo "clean: "
rm test_epub.epub

# epub作成 .DS_Storeなどをしたい
echo " "
echo "create: "
cd test_epub/
zip -X0 ../test_epub.epub mimetype
zip -r9 ../test_epub.epub * -x mimetype -x .*
cd ..

# mimetypeファイルがZIPファイルの先頭にあるのを確認したい
echo " "
echo "list: "
unzip -l test_epub.epub

# EPUBコンテナの妥当性を検証したい
echo " "
echo "check: "
epubcheck test_epub.epub
```