/usr/lib/python2.7/dist-packages/sphinx/builders/epub3.py is in python-sphinx 1.6.7-1ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | # -*- coding: utf-8 -*-
"""
sphinx.builders.epub3
~~~~~~~~~~~~~~~~~~~~~
Build epub3 files.
Originally derived from epub.py.
:copyright: Copyright 2007-2015 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
from os import path
from collections import namedtuple
from sphinx import package_dir
from sphinx.config import string_classes, ENUM
from sphinx.builders import _epub_base
from sphinx.util import logging, xmlname_checker
from sphinx.util.fileutil import copy_asset_file
from sphinx.util.i18n import format_date
if False:
# For type annotation
from typing import Any, Dict, Iterable, List # NOQA
from docutils import nodes # NOQA
from sphinx.application import Sphinx # NOQA
logger = logging.getLogger(__name__)
NavPoint = namedtuple('NavPoint', ['text', 'refuri', 'children'])
# writing modes
PAGE_PROGRESSION_DIRECTIONS = {
'horizontal': 'ltr',
'vertical': 'rtl',
}
IBOOK_SCROLL_AXIS = {
'horizontal': 'vertical',
'vertical': 'horizontal',
}
THEME_WRITING_MODES = {
'vertical': 'vertical-rl',
'horizontal': 'horizontal-tb',
}
DOCTYPE = '''<!DOCTYPE html>'''
HTML_TAG = (
u'<html xmlns="http://www.w3.org/1999/xhtml" '
u'xmlns:epub="http://www.idpf.org/2007/ops">'
)
class Epub3Builder(_epub_base.EpubBuilder):
"""
Builder that outputs epub3 files.
It creates the metainfo files content.opf, nav.xhtml, toc.ncx, mimetype,
and META-INF/container.xml. Afterwards, all necessary files are zipped to
an epub file.
"""
name = 'epub'
supported_remote_images = False
template_dir = path.join(package_dir, 'templates', 'epub3')
doctype = DOCTYPE
html_tag = HTML_TAG
use_meta_charset = True
# Finish by building the epub file
def handle_finish(self):
# type: () -> None
"""Create the metainfo files and finally the epub."""
self.validate_config_value()
self.get_toc()
self.build_mimetype(self.outdir, 'mimetype')
self.build_container(self.outdir, 'META-INF/container.xml')
self.build_content(self.outdir, 'content.opf')
self.build_navigation_doc(self.outdir, 'nav.xhtml')
self.build_toc(self.outdir, 'toc.ncx')
self.build_epub(self.outdir, self.config.epub_basename + '.epub')
def validate_config_value(self):
# <package> lang attribute, dc:language
if not self.app.config.epub_language:
logger.warning('conf value "epub_language" (or "language") '
'should not be empty for EPUB3')
# <package> unique-identifier attribute
if not xmlname_checker().match(self.app.config.epub_uid):
logger.warning('conf value "epub_uid" should be XML NAME for EPUB3')
# dc:title
if not self.app.config.epub_title:
logger.warning('conf value "epub_title" (or "html_title") '
'should not be empty for EPUB3')
# dc:creator
if not self.app.config.epub_author:
logger.warning('conf value "epub_author" should not be empty for EPUB3')
# dc:contributor
if not self.app.config.epub_contributor:
logger.warning('conf value "epub_contributor" should not be empty for EPUB3')
# dc:description
if not self.app.config.epub_description:
logger.warning('conf value "epub_description" should not be empty for EPUB3')
# dc:publisher
if not self.app.config.epub_publisher:
logger.warning('conf value "epub_publisher" should not be empty for EPUB3')
# dc:rights
if not self.app.config.epub_copyright:
logger.warning('conf value "epub_copyright" (or "copyright")'
'should not be empty for EPUB3')
# dc:identifier
if not self.app.config.epub_identifier:
logger.warning('conf value "epub_identifier" should not be empty for EPUB3')
# meta ibooks:version
if not self.app.config.version:
logger.warning('conf value "version" should not be empty for EPUB3')
def content_metadata(self):
# type: () -> Dict
"""Create a dictionary with all metadata for the content.opf
file properly escaped.
"""
writing_mode = self.config.epub_writing_mode
metadata = super(Epub3Builder, self).content_metadata()
metadata['description'] = self.esc(self.config.epub_description)
metadata['contributor'] = self.esc(self.config.epub_contributor)
metadata['page_progression_direction'] = PAGE_PROGRESSION_DIRECTIONS.get(writing_mode)
metadata['ibook_scroll_axis'] = IBOOK_SCROLL_AXIS.get(writing_mode)
metadata['date'] = self.esc(format_date("%Y-%m-%dT%H:%M:%SZ"))
metadata['version'] = self.esc(self.config.version)
return metadata
def prepare_writing(self, docnames):
# type: (Iterable[unicode]) -> None
super(Epub3Builder, self).prepare_writing(docnames)
writing_mode = self.config.epub_writing_mode
self.globalcontext['theme_writing_mode'] = THEME_WRITING_MODES.get(writing_mode)
self.globalcontext['html_tag'] = self.html_tag
self.globalcontext['use_meta_charset'] = self.use_meta_charset
def build_navlist(self, navnodes):
# type: (List[nodes.Node]) -> List[NavPoint]
"""Create the toc navigation structure.
This method is almost same as build_navpoints method in epub.py.
This is because the logical navigation structure of epub3 is not
different from one of epub2.
The difference from build_navpoints method is templates which are used
when generating navigation documents.
"""
navstack = [] # type: List[NavPoint]
navstack.append(NavPoint('', '', []))
level = 0
for node in navnodes:
if not node['text']:
continue
file = node['refuri'].split('#')[0]
if file in self.ignored_files:
continue
if node['level'] > self.config.epub_tocdepth:
continue
navpoint = NavPoint(node['text'], node['refuri'], [])
if node['level'] == level:
navstack.pop()
navstack[-1].children.append(navpoint)
navstack.append(navpoint)
elif node['level'] == level + 1:
level += 1
navstack[-1].children.append(navpoint)
navstack.append(navpoint)
elif node['level'] < level:
while node['level'] < len(navstack):
navstack.pop()
level = node['level']
navstack[-1].children.append(navpoint)
navstack.append(navpoint)
else:
raise
return navstack[0].children
def navigation_doc_metadata(self, navlist):
# type: (List[NavPoint]) -> Dict
"""Create a dictionary with all metadata for the nav.xhtml file
properly escaped.
"""
metadata = {} # type: Dict
metadata['lang'] = self.esc(self.config.epub_language)
metadata['toc_locale'] = self.esc(self.guide_titles['toc'])
metadata['navlist'] = navlist
return metadata
def build_navigation_doc(self, outdir, outname):
# type: (unicode, unicode) -> None
"""Write the metainfo file nav.xhtml."""
logger.info('writing %s file...', outname)
if self.config.epub_tocscope == 'default':
doctree = self.env.get_and_resolve_doctree(
self.config.master_doc, self,
prune_toctrees=False, includehidden=False)
refnodes = self.get_refnodes(doctree, [])
self.toc_add_files(refnodes)
else:
# 'includehidden'
refnodes = self.refnodes
navlist = self.build_navlist(refnodes)
copy_asset_file(path.join(self.template_dir, 'nav.xhtml_t'),
path.join(outdir, outname),
self.navigation_doc_metadata(navlist))
# Add nav.xhtml to epub file
if outname not in self.files:
self.files.append(outname)
def setup(app):
# type: (Sphinx) -> Dict[unicode, Any]
app.setup_extension('sphinx.builders.epub2')
app.add_builder(Epub3Builder)
# config values
app.add_config_value('epub_description', 'unknown', 'epub3', string_classes)
app.add_config_value('epub_contributor', 'unknown', 'epub3', string_classes)
app.add_config_value('epub_writing_mode', 'horizontal', 'epub3',
ENUM('horizontal', 'vertical'))
return {
'version': 'builtin',
'parallel_read_safe': True,
'parallel_write_safe': True,
}
|