diff --git a/doc/config.rst b/doc/config.rst index b579d7e2b..2d427042f 100644 --- a/doc/config.rst +++ b/doc/config.rst @@ -1388,6 +1388,10 @@ the `Dublin Core metadata `_. a chapter, but can be confusing because it mixes entries of different depth in one list. The default value is ``True``. + .. note:: + + ``epub3`` builder ignores ``epub_tocdup`` option(always ``False``) + .. confval:: epub_tocscope This setting control the scope of the epub table of contents. The setting diff --git a/sphinx/builders/epub.py b/sphinx/builders/epub.py index f0aa97277..f5f0d8098 100644 --- a/sphinx/builders/epub.py +++ b/sphinx/builders/epub.py @@ -15,6 +15,7 @@ import re import codecs import zipfile from os import path +from datetime import datetime try: from PIL import Image @@ -28,7 +29,6 @@ from docutils import nodes from sphinx import addnodes from sphinx.builders.html import StandaloneHTMLBuilder -from sphinx.util.i18n import format_date from sphinx.util.osutil import ensuredir, copyfile, EEXIST from sphinx.util.smartypants import sphinx_smarty_pants as ssp from sphinx.util.console import brown @@ -129,8 +129,7 @@ GUIDE_TEMPLATE = u'''\ TOCTREE_TEMPLATE = u'toctree-l%d' DOCTYPE = u''' -''' + "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">''' LINK_TARGET_TEMPLATE = u' [%(uri)s]' @@ -541,8 +540,7 @@ class EpubBuilder(StandaloneHTMLBuilder): 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(format_date('%Y-%m-%d', language=self.config.language, - warn=self.warn)) + metadata['date'] = self.esc(datetime.utcnow().strftime("%Y-%m-%d")) metadata['files'] = files metadata['spine'] = spine metadata['guide'] = guide diff --git a/sphinx/builders/epub3.py b/sphinx/builders/epub3.py index a91779f88..d792bd6e9 100644 --- a/sphinx/builders/epub3.py +++ b/sphinx/builders/epub3.py @@ -12,6 +12,7 @@ import codecs from os import path +from datetime import datetime from sphinx.builders.epub import EpubBuilder @@ -41,13 +42,12 @@ NAVIGATION_DOC_TEMPLATE = u'''\ ''' -NAVLIST_TEMPLATE = u'''\ -%(indent)s
  • -%(indent)s %(text)s -%(indent)s
  • -''' -NAVLIST_INDENT = ' ' - +NAVLIST_TEMPLATE = u'''%(indent)s
  • %(text)s
  • ''' +NAVLIST_TEMPLATE_HAS_CHILD = u'''%(indent)s
  • %(text)s''' +NAVLIST_TEMPLATE_BEGIN_BLOCK = u'''%(indent)s
      ''' +NAVLIST_TEMPLATE_END_BLOCK = u'''%(indent)s
    +%(indent)s
  • ''' +NAVLIST_INDENT = ' ' PACKAGE_DOC_TEMPLATE = u'''\ @@ -81,8 +81,7 @@ PACKAGE_DOC_TEMPLATE = u'''\ ''' -DOCTYPE = u''' -''' +DOCTYPE = u'''''' # The epub3 publisher @@ -99,6 +98,9 @@ class Epub3Builder(EpubBuilder): navigation_doc_template = NAVIGATION_DOC_TEMPLATE navlist_template = NAVLIST_TEMPLATE + navlist_template_has_child = NAVLIST_TEMPLATE_HAS_CHILD + navlist_template_begin_block = NAVLIST_TEMPLATE_BEGIN_BLOCK + navlist_template_end_block = NAVLIST_TEMPLATE_END_BLOCK navlist_indent = NAVLIST_INDENT content_template = PACKAGE_DOC_TEMPLATE doctype = DOCTYPE @@ -124,15 +126,26 @@ class Epub3Builder(EpubBuilder): metadata['contributor'] = self.esc(self.config.epub3_contributor) metadata['page_progression_direction'] = self.esc( self.config.epub3_page_progression_direction) or 'default' + metadata['date'] = self.esc(datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ")) return metadata - def new_navlist(self, node, level): + def new_navlist(self, node, level, has_child): """Create a new entry in the toc from the node at given level.""" # XXX Modifies the node self.tocid += 1 node['indent'] = self.navlist_indent * level - navpoint = self.navlist_template % node - return navpoint + if has_child: + return self.navlist_template_has_child % node + else: + return self.navlist_template % node + + def begin_navlist_block(self, level): + return self.navlist_template_begin_block % { + "indent": self.navlist_indent * level + } + + def end_navlist_block(self, level): + return self.navlist_template_end_block % {"indent": self.navlist_indent * level} def build_navlist(self, nodes): """Create the toc navigation structure. @@ -144,10 +157,9 @@ class Epub3Builder(EpubBuilder): The difference from build_navpoints method is templates which are used when generating navigation documents. """ - navstack = [] navlist = [] level = 1 - lastnode = None + usenodes = [] for node in nodes: if not node['text']: continue @@ -156,30 +168,23 @@ class Epub3Builder(EpubBuilder): continue if node['level'] > self.config.epub_tocdepth: continue - if node['level'] == level: - navlist.append(self.new_navlist(node, level)) - elif node['level'] == level + 1: - navstack.append(navlist) - navlist = [] - level += 1 - if lastnode and self.config.epub_tocdup: - navlist.append(self.new_navlist(node, level)) - navlist[-1] = '
      \n' + navlist[-1] + usenodes.append(node) + for i, node in enumerate(usenodes): + curlevel = node['level'] + if curlevel == level + 1: + navlist.append(self.begin_navlist_block(level)) + while curlevel < level: + level -= 1 + navlist.append(self.end_navlist_block(level)) + level = curlevel + if i != len(usenodes) - 1 and usenodes[i + 1]['level'] > level: + has_child = True else: - while node['level'] < level: - subnav = '\n'.join(navlist) - navlist = navstack.pop() - navlist[-1] = self.insert_subnav(navlist[-1], subnav) - level -= 1 - navlist[-1] = navlist[-1] + '
    ' - navlist.append(self.new_navlist(node, level)) - lastnode = node + has_child = False + navlist.append(self.new_navlist(node, level, has_child)) while level != 1: - subnav = '\n'.join(navlist) - navlist = navstack.pop() - navlist[-1] = self.insert_subnav(navlist[-1], subnav) level -= 1 - navlist[-1] = navlist[-1] + '' + navlist.append(self.end_navlist_block(level)) return '\n'.join(navlist) def navigation_doc_metadata(self, navlist): @@ -213,4 +218,5 @@ class Epub3Builder(EpubBuilder): finally: f.close() # Add nav.xhtml to epub file - self.files.append(outname) + if outname not in self.files: + self.files.append(outname)