merge with trunk

This commit is contained in:
Georg Brandl 2009-12-31 18:40:58 +01:00
commit f3a2854ba9
25 changed files with 1143 additions and 13 deletions

View File

@ -15,6 +15,7 @@ Other contributors, listed alphabetically, are:
* Thomas Lamb -- linkcheck builder
* Dan MacKinlay -- metadata fixes
* Will Maier -- directory HTML builder
* Roland Meister -- epub builder
* Christopher Perkins -- autosummary integration
* Benjamin Peterson -- unittests
* Stefan Seefeld -- toctree improvements

12
CHANGES
View File

@ -1,8 +1,14 @@
Release 1.0 (in development)
============================
.. XXX add short info about domains
* Support for domains has been added.
* Support for docutils 0.4 has been removed.
* Added Epub builder.
* #284: All docinfo metadata is now put into the document metadata, not
just the author.
@ -54,6 +60,12 @@ Release 1.0 (in development)
Release 0.6.4 (in development)
==============================
* #303: ``html_context`` values given on the command line via ``-A``
should not override other values given in conf.py.
* Fix a bug preventing incremental rebuilds for the ``dirhtml``
builder.
* #299: Fix the mangling of quotes in some literal blocks.
* #292: Fix path to the search index for the ``dirhtml`` builder.

View File

@ -19,6 +19,7 @@ help:
@echo " dirhtml to make HTML files called index.html in directories"
@echo " pickle to make pickle files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " epub to make an epub file"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " changes to make an overview over all changed/added/deprecated items"
@echo " linkcheck to check all external links for integrity"
@ -65,6 +66,11 @@ qthelp:
@echo "To view the help collection:"
@echo "# assistant -collectionFile _build/qthelp/Sphinx.qhc"
epub:
mkdir -p _build/epub _build/doctrees
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) _build/epub
@echo
@echo "Build finished. The epub file is in _build/epub."
latex:
mkdir -p _build/latex _build/doctrees
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex

View File

