尝试解析下 Epub.js:一个在浏览器上渲染 Epub 图书的工具

标签: dev | 发表时间:2021-11-20 00:00 | 作者:
出处:http://itindex.net/relian

一直在看 Epub 类型的图书, 很好奇一个 Epub 解析器是如果工作的。 碰巧看到了 Epub.js, 体验了一下还可以。 就尝试分析一下它的实现。本文会先介绍下 EPUB 格式,再来分析 Epubjs 的实现. 我前端经验仅限于了解常见标签含义,可能会有各种错误恳请斧正。

Epub

EPub是一个自由的开放标准,属于一种可以“自动重新排版”的内容;也就是文字内容可以根据阅读设备的特性,以最适于阅读的方式显示。EPub档案内部使用了XHTML或DTBook(一种由DAISY Consortium提出的XML标准)来展现文字、并以zip压缩格式来包裹档案内容。EPub格式中包含了数位版权管理(DRM)相关功能可供选用

以上来自维基百科: https://zh.wikipedia.org/wiki/EPUB

本文参考的规范为: Epub 3.2该规范发布于 2019-05-08, 定义了 EPUB 图书格式和 EPUB 图书的浏览器应实现的功能. Epub格式由以下规范组成:

  • EPUB Packages — 定义内容的每个Rendition的要求。
  • EPUB Content Documents — 定义了在 EPUB 出版物上下文中使用的 XHTML、SVG 和 CSS 的配置文件。
  • EPUB Media Overlays — 定义了文本和音频同步的格式和处理模型。
  • EPUB Open Container Format — 定义了一种文件格式和处理模型,用于将一组相关资源封装到单个文件 (ZIP) EPUB 容器中。
  • EPUB Accessibility — 定义 EPUB 出版物的可访问性一致性和发现要求。

如下图: EPUB图书的内容是由一个或多个Rendition组成,每个Rendition都由所谓的EPUB Package 表示。 EPUB Package包含呈现内容所需的所有资源。其中的关键文件是Package Document,它包括阅读系统用于向用户呈现EPUB图书的所有元数据(例如标题和作者等)。它还提供了一个完整的资源清单,并包括一个 SPINE(用来表是文档出现的顺序)。 EPUB Package还包括另一个称为EPUB Navigation Document的文件。本文档提供了导航功能,例如目录,允许用户快速轻松地导航内容。 EPUB 图书的资源捆绑在一个基于 ZIP 的文件中,文件扩展名为.epub. 作为符合 ZIP 格式的文件,EPUB 出版物可以被许多软件程序解压缩,从而简化了它们的使用。 Epub Structure

参考规范来制作一个简单Epub 图书

按照下图的方式来组织目录和文件

Dirtctor

mimetype 文件名固定, 内容也固定位: application/epub+zip

META-INF/container.xml 为入口文件,文件名固定.

内容如下: 其中rootfile指定了package file

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

OPS/package.opf

Package 文件, 定义了书籍的 meta 信息, 资源列表和阅读顺序(Spine) 内容如下:

  • metadata: 标签定义的作者等信息
  • manifest: 定义了资源列表,如 正文页面, 目录, 封面图片, CSS, JS 等等
  • spine: 定义了书籍连续阅读的顺序.
    • Liner 代表顺序是否为必要顺序. 如目录和封面不一定强制按照这个顺序来阅读. 或者说是在做阅读器是可以把 Liner=no页面弹窗
    • 和目录/书签最显著的区别, Spine 是按照资源文件来组织循序. 目录/书签等是可以指定到资源内的标签.
    <?xml version='1.0' encoding='utf-8'?><packagexmlns="http://www.idpf.org/2007/opf"unique-identifier="uuid_id"version="3.2"prefix="calibre: https://calibre-ebook.com"><metadataxmlns:dc="http://purl.org/dc/elements/1.1/"><dc:titleid="id">Calvin用来演示 EPUBJS 的书</dc:title><dc:creatorid="Creator">Calvin Wang</dc:creator><dc:identifierid="uuid_id">urn:uuid:5F1E4C07-2A52-48BC-BBA5-E98564559794</dc:identifier><dc:language>zh-CN</dc:language><metaproperty="dcterms:modified">2021-11-14T08:32:29Z</meta></metadata><manifest><itemid="cover"href="cover.xhtml"media-type="application/xhtml+xml"/><itemid="toc"properties="nav"href="toc.xhtml"media-type="application/xhtml+xml"/><itemid="firstpage"href="first_page.xhtml"media-type="application/xhtml+xml"/><itemid="secondpage"href="second_page.xhtml"media-type="application/xhtml+xml"/><itemid="ncxtoc"href="toc.ncx"media-type="application/x-dtbncx+xml"/><itemid="cover-image"properties="cover-image"href="images/cover.png"media-type="image/png"/></manifest><spinetoc="ncxtoc"><itemrefidref="cover"linear="no"/><itemrefidref="toc"linear="no"/>ß<itemrefidref="firstpage"linear="yes"/><itemrefidref="secondpage"linear="yes"/></spine></package>

