Commits

Georg Brandl committed 6ac1f33

Review of epub builder. Add a separate "epub_theme" config value for selecting a different theme.

Comments (0)

Files changed (10)

doc/_templates/layout.html

 {% extends "!layout.html" %}
 
 {% block extrahead %}
+{{ super() }}
 {%- if not embedded %}
 <style type="text/css">
   table.right { float: right; margin-left: 20px; }
   table.right td { border: 1px solid #ccc; }
 </style>
-{% endif %}
+{%- endif %}
 {% endblock %}
 
 {% block rootrellink %}
 .. class:: EpubBuilder
 
    This builder produces the same output as the standalone HTML builder, but
-   also generates an *epub* file for ebook readers.
-   This builder is meant to be used together with the
-   :confval:`html_theme` ``'epub'``.
-   See `<http://www.idpf.org/specs.htm>`_ or
-   `<http://en.wikipedia.org/wiki/EPUB>`_ for the definition of epubs.
+   also generates an *epub* file for ebook readers.  See
+   `<http://www.idpf.org/specs.htm>`_ or `<http://en.wikipedia.org/wiki/EPUB>`_
+   for the definition of the epub format.
 
    Its name is ``epub``.
 
 show_authors = True
 
 # The HTML template theme.
-html_theme = 'epub'
+html_theme = 'sphinxdoc'
 
 # A list of ignored prefixes names for module index sorting.
 modindex_common_prefix = ['sphinx.']
 htmlhelp_basename = 'Sphinxdoc'
 
 # Epub fields
+epub_theme = 'epub'
 epub_basename = 'sphinx'
-epub_author = 'Georg  Brandl'
+epub_author = 'Georg Brandl'
 epub_publisher = 'http://sphinx.pocoo.org/'
 epub_scheme = 'url'
 epub_identifier = epub_publisher
-epub_pre_files = [ ('index', 'Welcome')]
+epub_pre_files = [('index', 'Welcome')]
 epub_exclude_files = ['_static/opensearch.xml', '_static/doctools.js',
     '_static/jquery.js', '_static/searchtools.js',
     '_static/basic.css', 'search.html']
 Options for epub output
 -----------------------
 
-These options influence the epub output. As this writer derives from the
-HTMLWriter the HTML options also apply where appropriate.
-The actual values for some of the options is not really important,
-they just have to be entered into
+These options influence the epub output.  As this builder derives from the HTML
+builder, the HTML options also apply where appropriate.  The actual values for
+some of the options is not really important, they just have to be entered into
 the `Dublin Core metadata <http://dublincore.org/>`_.
 
 .. confval:: epub_basename
 
-  The basename for the epub file. It defaults to the :confval:`project` name.
+   The basename for the epub file.  It defaults to the :confval:`project` name.
+
+.. confval:: epub_theme
+
+   The HTML theme for the epub output.  Since the default themes are not
+   optimized for small screen space, using the same theme for HTML and epub
+   output is usually not wise.  This defaults to ``'epub'``, a theme designed to
+   save visual space.
 
 .. confval:: epub_title
 
-  The title of the document.
-  It defaults to the :confval:`html_title` option
-  but can be set independently for epub creation.
+   The title of the document.  It defaults to the :confval:`html_title` option
+   but can be set independently for epub creation.
 
 .. confval:: epub_author
 
-  The author of the document.
-  This is put in the Dublin Core metadata.
-  The default value is ``'unknown'``.
+   The author of the document.  This is put in the Dublin Core metadata.  The
+   default value is ``'unknown'``.
 
 .. confval:: epub_language
 
-  The language of the document.
-  This is put in the Dublin Core metadata.
-  The default is the :confval:`language` option or ``'en'`` if unset.
+   The language of the document.  This is put in the Dublin Core metadata.  The
+   default is the :confval:`language` option or ``'en'`` if unset.
 
 .. confval:: epub_publisher
 
-  The publisher of the document.
-  This is put in the Dublin Core metadata.
-  You may use any sensible string, e.g. the project homepage.
-  The default value is ``'unknown'``.
+   The publisher of the document.  This is put in the Dublin Core metadata.  You
+   may use any sensible string, e.g. the project homepage.  The default value is
+   ``'unknown'``.
 
 .. confval:: epub_copyright
 
-  The copyright of the document.
-  It defaults to the :confval:`copyright` option
-  but can be set independently for epub creation.
+   The copyright of the document.  It defaults to the :confval:`copyright`
+   option but can be set independently for epub creation.
 
 .. confval:: epub_identifier
 
-  An identifier for the document.
-  This is put in the Dublin Core metadata.
-  For published documents this is the ISBN number, but you can
-  also use an alternative scheme, e.g. the project homepage.
-  The default value is ``'unknown'``.
+   An identifier for the document.  This is put in the Dublin Core metadata.
+   For published documents this is the ISBN number, but you can also use an
+   alternative scheme, e.g. the project homepage.  The default value is
+   ``'unknown'``.
 
 .. confval:: epub_scheme
 
-  The publication scheme for the :confval:`epub_identifier`.
-  This is put in the Dublin Core metadata.
-  For published books the scheme is ``'ISBN'``.
-  If you use the project homepage, ``'URL'`` seems reasonable.
+   The publication scheme for the :confval:`epub_identifier`.  This is put in
+   the Dublin Core metadata.  For published books the scheme is ``'ISBN'``.  If
+   you use the project homepage, ``'URL'`` seems reasonable.  The default value
+   is ``'unknown'``.
 
 .. confval:: epub_uid
 
-  A unique identifier for the document.
-  This is put in the Dublin Core metadata.
-  You may use a random string.
-  The default value is ``'unknown'``.
+   A unique identifier for the document.  This is put in the Dublin Core
+   metadata.  You may use a random string.  The default value is ``'unknown'``.
 
 .. confval:: epub_pre_files
 
-  Additional files that should be inserted before the text generated by
-  Sphinx. It is a list of tuples containing the file name and the title.
-  Example::
+   Additional files that should be inserted before the text generated by
+   Sphinx. It is a list of tuples containing the file name and the title.
+   Example::
 
       epub_pre_files = [
-         ('index.html', 'Welcome'),
+          ('index.html', 'Welcome'),
       ]
 
-  The default value is ``[]``.
+   The default value is ``[]``.
 
 .. confval:: epub_post_files
 
-  Additional files that should be inserted after the text generated by
-  Sphinx. It is a list of tuples containing the file name and the title.
-  The default value is ``[]``.
+   Additional files that should be inserted after the text generated by Sphinx.
+   It is a list of tuples containing the file name and the title.  The default
+   value is ``[]``.
 
 .. confval:: epub_exclude_files
 
-  A list of files that are generated/copied in the build directory
-  but should not be included in the epub file.
-  The default value is ``[]``.
+   A list of files that are generated/copied in the build directory but should
+   not be included in the epub file.  The default value is ``[]``.
 
 
 .. _latex-options:
    Sphinx HTML output.
 
 
+.. _api role: http://git.savannah.gnu.org/cgit/kenozooid.git/tree/doc/extapi.py
+.. _xhtml to reST: http://docutils.sourceforge.net/sandbox/xhtml2rest/xhtml2rest.py
+
+
 Epub
 ----
 
-The EpubBuilder is currently in an experimental stage.
-It has only been tested with the Sphinx documentation itself.
-If you want to create epubs, here are some notes:
+The epub builder is currently in an experimental stage.  It has only been tested
+with the Sphinx documentation itself.  If you want to create epubs, here are
+some notes:
 
-* Split the text into several files. The longer the individual HTML files
-  are, the longer it takes the ebook reader to render them.
-  In extreme cases, the rendering can take up to one minute.
+* Split the text into several files. The longer the individual HTML files are,
+  the longer it takes the ebook reader to render them.  In extreme cases, the
+  rendering can take up to one minute.
 
-* Try to minimize the markup. This also pays in rendering time.
+* Try to minimize the markup.  This also pays in rendering time.
 
-* For some readers you can use embedded or external fonts
-  using the CSS ``@font-face`` directive.
-  This is *extremely* useful for code listings which are often cut
-  at the right margin. The default Courier font (or variant) is quite
-  wide and you can only display up to 60 characters on a line.
-  If you replace it with a narrower font, you can get more characters
-  on a line. You may even use
-  `fontforge <http://fontforge.sourceforge.net/>`_
-  and create narrow variants
-  of some free font. In my case I get up to 70 characters on a line.
+* For some readers you can use embedded or external fonts using the CSS
+  ``@font-face`` directive.  This is *extremely* useful for code listings which
+  are often cut at the right margin.  The default Courier font (or variant) is
+  quite wide and you can only display up to 60 characters on a line.  If you
+  replace it with a narrower font, you can get more characters on a line.  You
+  may even use `FontForge <http://fontforge.sourceforge.net/>`_ and create
+  narrow variants of some free font.  In my case I get up to 70 characters on a
+  line.
 
   You may have to experiment a little until you get reasonable results.
 
-* Test the created epubs. You can use several alternatives.
-  The ones I am aware of are
-  Epubcheck
-  (`http://code.google.com/p/epubcheck/
-  <http://code.google.com/p/epubcheck/>`_),
-  Calibre 
-  (`http://calibre-ebook.com/ <http://calibre-ebook.com/>`_),
-  FBreader (`http://www.fbreader.org/ <http://www.fbreader.org/>`_,
-  although it does not render the CSS), and
-  Bookworm (`http://bookworm.oreilly.com/ <http://bookworm.oreilly.com/>`_).
-  For bookworm you can download the source from
-  `http://code.google.com/p/threepress/ <http://code.google.com/p/threepress/>`_
-  and run you own local server.
+* Test the created epubs. You can use several alternatives.  The ones I am aware
+  of are Epubcheck_, Calibre_, FBreader_ (although it does not render the CSS),
+  and Bookworm_.  For bookworm you can download the source from
+  http://code.google.com/p/threepress/ and run your own local server.
 
-
-.. _api role: http://git.savannah.gnu.org/cgit/kenozooid.git/tree/doc/extapi.py
-.. _xhtml to reST: http://docutils.sourceforge.net/sandbox/xhtml2rest/xhtml2rest.py
+.. _Epubcheck: http://code.google.com/p/epubcheck/
+.. _Calibre: http://calibre-ebook.com/
+.. _FBreader: http://www.fbreader.org/
+.. _Bookworm: http://bookworm.oreilly.com/
 * **traditional** -- A theme resembling the old Python documentation.  There are
   currently no options beyond *nosidebar*.
 
-* **epub** -- A theme for the epub formatter. There are currently no
-  options. This theme tries to reduce visual space which is a sparse
-  resource on ebook readers.
+* **epub** -- A theme for the epub builder.  There are currently no options.
+  This theme tries to save visual space which is a sparse resource on ebook
+  readers.
 
 
 Creating themes

sphinx/builders/epub.py

 """
 
 import os
-import re
 import codecs
 from os import path
 import zipfile
 
 from docutils import nodes
 
-from sphinx import addnodes
 from sphinx.builders.html import StandaloneHTMLBuilder
 
 
-# (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, toc.ncx,
+# mimetype, and META-INF/container.xml are created.
 
 _mimetype_template = 'application/epub+zip' # no EOL!
 
 
 class EpubBuilder(StandaloneHTMLBuilder):
     """Builder that outputs epub files.
-    It creates the metainfo files
-    container.opf, toc.ncx, mimetype, and META-INF/container.xml.
-    Afterwards, all necessary files are zipped to an epub file.
+
+    It creates the metainfo files container.opf, toc.ncx, mimetype, and
+    META-INF/container.xml.  Afterwards, all necessary files are zipped to an
+    epub file.
     """
     name = 'epub'
 
 
     def init(self):
         StandaloneHTMLBuilder.init(self)
-        # the output files for HTML help must be .html only
+        # the output files for epub must be .html only
         self.out_suffix = '.html'
         self.playorder = 0
 
+    def get_theme_config(self):
+        return self.config.epub_theme, {}
 
     # generic support functions
     def make_id(self, name):
-        """Replace all characters not allowed for (X)HTML ids"""
+        """Replace all characters not allowed for (X)HTML ids."""
         return name.replace('/', '_')
 
     def esc(self, name):
-        """Replace all characters not allowed in text an attribute values"""
+        """Replace all characters not allowed in text an attribute values."""
         # Like cgi.escape, but also replace apostrophe
         name = name.replace('&', '&amp;')
         name = name.replace('<', '&lt;')
         return name
 
     def collapse_text(self, doctree, result):
-       """Remove all HTML markup and return only the text nodes"""
+       """Remove all HTML markup and return only the text nodes."""
        for c in doctree.children:
             if isinstance(c, nodes.Text):
-                result.append(c.data)
+                result.append(unicode(c))
             else:
                 result = self.collapse_text(c, result)
        return result
 
     def get_refnodes(self, doctree, result):
-        """Collect section titles, their depth in the toc and the refuri"""
-        # XXX: is there a betterr way than checking the attribute
+        """Collect section titles, their depth in the toc and the refuri."""
+        # XXX: is there a better way than checking the attribute
         # toctree-l[1-6] on the parent node?
         if isinstance(doctree, nodes.reference):
             classes = doctree.parent.attributes['classes']
 
     def get_toc(self):
         """Get the total table of contents, containg the master_doc
-        and pre and post files not managed by sphinx"""
+        and pre and post files not managed by sphinx.
+        """
         doctree = self.env.get_and_resolve_doctree(self.config.master_doc, self)
         self.refnodes = self.get_refnodes(doctree, [])
         self.refnodes.insert(0, {
 
     # Finish by building the epub file
     def handle_finish(self):
-        """Create the metainfo files and finally the epub"""
+        """Create the metainfo files and finally the epub."""
         self.get_toc()
         self.build_mimetype(self.outdir, 'mimetype')
         self.build_container(self.outdir, 'META-INF/container.xml')
         self.build_epub(self.outdir, self.config.epub_basename + '.epub')
 
     def build_mimetype(self, outdir, outname):
-        """Write the metainfo file mimetype"""
+        """Write the metainfo file mimetype."""
         self.info('writing %s file...' % outname)
         f = codecs.open(path.join(outdir, outname), 'w', 'utf-8')
         try:
             f.close()
 
     def build_container(self, outdir, outname):
-        """Write the metainfo file META-INF/cointainer.xml"""
+        """Write the metainfo file META-INF/cointainer.xml."""
         self.info('writing %s file...' % outname)
         fn = path.join(outdir, outname)
         try:
 
     def content_metadata(self, files, spine):
         """Create a dictionary with all metadata for the content.opf
-        file properly escaped"""
+        file properly escaped.
+        """
         metadata = {}
         metadata['title'] = self.esc(self.config.epub_title)
         metadata['author'] = self.esc(self.config.epub_author)
         return metadata
 
     def build_content(self, outdir, outname):
-        """Write the metainfo file content.opf
-        It contains bibliographic data, a file list and
-        the spine (the reading order)."""
+        """Write the metainfo file content.opf It contains bibliographic data,
+        a file list and the spine (the reading order).
+        """
         self.info('writing %s file...' % outname)
 
         # files
             f.close()
 
     def new_navpoint(self, node, level, incr=True):
-        """Create a new entry in the toc from the node at given level"""
+        """Create a new entry in the toc from the node at given level."""
         # XXX Modifies the node
         if incr:
             self.playorder += 1
         return _navpoint_template % node
 
     def insert_subnav(self, node, subnav):
-        """Insert nested navpoints for given node
-        The node and subnav are already rendered to text"""
+        """Insert nested navpoints for given node.
+        The node and subnav are already rendered to text.
+        """
         nlist = node.split('\n')
         nlist.insert(-1, subnav)
         return '\n'.join(nlist)
 
     def build_navpoints(self, nodes):
-        """Create the toc navigation structure
+        """Create the toc navigation structure.
+
         Subelements of a node are nested inside the navpoint.
-        For nested nodes the parent node is reinserted in the subnav."""
+        For nested nodes the parent node is reinserted in the subnav.
+        """
         navstack = []
         navlist = []
         level = 1
 
     def toc_metadata(self, level, navpoints):
         """Create a dictionary with all metadata for the toc.ncx
-        file properly escaped"""
+        file properly escaped.
+        """
         metadata = {}
         metadata['uid'] = self.config.epub_uid
         metadata['title'] = self.config.epub_title
         return metadata
 
     def build_toc(self, outdir, outname):
-        """Write the metainfo file toc.ncx"""
+        """Write the metainfo file toc.ncx."""
         self.info('writing %s file...' % outname)
 
         navpoints = self.build_navpoints(self.refnodes)
             f.close()
 
     def build_epub(self, outdir, outname):
-        """Write the epub file
+        """Write the epub file.
+
         It is a zip file with the mimetype file stored uncompressed
-        as the first entry."""
+        as the first entry.
+        """
         self.info('writing %s file...' % outname)
         projectfiles = ['META-INF/container.xml', 'content.opf', 'toc.ncx'] \
             + self.files
         for file in projectfiles:
             epub.write(path.join(outdir, file), file, zipfile.ZIP_DEFLATED)
         epub.close()
-

sphinx/builders/html.py

             if path.isfile(jsfile):
                 self.script_files.append('_static/translations.js')
 
+    def get_theme_config(self):
+        return self.config.html_theme, self.config.html_theme_options
+
     def init_templates(self):
         Theme.init_themes(self)
-        self.theme = Theme(self.config.html_theme)
+        themename, themeoptions = self.get_theme_config()
+        self.theme = Theme(themename)
+        self.theme_options = themeoptions.copy()
         self.create_template_bridge()
         self.templates.init(self, self.theme)
 
         if self.theme:
             self.globalcontext.update(
                 ('theme_' + key, val) for (key, val) in
-                self.theme.get_options(
-                self.config.html_theme_options).iteritems())
+                self.theme.get_options(self.theme_options).iteritems())
         self.globalcontext.update(self.config.html_context)
 
     def get_doc_context(self, docname, body, metatags):
         # Devhelp only options
         devhelp_basename = (lambda self: make_filename(self.project), None),
 
+        # Epub options
+        epub_basename = (lambda self: make_filename(self.project), None),
+        epub_theme = ('epub', 'html'),
+        epub_title = (lambda self: self.html_title, 'html'),
+        epub_author = ('unknown', 'html'),
+        epub_language = (lambda self: self.language or 'en', 'html'),
+        epub_publisher = ('unknown', 'html'),
+        epub_copyright = (lambda self: self.copyright, 'html'),
+        epub_identifier = ('unknown', 'html'),
+        epub_scheme = ('unknown', 'html'),
+        epub_uid = ('unknown', 'env'),
+        epub_pre_files = ([], 'env'),
+        epub_post_files = ([], 'env'),
+        epub_exclude_files = ([], 'env'),
+
         # LaTeX options
         latex_documents = ([], None),
         latex_logo = (None, None),
         latex_docclass = ({}, None),
         # now deprecated - use latex_elements
         latex_preamble = ('', None),
-
-        # Epub options
-        epub_basename = (lambda self: make_filename(self.project), None),
-        epub_title = (lambda self: self.html_title, 'html'),
-        epub_author = ('unknown', 'html'),
-        epub_language = (lambda self: self.language or 'en', 'html'),
-        epub_publisher = ('unknown', 'html'),
-        epub_copyright = (lambda self: self.copyright, 'html'),
-        epub_identifier = ('unknown', 'html'),
-        epub_scheme = ('unknown', 'html'),
-        epub_uid = ('unknown', 'env'),
-        epub_pre_files = ([], 'env'),
-        epub_post_files = ([], 'env'),
-        epub_exclude_files = ([], 'env'),
     )
 
     def __init__(self, dirname, filename, overrides, tags):
 
 # -- Options for Epub output ---------------------------------------------------
 
-# Please also set the html_theme to 'epub' or any other approriate theme.
-# The display size is quite small for ebook readers.
-# The default themes may take too much space.
-
-# bibliographic Dublin Core description of the content.opf and
-# in the toc.ncx file. It defaults to the html_title option.
+# Bibliographic Dublin Core info.
 #epub_title = ''
-
-# The author of the text. The author is inserted into the
-# bibliographic Dublin Core description of the content.opf file.
 #epub_author = ''
+#epub_publisher = ''
+#epub_copyright = ''
 
 # The language of the text. It defaults to the language option
 # or en if the language is not set.
 #epub_language = ''
 
-# The publisher of the text. The publisher is inserted  into the
-# bibliographic Dublin Core description of the content.opf file.
-# You may use the project homepage.
-#epub_publisher = ''
-
-# The copyright of the text. The copyright is inserted into the
-# bibliographci Dublin Core description of the content.opf file.
-# It defaults to the copyright option.
-#epub_copyright = ''
+# The scheme of the identifier. Typical schemes are ISBN or URL.
+#epub_scheme = ''
 
 # The unique identifier of the text. This can be a ISBN number
 # or the project homepage.
 #epub_identifier = ''
 
-# The scheme of the identifier. Typical schemes are ISBN or URL.
-#epub_scheme = ''
-
 # A unique identification for the text.
 #epub_uid = ''