mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Add EPUB 3 builder.
This commit is contained in:
@@ -462,6 +462,7 @@ BUILTIN_BUILDERS = {
|
||||
'qthelp': ('qthelp', 'QtHelpBuilder'),
|
||||
'applehelp': ('applehelp', 'AppleHelpBuilder'),
|
||||
'epub': ('epub', 'EpubBuilder'),
|
||||
'epub3': ('epub3', 'Epub3Builder'),
|
||||
'latex': ('latex', 'LaTeXBuilder'),
|
||||
'text': ('text', 'TextBuilder'),
|
||||
'man': ('manpage', 'ManualPageBuilder'),
|
||||
|
||||
213
sphinx/builders/epub3.py
Normal file
213
sphinx/builders/epub3.py
Normal file
@@ -0,0 +1,213 @@
|
||||
# -*- 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.
|
||||
"""
|
||||
|
||||
import codecs
|
||||
from os import path
|
||||
|
||||
from sphinx.builders.epub import EpubBuilder
|
||||
|
||||
|
||||
# (Fragment) templates from which the metainfo files content.opf, toc.ncx,
|
||||
# mimetype, and META-INF/container.xml are created.
|
||||
# This template section also defines strings that are embedded in the html
|
||||
# output but that may be customized by (re-)setting module attributes,
|
||||
# e.g. from conf.py.
|
||||
|
||||
NAVIGATION_DOC_TEMPLATE = u'''\
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"\
|
||||
xmlns:epub="http://www.idpf.org/2007/ops" lang="%(lang)s" xml:lang="%(lang)s">
|
||||
<head>
|
||||
<title>%(toc_locale)s</title>
|
||||
</head>
|
||||
<body>
|
||||
<nav epub:type="toc">
|
||||
<h1>%(toc_locale)s</h1>
|
||||
<ol>
|
||||
%(navlist)s
|
||||
</ol>
|
||||
</nav>
|
||||
</body>
|
||||
</html>
|
||||
'''
|
||||
|
||||
NAVLIST_TEMPLATE = u'''\
|
||||
%(indent)s <li>
|
||||
%(indent)s <a href="%(refuri)s">%(text)s</a>
|
||||
%(indent)s </li>
|
||||
'''
|
||||
NAVLIST_INDENT = ' '
|
||||
|
||||
|
||||
PACKAGE_DOC_TEMPLATE = u'''\
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<package xmlns="http://www.idpf.org/2007/opf" version="3.0" xml:lang="%(lang)s"
|
||||
unique-identifier="%(uid)s">
|
||||
<metadata xmlns:opf="http://www.idpf.org/2007/opf"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<dc:language>%(lang)s</dc:language>
|
||||
<dc:title>%(title)s</dc:title>
|
||||
<dc:description>%(description)s</dc:description>
|
||||
<dc:creator>%(author)s</dc:creator>
|
||||
<dc:contributor>%(contributor)s</dc:contributor>
|
||||
<dc:publisher>%(publisher)s</dc:publisher>
|
||||
<dc:rights>%(copyright)s</dc:rights>
|
||||
<dc:identifier id="%(uid)s">%(id)s</dc:identifier>
|
||||
<dc:date>%(date)s</dc:date>
|
||||
<meta property="dcterms:modified">%(date)s</meta>
|
||||
</metadata>
|
||||
<manifest>
|
||||
<item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml" />
|
||||
<item id="nav" href="nav.xhtml"\
|
||||
media-type="application/xhtml+xml" properties="nav"/>
|
||||
%(files)s
|
||||
</manifest>
|
||||
<spine toc="ncx" page-progression-direction="%(page_progression_direction)s">
|
||||
<itemref idref="nav" />
|
||||
%(spine)s
|
||||
</spine>
|
||||
<guide>
|
||||
%(guide)s
|
||||
</guide>
|
||||
</package>
|
||||
'''
|
||||
|
||||
# The epub3 publisher
|
||||
|
||||
|
||||
class Epub3Builder(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 = 'epub3'
|
||||
|
||||
navigation_doc_template = NAVIGATION_DOC_TEMPLATE
|
||||
navlist_template = NAVLIST_TEMPLATE
|
||||
navlist_indent = NAVLIST_INDENT
|
||||
content_template = PACKAGE_DOC_TEMPLATE
|
||||
|
||||
# Finish by building the epub file
|
||||
def handle_finish(self):
|
||||
"""Create the metainfo files and finally the epub."""
|
||||
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 content_metadata(self, files, spine, guide):
|
||||
"""Create a dictionary with all metadata for the content.opf
|
||||
file properly escaped.
|
||||
"""
|
||||
metadata = super(Epub3Builder, self).content_metadata(
|
||||
files, spine, guide)
|
||||
metadata['description'] = self.esc(self.config.epub3_description)
|
||||
metadata['contributor'] = self.esc(self.config.epub3_contributor)
|
||||
metadata['page_progression_direction'] = self.esc(
|
||||
self.config.epub3_page_progression_direction)
|
||||
return metadata
|
||||
|
||||
def new_navlist(self, node, level):
|
||||
"""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
|
||||
|
||||
def build_navlist(self, nodes):
|
||||
"""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 = []
|
||||
navlist = []
|
||||
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
|
||||
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] = '<ol>\n' + navlist[-1]
|
||||
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] + '</ol>'
|
||||
navlist.append(self.new_navlist(node, level))
|
||||
lastnode = node
|
||||
while level != 1:
|
||||
subnav = '\n'.join(navlist)
|
||||
navlist = navstack.pop()
|
||||
navlist[-1] = self.insert_subnav(navlist[-1], subnav)
|
||||
level -= 1
|
||||
navlist[-1] = navlist[-1] + '</ol>'
|
||||
return '\n'.join(navlist)
|
||||
|
||||
def navigation_doc_metadata(self, navlist):
|
||||
"""Create a dictionary with all metadata for the nav.xhtml file
|
||||
properly escaped.
|
||||
"""
|
||||
metadata = {}
|
||||
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):
|
||||
"""Write the metainfo file nav.xhtml."""
|
||||
self.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)
|
||||
f = codecs.open(path.join(outdir, outname), 'w', 'utf-8')
|
||||
try:
|
||||
f.write(self.navigation_doc_template %
|
||||
self.navigation_doc_metadata(navlist))
|
||||
finally:
|
||||
f.close()
|
||||
# Add nav.xhtml to epub file
|
||||
self.files.append(outname)
|
||||
@@ -169,7 +169,9 @@ class Config(object):
|
||||
epub_theme = ('epub', 'html'),
|
||||
epub_theme_options = ({}, 'html'),
|
||||
epub_title = (lambda self: self.html_title, 'html'),
|
||||
epub3_description = ('', 'epub3', [str]),
|
||||
epub_author = ('unknown', 'html'),
|
||||
epub3_contributor = ('unknown', 'epub3', [str]),
|
||||
epub_language = (lambda self: self.language or 'en', 'html'),
|
||||
epub_publisher = ('unknown', 'html'),
|
||||
epub_copyright = (lambda self: self.copyright, 'html'),
|
||||
@@ -188,6 +190,7 @@ class Config(object):
|
||||
epub_max_image_width = (0, 'env'),
|
||||
epub_show_urls = ('inline', 'html'),
|
||||
epub_use_index = (lambda self: self.html_use_index, 'html'),
|
||||
epub3_page_progression_direction = ('ltr', 'epub3', [str]),
|
||||
|
||||
# LaTeX options
|
||||
latex_documents = (lambda self: [(self.master_doc,
|
||||
|
||||
@@ -503,6 +503,7 @@ help:
|
||||
\t@echo " applehelp to make an Apple Help Book"
|
||||
\t@echo " devhelp to make HTML files and a Devhelp project"
|
||||
\t@echo " epub to make an epub"
|
||||
\t@echo " epub3 to make an epub3"
|
||||
\t@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||
\t@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||
\t@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
|
||||
@@ -596,6 +597,12 @@ epub:
|
||||
\t@echo
|
||||
\t@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||
|
||||
.PHONY: epub3
|
||||
epub3:
|
||||
\t$(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
|
||||
\t@echo
|
||||
\t@echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
|
||||
|
||||
.PHONY: latex
|
||||
latex:
|
||||
\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||
@@ -719,6 +726,7 @@ if "%%1" == "help" (
|
||||
\techo. qthelp to make HTML files and a qthelp project
|
||||
\techo. devhelp to make HTML files and a Devhelp project
|
||||
\techo. epub to make an epub
|
||||
\techo. epub3 to make an epub3
|
||||
\techo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
|
||||
\techo. text to make text files
|
||||
\techo. man to make manual pages
|
||||
@@ -841,6 +849,14 @@ if "%%1" == "epub" (
|
||||
\tgoto end
|
||||
)
|
||||
|
||||
if "%%1" == "epub3" (
|
||||
\t%%SPHINXBUILD%% -b epub3 %%ALLSPHINXOPTS%% %%BUILDDIR%%/epub3
|
||||
\tif errorlevel 1 exit /b 1
|
||||
\techo.
|
||||
\techo.Build finished. The epub3 file is in %%BUILDDIR%%/epub3.
|
||||
\tgoto end
|
||||
)
|
||||
|
||||
if "%%1" == "latex" (
|
||||
\t%%SPHINXBUILD%% -b latex %%ALLSPHINXOPTS%% %%BUILDDIR%%/latex
|
||||
\tif errorlevel 1 exit /b 1
|
||||
|
||||
Reference in New Issue
Block a user