epub: Use templates to generate EPUB files

This commit is contained in:
Takeshi KOMIYA 2017-01-08 15:47:34 +09:00
parent 37f3050933
commit 201ae9c1ac
7 changed files with 49 additions and 29 deletions

View File

@ -28,10 +28,12 @@ except ImportError:
from docutils import nodes from docutils import nodes
from sphinx import addnodes from sphinx import addnodes
from sphinx import package_dir
from sphinx.builders.html import StandaloneHTMLBuilder from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.util import logging from sphinx.util import logging
from sphinx.util import status_iterator from sphinx.util import status_iterator
from sphinx.util.osutil import ensuredir, copyfile, make_filename, EEXIST from sphinx.util.osutil import ensuredir, copyfile, make_filename
from sphinx.util.fileutil import copy_asset_file
from sphinx.util.smartypants import sphinx_smarty_pants as ssp from sphinx.util.smartypants import sphinx_smarty_pants as ssp
if False: if False:
@ -43,25 +45,12 @@ if False:
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
# (Fragment) templates from which the metainfo files content.opf, toc.ncx, # (Fragment) templates from which the metainfo files content.opf and
# mimetype, and META-INF/container.xml are created. # toc.ncx are created.
# This template section also defines strings that are embedded in the html # This template section also defines strings that are embedded in the html
# output but that may be customized by (re-)setting module attributes, # output but that may be customized by (re-)setting module attributes,
# e.g. from conf.py. # e.g. from conf.py.
MIMETYPE_TEMPLATE = 'application/epub+zip' # no EOL!
CONTAINER_TEMPLATE = u'''\
<?xml version="1.0" encoding="UTF-8"?>
<container version="1.0"
xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles>
<rootfile full-path="content.opf"
media-type="application/oebps-package+xml"/>
</rootfiles>
</container>
'''
TOC_TEMPLATE = u'''\ TOC_TEMPLATE = u'''\
<?xml version="1.0"?> <?xml version="1.0"?>
<ncx version="2005-1" xmlns="http://www.daisy.org/z3986/2005/ncx/"> <ncx version="2005-1" xmlns="http://www.daisy.org/z3986/2005/ncx/">
@ -190,6 +179,8 @@ class EpubBuilder(StandaloneHTMLBuilder):
""" """
name = 'epub2' name = 'epub2'
template_dir = path.join(package_dir, 'templates', 'epub2')
# don't copy the reST source # don't copy the reST source
copysource = False copysource = False
supported_image_types = ['image/svg+xml', 'image/png', 'image/gif', supported_image_types = ['image/svg+xml', 'image/png', 'image/gif',
@ -208,8 +199,6 @@ class EpubBuilder(StandaloneHTMLBuilder):
# don't generate search index or include search page # don't generate search index or include search page
search = False search = False
mimetype_template = MIMETYPE_TEMPLATE
container_template = CONTAINER_TEMPLATE
toc_template = TOC_TEMPLATE toc_template = TOC_TEMPLATE
navpoint_template = NAVPOINT_TEMPLATE navpoint_template = NAVPOINT_TEMPLATE
navpoint_indent = NAVPOINT_INDENT navpoint_indent = NAVPOINT_INDENT
@ -552,21 +541,16 @@ class EpubBuilder(StandaloneHTMLBuilder):
# type: (unicode, unicode) -> None # type: (unicode, unicode) -> None
"""Write the metainfo file mimetype.""" """Write the metainfo file mimetype."""
logger.info('writing %s file...', outname) logger.info('writing %s file...', outname)
with codecs.open(path.join(outdir, outname), 'w', 'utf-8') as f: # type: ignore copy_asset_file(path.join(self.template_dir, 'mimetype'),
f.write(self.mimetype_template) path.join(outdir, outname))
def build_container(self, outdir, outname): def build_container(self, outdir, outname):
# type: (unicode, unicode) -> None # type: (unicode, unicode) -> None
"""Write the metainfo file META-INF/cointainer.xml.""" """Write the metainfo file META-INF/container.xml."""
logger.info('writing %s file...', outname) logger.info('writing %s file...', outname)
fn = path.join(outdir, outname) filename = path.join(outdir, outname)
try: ensuredir(path.dirname(filename))
os.mkdir(path.dirname(fn)) copy_asset_file(path.join(self.template_dir, 'container.xml'), filename)
except OSError as err:
if err.errno != EEXIST:
raise
with codecs.open(path.join(outdir, outname), 'w', 'utf-8') as f: # type: ignore
f.write(self.container_template) # type: ignore
def content_metadata(self, files, spine, guide): def content_metadata(self, files, spine, guide):
# type: (List[unicode], List[unicode], List[unicode]) -> Dict[unicode, Any] # type: (List[unicode], List[unicode], List[unicode]) -> Dict[unicode, Any]

View File

@ -14,6 +14,7 @@ import codecs
from os import path from os import path
from datetime import datetime from datetime import datetime
from sphinx import package_dir
from sphinx.config import string_classes from sphinx.config import string_classes
from sphinx.builders.epub import EpubBuilder from sphinx.builders.epub import EpubBuilder
from sphinx.util import logging from sphinx.util import logging
@ -111,6 +112,8 @@ class Epub3Builder(EpubBuilder):
""" """
name = 'epub' name = 'epub'
template_dir = path.join(package_dir, 'templates', 'epub3')
navigation_doc_template = NAVIGATION_DOC_TEMPLATE navigation_doc_template = NAVIGATION_DOC_TEMPLATE
navlist_template = NAVLIST_TEMPLATE navlist_template = NAVLIST_TEMPLATE
navlist_template_has_child = NAVLIST_TEMPLATE_HAS_CHILD navlist_template_has_child = NAVLIST_TEMPLATE_HAS_CHILD

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles>
<rootfile full-path="content.opf" media-type="application/oebps-package+xml"/>
</rootfiles>
</container>

View File

@ -0,0 +1 @@
application/epub+zip

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles>
<rootfile full-path="content.opf" media-type="application/oebps-package+xml"/>
</rootfiles>
</container>

View File

@ -0,0 +1 @@
application/epub+zip

19
tests/test_build_epub.py Normal file
View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
"""
test_build_html
~~~~~~~~~~~~~~~
Test the HTML builder and check output against XPath.
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import pytest
@pytest.mark.sphinx('epub', testroot='basic')
def test_build_epub(app):
app.build()
assert (app.outdir / 'mimetype').text() == 'application/epub+zip'
assert (app.outdir / 'META-INF' / 'container.xml').exists()