Commits

Georg Brandl committed 12fbe25 Merge
  • Participants
  • Parent commits 0428588, 2649878

Comments (0)

Files changed (5)

File doc/config.rst

    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_cover
+
+   The cover page information.  This is a tuple containing the filenames of
+   the cover image and the html template.  The rendered html cover page is
+   inserted as the first item in the spine in :file:`content.opf`.  If the
+   template filename is empty, no html cover page is created.  No cover at all
+   is created if the tuple is empty.  Examples::
+
+      epub_cover = ('_static/cover.png', 'epub-cover.html')
+      epub_cover = ('_static/cover.png', '')
+      epub_cover = ()
+
+   The default value is ``()``.
+
+   .. versionadded:: 1.1
+
 .. 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::
+   If the title is empty, no entry is added to :file:`toc.ncx`.  Example::
 
       epub_pre_files = [
           ('index.html', 'Welcome'),
 
    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.  This option
-   can be used to add an appendix.  The default value is ``[]``.
+   can be used to add an appendix.  If the title is empty, no entry is added
+   to :file:`toc.ncx`.  The default value is ``[]``.
 
 .. confval:: epub_exclude_files
 

File sphinx/builders/epub.py

 import os
 import re
 import codecs
+import time
 import zipfile
 from os import path
 
     <dc:publisher>%(publisher)s</dc:publisher>
     <dc:rights>%(copyright)s</dc:rights>
     <dc:identifier id="%(uid)s" opf:scheme="%(scheme)s">%(id)s</dc:identifier>
+    <dc:date>%(date)s</dc:date>
   </metadata>
   <manifest>
     <item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml" />
 </package>
 '''
 
+_cover_template = u'''\
+    <meta name="cover" content="%(cover)s"/>
+'''
+
+_coverpage_name = u'epub-cover.html'
+
 _file_template = u'''\
     <item id="%(id)s"
           href="%(href)s"
         doctree = self.env.get_and_resolve_doctree(self.config.master_doc,
             self, prune_toctrees=False)
         self.refnodes = self.get_refnodes(doctree, [])
+        master_dir = os.path.dirname(self.config.master_doc)
+        if master_dir:
+            master_dir += '/' # XXX or os.sep?
+            for item in self.refnodes:
+                item['refuri'] = master_dir + item['refuri']
         self.refnodes.insert(0, {
             'level': 1,
             'refuri': self.esc(self.config.master_doc + '.html'),
                 'text': ssp(self.esc(text))
             })
 
-    def fix_fragment(self, match):
-        """Return a href attribute with colons replaced by hyphens."""
-        return match.group(1) + match.group(2).replace(':', '-')
+    def fix_fragment(self, prefix, fragment):
+        """Return a href/id attribute with colons replaced by hyphens."""
+        return prefix + fragment.replace(':', '-')
 
     def fix_ids(self, tree):
         """Replace colons with hyphens in href and id attributes.
             if 'refuri' in node:
                 m = _refuri_re.match(node['refuri'])
                 if m:
-                    node['refuri'] = self.fix_fragment(m)
+                    node['refuri'] = self.fix_fragment(m.group(1), m.group(2))
             if 'refid' in node:
-                node['refid'] = node['refid'].replace(':', '-')
+                node['refid'] = self.fix_fragment('', node['refid'])
         for node in tree.traverse(addnodes.desc_signature):
             ids = node.attributes['ids']
             newids = []
             for id in ids:
-                newids.append(id.replace(':', '-'))
+                newids.append(self.fix_fragment('', id))
             node.attributes['ids'] = newids
 
     def add_visible_links(self, tree):
                 for (i, link) in enumerate(links):
                     m = _refuri_re.match(link)
                     if m:
-                        links[i] = self.fix_fragment(m)
+                        links[i] = self.fix_fragment(m.group(1), m.group(2))
                 for subentryname, subentrylinks in subitems:
                     for (i, link) in enumerate(subentrylinks):
                         m = _refuri_re.match(link)
                         if m:
-                            subentrylinks[i] = self.fix_fragment(m)
+                            subentrylinks[i] = \
+                                self.fix_fragment(m.group(1), m.group(2))
 
     def handle_page(self, pagename, addctx, templatename='page.html',
                     outfilename=None, event_arg=None):
         metadata['copyright'] = self.esc(self.config.epub_copyright)
         metadata['scheme'] = self.esc(self.config.epub_scheme)
         metadata['id'] = self.esc(self.config.epub_identifier)
+        metadata['date'] = self.esc(time.strftime('%Y-%m-%d'))
         metadata['files'] = files
         metadata['spine'] = spine
         return metadata
                     'media_type': self.esc(_media_types[ext])
                 })
                 self.files.append(filename)
-        projectfiles = '\n'.join(projectfiles)
 
         # spine
         spine = []
             spine.append(_spine_template % {
                 'idref': self.esc(self.make_id(item['refuri']))
             })
+
+        # add the optional cover
+        content_tmpl = _content_template
+        if self.config.epub_cover:
+            image, tmpl = self.config.epub_cover
+            mpos = content_tmpl.rfind('</metadata>')
+            cpos = content_tmpl.rfind('\n', 0 , mpos) + 1
+            content_tmpl = content_tmpl[:cpos] + \
+                _cover_template % {'cover': self.esc(self.make_id(image))} + \
+                content_tmpl[cpos:]
+            if tmpl:
+                spine.insert(0, _spine_template % {
+                    'idref': self.esc(self.make_id(_coverpage_name))})
+                if _coverpage_name not in self.files:
+                    ext = path.splitext(_coverpage_name)[-1]
+                    self.files.append(_coverpage_name)
+                    projectfiles.append(_file_template % {
+                        'href': self.esc(_coverpage_name),
+                        'id': self.esc(self.make_id(_coverpage_name)),
+                        'media_type': self.esc(_media_types[ext])
+                    })
+                ctx = {'image': self.esc(image), 'title': self.config.project}
+                self.handle_page(
+                        os.path.splitext(_coverpage_name)[0], ctx, tmpl)
+
+        projectfiles = '\n'.join(projectfiles)
         spine = '\n'.join(spine)
 
         # write the project file
         f = codecs.open(path.join(outdir, outname), 'w', 'utf-8')
         try:
-            f.write(_content_template % \
+            f.write(content_tmpl % \
                 self.content_metadata(projectfiles, spine))
         finally:
             f.close()
         level = 1
         lastnode = None
         for node in nodes:
+            if not node['text']:
+                continue
             file = node['refuri'].split('#')[0]
             if file in self.ignored_files:
                 continue
         epub.write(path.join(outdir, 'mimetype'), 'mimetype', \
             zipfile.ZIP_STORED)
         for file in projectfiles:
+            if isinstance(file, unicode):
+                file = file.encode('utf-8')
             epub.write(path.join(outdir, file), file, zipfile.ZIP_DEFLATED)
         epub.close()

File sphinx/config.py

         epub_identifier = ('unknown', 'html'),
         epub_scheme = ('unknown', 'html'),
         epub_uid = ('unknown', 'env'),
+        epub_cover = ((), 'env'),
         epub_pre_files = ([], 'env'),
         epub_post_files = ([], 'env'),
         epub_exclude_files = ([], 'env'),

File sphinx/quickstart.py

 # A unique identification for the text.
 #epub_uid = ''
 
+# A tuple containing the cover image and cover page html template filenames.
+#epub_cover = ()
+
 # HTML files that should be inserted before the pages created by sphinx.
 # The format is a list of tuples containing the path and title.
 #epub_pre_files = []

File sphinx/themes/epub/epub-cover.html

+{#
+    epub/epub-cover.html
+    ~~~~~~~~~~~~~~~~~~~~
+
+    Sample template for the html cover page.
+
+    :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
+    :license: BSD, see LICENSE for details.
+#}
+{% extends "layout.html" %}
+{%- block rootrellink %}{% endblock %}
+{%- block relbaritems %}{% endblock %}
+{%- block sidebarlogo %}{% endblock %}
+{%- block linktags %}{% endblock %}
+{%- block relbar1 %}{% endblock %}
+{%- block sidebar1 %}{% endblock %}
+{%- block sidebar2 %}{% endblock %}
+{%- block footer %}{% endblock %}
+
+{% block content %}
+  <div class="epub-cover">
+    <img src="{{ image }}" alt="Cover image" />
+  </div>
+{% endblock %}