From 201ae9c1acd3800c224666e2031846cda719e48e Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Sun, 8 Jan 2017 15:47:34 +0900 Subject: [PATCH] epub: Use templates to generate EPUB files --- sphinx/builders/epub.py | 42 +++++++++------------------- sphinx/builders/epub3.py | 3 ++ sphinx/templates/epub2/container.xml | 6 ++++ sphinx/templates/epub2/mimetype | 1 + sphinx/templates/epub3/container.xml | 6 ++++ sphinx/templates/epub3/mimetype | 1 + tests/test_build_epub.py | 19 +++++++++++++ 7 files changed, 49 insertions(+), 29 deletions(-) create mode 100644 sphinx/templates/epub2/container.xml create mode 100644 sphinx/templates/epub2/mimetype create mode 100644 sphinx/templates/epub3/container.xml create mode 100644 sphinx/templates/epub3/mimetype create mode 100644 tests/test_build_epub.py diff --git a/sphinx/builders/epub.py b/sphinx/builders/epub.py index d61f4868f..cdb766012 100644 --- a/sphinx/builders/epub.py +++ b/sphinx/builders/epub.py @@ -28,10 +28,12 @@ except ImportError: from docutils import nodes from sphinx import addnodes +from sphinx import package_dir from sphinx.builders.html import StandaloneHTMLBuilder from sphinx.util import logging 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 if False: @@ -43,25 +45,12 @@ if False: logger = logging.getLogger(__name__) -# (Fragment) templates from which the metainfo files content.opf, toc.ncx, -# mimetype, and META-INF/container.xml are created. +# (Fragment) templates from which the metainfo files content.opf and +# toc.ncx are created. # This template section also defines strings that are embedded in the html # output but that may be customized by (re-)setting module attributes, # e.g. from conf.py. -MIMETYPE_TEMPLATE = 'application/epub+zip' # no EOL! - -CONTAINER_TEMPLATE = u'''\ - - - - - - -''' - TOC_TEMPLATE = u'''\ @@ -190,6 +179,8 @@ class EpubBuilder(StandaloneHTMLBuilder): """ name = 'epub2' + template_dir = path.join(package_dir, 'templates', 'epub2') + # don't copy the reST source copysource = False 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 search = False - mimetype_template = MIMETYPE_TEMPLATE - container_template = CONTAINER_TEMPLATE toc_template = TOC_TEMPLATE navpoint_template = NAVPOINT_TEMPLATE navpoint_indent = NAVPOINT_INDENT @@ -552,21 +541,16 @@ class EpubBuilder(StandaloneHTMLBuilder): # type: (unicode, unicode) -> None """Write the metainfo file mimetype.""" logger.info('writing %s file...', outname) - with codecs.open(path.join(outdir, outname), 'w', 'utf-8') as f: # type: ignore - f.write(self.mimetype_template) + copy_asset_file(path.join(self.template_dir, 'mimetype'), + path.join(outdir, outname)) def build_container(self, outdir, outname): # 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) - fn = path.join(outdir, outname) - try: - os.mkdir(path.dirname(fn)) - 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 + filename = path.join(outdir, outname) + ensuredir(path.dirname(filename)) + copy_asset_file(path.join(self.template_dir, 'container.xml'), filename) def content_metadata(self, files, spine, guide): # type: (List[unicode], List[unicode], List[unicode]) -> Dict[unicode, Any] diff --git a/sphinx/builders/epub3.py b/sphinx/builders/epub3.py index 2723bff9c..040f4fc41 100644 --- a/sphinx/builders/epub3.py +++ b/sphinx/builders/epub3.py @@ -14,6 +14,7 @@ import codecs from os import path from datetime import datetime +from sphinx import package_dir from sphinx.config import string_classes from sphinx.builders.epub import EpubBuilder from sphinx.util import logging @@ -111,6 +112,8 @@ class Epub3Builder(EpubBuilder): """ name = 'epub' + template_dir = path.join(package_dir, 'templates', 'epub3') + navigation_doc_template = NAVIGATION_DOC_TEMPLATE navlist_template = NAVLIST_TEMPLATE navlist_template_has_child = NAVLIST_TEMPLATE_HAS_CHILD diff --git a/sphinx/templates/epub2/container.xml b/sphinx/templates/epub2/container.xml new file mode 100644 index 000000000..326cf15fa --- /dev/null +++ b/sphinx/templates/epub2/container.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/sphinx/templates/epub2/mimetype b/sphinx/templates/epub2/mimetype new file mode 100644 index 000000000..57ef03f24 --- /dev/null +++ b/sphinx/templates/epub2/mimetype @@ -0,0 +1 @@ +application/epub+zip \ No newline at end of file diff --git a/sphinx/templates/epub3/container.xml b/sphinx/templates/epub3/container.xml new file mode 100644 index 000000000..326cf15fa --- /dev/null +++ b/sphinx/templates/epub3/container.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/sphinx/templates/epub3/mimetype b/sphinx/templates/epub3/mimetype new file mode 100644 index 000000000..57ef03f24 --- /dev/null +++ b/sphinx/templates/epub3/mimetype @@ -0,0 +1 @@ +application/epub+zip \ No newline at end of file diff --git a/tests/test_build_epub.py b/tests/test_build_epub.py new file mode 100644 index 000000000..ad08dbe7d --- /dev/null +++ b/tests/test_build_epub.py @@ -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()