From fe07254b9c0088138cba3b7af1f7b3d8be2b74eb Mon Sep 17 00:00:00 2001 From: Roland Meister Date: Sun, 27 Feb 2011 22:02:30 +0100 Subject: [PATCH 1/7] Added epub_fix_images configuration option --- doc/conf.py | 1 + doc/config.rst | 8 ++++++ sphinx/builders/epub.py | 55 ++++++++++++++++++++++++++++++++++++++++- sphinx/config.py | 1 + sphinx/quickstart.py | 3 +++ 5 files changed, 67 insertions(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index 299f321ac..81c645c1c 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -38,6 +38,7 @@ 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'] +epub_fix_images = False latex_documents = [('contents', 'sphinx.tex', 'Sphinx Documentation', 'Georg Brandl', 'manual', 1)] diff --git a/doc/config.rst b/doc/config.rst index 9a618d29f..b5b65079b 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -804,6 +804,14 @@ the `Dublin Core metadata `_. a chapter, but can be confusing because it mixes entries of differnet 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 loose information. + .. _latex-options: Options for LaTeX output diff --git a/sphinx/builders/epub.py b/sphinx/builders/epub.py index 218a93e1c..101cb936b 100644 --- a/sphinx/builders/epub.py +++ b/sphinx/builders/epub.py @@ -17,12 +17,21 @@ import time 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, @@ -299,6 +308,50 @@ class EpubBuilder(StandaloneHTMLBuilder): subentrylinks[i] = \ 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 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 img.mode in ('P',): + # See PIL documentation for Image.convert() + img = img.convert() + 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: + 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. diff --git a/sphinx/config.py b/sphinx/config.py index 58d5c76a7..aa689f2e0 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -126,6 +126,7 @@ class Config(object): epub_exclude_files = ([], 'env'), epub_tocdepth = (3, 'env'), epub_tocdup = (True, 'env'), + epub_fix_images = (False, 'html'), # LaTeX options latex_documents = ([], None), diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index b606c9be9..e1a5d9e84 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -285,6 +285,9 @@ epub_copyright = u'%(copyright_str)s' # Allow duplicate toc entries. #epub_tocdup = True + +# Fix unsupported image types using the PIL. +#epub_fix_images = False ''' INTERSPHINX_CONFIG = ''' From 246d07807d2619c30e93fd958255db1263f81dda Mon Sep 17 00:00:00 2001 From: Roland Meister Date: Mon, 28 Feb 2011 21:17:52 +0100 Subject: [PATCH 2/7] Added epub_max_image_width configuration option. --- doc/conf.py | 1 + doc/config.rst | 9 +++++++++ sphinx/builders/epub.py | 17 ++++++++++++----- sphinx/config.py | 1 + sphinx/quickstart.py | 3 +++ 5 files changed, 26 insertions(+), 5 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 81c645c1c..8b76d23f1 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -39,6 +39,7 @@ epub_exclude_files = ['_static/opensearch.xml', '_static/doctools.js', '_static/jquery.js', '_static/searchtools.js', '_static/underscore.js', '_static/basic.css', 'search.html'] 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 b5b65079b..ea9b731ad 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -812,6 +812,15 @@ the `Dublin Core metadata `_. to use this option. The default value is ``False`` because the automatic conversion may loose 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/sphinx/builders/epub.py b/sphinx/builders/epub.py index 101cb936b..fbe88c3b2 100644 --- a/sphinx/builders/epub.py +++ b/sphinx/builders/epub.py @@ -311,7 +311,7 @@ class EpubBuilder(StandaloneHTMLBuilder): 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 if necessary/possible. + 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... ', @@ -329,9 +329,16 @@ class EpubBuilder(StandaloneHTMLBuilder): self.warn('cannot copy image file %r: %s' % (path.join(self.srcdir, src), err)) continue - if img.mode in ('P',): - # See PIL documentation for Image.convert() - img = img.convert() + 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: @@ -343,7 +350,7 @@ class EpubBuilder(StandaloneHTMLBuilder): This overwritten method can use the PIL to convert image files. """ if self.images: - if self.config.epub_fix_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() diff --git a/sphinx/config.py b/sphinx/config.py index aa689f2e0..9841ba46a 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -127,6 +127,7 @@ class Config(object): epub_tocdepth = (3, 'env'), epub_tocdup = (True, 'env'), epub_fix_images = (False, 'html'), + epub_max_image_width = (0, 'html'), # LaTeX options latex_documents = ([], None), diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index e1a5d9e84..db18ef4eb 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -288,6 +288,9 @@ epub_copyright = u'%(copyright_str)s' # Fix unsupported image types using the PIL. #epub_fix_images = False + +# Scale large images. +#epub_max_image_width = 0 ''' INTERSPHINX_CONFIG = ''' From 9041a3396d46f4eaaf01355a3e83b10b0e01491e Mon Sep 17 00:00:00 2001 From: Roland Meister Date: Mon, 28 Feb 2011 21:20:37 +0100 Subject: [PATCH 3/7] Changed new epub option rebuild parameter to 'env'. --- sphinx/config.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sphinx/config.py b/sphinx/config.py index 9841ba46a..93250f9b0 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -126,8 +126,8 @@ class Config(object): epub_exclude_files = ([], 'env'), epub_tocdepth = (3, 'env'), epub_tocdup = (True, 'env'), - epub_fix_images = (False, 'html'), - epub_max_image_width = (0, 'html'), + epub_fix_images = (False, 'env'), + epub_max_image_width = (0, 'env'), # LaTeX options latex_documents = ([], None), From 5cb382322381e48825e3bdb080f2f0e50cabd8d7 Mon Sep 17 00:00:00 2001 From: Roland Meister Date: Mon, 28 Feb 2011 23:20:08 +0100 Subject: [PATCH 4/7] Add _static/websupport.js to epub_exclude_files. --- doc/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index 19b952942..216d70ceb 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -36,7 +36,7 @@ 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 From f107cf77873217dedeb336284fefe021acdc3bea Mon Sep 17 00:00:00 2001 From: Roland Meister Date: Mon, 28 Feb 2011 23:24:48 +0100 Subject: [PATCH 5/7] Fix typo in description for epub_fix_images. --- doc/config.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/config.rst b/doc/config.rst index 1260796a9..98b8a0cfa 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -875,7 +875,7 @@ the `Dublin Core metadata `_. 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 loose information. + conversion may lose information. .. confval:: epub_max_image_width From 0da0c03b53e9bac797d6ac7e0772e6f9fb0a229a Mon Sep 17 00:00:00 2001 From: Roland Meister Date: Mon, 23 May 2011 21:09:51 +0200 Subject: [PATCH 6/7] Added the epub theme options relbar1 and footer. --- doc/config.rst | 6 ++++++ doc/theming.rst | 10 +++++++--- sphinx/builders/epub.py | 2 +- sphinx/config.py | 1 + sphinx/themes/epub/layout.html | 9 +++++++++ sphinx/themes/epub/theme.conf | 4 ++++ 6 files changed, 28 insertions(+), 4 deletions(-) diff --git a/doc/config.rst b/doc/config.rst index 98b8a0cfa..649490cd2 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -770,6 +770,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 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 3ee4de5f1..ba1eff5b4 100644 --- a/sphinx/builders/epub.py +++ b/sphinx/builders/epub.py @@ -174,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): diff --git a/sphinx/config.py b/sphinx/config.py index d4aacb225..37b2dcbd5 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -122,6 +122,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'), 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 From 49393ad118f66d3effdcc6a24bd66739d6efc40d Mon Sep 17 00:00:00 2001 From: Roland Meister Date: Mon, 13 Feb 2012 21:04:28 +0100 Subject: [PATCH 7/7] Bug #868: Add hidden toctree entries to content.opf/spine --- sphinx/builders/epub.py | 9 ++++++--- sphinx/environment.py | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/sphinx/builders/epub.py b/sphinx/builders/epub.py index ba1eff5b4..ad9906155 100644 --- a/sphinx/builders/epub.py +++ b/sphinx/builders/epub.py @@ -215,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: @@ -589,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/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: