fix epub3 toc.xhtml, epub date format to satisfy spec

This commit is contained in:
Yoshiki Shibukawa 2016-07-21 10:08:06 +09:00
parent 511a0aaef7
commit 59ebeb7f1f
3 changed files with 49 additions and 41 deletions

View File

@ -1388,6 +1388,10 @@ the `Dublin Core metadata <http://dublincore.org/>`_.
a chapter, but can be confusing because it mixes entries of different a chapter, but can be confusing because it mixes entries of different
depth in one list. The default value is ``True``. depth in one list. The default value is ``True``.
.. note::
``epub3`` builder ignores ``epub_tocdup`` option(always ``False``)
.. confval:: epub_tocscope .. confval:: epub_tocscope
This setting control the scope of the epub table of contents. The setting This setting control the scope of the epub table of contents. The setting

View File

@ -15,6 +15,7 @@ import re
import codecs import codecs
import zipfile import zipfile
from os import path from os import path
from datetime import datetime
try: try:
from PIL import Image from PIL import Image
@ -28,7 +29,6 @@ from docutils import nodes
from sphinx import addnodes from sphinx import addnodes
from sphinx.builders.html import StandaloneHTMLBuilder from sphinx.builders.html import StandaloneHTMLBuilder
from sphinx.util.i18n import format_date
from sphinx.util.osutil import ensuredir, copyfile, EEXIST from sphinx.util.osutil import ensuredir, copyfile, EEXIST
from sphinx.util.smartypants import sphinx_smarty_pants as ssp from sphinx.util.smartypants import sphinx_smarty_pants as ssp
from sphinx.util.console import brown from sphinx.util.console import brown
@ -129,8 +129,7 @@ GUIDE_TEMPLATE = u'''\
TOCTREE_TEMPLATE = u'toctree-l%d' TOCTREE_TEMPLATE = u'toctree-l%d'
DOCTYPE = u'''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" DOCTYPE = u'''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">'''
'''
LINK_TARGET_TEMPLATE = u' [%(uri)s]' LINK_TARGET_TEMPLATE = u' [%(uri)s]'
@ -541,8 +540,7 @@ class EpubBuilder(StandaloneHTMLBuilder):
metadata['copyright'] = self.esc(self.config.epub_copyright) metadata['copyright'] = self.esc(self.config.epub_copyright)
metadata['scheme'] = self.esc(self.config.epub_scheme) metadata['scheme'] = self.esc(self.config.epub_scheme)
metadata['id'] = self.esc(self.config.epub_identifier) metadata['id'] = self.esc(self.config.epub_identifier)
metadata['date'] = self.esc(format_date('%Y-%m-%d', language=self.config.language, metadata['date'] = self.esc(datetime.utcnow().strftime("%Y-%m-%d"))
warn=self.warn))
metadata['files'] = files metadata['files'] = files
metadata['spine'] = spine metadata['spine'] = spine
metadata['guide'] = guide metadata['guide'] = guide

View File

@ -12,6 +12,7 @@
import codecs import codecs
from os import path from os import path
from datetime import datetime
from sphinx.builders.epub import EpubBuilder from sphinx.builders.epub import EpubBuilder
@ -41,13 +42,12 @@ NAVIGATION_DOC_TEMPLATE = u'''\
</html> </html>
''' '''
NAVLIST_TEMPLATE = u'''\ NAVLIST_TEMPLATE = u'''%(indent)s <li><a href="%(refuri)s">%(text)s</a></li>'''
%(indent)s <li> NAVLIST_TEMPLATE_HAS_CHILD = u'''%(indent)s <li><a href="%(refuri)s">%(text)s</a>'''
%(indent)s <a href="%(refuri)s">%(text)s</a> NAVLIST_TEMPLATE_BEGIN_BLOCK = u'''%(indent)s <ol>'''
%(indent)s </li> NAVLIST_TEMPLATE_END_BLOCK = u'''%(indent)s </ol>
''' %(indent)s </li>'''
NAVLIST_INDENT = ' ' NAVLIST_INDENT = ' '
PACKAGE_DOC_TEMPLATE = u'''\ PACKAGE_DOC_TEMPLATE = u'''\
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
@ -81,8 +81,7 @@ PACKAGE_DOC_TEMPLATE = u'''\
</package> </package>
''' '''
DOCTYPE = u'''<!DOCTYPE html> DOCTYPE = u'''<!DOCTYPE html>'''
'''
# The epub3 publisher # The epub3 publisher
@ -99,6 +98,9 @@ class Epub3Builder(EpubBuilder):
navigation_doc_template = NAVIGATION_DOC_TEMPLATE navigation_doc_template = NAVIGATION_DOC_TEMPLATE
navlist_template = NAVLIST_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 navlist_indent = NAVLIST_INDENT
content_template = PACKAGE_DOC_TEMPLATE content_template = PACKAGE_DOC_TEMPLATE
doctype = DOCTYPE doctype = DOCTYPE
@ -124,15 +126,26 @@ class Epub3Builder(EpubBuilder):
metadata['contributor'] = self.esc(self.config.epub3_contributor) metadata['contributor'] = self.esc(self.config.epub3_contributor)
metadata['page_progression_direction'] = self.esc( metadata['page_progression_direction'] = self.esc(
self.config.epub3_page_progression_direction) or 'default' self.config.epub3_page_progression_direction) or 'default'
metadata['date'] = self.esc(datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"))
return metadata 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.""" """Create a new entry in the toc from the node at given level."""
# XXX Modifies the node # XXX Modifies the node
self.tocid += 1 self.tocid += 1
node['indent'] = self.navlist_indent * level node['indent'] = self.navlist_indent * level
navpoint = self.navlist_template % node if has_child:
return navpoint 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): def build_navlist(self, nodes):
"""Create the toc navigation structure. """Create the toc navigation structure.
@ -144,10 +157,9 @@ class Epub3Builder(EpubBuilder):
The difference from build_navpoints method is templates which are used The difference from build_navpoints method is templates which are used
when generating navigation documents. when generating navigation documents.
""" """
navstack = []
navlist = [] navlist = []
level = 1 level = 1
lastnode = None usenodes = []
for node in nodes: for node in nodes:
if not node['text']: if not node['text']:
continue continue
@ -156,30 +168,23 @@ class Epub3Builder(EpubBuilder):
continue continue
if node['level'] > self.config.epub_tocdepth: if node['level'] > self.config.epub_tocdepth:
continue continue
if node['level'] == level: usenodes.append(node)
navlist.append(self.new_navlist(node, level)) for i, node in enumerate(usenodes):
elif node['level'] == level + 1: curlevel = node['level']
navstack.append(navlist) if curlevel == level + 1:
navlist = [] navlist.append(self.begin_navlist_block(level))
level += 1 while curlevel < level:
if lastnode and self.config.epub_tocdup: level -= 1
navlist.append(self.new_navlist(node, level)) navlist.append(self.end_navlist_block(level))
navlist[-1] = '<ol>\n' + navlist[-1] level = curlevel
if i != len(usenodes) - 1 and usenodes[i + 1]['level'] > level:
has_child = True
else: else:
while node['level'] < level: has_child = False
subnav = '\n'.join(navlist) navlist.append(self.new_navlist(node, level, has_child))
navlist = navstack.pop()
navlist[-1] = self.insert_subnav(navlist[-1], subnav)
level -= 1
navlist[-1] = navlist[-1] + '</ol>'
navlist.append(self.new_navlist(node, level))
lastnode = node
while level != 1: while level != 1:
subnav = '\n'.join(navlist)
navlist = navstack.pop()
navlist[-1] = self.insert_subnav(navlist[-1], subnav)
level -= 1 level -= 1
navlist[-1] = navlist[-1] + '</ol>' navlist.append(self.end_navlist_block(level))
return '\n'.join(navlist) return '\n'.join(navlist)
def navigation_doc_metadata(self, navlist): def navigation_doc_metadata(self, navlist):
@ -213,4 +218,5 @@ class Epub3Builder(EpubBuilder):
finally: finally:
f.close() f.close()
# Add nav.xhtml to epub file # Add nav.xhtml to epub file
self.files.append(outname) if outname not in self.files:
self.files.append(outname)