最近折腾了半天 epub,原因是不知从何处 Down 到一份 epub,打开被绚丽的粉底和满屏所谓的“特效”闪吓了狗眼。为了能弄出来个“能看”的 epub 塞进手机里,而不继续被这些傻**恶心,我决定研究下 epub 这种格式。

恋骑士 PurelyKiss 由宇的祈愿

如果其实不在意这些技术问题,认为 epub 应该是有人做好拿给你(其实确实应该这样),那么不要继续向下看了。

关于 epub 这个东西

epub 是一种挺好用的电子书格式,比 pdf 更容易排版,制作起来也很简单。

文件结构

epub 本质是一个 zip 文件,用 7-zip 等软件都可以轻易打开。一般来说,整理的比较好的文件结构应该像这样:

mimetype
META-INF/
  container.xml
OEBPS/
  content.opf
  toc.ncx
  Text/
    chapter1.xhtml
  Images/
    ch1-pic.png
  Styles/
    style.css

其中,一般固定的会包含的 4 个文件是:mimetypeMETA-INF/container.xmlOEBPS/content.opfOEBPS/toc.ncx

mimetype

只有一行,固定为application/epub+zip

META-INF/container.xml

container.xml是一个 xml 文件,路径和名字固定,里面指明了content.opf文件的位置。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="OEBPS/content.opf" media-type="application/oebps-package+xml"/>
  </rootfiles>
</container>

OEBPS/content.opf

content.opf是一个 xml 文件,里面指明了实际书页文件、书本的阅读数序等,可以说是 epub 中除了实际的书页内容最有用的文件了。被称为“EPUB Package Document”。其路径由container.xml文件制定,文件名和位置其实随意,OEBPS/这个文件夹可以也不存在。不过把 epub 的内容都放在这个文件夹里是个习惯。

content.opf的一个例子:

<?xml version="1.0" encoding="UTF-8"?>
<package version="2.0" xmlns="http://www.idpf.org/2007/opf" unique-identifier="BookId">

  <metadata xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:opf="http://www.idpf.org/2007/opf">
    <dc:title>Pride and Prejudice</dc:title>
    <dc:language>en</dc:language>
    <dc:identifier id="BookId" opf:scheme="ISBN">123456789X</dc:identifier>
    <dc:creator opf:file-as="Austen, Jane" opf:role="aut">Jane Austen</dc:creator>
  </metadata>

  <manifest>
    <item id="chapter1" href="chapter1.xhtml" media-type="application/xhtml+xml"/>
    <item id="stylesheet" href="style.css" media-type="text/css"/>
    <item id="ch1-pic" href="ch1-pic.png" media-type="image/png"/>
    <item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/>
  </manifest>

  <spine toc="ncx">
    <itemref idref="chapter1" />
  </spine>

  <guide>
    <reference type="loi" title="List Of Illustrations" href="appendix.html#figures" />
  </guide>

</package>

<metadata>一节储存书本的属性信息,比如书名、作者等。

<manifest>一节需要列出 epub 中,除了自己、除了META-INF/下,剩下的所有文件。包括 css、图片、字体、目录文件什么的。每个文件需要给与一个 id。

<spine>一节列出书本的阅读顺序,用itemrefidref属性指明。同时其toc属性制定了书本的目录文件的 id。

<gudie>一节列出书本的附录,比如表目录、图目录等。

OEBPS/toc.ncx

所谓的目录文件,名字也是随意,指明使用这个文件的语句在 content.opf 中。阅读器从这个文件获取目录信息。一个例子

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE ncx PUBLIC "-//NISO//DTD ncx 2005-1//EN"
  "http://www.daisy.org/z3986/2005/ncx-2005-1.dtd">

<ncx version="2005-1" xml:lang="en" xmlns="http://www.daisy.org/z3986/2005/ncx/">

  <head>
<!-- The following four metadata items are required for all NCX documents,
including those that conform to the relaxed constraints of OPS 2.0 -->

    <meta name="dtb:uid" content="123456789X"/> <!-- same as in .opf -->
    <meta name="dtb:depth" content="1"/> <!-- 1 or higher -->
    <meta name="dtb:totalPageCount" content="0"/> <!-- must be 0 -->
    <meta name="dtb:maxPageNumber" content="0"/> <!-- must be 0 -->
  </head>

  <docTitle>
    <text>Pride and Prejudice</text>
  </docTitle>

  <docAuthor>
    <text>Austen, Jane</text>
  </docAuthor>

  <navMap>
    <navPoint class="chapter" id="chapter1" playOrder="1">
      <navLabel><text>Chapter 1</text></navLabel>
      <content src="chapter1.xhtml"/>
    </navPoint>
  </navMap>

</ncx>

固定包含的文件之后,就是实际的书本的内容了。OEBPS/Text/文件夹下存放文字,格式是 xhtml,不过文件名后缀也可以使用 html。OEBPS/image/下存放所有的图片,OEBPS/Styles/下存放 css 文件。如果有 Fonts、Video、Audio 等也可以建立对应文件夹塞进去。

chapter1.xhtml的例子:

<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
  "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <title>chapter1</title>
    <link href="../Styles/style.css" rel="stylesheet" type="text/css"/>
  </head>

  <body>
    <div><img alt="" src="../image/ch1-pic.png"/></div>
  </body>
</html>

Sigil

Sigil是一个挺好用的 epub 编辑工具。它可以帮助你完成一些非常让人烦躁的事情,比如把所有文件都写在content.opf文件里。其它的功能包括自动代码检查更正、epub 文件审查、生成toc.ncx等等。我强烈建议你使用这个工具而不是手写上面那些 xml 或者 xhtml,容易出错而且没有价值。

Pandoc

如果你已经有了 Txt 和图片,Pandoc可能是个不错的工具来把它们合成 epub。这样就不用手动分章、粘贴进 Sigil 了。你需要做的只是把 txt 给整理成合理的 markdown 格式。具体可以参考Pandoc 关于 epub 的文档

pandoc -S -o book.epub book.txt

需要注意的是,如果是多个 markdown/txt 文件合成 epub 的话,pandoc 实际上是把这几个文件直接连在一起之后转换。所以,在每个文件末尾一定要有一个额外的空行,不然两个文件连在一起就像这样:

:::markdown
end of 1st file
# Begin of 2nd file

这不是一个合法的 Markdown 格式,转换出来会有错误。

参考

  1. epubcafe有一篇比较详细的 epub 和 Sigil 教程(日文和英文)
  2. idpf的标准文档可能也会有用,当然作为标准文档,它太繁冗了。