其他页面

    <--!CoverPage--><?xml version="1.0" encoding="UTF-8"?><htmlxmlns="http://www.w3.org/1999/xhtml"xmlns:epub="http://www.idpf.org/2007/ops"><head><title>Cover Page</title><metacharset="utf-8"/></head><body><div><imgsrc="images/cover.png"alt="Cover Image"title="Cover Image"/></div></body></html><--!firstpage--><?xml version="1.0" encoding="UTF-8"?><htmlxmlns="http://www.w3.org/1999/xhtml"xmlns:epub="http://www.idpf.org/2007/ops"><head><title>First Page</title><metacharset="utf-8"/></head><body><sectionepub:type="bodymatter chapter"><header><h1><spanid="c002p0000">First Page</span></h1></header><p><spanid="c002p0001">First Page: aaaaaaaaaaaa</span></p><p><spanid="c002p0002">First Page: bbbbbbbbbbbbb</span></p></section></body></html><--!TOCPage--><?xml version='1.0' encoding='utf-8'?><htmlxmlns="http://www.w3.org/1999/xhtml"xmlns:epub="http://purl.org/dc/elements/1.1/"><head><title>Cover</title></head><body><navxmlns:ns0="http://www.idpf.org/2007/ops"ns0:type="toc"><ol><li><ahref="cover.xhtml">Cover Page</a></li><li><ahref="toc.xhtml">Nav Page</a></li><li><ahref="first_page.xhtml">First Page</a></li><li><ahref="second_page.xhtml">Second Page</a></li></ol></nav></body></html>

把目录打包成 EPUB 文件

如下图: 用 ZIP 压缩文件至 first-epub.epub

    zip-r../first-epub.epub*

把做好的图书用自带的 Book 打开来看看

Epub.js

Epub.js 是一个 JavaScript 库,用于在浏览器中跨多种设备呈现 ePub 文档。 Epub.js 为常见的电子书功能(如渲染、持久化和分页)提供了一个接口,而无需开发专用的应用程序或插件。 重要的是,它是 BSD 许可证。

翻译自 项目 README

来看看官方的DEMO

高亮 备注 分页等等常用功能是均支持的

来实现一个”Hello Word”

    <!DOCTYPE html><html><head><metacharset="utf-8"><title>Demo for Epub.js</title><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.5/jszip.min.js"></script><scriptsrc="https://futurepress.github.io/epub.js/dist/epub.js"></script></head><body><divid="nav"><selectid="toc"></select></div><divid="viewer"></div><script>var$viewer=document.getElementById("viewer");// Load the opfvarbook=ePub("https://blog.calvin.wang/assets/first-epub.epub",{store:"epubjs-test"});varrendition=book.renderTo("viewer",{width:"100%"});vardisplayed=rendition.display();book.loaded.navigation.then(function(toc){var$select=document.getElementById("toc"),docfrag=document.createDocumentFragment();toc.forEach(function(chapter){varoption=document.createElement("option");option.textContent=chapter.label;option.ref=chapter.href;docfrag.appendChild(option);});$select.appendChild(docfrag);$select.onchange=function(){varindex=$select.selectedIndex,url=$select.options[index].ref;rendition.display(url);returnfalse;};});</script></body></html>

来看看它有哪些 Model

  • Book: 用来代表一个 Epub 图书,用来加载和解析其内容
    • Container: 用来解析 Container, 主要用来从 “META-INF/container.xml”获取 PackagePath
    • Packaging: 用来解析 Package, 主要用来获取manifest cover spine metadata nav ncx
  • Rendition: 负责将 Book 的内容渲染在网页上,并进行控制.
    • Manager: 用来控制网页上的呈现方式(default: DefaultViewManager)
    • View: 展现在页面上的样式(default: IframeView)
  • EpubCFI: 是一个规范,定义了一种标准化方法,用于通过使用片段标识符来引用 EPUB® 出版物中的任意内容. 可以参考: http://idpf.org/epub/linking/cfi/epub-cfi.html
  • 辅助类:
    • Theme: 样式主题
    • Annotations: 注解

流程怎么控制的

  • Rendition:
    • 支持HOOK的阶段:
      • content: Pages/View内容被解析和加载,现有的 HOOK
        • handleLinks: 处理内容中的连接
        • passEvents: 内容中产生的事件同步
        • adjustImages: 调整图片
      • unloaded: Pages/View内容从屏幕中卸载
      • render: Pages/View被渲染到屏幕
  • Spin:
    • 支持HOOK的阶段:
      • Serialize: Pages/View 被转换为 text
      • Content: Pages/View 被加载和解析. 现有的 HOOK
        • injectStylesheet: 注入样式表
        • injectScript: 注入脚本

