diff --git a/doc/conf.py b/doc/conf.py
index 1b8ba3e4d..6b547edde 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -36,7 +36,9 @@ epub_identifier = epub_publisher
epub_pre_files = [('index.html', 'Welcome')]
epub_exclude_files = ['_static/opensearch.xml', '_static/doctools.js',
'_static/jquery.js', '_static/searchtools.js', '_static/underscore.js',
- '_static/basic.css', 'search.html']
+ '_static/basic.css', 'search.html', '_static/websupport.js']
+epub_fix_images = False
+epub_max_image_width = 0
latex_documents = [('contents', 'sphinx.tex', 'Sphinx Documentation',
'Georg Brandl', 'manual', 1)]
diff --git a/doc/config.rst b/doc/config.rst
index d890f7fff..61154ebb9 100644
--- a/doc/config.rst
+++ b/doc/config.rst
@@ -785,6 +785,12 @@ the `Dublin Core metadata `_.
output is usually not wise. This defaults to ``'epub'``, a theme designed to
save visual space.
+.. confval:: epub_theme_options
+
+ A dictionary of options that influence the look and feel of the selected
+ theme. These are theme-specific. For the options understood by the builtin
+ themes, see :ref:`this section `.
+
.. confval:: epub_title
The title of the document. It defaults to the :confval:`html_title` option
@@ -884,6 +890,23 @@ the `Dublin Core metadata `_.
depth in one list. The default value is ``True``.
+.. confval:: epub_fix_images
+
+ This flag determines if sphinx should try to fix image formats that are not
+ supported by some epub readers. At the moment palette images with a small
+ color table are upgraded. You need the Python Image Library (PIL) installed
+ to use this option. The default value is ``False`` because the automatic
+ conversion may lose information.
+
+.. confval:: epub_max_image_width
+
+ This option specifies the maximum width of images. If it is set to a value
+ greater than zero, images with a width larger than the given value are
+ scaled accordingly. If it is zero, no scaling is performed. The default
+ value is ``0``. You need the Python Image Library (PIL) installed to use
+ this option.
+
+
.. _latex-options:
Options for LaTeX output
diff --git a/doc/theming.rst b/doc/theming.rst
index 802b211f4..334f6ffe7 100644
--- a/doc/theming.rst
+++ b/doc/theming.rst
@@ -200,10 +200,14 @@ These themes are:
* **traditional** -- A theme resembling the old Python documentation. There are
currently no options beyond *nosidebar* and *sidebarwidth*.
-* **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.
+* **epub** -- A theme for the epub builder. This theme tries to save visual
+ space which is a sparse resource on ebook readers. The following options
+ are supported:
+ - **relbar1** (true or false, default true): If this is true, the
+ `relbar1` block is inserted in the epub output, otherwise it is omitted.
+ - **footer** (true or false, default true): If this is true, the
+ `footer` block is inserted in the epub output, otherwise it is ommitted.
Creating themes
---------------
diff --git a/sphinx/builders/epub.py b/sphinx/builders/epub.py
index e946e0d39..ad9906155 100644
--- a/sphinx/builders/epub.py
+++ b/sphinx/builders/epub.py
@@ -18,12 +18,21 @@ import codecs
import zipfile
from os import path
+try:
+ from PIL import Image
+except ImportError:
+ try:
+ import Image
+ except ImportError:
+ Image = None
+
from docutils import nodes
from sphinx import addnodes
from sphinx.builders.html import StandaloneHTMLBuilder
-from sphinx.util.osutil import EEXIST
+from sphinx.util.osutil import ensuredir, EEXIST
from sphinx.util.smartypants import sphinx_smarty_pants as ssp
+from sphinx.util.console import brown
# (Fragment) templates from which the metainfo files content.opf, toc.ncx,
@@ -165,7 +174,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
self.playorder = 0
def get_theme_config(self):
- return self.config.epub_theme, {}
+ return self.config.epub_theme, self.config.epub_theme_options
# generic support functions
def make_id(self, name):
@@ -206,11 +215,11 @@ class EpubBuilder(StandaloneHTMLBuilder):
return result
def get_toc(self):
- """Get the total table of contents, containg the master_doc
+ """Get the total table of contents, containing the master_doc
and pre and post files not managed by sphinx.
"""
doctree = self.env.get_and_resolve_doctree(self.config.master_doc,
- self, prune_toctrees=False)
+ self, prune_toctrees=False, includehidden=True)
self.refnodes = self.get_refnodes(doctree, [])
master_dir = os.path.dirname(self.config.master_doc)
if master_dir:
@@ -301,6 +310,57 @@ class EpubBuilder(StandaloneHTMLBuilder):
subentrylinks[i] = (ismain,
self.fix_fragment(m.group(1), m.group(2)))
+ def copy_image_files_pil(self):
+ """Copy images using the PIL.
+ The method tries to read and write the files with the PIL,
+ converting the format and resizing the image if necessary/possible.
+ """
+ ensuredir(path.join(self.outdir, '_images'))
+ for src in self.status_iterator(self.images, 'copying images... ',
+ brown, len(self.images)):
+ dest = self.images[src]
+ try:
+ img = Image.open(path.join(self.srcdir, src))
+ except IOError:
+ self.warn('cannot read image file %r: copying it instead' %
+ (path.join(self.srcdir, src), ))
+ try:
+ copyfile(path.join(self.srcdir, src),
+ path.join(self.outdir, '_images', dest))
+ except Exception, err:
+ self.warn('cannot copy image file %r: %s' %
+ (path.join(self.srcdir, src), err))
+ continue
+ if self.config.epub_fix_images:
+ if img.mode in ('P',):
+ # See PIL documentation for Image.convert()
+ img = img.convert()
+ if self.config.epub_max_image_width > 0:
+ (width, height) = img.size
+ nw = self.config.epub_max_image_width
+ if width > nw:
+ nh = (height * nw) / width
+ img = img.resize((nw, nh), Image.BICUBIC)
+ try:
+ img.save(path.join(self.outdir, '_images', dest))
+ except IOError, err:
+ self.warn('cannot write image file %r: %s' %
+ (path.join(self.srcdir, src), err))
+
+ def copy_image_files(self):
+ """Copy image files to destination directory.
+ This overwritten method can use the PIL to convert image files.
+ """
+ if self.images:
+ if self.config.epub_fix_images or self.config.epub_max_image_width:
+ if not Image:
+ self.warn('PIL not found - copying image files')
+ super(EpubBuilder, self).copy_image_files()
+ else:
+ self.copy_image_files_pil()
+ else:
+ super(EpubBuilder, self).copy_image_files()
+
def handle_page(self, pagename, addctx, templatename='page.html',
outfilename=None, event_arg=None):
"""Create a rendered page.
@@ -529,7 +589,10 @@ class EpubBuilder(StandaloneHTMLBuilder):
"""Write the metainfo file toc.ncx."""
self.info('writing %s file...' % outname)
- navpoints = self.build_navpoints(self.refnodes)
+ doctree = self.env.get_and_resolve_doctree(self.config.master_doc,
+ self, prune_toctrees=False, includehidden=False)
+ refnodes = self.get_refnodes(doctree, [])
+ navpoints = self.build_navpoints(refnodes)
level = max(item['level'] for item in self.refnodes)
level = min(level, self.config.epub_tocdepth)
f = codecs.open(path.join(outdir, outname), 'w', 'utf-8')
diff --git a/sphinx/config.py b/sphinx/config.py
index 4bcf1b2cd..767bf0882 100644
--- a/sphinx/config.py
+++ b/sphinx/config.py
@@ -123,6 +123,7 @@ class Config(object):
# Epub options
epub_basename = (lambda self: make_filename(self.project), None),
epub_theme = ('epub', 'html'),
+ epub_theme_options = ({}, 'html'),
epub_title = (lambda self: self.html_title, 'html'),
epub_author = ('unknown', 'html'),
epub_language = (lambda self: self.language or 'en', 'html'),
@@ -137,6 +138,8 @@ class Config(object):
epub_exclude_files = ([], 'env'),
epub_tocdepth = (3, 'env'),
epub_tocdup = (True, 'env'),
+ epub_fix_images = (False, 'env'),
+ epub_max_image_width = (0, 'env'),
# LaTeX options
latex_documents = ([], None),
diff --git a/sphinx/environment.py b/sphinx/environment.py
index 9fd9ff89a..77dfbb3db 100644
--- a/sphinx/environment.py
+++ b/sphinx/environment.py
@@ -1217,7 +1217,7 @@ class BuildEnvironment:
def get_and_resolve_doctree(self, docname, builder, doctree=None,
- prune_toctrees=True):
+ prune_toctrees=True, includehidden=False):
"""Read the doctree from the pickle, resolve cross-references and
toctrees and return it.
"""
@@ -1230,7 +1230,7 @@ class BuildEnvironment:
# now, resolve all toctree nodes
for toctreenode in doctree.traverse(addnodes.toctree):
result = self.resolve_toctree(docname, builder, toctreenode,
- prune=prune_toctrees)
+ prune=prune_toctrees, includehidden=includehidden)
if result is None:
toctreenode.replace_self([])
else:
diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py
index 86dc04762..172382ad5 100644
--- a/sphinx/quickstart.py
+++ b/sphinx/quickstart.py
@@ -325,6 +325,12 @@ epub_copyright = u'%(copyright_str)s'
# Allow duplicate toc entries.
#epub_tocdup = True
+
+# Fix unsupported image types using the PIL.
+#epub_fix_images = False
+
+# Scale large images.
+#epub_max_image_width = 0
'''
INTERSPHINX_CONFIG = '''
diff --git a/sphinx/themes/epub/layout.html b/sphinx/themes/epub/layout.html
index 24395a66a..1f5ad077f 100644
--- a/sphinx/themes/epub/layout.html
+++ b/sphinx/themes/epub/layout.html
@@ -14,3 +14,12 @@
{% block sidebar2 %}{% endblock %}
{% block relbar2 %}{% endblock %}
{% block linktags %}{% endblock %}
+
+{# redefine relbar1 and footer to only call super if options are true #}
+{%- block relbar1 %}
+{% if theme_relbar1|tobool %}{{ super() }}{% endif %}
+{%- endblock %}
+{%- block footer %}
+{% if theme_footer|tobool %}{{ super() }}{% endif %}
+{%- endblock %}
+
diff --git a/sphinx/themes/epub/theme.conf b/sphinx/themes/epub/theme.conf
index d5806ec50..11f098ec9 100644
--- a/sphinx/themes/epub/theme.conf
+++ b/sphinx/themes/epub/theme.conf
@@ -2,3 +2,7 @@
inherit = basic
stylesheet = epub.css
pygments_style = none
+
+[options]
+relbar1 = true
+footer = true