merge with trunk

This commit is contained in:
Georg Brandl 2010-01-07 19:19:58 +01:00
commit 5e17487b74
14 changed files with 275 additions and 21 deletions

10
CHANGES
View File

@ -23,13 +23,15 @@ Release 1.0 (in development)
* #284: All docinfo metadata is now put into the document metadata, not * #284: All docinfo metadata is now put into the document metadata, not
just the author. just the author.
* Added new HTML theme ``nature``.
* Added new HTML theme ``agogo``, created by Andi Albrecht. * Added new HTML theme ``agogo``, created by Andi Albrecht.
* Added new HTML theme called scrolls, created by Armin Ronacher.
* The ``toctree()`` callable in templates now has a ``maxdepth`` * The ``toctree()`` callable in templates now has a ``maxdepth``
keyword argument to control the depth of the generated tree. keyword argument to control the depth of the generated tree.
* Added new minimal theme called scrolls, created by Armin Ronacher.
* Added Catalan translation, thanks to Pau Fernández. * Added Catalan translation, thanks to Pau Fernández.
* Added ``html_output_encoding`` config value. * Added ``html_output_encoding`` config value.
@ -71,6 +73,10 @@ Release 1.0 (in development)
Release 0.6.4 (in development) Release 0.6.4 (in development)
============================== ==============================
* Restore compatibility with Pygments >= 1.2.
* #295: Fix escaping of hyperref targets in LaTeX output.
* #302: Fix links generated by the ``:doc:`` role for LaTeX output. * #302: Fix links generated by the ``:doc:`` role for LaTeX output.
* #286: collect todo nodes after the whole document has been read; * #286: collect todo nodes after the whole document has been read;

View File

@ -133,8 +133,8 @@ tables of contents. The ``toctree`` directive is the central element.
In the end, all documents in the :term:`source directory` (or subdirectories) In the end, all documents in the :term:`source directory` (or subdirectories)
must occur in some ``toctree`` directive; Sphinx will emit a warning if it must occur in some ``toctree`` directive; Sphinx will emit a warning if it
finds a file that is not included, because that means that this file will not finds a file that is not included, because that means that this file will not
be reachable through standard navigation. Use :confval:`unused_documents` to be reachable through standard navigation. Use :confval:`unused_docs` to
explicitly exclude documents from building, and :confval:`exclude_dirs` to explicitly exclude documents from building, and :confval:`exclude_trees` to
exclude whole directories. exclude whole directories.
The "master document" (selected by :confval:`master_doc`) is the "root" of The "master document" (selected by :confval:`master_doc`) is the "root" of

View File