@ -1,10 +1,13 @@
{% extends "!layout.html" %}
{% block extrahead %}
{{ super() }}
{%- if not embedded %}
<style type="text/css">
table.right { float: right; margin-left: 20px; }
table.right td { border: 1px solid #ccc; }
</style>
{%- endif %}
{% endblock %}
{% block rootrellink %}

View File

@ -63,6 +63,16 @@ The builder's "name" must be given to the **-b** command-line option of
Its name is ``devhelp``.
.. module:: sphinx.builders.epub
.. class:: EpubBuilder
This builder produces the same output as the standalone HTML builder, but
also generates an *epub* file for ebook readers. See :ref:`epub-faq` for
details about it. For definition of the epub format, have a look at
`<http://www.idpf.org/specs.htm>`_ or `<http://en.wikipedia.org/wiki/EPUB>`_.
Its name is ``epub``.
.. module:: sphinx.builders.latex
.. class:: LaTeXBuilder

View File

@ -64,6 +64,19 @@ html_use_opensearch = 'http://sphinx.pocoo.org'
# Output file base name for HTML help builder.
htmlhelp_basename = 'Sphinxdoc'
# Epub fields
epub_theme = 'epub'
epub_basename = 'sphinx'
epub_author = 'Georg Brandl'
epub_publisher = 'http://sphinx.pocoo.org/'
epub_scheme = 'url'
epub_identifier = epub_publisher
epub_pre_files = [('index', 'Welcome')]
epub_exclude_files = ['_static/opensearch.xml', '_static/doctools.js',
'_static/jquery.js', '_static/searchtools.js',
'_static/basic.css', 'search.html']
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [('contents', 'sphinx.tex', 'Sphinx Documentation',

View File

@ -550,6 +550,96 @@ that use Sphinx' HTMLWriter class.
Output file base name for HTML help builder. Default is ``'pydoc'``.
.. _epub-options:
Options for epub output
-----------------------
These options influence the epub output. As this builder derives from the HTML
builder, the HTML options also apply where appropriate. The actual values for
some of the options is not really important, they just have to be entered into
the `Dublin Core metadata <http://dublincore.org/>`_.
.. confval:: epub_basename
The basename for the epub file. It defaults to the :confval:`project` name.
.. confval:: epub_theme
The HTML theme for the epub output. Since the default themes are not
optimized for small screen space, using the same theme for HTML and epub
output is usually not wise. This defaults to ``'epub'``, a theme designed to
save visual space.
.. confval:: epub_title
The title of the document. It defaults to the :confval:`html_title` option
but can be set independently for epub creation.
.. confval:: epub_author
The author of the document. This is put in the Dublin Core metadata. The
default value is ``'unknown'``.
.. confval:: epub_language
The language of the document. This is put in the Dublin Core metadata. The
default is the :confval:`language` option or ``'en'`` if unset.
.. confval:: epub_publisher
The publisher of the document. This is put in the Dublin Core metadata. You
may use any sensible string, e.g. the project homepage. The default value is
``'unknown'``.
.. confval:: epub_copyright
The copyright of the document. It defaults to the :confval:`copyright`
option but can be set independently for epub creation.
.. confval:: epub_identifier
An identifier for the document. This is put in the Dublin Core metadata.
For published documents this is the ISBN number, but you can also use an
alternative scheme, e.g. the project homepage. The default value is
``'unknown'``.
.. confval:: epub_scheme
The publication scheme for the :confval:`epub_identifier`. This is put in
the Dublin Core metadata. For published books the scheme is ``'ISBN'``. If
you use the project homepage, ``'URL'`` seems reasonable. The default value
is ``'unknown'``.
.. confval:: epub_uid
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_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::
epub_pre_files = [
('index.html', 'Welcome'),
]
The default value is ``[]``.
.. confval:: epub_post_files
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. The default
value is ``[]``.
.. confval:: epub_exclude_files
A list of files that are generated/copied in the build directory but should
not be included in the epub file. The default value is ``[]``.
.. _latex-options:
Options for LaTeX output

View File

@ -66,3 +66,40 @@ github pages
.. _api role: http://git.savannah.gnu.org/cgit/kenozooid.git/tree/doc/extapi.py
.. _xhtml to reST: http://docutils.sourceforge.net/sandbox/xhtml2rest/xhtml2rest.py
.. _epub-faq:
Epub info
---------
The epub builder is currently in an experimental stage. It has only been tested
with the Sphinx documentation itself. If you want to create epubs, here are
some notes:
* Split the text into several files. The longer the individual HTML files are,
the longer it takes the ebook reader to render them. In extreme cases, the
rendering can take up to one minute.
* Try to minimize the markup. This also pays in rendering time.
* For some readers you can use embedded or external fonts using the CSS
``@font-face`` directive. This is *extremely* useful for code listings which
are often cut at the right margin. The default Courier font (or variant) is
quite wide and you can only display up to 60 characters on a line. If you
replace it with a narrower font, you can get more characters on a line. You
may even use `FontForge <http://fontforge.sourceforge.net/>`_ and create
narrow variants of some free font. In my case I get up to 70 characters on a
line.
You may have to experiment a little until you get reasonable results.
* Test the created epubs. You can use several alternatives. The ones I am aware
of are Epubcheck_, Calibre_, FBreader_ (although it does not render the CSS),
and Bookworm_. For bookworm you can download the source from
http://code.google.com/p/threepress/ and run your own local server.
.. _Epubcheck: http://code.google.com/p/epubcheck/
.. _Calibre: http://calibre-ebook.com/
.. _FBreader: http://www.fbreader.org/
.. _Bookworm: http://bookworm.oreilly.com/

View File

@ -160,6 +160,10 @@ These themes are:
* **traditional** -- A theme resembling the old Python documentation. There are
currently no options beyond *nosidebar*.
* **epub** -- A theme for the epub builder. There are currently no options.
This theme tries to save visual space which is a sparse resource on ebook
readers.
Creating themes
---------------

View File

@ -323,6 +323,7 @@ BUILTIN_BUILDERS = {
'htmlhelp': ('htmlhelp', 'HTMLHelpBuilder'),
'devhelp': ('devhelp', 'DevhelpBuilder'),
'qthelp': ('qthelp', 'QtHelpBuilder'),
'epub': ('epub', 'EpubBuilder'),
'latex': ('latex', 'LaTeXBuilder'),
'text': ('text', 'TextBuilder'),
'changes': ('changes', 'ChangesBuilder'),

421
sphinx/builders/epub.py Normal file
View File

@ -0,0 +1,421 @@
# -*- coding: utf-8 -*-
"""
sphinx.builders.epub
~~~~~~~~~~~~~~~~~~~~
Build epub files.
Originally derived from qthelp.py.
:copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import os
import codecs
from os import path
import zipfile
from docutils import nodes
from sphinx.builders.html import StandaloneHTMLBuilder
# (Fragment) templates from which the metainfo files content.opf, toc.ncx,
# mimetype, and META-INF/container.xml are created.
_mimetype_template = 'application/epub+zip' # no EOL!
_container_template = u'''\
<?xml version="1.0" encoding="UTF-8"?>
<container version="1.0"
xmlns="urn:oasis:names:tc:opendocument:xmlns:container">
<rootfiles>
<rootfile full-path="content.opf"
media-type="application/oebps-package+xml"/>
</rootfiles>
</container>
'''
_toc_template = u'''\
<?xml version="1.0"?>
<ncx version="2005-1" xmlns="http://www.daisy.org/z3986/2005/ncx/">
<head>
<meta name="dtb:uid" content="%(uid)s"/>
<meta name="dtb:depth" content="%(level)d"/>
<meta name="dtb:totalPageCount" content="0"/>
<meta name="dtb:maxPageNumber" content="0"/>
</head>
<docTitle>
<text>%(title)s</text>
</docTitle>
<navMap>
%(navpoints)s
</navMap>
</ncx>
'''
_navpoint_template = u'''\
%(indent)s <navPoint id="%(navpoint)s" playOrder="%(playorder)d">
%(indent)s <navLabel>
%(indent)s <text>%(text)s</text>
%(indent)s </navLabel>
%(indent)s <content src="%(refuri)s" />
%(indent)s </navPoint>'''
_navpoint_indent = ' '
_navPoint_template = 'navPoint%d'
_content_template = u'''\
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="2.0"
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:creator opf:role="aut">%(author)s</dc:creator>
<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>
</metadata>
<manifest>
<item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml" />
%(files)s
</manifest>
<spine toc="ncx">
%(spine)s
</spine>
</package>
'''
_file_template = u'''\
<item id="%(id)s"
href="%(href)s"
media-type="%(media_type)s" />'''
_spine_template = u'''\
<itemref idref="%(idref)s" />'''
_toctree_template = u'toctree-l%d'
_media_types = {
'.html': 'application/xhtml+xml',
'.css': 'text/css',
'.png': 'image/png',
'.gif': 'image/gif',
'.svg': 'image/svg+xml',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.otf': 'application/x-font-otf',
'.ttf': 'application/x-font-ttf',
}
# The epub publisher
class EpubBuilder(StandaloneHTMLBuilder):
"""Builder that outputs epub files.
It creates the metainfo files container.opf, toc.ncx, mimetype, and
META-INF/container.xml. Afterwards, all necessary files are zipped to an
epub file.
"""
name = 'epub'
# don't copy the reST source
copysource = False
supported_image_types = ['image/svg+xml', 'image/png', 'image/gif',
'image/jpeg']
# don't add links
add_permalinks = False
# don't add sidebar etc.
embedded = True
def init(self):
StandaloneHTMLBuilder.init(self)
# the output files for epub must be .html only
self.out_suffix = '.html'
self.playorder = 0
def get_theme_config(self):
return self.config.epub_theme, {}
# generic support functions
def make_id(self, name):
"""Replace all characters not allowed for (X)HTML ids."""
return name.replace('/', '_')
def esc(self, name):
"""Replace all characters not allowed in text an attribute values."""
# Like cgi.escape, but also replace apostrophe
name = name.replace('&', '&amp;')
name = name.replace('<', '&lt;')
name = name.replace('>', '&gt;')
name = name.replace('"', '&quot;')
name = name.replace('\'', '&apos;')
return name
def collapse_text(self, doctree, result):
"""Remove all HTML markup and return only the text nodes."""
for c in doctree.children:
if isinstance(c, nodes.Text):
try:
# docutils 0.4 and 0.5: Text is a UserString subclass
result.append(c.data)
except AttributeError:
# docutils 0.6: Text is a unicode subclass
result.append(c)
else:
result = self.collapse_text(c, result)
return result
def get_refnodes(self, doctree, result):
"""Collect section titles, their depth in the toc and the refuri."""
# XXX: is there a better way than checking the attribute
# toctree-l[1-6] on the parent node?
if isinstance(doctree, nodes.reference):
classes = doctree.parent.attributes['classes']
level = 1
for l in range(5,0,-1): # or range(1,6)?
if (_toctree_template % l) in classes:
level = l
result.append({
'level': level,
'refuri': self.esc(doctree['refuri']),
'text': self.esc(''.join(self.collapse_text(doctree, [])))
})
else:
for elem in doctree.children:
result = self.get_refnodes(elem, result)
return result
def get_toc(self):
"""Get the total table of contents, containg the master_doc
and pre and post files not managed by sphinx.
"""
doctree = self.env.get_and_resolve_doctree(self.config.master_doc, self)
self.refnodes = self.get_refnodes(doctree, [])
self.refnodes.insert(0, {
'level': 1,
'refuri': self.esc(self.config.master_doc + '.html'),
'text': self.esc(''.join(self.collapse_text(
self.env.titles[self.config.master_doc], []
))),
})
# XXX: is reversed ok?
for file, text in reversed(self.config.epub_pre_files):
self.refnodes.insert(0, {
'level': 1,
'refuri': self.esc(file + '.html'),
'text': self.esc(text)
})
for file, text in self.config.epub_post_files:
self.refnodes.append({
'level': 1,
'refuri': self.esc(file + '.html'),
'text': self.esc(text)
})
# 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_toc(self.outdir, 'toc.ncx')
self.build_epub(self.outdir, self.config.epub_basename + '.epub')
def build_mimetype(self, outdir, outname):
"""Write the metainfo file mimetype."""
self.info('writing %s file...' % outname)
f = codecs.open(path.join(outdir, outname), 'w', 'utf-8')
try:
f.write(_mimetype_template)
finally:
f.close()
def build_container(self, outdir, outname):
"""Write the metainfo file META-INF/cointainer.xml."""
self.info('writing %s file...' % outname)
fn = path.join(outdir, outname)
try:
os.mkdir(path.dirname(fn))
except OSError, err:
if err.errno != os.errno.EEXIST:
raise
f = codecs.open(path.join(outdir, outname), 'w', 'utf-8')
try:
f.write(_container_template)
finally:
f.close()
def content_metadata(self, files, spine):
"""Create a dictionary with all metadata for the content.opf
file properly escaped.
"""
metadata = {}
metadata['title'] = self.esc(self.config.epub_title)
metadata['author'] = self.esc(self.config.epub_author)
metadata['uid'] = self.esc(self.config.epub_uid)
metadata['lang'] = self.esc(self.config.epub_language)
metadata['publisher'] = self.esc(self.config.epub_publisher)
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['files'] = files
metadata['spine'] = spine
return metadata
def build_content(self, outdir, outname):
"""Write the metainfo file content.opf It contains bibliographic data,
a file list and the spine (the reading order).
"""
self.info('writing %s file...' % outname)
# files
if not outdir.endswith(os.sep):
outdir += os.sep
olen = len(outdir)
projectfiles = []
self.files = []
self.ignored_files = ['.buildinfo',
'mimetype', 'content.opf', 'toc.ncx', 'META-INF/container.xml',
self.config.epub_basename + '.epub'] + \
self.config.epub_exclude_files
for root, dirs, files in os.walk(outdir):
for fn in files:
filename = path.join(root, fn)[olen:]
if filename in self.ignored_files:
# self.warn("ignoring %s" % filename)
continue
ext = path.splitext(filename)[-1]
if ext not in _media_types:
self.warn("unknown mimetype for %s, ignoring" % filename)
continue
projectfiles.append(_file_template % {
'href': self.esc(filename),
'id': self.esc(self.make_id(filename)),
'media_type': self.esc(_media_types[ext])
})
self.files.append(filename)
projectfiles = '\n'.join(projectfiles)
# spine
spine = []
for item in self.refnodes:
if '#' in item['refuri']:
continue
if item['refuri'] in self.ignored_files:
continue
spine.append(_spine_template % {
'idref': self.esc(self.make_id(item['refuri']))
})
spine = '\n'.join(spine)
# write the project file
f = codecs.open(path.join(outdir, outname), 'w', 'utf-8')
try:
f.write(_content_template % \
self.content_metadata(projectfiles, spine))
finally:
f.close()
def new_navpoint(self, node, level, incr=True):
"""Create a new entry in the toc from the node at given level."""
# XXX Modifies the node
if incr:
self.playorder += 1
node['indent'] = _navpoint_indent * level
node['navpoint'] = self.esc(_navPoint_template % self.playorder)
node['playorder'] = self.playorder
return _navpoint_template % node
def insert_subnav(self, node, subnav):
"""Insert nested navpoints for given node.
The node and subnav are already rendered to text.
"""
nlist = node.split('\n')
nlist.insert(-1, subnav)
return '\n'.join(nlist)
def build_navpoints(self, nodes):
"""Create the toc navigation structure.
Subelements of a node are nested inside the navpoint.
For nested nodes the parent node is reinserted in the subnav.
"""
navstack = []
navlist = []
level = 1
lastnode = None
for node in nodes:
file = node['refuri'].split('#')[0]
if file in self.ignored_files:
continue
if node['level'] == level:
navlist.append(self.new_navpoint(node,level))
elif node['level'] == level + 1:
navstack.append(navlist)
navlist = []
level += 1
if lastnode:
# Insert starting point in subtoc with same playOrder
navlist.append(self.new_navpoint(lastnode, level, False))
navlist.append(self.new_navpoint(node, level))
else:
while node['level'] < level:
subnav = '\n'.join(navlist)
navlist = navstack.pop()
navlist[-1] = self.insert_subnav(navlist[-1], subnav)
level -= 1
navlist.append(self.new_navpoint(node, level))
lastnode = node
while level != 1:
subnav = '\n'.join(navlist)
navlist = navstack.pop()
navlist[-1] = self.insert_subnav(navlist[-1], subnav)
level -= 1
return '\n'.join(navlist)
def toc_metadata(self, level, navpoints):
"""Create a dictionary with all metadata for the toc.ncx
file properly escaped.
"""
metadata = {}
metadata['uid'] = self.config.epub_uid
metadata['title'] = self.config.epub_title
metadata['level'] = level
metadata['navpoints'] = navpoints
return metadata
def build_toc(self, outdir, outname):
"""Write the metainfo file toc.ncx."""
self.info('writing %s file...' % outname)
navpoints = self.build_navpoints(self.refnodes)
level = max(item['level'] for item in self.refnodes)
f = codecs.open(path.join(outdir, outname), 'w', 'utf-8')
try:
f.write(_toc_template % self.toc_metadata(level, navpoints))
finally:
f.close()
def build_epub(self, outdir, outname):
"""Write the epub file.
It is a zip file with the mimetype file stored uncompressed
as the first entry.
"""
self.info('writing %s file...' % outname)
projectfiles = ['META-INF/container.xml', 'content.opf', 'toc.ncx'] \
+ self.files
epub = zipfile.ZipFile(path.join(outdir, outname), 'w', \
zipfile.ZIP_DEFLATED)
epub.write(path.join(outdir, 'mimetype'), 'mimetype', \
zipfile.ZIP_STORED)
for file in projectfiles:
epub.write(path.join(outdir, file), file, zipfile.ZIP_DEFLATED)
epub.close()

View File

@ -103,9 +103,14 @@ class StandaloneHTMLBuilder(Builder):
if path.isfile(jsfile):
self.script_files.append('_static/translations.js')
def get_theme_config(self):
return self.config.html_theme, self.config.html_theme_options
def init_templates(self):
Theme.init_themes(self)
self.theme = Theme(self.config.html_theme)
themename, themeoptions = self.get_theme_config()
self.theme = Theme(themename)
self.theme_options = themeoptions.copy()
self.create_template_bridge()
self.templates.init(self, self.theme)
@ -169,8 +174,7 @@ class StandaloneHTMLBuilder(Builder):
if docname not in self.env.all_docs:
yield docname
continue
targetname = self.env.doc2path(docname, self.outdir,
self.out_suffix)
targetname = self.get_outfilename(docname)
try:
targetmtime = path.getmtime(targetname)
except Exception:
@ -283,8 +287,7 @@ class StandaloneHTMLBuilder(Builder):
if self.theme:
self.globalcontext.update(
('theme_' + key, val) for (key, val) in
self.theme.get_options(
self.config.html_theme_options).iteritems())
self.theme.get_options(self.theme_options).iteritems())
self.globalcontext.update(self.config.html_context)
def get_doc_context(self, docname, body, metatags):

View File

@ -96,7 +96,6 @@ def main(argv):
error = sys.stderr
warnfile = None
confoverrides = {}
htmlcontext = {}
tags = []
doctreedir = path.join(outdir, '.doctrees')
for opt, val in opts:
@ -142,7 +141,7 @@ def main(argv):
val = int(val)
except ValueError:
pass
htmlcontext[key] = val
confoverrides['html_context.%s' % key] = val
elif opt == '-N':
nocolor()
elif opt == '-E':
@ -158,7 +157,6 @@ def main(argv):
warnfile = val
elif opt == '-P':
use_pdb = True
confoverrides['html_context'] = htmlcontext
if warning and warnfile:
warnfp = open(warnfile, 'w')

View File

@ -98,6 +98,21 @@ class Config(object):
# Devhelp only options
devhelp_basename = (lambda self: make_filename(self.project), None),
# Epub options
epub_basename = (lambda self: make_filename(self.project), None),
epub_theme = ('epub', 'html'),
epub_title = (lambda self: self.html_title, 'html'),
epub_author = ('unknown', 'html'),
epub_language = (lambda self: self.language or 'en', 'html'),
epub_publisher = ('unknown', 'html'),
epub_copyright = (lambda self: self.copyright, 'html'),
epub_identifier = ('unknown', 'html'),
epub_scheme = ('unknown', 'html'),
epub_uid = ('unknown', 'env'),
epub_pre_files = ([], 'env'),
epub_post_files = ([], 'env'),
epub_exclude_files = ([], 'env'),
# LaTeX options
latex_documents = ([], None),
latex_logo = (None, None),

View File

@ -148,7 +148,7 @@ class Index(Directive):
option_spec = {}
indextypes = [
'single', 'pair', 'triple',
'single', 'pair', 'double', 'triple',
]
def run(self):
@ -171,6 +171,8 @@ class Index(Directive):
for type in self.indextypes:
if entry.startswith(type+':'):
value = entry[len(type)+1:].strip()
if type == 'double':
type = 'pair'
ne.append((type, value, targetid, value))
break
# shorthand notation for single entries

View File

@ -223,6 +223,40 @@ latex_documents = [
# If false, no module index is generated.
#latex_use_modindex = True
# -- Options for Epub output ---------------------------------------------------
# Bibliographic Dublin Core info.
#epub_title = ''
#epub_author = ''
#epub_publisher = ''
#epub_copyright = ''
# The language of the text. It defaults to the language option
# or en if the language is not set.
#epub_language = ''
# The scheme of the identifier. Typical schemes are ISBN or URL.
#epub_scheme = ''
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#epub_identifier = ''
# A unique identification for the text.
#epub_uid = ''
# 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 = []
# HTML files shat should be inserted after the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#epub_post_files = []
# A list of files that should not be packed into the epub file.
#epub_exclude_files = []
'''
INTERSPHINX_CONFIG = '''
@ -270,8 +304,8 @@ PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) \
$(SPHINXOPTS) %(rsrcdir)s
.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes \
linkcheck doctest
.PHONY: help clean html dirhtml pickle json htmlhelp qthelp epub \
latex changes linkcheck doctest
help:
\t@echo "Please use \\`make <target>' where <target> is one of"
@ -282,6 +316,7 @@ help:
\t@echo " htmlhelp to make HTML files and a HTML help project"
\t@echo " qthelp to make HTML files and a qthelp project"
\t@echo " devhelp to make HTML files and a Devhelp project"
\t@echo " epub to make an epub"
\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 " changes to make an overview of all changed/added/deprecated items"
@ -337,6 +372,11 @@ devhelp:
$$HOME/.local/share/devhelp/%(project_fn)s"
\t@echo "# devhelp"
epub:
\t$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
\t@echo
\t@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
\t$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
\t@echo
@ -391,6 +431,7 @@ if "%%1" == "help" (
\techo. htmlhelp to make HTML files and a HTML help project
\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. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter
\techo. changes to make an overview over all changed/added/deprecated items
\techo. linkcheck to check all external links for integrity
@ -458,6 +499,13 @@ if "%%1" == "devhelp" (
\tgoto end
)
if "%%1" == "epub" (
\t%%SPHINXBUILD%% -b epub %%ALLSPHINXOPTS%% %%BUILDDIR%%/epub
\techo.
\techo.Build finished. The epub file is in %%BUILDDIR%%/epub.
\tgoto end
)
if "%%1" == "latex" (
\t%%SPHINXBUILD%% -b latex %%ALLSPHINXOPTS%% %%BUILDDIR%%/latex
\techo.

View File

@ -0,0 +1,7 @@
{% extends "basic/layout.html" %}
{# add only basic navigation links #}
{% block sidebar1 %}{% endblock %}
{% block sidebar2 %}{% endblock %}
{% block relbar2 %}{% endblock %}
{% block linktags %}{% endblock %}

View File

@ -0,0 +1,445 @@
/**
* Sphinx stylesheet -- epub theme
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
/* -- main layout ----------------------------------------------------------- */
div.clearer {
clear: both;
}
a:link, a:visited {
color: #3333ff;
text-decoration: underline;
}
img {
border: 0;
}
/* -- relbar ---------------------------------------------------------------- */
div.related {
width: 100%;
font-family: sans-serif;
font-size: 90%;
}
div.related h3 {
display: none;
}
div.related ul {
margin: 0;
padding: 0 0 0 10px;
list-style: none;
}
div.related li {
display: inline;
}
div.related li.right {
float: right;
margin-right: 5px;
}
/* -- sidebar --------------------------------------------------------------- */
div.sphinxsidebarwrapper {
padding: 10px 5px 0 10px;
}
div.sphinxsidebar {
float: left;
width: 230px;
margin-left: -100%;
font-size: 90%;
}
div.sphinxsidebar ul {
list-style: none;
}
div.sphinxsidebar ul ul,
div.sphinxsidebar ul.want-points {
margin-left: 20px;
list-style: square;
}
div.sphinxsidebar ul ul {
margin-top: 0;
margin-bottom: 0;
}
div.sphinxsidebar form {
margin-top: 10px;
}
div.sphinxsidebar input {
border: 1px solid #98dbcc;
font-family: sans-serif;
font-size: 100%;
}
img {
border: 0;
}
/* -- search page ----------------------------------------------------------- */
ul.search {
margin: 10px 0 0 20px;
padding: 0;
}
ul.search li {
padding: 5px 0 5px 20px;
background-image: url(file.png);
background-repeat: no-repeat;
background-position: 0 7px;
}
ul.search li a {
font-weight: bold;
}
ul.search li div.context {
color: #888;
margin: 2px 0 0 30px;
text-align: left;
}
ul.keywordmatches li.goodmatch a {
font-weight: bold;
}
/* -- index page ------------------------------------------------------------ */
table.contentstable {
width: 90%;
}
table.contentstable p.biglink {
line-height: 150%;
}
a.biglink {
font-size: 130%;
}
span.linkdescr {
font-style: italic;
padding-top: 5px;
font-size: 90%;
}
/* -- general index --------------------------------------------------------- */
table.indextable td {
text-align: left;
vertical-align: top;
}
table.indextable dl, table.indextable dd {
margin-top: 0;
margin-bottom: 0;
}
table.indextable tr.pcap {
height: 10px;
}
table.indextable tr.cap {
margin-top: 10px;
background-color: #f2f2f2;
}
img.toggler {
margin-right: 3px;
margin-top: 3px;
cursor: pointer;
}
/* -- general body styles --------------------------------------------------- */
a.headerlink {
visibility: hidden;
}
div.body p.caption {
text-align: inherit;
}
div.body td {
text-align: left;
}
.field-list ul {
padding-left: 100%;
}
.first {
margin-top: 0 !important;
}
p.rubric {
margin-top: 30px;
font-weight: bold;
}
/* -- sidebars -------------------------------------------------------------- */
div.sidebar {
margin: 0 0 0.5em 1em;
border: 1px solid #ddb;
padding: 7px 7px 0 7px;
background-color: #ffe;
width: 40%;
float: right;
}
p.sidebar-title {
font-weight: bold;
}
/* -- topics ---------------------------------------------------------------- */
div.topic {
border: 1px solid #ccc;
padding: 7px 7px 0 7px;
margin: 10px 0 10px 0;
}
p.topic-title {
font-size: 110%;
font-weight: bold;
margin-top: 10px;
}
/* -- admonitions ----------------------------------------------------------- */
div.admonition {
margin-top: 10px;
margin-bottom: 10px;
padding: 7px;
}
div.admonition dt {
font-weight: bold;
}
div.admonition dl {
margin-bottom: 0;
}
p.admonition-title {
margin: 0px 10px 5px 0px;
font-weight: bold;
}
div.body p.centered {
text-align: center;
margin-top: 25px;
}
/* -- tables ---------------------------------------------------------------- */
table.docutils {
border: 0;
border-collapse: collapse;
}
table.docutils td, table.docutils th {
padding: 1px 8px 1px 5px;
border-top: 0;
border-left: 0;
border-right: 0;
border-bottom: 1px solid #aaa;
}
table.field-list td, table.field-list th {
border: 0 !important;
}
table.footnote td, table.footnote th {
border: 0 !important;
}
th {
text-align: left;
padding-right: 5px;
}
/* -- other body styles ----------------------------------------------------- */
dl {
margin-bottom: 15px;
}
dd p {
margin-top: 0px;
}
dd ul, dd table {
margin-bottom: 10px;
}
dd {
margin-top: 3px;
margin-bottom: 10px;
margin-left: 30px;
}
dt:target, .highlight {
background-color: #ddd;
}
dl.glossary dt {
font-weight: bold;
font-size: 110%;
}
.field-list ul {
margin: 0;
padding-left: 1em;
}
.field-list p {
margin: 0;
}
.refcount {
color: #060;
}
.optional {
font-size: 130%;
}
.versionmodified {
font-style: italic;
}
.system-message {
background-color: #fda;
padding: 5px;
border: 3px solid red;
}
.footnote:target {
background-color: #dddddd;
}
/* -- code displays --------------------------------------------------------- */
pre {
font-family: "LiberationNarrow", monospace;
overflow: auto;
}
td.linenos pre {
padding: 5px 0px;
border: 0;
background-color: transparent;
color: #aaa;
}
table.highlighttable {
margin-left: 0.5em;
}
table.highlighttable td {
padding: 0 0.5em 0 0.5em;
}
tt {
font-family: "LiberationNarrow", monospace;
}
tt.descname {
background-color: transparent;
font-weight: bold;
font-size: 1.2em;
}
tt.descclassname {
background-color: transparent;
}
tt.xref, a tt {
background-color: transparent;
font-weight: bold;
}
h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
background-color: transparent;
}
/* -- math display ---------------------------------------------------------- */
img.math {
vertical-align: middle;
}
div.body div.math p {
text-align: center;
}
span.eqno {
float: right;
}
/* -- special divs --------------------------------------------------------- */
div.quotebar {
background-color: #e3eff1;
max-width: 250px;
float: right;
font-family: sans-serif;
padding: 7px 7px;
border: 1px solid #ccc;
}
div.footer {
background-color: #e3eff1;
padding: 3px 8px 3px 0;
clear: both;
font-family: sans-serif;
font-size: 80%;
text-align: right;
}
div.footer a {
text-decoration: underline;
}
@font-face {
font-family: "LiberationNarrow";
font-style: normal;
font-weight: normal;
src: url("res:///Data/fonts/LiberationNarrow-Regular.otf")
format("opentype");
}
@font-face {
font-family: "LiberationNarrow";
font-style: oblique, italic;
font-weight: normal;
src: url("res:///Data/fonts/LiberationNarrow-Italic.otf")
format("opentype");
}
@font-face {
font-family: "LiberationNarrow";
font-style: normal;
font-weight: bold;
src: url("res:///Data/fonts/LiberationNarrow-Bold.otf")
format("opentype");
}
@font-face {
font-family: "LiberationNarrow";
font-style: oblique, italic;
font-weight: bold;
src: url("res:///Data/fonts/LiberationNarrow-BoldItalic.otf")
format("opentype");
}

View File

@ -0,0 +1,4 @@
[theme]
inherit = basic
stylesheet = epub.css
pygments_style = none

View File

@ -1,7 +1,10 @@
{% extends "!layout.html" %}
{% block extrahead %}
{# html_context variable from conf.py #}
<meta name="hc" content="{{ hckey }}" />
{# html_context variable from confoverrides (as if given on cmdline) #}
<meta name="hc_co" content="{{ hckey_co }}" />
{{ super() }}
{% endblock %}

View File

@ -36,7 +36,7 @@ html_theme_options = {'testopt': 'testoverride'}
html_style = 'default.css'
html_static_path = ['_static']
html_last_updated_fmt = '%b %d, %Y'
html_context = {'hckey': 'hcval'}
html_context = {'hckey': 'hcval', 'hckey_co': 'wrong_hcval_co'}
htmlhelp_basename = 'SphinxTestsdoc'

View File

@ -227,6 +227,7 @@ Index markup
.. index::
single: entry
pair: entry; pair
double: entry; double
triple: index; entry; triple
keyword: with

View File

@ -124,6 +124,10 @@ def test_htmlhelp(app):
def test_qthelp(app):
app.builder.build_all()
@with_app(buildername='epub')
def test_epub(app):
app.builder.build_all()
@with_app(buildername='changes', cleanenv=True)
def test_changes(app):
app.builder.build_all()

View File

@ -152,6 +152,7 @@ HTML_XPATH = {
},
'contents.html': {
".//meta[@name='hc'][@content='hcval']": '',
".//meta[@name='hc_co'][@content='hcval_co']": '',
".//meta[@name='testopt'][@content='testoverride']": '',
#".//td[@class='label']": r'\[Ref1\]', # docutils 0.5 only
".//td[@class='label']": '',
@ -228,6 +229,7 @@ def check_xpath(etree, fname, path, check):
[node.text for node in nodes]))
@gen_with_app(buildername='html', warning=html_warnfile, cleanenv=True,
confoverrides={'html_context.hckey_co': 'hcval_co'},
tags=['testtag'])
def test_html(app):
app.builder.build_all()

View File

@ -25,7 +25,7 @@ def test_theme_api(app):
# test Theme class API
assert set(Theme.themes.keys()) == \
set(['basic', 'default', 'scrolls', 'agogo', 'sphinxdoc',
'traditional', 'testtheme', 'ziptheme'])
'traditional', 'testtheme', 'ziptheme', 'epub'])
assert Theme.themes['testtheme'][1] is None
assert isinstance(Theme.themes['ziptheme'][1], zipfile.ZipFile)