还没有完全看懂的内容, 感觉是语言特性:

  1. Promise 的用处?
  2. Event的传递方式?

相关 [解析 epub js] 推荐:

JS跨浏览器解析XML应用

- - ITeye博客
对于XML,我们可以理解它是一种树结构,它包含根,元素,属性,文本等内容. 不同浏览器都有自己的解析器,把XML读入内存,并把它转换为可被 JavaScript 访问的 XML DOM 对象. 微软的 XML 解析器与其他浏览器中的解析器是有差异的. 微软的解析器支持对 XML 文件和 XML 字符串(文本)的加载,而其他浏览器使用单独的解析器.

尝试解析下 Epub.js:一个在浏览器上渲染 Epub 图书的工具

- - IT瘾-dev
一直在看 Epub 类型的图书, 很好奇一个 Epub 解析器是如果工作的. 碰巧看到了 Epub.js, 体验了一下还可以. 本文会先介绍下 EPUB 格式,再来分析 Epubjs 的实现. 我前端经验仅限于了解常见标签含义,可能会有各种错误恳请斧正. EPub是一个自由的开放标准,属于一种可以“自动重新排版”的内容;也就是文字内容可以根据阅读设备的特性,以最适于阅读的方式显示.

PDF to EPUB Converter绿色便携版:PDF转换为EPUB

- 抹布 - 精品绿色便携软件
Xilisoft PDF to EPUB Converter是一个将PDF转换为EPUB格式的软件,有文本和图片两种转换模式,支持编辑EPUB信息,包括名称、作者、ISBN、发行商、图片类别与注释等. EPUB是一种电子图书标准,其文字内容可以根据阅读设备的不同而以最佳阅读方式显示,iPad、iPhone、Android等均支持EPUB图书.

用Calibre製作ePub格式電子書

- RaRo - appleseed, 蘋果核
前陣子在讀奧修的網頁版文章,因為網頁的排版很恐怖,看久了就開始眼花,所以才興起把文章轉成iOS裝置可以用的電子書,一開始的想法很簡單,就是把網頁的文字複製到「文字編輯器」,然後再用 Calibre 轉成ePub,稍微熟悉Calibre的操作流程的話,其實是沒有什麼問題的. 這樣轉換出來的ePub格式並不會自己形成章節,當書讀到後半段時,就會發現整個效能降低很多,翻頁或是要畫個螢光筆標註都很慢,所以覺得還是要把章節給做出來,當然這樣用起來爽度也比較高啦.

《把时间当作朋友》epub版

- kirby - Pure Pleasure - Reborn
10月7日在香港终于拿到iPhone4,各个方面都很满意. 原本以为手机屏幕太小不适合阅读,结果实际使用才发现其实阅读体验还是相当不错的──用iBooks阅读epub格式的书,实际上非常方便,并且也不累眼睛. 《把时间当作朋友》epub版下载链接:http://is.gd/fYaLN.

Kindle 原系统上读 ePub 电子书

- stier - Page to Page
在Kindle上安装过Launchpad以后,再安装fbKindle好像是顺理成章的事,毕竟剩下的就是复制fbKindle文件到Kindle上就可以了. 虽然平时遇到Epub格式的电子书习惯上是拿软件转一下,不过有了fbKindle以后也可以直接拷到Kindle阅读,迈开了越狱的步子,也不怕多走一步,继续动手.

Readium – 在 Chrome 上阅读 epub 电子书

- - 小众软件 - Appinn
在网络上下载了 epub 格式的电子书,想浏览一下内容对不对的话,可以试试. Readium 这个 Chrome 扩展. 安装之后,新建标签页,在应用程序可以找到它. Readium 可以阅读网络上的 epub 文件,或者从你的电脑上选择一个 epub 文件. 打开之后,它会提取图片,提取之后下次打开就很快了.

用kindle阅读epub的3个办法

- -
向大家介绍3种方便的让kindle可以阅读epub电子书的办法. 大家都知道kindle是不能直接epub文件的,而且有的epub文件都DRM保护(. DRM脱壳工具下载),需要DRM Removal之后,才能进行后续格式转换操作. 办法一:将EPUB文件转换为MOBI电子书格式. 下面介绍两个电子书管理工具,都可以实现转换EPUB为Kindle支持的格式MOBI, AZW3, PDF.

WebView JS 交互

- - ITeye博客
WebView加jquery做页面会怎么样呢. // 创建WebView对象. // 把programList添加到js的全局对象window中,. // 这样就可以使用window.programList来获取数据. * 定义js回调java函数. // 绑定键盘的向上,向下按钮事件触发相应的js事件.

简单***的实现,利用js解析把web网页转换成自己的网页,加快开发

- - ITeye博客
利用开源js引擎rhino+jsoup进行web裁制,使用javascript来解析页面. 已有 0 人发表留言,猛击->> 这里<<-参与讨论. —软件人才免语言低担保 赴美带薪读研.