@ -56,9 +56,11 @@ the following public API:
given as keyword arguments: the keyword must be one or more of ``'html'``, given as keyword arguments: the keyword must be one or more of ``'html'``,
``'latex'``, ``'text'``, the value a 2-tuple of ``(visit, depart)`` methods. ``'latex'``, ``'text'``, the value a 2-tuple of ``(visit, depart)`` methods.
``depart`` can be ``None`` if the ``visit`` function raises ``depart`` can be ``None`` if the ``visit`` function raises
:exc:`docutils.nodes.SkipNode`. Example:: :exc:`docutils.nodes.SkipNode`. Example:
class math(docutils.nodes.Element) .. code-block:: python
class math(docutils.nodes.Element): pass
def visit_math_html(self, node): def visit_math_html(self, node):
self.body.append(self.starttag(node, 'math')) self.body.append(self.starttag(node, 'math'))
@ -98,7 +100,9 @@ the following public API:
support directive classes otherwise). support directive classes otherwise).
For example, the (already existing) :dir:`literalinclude` directive would be For example, the (already existing) :dir:`literalinclude` directive would be
added like this:: added like this:
.. code-block:: python
from docutils.parsers.rst import directives from docutils.parsers.rst import directives
add_directive('literalinclude', literalinclude_directive, add_directive('literalinclude', literalinclude_directive,

BIN
doc/themes/fullsize/nature.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
doc/themes/nature.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@ -65,9 +65,9 @@ Builtin themes
| | | | | |
| *scrolls* | *agogo* | | *scrolls* | *agogo* |
+--------------------+--------------------+ +--------------------+--------------------+
| |traditional| | | | |traditional| | |nature| |
| | | | | |
| *traditional* | | | *traditional* | *nature* |
+--------------------+--------------------+ +--------------------+--------------------+
.. |default| image:: themes/default.png .. |default| image:: themes/default.png
@ -75,6 +75,7 @@ Builtin themes
.. |scrolls| image:: themes/scrolls.png .. |scrolls| image:: themes/scrolls.png
.. |agogo| image:: themes/agogo.png .. |agogo| image:: themes/agogo.png
.. |traditional| image:: themes/traditional.png .. |traditional| image:: themes/traditional.png
.. |nature| image:: themes/nature.png
Sphinx comes with a selection of themes to choose from. Sphinx comes with a selection of themes to choose from.
@ -157,6 +158,9 @@ These themes are:
- **headerlinkcolor** (CSS color): Color for the backreference link in - **headerlinkcolor** (CSS color): Color for the backreference link in
headings. headings.
* **nature** -- A greenish theme. There are currently no options beyond
*nosidebar*.
* **traditional** -- A theme resembling the old Python documentation. There are * **traditional** -- A theme resembling the old Python documentation. There are
currently no options beyond *nosidebar*. currently no options beyond *nosidebar*.

View File

@ -1300,7 +1300,8 @@ class BuildEnvironment:
# keywords are oddballs: they are referenced by named labels # keywords are oddballs: they are referenced by named labels
docname, labelid, _ = self.labels.get(target, ('','','')) docname, labelid, _ = self.labels.get(target, ('','',''))
if not docname: if not docname:
#self.warn(node['refdoc'], 'unknown keyword: %s' % target) #self.warn(node['refdoc'],
# 'unknown keyword: %s' % target)
newnode = None newnode = None
else: else:
newnode = make_refnode(builder, fromdocname, docname, newnode = make_refnode(builder, fromdocname, docname,

View File

@ -20,7 +20,7 @@ except ImportError:
# parser is not available on Jython # parser is not available on Jython
parser = None parser = None
from sphinx.util.texescape import tex_hl_escape_map from sphinx.util.texescape import tex_hl_escape_map_old, tex_hl_escape_map_new
try: try:
import pygments import pygments
@ -130,7 +130,7 @@ class PygmentsBridge(object):
# first, escape highlighting characters like Pygments does # first, escape highlighting characters like Pygments does
source = source.translate(escape_hl_chars) source = source.translate(escape_hl_chars)
# then, escape all characters nonrepresentable in LaTeX # then, escape all characters nonrepresentable in LaTeX
source = source.translate(tex_hl_escape_map) source = source.translate(tex_hl_escape_map_old)
return '\\begin{Verbatim}[commandchars=@\\[\\]]\n' + \ return '\\begin{Verbatim}[commandchars=@\\[\\]]\n' + \
source + '\\end{Verbatim}\n' source + '\\end{Verbatim}\n'
@ -215,7 +215,10 @@ class PygmentsBridge(object):
return highlight(source, lexer, self.fmter[bool(linenos)]) return highlight(source, lexer, self.fmter[bool(linenos)])
else: else:
hlsource = highlight(source, lexer, self.fmter[bool(linenos)]) hlsource = highlight(source, lexer, self.fmter[bool(linenos)])
return hlsource.translate(tex_hl_escape_map) if hlsource.startswith(r'\begin{Verbatim}[commandchars=\\\{\}'):
# Pygments >= 1.2
return hlsource.translate(tex_hl_escape_map_new)
return hlsource.translate(tex_hl_escape_map_old)
except ErrorToken: except ErrorToken:
# this is most probably not the selected language, # this is most probably not the selected language,
# so let it pass unhighlighted # so let it pass unhighlighted

View File

@ -0,0 +1,229 @@
/**
* Sphinx stylesheet -- nature theme
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
@import url("basic.css");
/* -- page layout ----------------------------------------------------------- */
body {
font-family: Arial, sans-serif;
font-size: 100%;
background-color: #111;
color: #555;
margin: 0;
padding: 0;
}
div.documentwrapper {
float: left;
width: 100%;
}
div.bodywrapper {
margin: 0 0 0 230px;
}
hr {
border: 1px solid #B1B4B6;
}
div.document {
background-color: #eee;
}
div.body {
background-color: #ffffff;
color: #3E4349;
padding: 0 30px 30px 30px;
font-size: 0.9em;
}
div.footer {
color: #555;
width: 100%;
padding: 13px 0;
text-align: center;
font-size: 75%;
}
div.footer a {
color: #444;
text-decoration: underline;
}
div.related {
background-color: #6BA81E;
line-height: 32px;
color: #fff;
text-shadow: 0px 1px 0 #444;
font-size: 0.9em;
}
div.related a {
color: #E2F3CC;
}
div.sphinxsidebar {
font-size: 0.75em;
line-height: 1.5em;
}
div.sphinxsidebarwrapper{
padding: 20px 0;
}
div.sphinxsidebar h3,
div.sphinxsidebar h4 {
font-family: Arial, sans-serif;
color: #222;
font-size: 1.2em;
font-weight: normal;
margin: 0;
padding: 5px 10px;
background-color: #ddd;
text-shadow: 1px 1px 0 white
}
div.sphinxsidebar h4{
font-size: 1.1em;
}
div.sphinxsidebar h3 a {
color: #444;
}
div.sphinxsidebar p {
color: #888;
padding: 5px 20px;
}
div.sphinxsidebar p.topless {
}
div.sphinxsidebar ul {
margin: 10px 20px;
padding: 0;
color: #000;
}
div.sphinxsidebar a {
color: #444;
}
div.sphinxsidebar input {
border: 1px solid #ccc;
font-family: sans-serif;
font-size: 1em;
}
div.sphinxsidebar input[type=text]{
margin-left: 20px;
}
/* -- body styles ----------------------------------------------------------- */
a {
color: #005B81;
text-decoration: none;
}
a:hover {
color: #E32E00;
text-decoration: underline;
}
div.body h1,
div.body h2,
div.body h3,
div.body h4,
div.body h5,
div.body h6 {
font-family: Arial, sans-serif;
background-color: #BED4EB;
font-weight: normal;
color: #212224;
margin: 30px 0px 10px 0px;
padding: 5px 0 5px 10px;
text-shadow: 0px 1px 0 white
}
div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; }
div.body h2 { font-size: 150%; background-color: #C8D5E3; }
div.body h3 { font-size: 120%; background-color: #D8DEE3; }
div.body h4 { font-size: 110%; background-color: #D8DEE3; }
div.body h5 { font-size: 100%; background-color: #D8DEE3; }
div.body h6 { font-size: 100%; background-color: #D8DEE3; }
a.headerlink {
color: #c60f0f;
font-size: 0.8em;
padding: 0 4px 0 4px;
text-decoration: none;
}
a.headerlink:hover {
background-color: #c60f0f;
color: white;
}
div.body p, div.body dd, div.body li {
line-height: 1.5em;
}
div.admonition p.admonition-title + p {
display: inline;
}
div.highlight{
background-color: white;
}
div.note {
background-color: #eee;
border: 1px solid #ccc;
}
div.seealso {
background-color: #ffc;
border: 1px solid #ff6;
}
div.topic {
background-color: #eee;
}
div.warning {
background-color: #ffe4e4;
border: 1px solid #f66;
}
p.admonition-title {
display: inline;
}
p.admonition-title:after {
content: ":";
}
pre {
padding: 10px;
background-color: White;
color: #222;
line-height: 1.2em;
border: 1px solid #C6C9CB;
font-size: 1.1em;
margin: 1.5em 0 1.5em 0;
-webkit-box-shadow: 1px 1px 1px #d8d8d8;
-moz-box-shadow: 1px 1px 1px #d8d8d8;
}
tt {
background-color: #ecf0f3;
color: #222;
/* padding: 1px 2px; */
font-size: 1.1em;
font-family: monospace;
}

View File

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

View File

@ -280,7 +280,6 @@ def patfilter(names, pat):
Return the subset of the list NAMES that match PAT. Return the subset of the list NAMES that match PAT.
Adapted from fnmatch module. Adapted from fnmatch module.
""" """
result = []
if pat not in _pat_cache: if pat not in _pat_cache:
_pat_cache[pat] = re.compile(_translate_pattern(pat)) _pat_cache[pat] = re.compile(_translate_pattern(pat))
match = _pat_cache[pat].match match = _pat_cache[pat].match
@ -411,7 +410,6 @@ def movefile(source, dest):
def copytimes(source, dest): def copytimes(source, dest):
"""Copy a file's modification times.""" """Copy a file's modification times."""
st = os.stat(source) st = os.stat(source)
mode = stat.S_IMODE(st.st_mode)
if hasattr(os, 'utime'): if hasattr(os, 'utime'):
os.utime(dest, (st.st_atime, st.st_mtime)) os.utime(dest, (st.st_atime, st.st_mtime))

View File

@ -99,8 +99,9 @@ tex_replacements = [
] ]
tex_escape_map = {} tex_escape_map = {}
tex_hl_escape_map = {} tex_hl_escape_map_old = {} # replacement map for Pygments <= 1.1
_new_cmd_chars = {ord(u'\\'): u'@', ord(u'{'): u'[', ord(u'}'): u']'} tex_hl_escape_map_new = {} # replacement map for Pygments >= 1.2
_old_cmd_chars = {ord(u'\\'): u'@', ord(u'{'): u'[', ord(u'}'): u']'}
def init(): def init():
for a, b in tex_replacements: for a, b in tex_replacements:
@ -108,4 +109,5 @@ def init():
for a, b in tex_replacements: for a, b in tex_replacements:
if a in u'[]{}\\': continue if a in u'[]{}\\': continue
tex_hl_escape_map[ord(a)] = b.translate(_new_cmd_chars) tex_hl_escape_map_new[ord(a)] = b
tex_hl_escape_map_old[ord(a)] = b.translate(_old_cmd_chars)

View File

@ -253,6 +253,9 @@ class LaTeXTranslator(nodes.NodeVisitor):
return (HEADER % self.elements + self.highlighter.get_stylesheet() + return (HEADER % self.elements + self.highlighter.get_stylesheet() +
u''.join(self.body) + FOOTER % self.elements) u''.join(self.body) + FOOTER % self.elements)
def idescape(self, id):
return str(unicode(id).translate(tex_escape_map))
def visit_document(self, node): def visit_document(self, node):
self.footnotestack.append(self.collect_footnotes(node)) self.footnotestack.append(self.collect_footnotes(node))
self.curfilestack.append(node.get('docname', '')) self.curfilestack.append(node.get('docname', ''))
@ -467,7 +470,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
d = self.descstack[-1] d = self.descstack[-1]
d.cls = d.cls.rstrip('.') d.cls = d.cls.rstrip('.')
if node.parent['objtype'] != 'describe' and node['ids']: if node.parent['objtype'] != 'describe' and node['ids']:
hyper = '\\hypertarget{%s}{}' % node['ids'][0] hyper = '\\hypertarget{%s}{}' % self.idescape(node['ids'][0])
else: else:
hyper = '' hyper = ''
if d.count == 0: if d.count == 0:
@ -758,7 +761,7 @@ class LaTeXTranslator(nodes.NodeVisitor):
def visit_term(self, node): def visit_term(self, node):
ctx = '] \\leavevmode' ctx = '] \\leavevmode'
if node.has_key('ids') and node['ids']: if node.has_key('ids') and node['ids']:
ctx += '\\hypertarget{%s}{}' % node['ids'][0] ctx += '\\hypertarget{%s}{}' % self.idescape(node['ids'][0])
self.body.append('\\item[') self.body.append('\\item[')
self.context.append(ctx) self.context.append(ctx)
def depart_term(self, node): def depart_term(self, node):

View File

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