mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
merge with trunk
This commit is contained in:
commit
a43738e47a
1
AUTHORS
1
AUTHORS
@ -5,6 +5,7 @@ Substantial parts of the templates were written by Armin Ronacher
|
|||||||
|
|
||||||
Other contributors, listed alphabetically, are:
|
Other contributors, listed alphabetically, are:
|
||||||
|
|
||||||
|
* Henrique Bastos -- SVG support for graphviz extension
|
||||||
* Daniel Bültmann -- todo extension
|
* Daniel Bültmann -- todo extension
|
||||||
* Michael Droettboom -- inheritance_diagram extension
|
* Michael Droettboom -- inheritance_diagram extension
|
||||||
* Charles Duffy -- original graphviz extension
|
* Charles Duffy -- original graphviz extension
|
||||||
|
7
CHANGES
7
CHANGES
@ -9,6 +9,9 @@ Release 1.0 (in development)
|
|||||||
|
|
||||||
* Added Epub builder.
|
* Added Epub builder.
|
||||||
|
|
||||||
|
* #309: The ``graphviz`` extension can now output SVG instead of PNG
|
||||||
|
images, controlled by the ``graphviz_output_format`` config value.
|
||||||
|
|
||||||
* #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.
|
||||||
|
|
||||||
@ -60,6 +63,10 @@ Release 1.0 (in development)
|
|||||||
Release 0.6.4 (in development)
|
Release 0.6.4 (in development)
|
||||||
==============================
|
==============================
|
||||||
|
|
||||||
|
* The ``alt`` text of inheritance diagrams is now much cleaner.
|
||||||
|
|
||||||
|
* Ignore images in section titles when generating link captions.
|
||||||
|
|
||||||
* #310: support exception messages in the ``testoutput`` blocks of
|
* #310: support exception messages in the ``testoutput`` blocks of
|
||||||
the ``doctest`` extension.
|
the ``doctest`` extension.
|
||||||
|
|
||||||
|
2
Makefile
2
Makefile
@ -8,7 +8,7 @@ all: clean-pyc check test
|
|||||||
|
|
||||||
check:
|
check:
|
||||||
@$(PYTHON) utils/check_sources.py -i build -i dist -i sphinx/style/jquery.js \
|
@$(PYTHON) utils/check_sources.py -i build -i dist -i sphinx/style/jquery.js \
|
||||||
-i sphinx/pycode/pgen2 -i sphinx/util/smartypants.py \
|
-i sphinx/pycode/pgen2 -i sphinx/util/smartypants.py -i .ropeproject \
|
||||||
-i doc/_build -i ez_setup.py -i tests/path.py -i tests/coverage.py -i env .
|
-i doc/_build -i ez_setup.py -i tests/path.py -i tests/coverage.py -i env .
|
||||||
|
|
||||||
clean: clean-pyc clean-patchfiles
|
clean: clean-pyc clean-patchfiles
|
||||||
|
@ -47,3 +47,8 @@ The extension adds one new config value:
|
|||||||
You can also use the usual "explicit title" syntax supported by other roles
|
You can also use the usual "explicit title" syntax supported by other roles
|
||||||
that generate links, i.e. ``:issue:`this issue <123>```. In this case, the
|
that generate links, i.e. ``:issue:`this issue <123>```. In this case, the
|
||||||
*prefix* is not relevant.
|
*prefix* is not relevant.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
Since links are generated from the role in the reading stage, they appear as
|
||||||
|
ordinary links to e.g. the ``linkcheck`` builder.
|
||||||
|
@ -25,8 +25,9 @@ It adds these directives:
|
|||||||
"bar" -> "baz";
|
"bar" -> "baz";
|
||||||
}
|
}
|
||||||
|
|
||||||
In HTML output, the code will be rendered to a PNG image. In LaTeX output,
|
In HTML output, the code will be rendered to a PNG or SVG image (see
|
||||||
the code will be rendered to an embeddable PDF file.
|
:confval:`graphviz_output_format`). In LaTeX output, the code will be
|
||||||
|
rendered to an embeddable PDF file.
|
||||||
|
|
||||||
|
|
||||||
.. directive:: graph
|
.. directive:: graph
|
||||||
@ -75,3 +76,11 @@ There are also these new config values:
|
|||||||
Additional command-line arguments to give to dot, as a list. The default is
|
Additional command-line arguments to give to dot, as a list. The default is
|
||||||
an empty list. This is the right place to set global graph, node or edge
|
an empty list. This is the right place to set global graph, node or edge
|
||||||
attributes via dot's ``-G``, ``-N`` and ``-E`` options.
|
attributes via dot's ``-G``, ``-N`` and ``-E`` options.
|
||||||
|
|
||||||
|
.. confval:: graphviz_output_format
|
||||||
|
|
||||||
|
The output format for Graphviz when building HTML files. This must be either
|
||||||
|
``'png'`` or ``'svg'``; the default is ``'png'``.
|
||||||
|
|
||||||
|
.. versionadded:: 1.0
|
||||||
|
Previously, output always was PNG.
|
||||||
|
@ -128,7 +128,7 @@ These themes are:
|
|||||||
on the right side. There are currently no options beyond *nosidebar*.
|
on the right side. There are currently no options beyond *nosidebar*.
|
||||||
|
|
||||||
* **scrolls** -- A more lightweight theme, based on `the Jinja documentation
|
* **scrolls** -- A more lightweight theme, based on `the Jinja documentation
|
||||||
<http://jinja.pocoo.org/documentation/2>`_. The following color options are
|
<http://jinja.pocoo.org/2/documentation/>`_. The following color options are
|
||||||
available:
|
available:
|
||||||
|
|
||||||
- **headerbordercolor**
|
- **headerbordercolor**
|
||||||
|
@ -443,6 +443,10 @@ class StandaloneHTMLBuilder(Builder):
|
|||||||
else:
|
else:
|
||||||
stripped = ''
|
stripped = ''
|
||||||
|
|
||||||
|
# we stripped the whole module name
|
||||||
|
if not mn:
|
||||||
|
continue
|
||||||
|
|
||||||
if fl != mn[0].lower() and mn[0] != '_':
|
if fl != mn[0].lower() and mn[0] != '_':
|
||||||
# heading
|
# heading
|
||||||
letter = mn[0].upper()
|
letter = mn[0].upper()
|
||||||
|
@ -70,6 +70,8 @@ class CheckExternalLinksBuilder(Builder):
|
|||||||
lineno = node.line
|
lineno = node.line
|
||||||
|
|
||||||
if uri[0:5] == 'http:' or uri[0:6] == 'https:':
|
if uri[0:5] == 'http:' or uri[0:6] == 'https:':
|
||||||
|
if lineno:
|
||||||
|
self.info('(line %3d) ' % lineno, nonl=1)
|
||||||
self.info(uri, nonl=1)
|
self.info(uri, nonl=1)
|
||||||
|
|
||||||
if uri in self.broken:
|
if uri in self.broken:
|
||||||
|
@ -35,7 +35,7 @@ from docutils.transforms.parts import ContentsFilter
|
|||||||
|
|
||||||
from sphinx import addnodes
|
from sphinx import addnodes
|
||||||
from sphinx.util import movefile, get_matching_docs, SEP, ustrftime, \
|
from sphinx.util import movefile, get_matching_docs, SEP, ustrftime, \
|
||||||
docname_join, FilenameUniqDict, url_re, make_refnode
|
docname_join, FilenameUniqDict, url_re, make_refnode, clean_astext
|
||||||
from sphinx.errors import SphinxError, ExtensionError
|
from sphinx.errors import SphinxError, ExtensionError
|
||||||
|
|
||||||
|
|
||||||
@ -898,11 +898,11 @@ class BuildEnvironment:
|
|||||||
node.line)
|
node.line)
|
||||||
self.anonlabels[name] = docname, labelid
|
self.anonlabels[name] = docname, labelid
|
||||||
if node.tagname == 'section':
|
if node.tagname == 'section':
|
||||||
sectname = node[0].astext() # node[0] == title node
|
sectname = clean_astext(node[0]) # node[0] == title node
|
||||||
elif node.tagname == 'figure':
|
elif node.tagname == 'figure':
|
||||||
for n in node:
|
for n in node:
|
||||||
if n.tagname == 'caption':
|
if n.tagname == 'caption':
|
||||||
sectname = n.astext()
|
sectname = clean_astext(n)
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
@ -1130,7 +1130,7 @@ class BuildEnvironment:
|
|||||||
# toctree originates
|
# toctree originates
|
||||||
ref = toctreenode['parent']
|
ref = toctreenode['parent']
|
||||||
if not title:
|
if not title:
|
||||||
title = self.titles[ref].astext()
|
title = clean_astext(self.titles[ref])
|
||||||
reference = nodes.reference('', '',
|
reference = nodes.reference('', '',
|
||||||
refuri=ref,
|
refuri=ref,
|
||||||
anchorname='',
|
anchorname='',
|
||||||
@ -1281,7 +1281,7 @@ class BuildEnvironment:
|
|||||||
# reference with explicit title
|
# reference with explicit title
|
||||||
caption = node.astext()
|
caption = node.astext()
|
||||||
else:
|
else:
|
||||||
caption = self.titles[docname].astext()
|
caption = clean_astext(self.titles[docname])
|
||||||
innernode = nodes.emphasis(caption, caption)
|
innernode = nodes.emphasis(caption, caption)
|
||||||
newnode = nodes.reference('', '')
|
newnode = nodes.reference('', '')
|
||||||
newnode['refuri'] = builder.get_relative_uri(
|
newnode['refuri'] = builder.get_relative_uri(
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
import re
|
import re
|
||||||
import posixpath
|
import posixpath
|
||||||
from os import path
|
from os import path
|
||||||
|
from math import ceil
|
||||||
from subprocess import Popen, PIPE
|
from subprocess import Popen, PIPE
|
||||||
try:
|
try:
|
||||||
from hashlib import sha1 as sha
|
from hashlib import sha1 as sha
|
||||||
@ -27,6 +28,7 @@ from sphinx.util.compat import Directive
|
|||||||
|
|
||||||
|
|
||||||
mapname_re = re.compile(r'<map id="(.*?)"')
|
mapname_re = re.compile(r'<map id="(.*?)"')
|
||||||
|
svg_dim_re = re.compile(r'<svg\swidth="(\d+)pt"\sheight="(\d+)pt"', re.M)
|
||||||
|
|
||||||
|
|
||||||
class GraphvizError(SphinxError):
|
class GraphvizError(SphinxError):
|
||||||
@ -128,9 +130,45 @@ def render_dot(self, code, options, format, prefix='graphviz'):
|
|||||||
return relfn, outfn
|
return relfn, outfn
|
||||||
|
|
||||||
|
|
||||||
def render_dot_html(self, node, code, options, prefix='graphviz', imgcls=None):
|
def get_svg_tag(svgref, svgfile, imgcls=None):
|
||||||
|
# Webkit can't figure out svg dimensions when using object tag
|
||||||
|
# so we need to get it from the svg file
|
||||||
|
fp = open(svgfile, 'r')
|
||||||
try:
|
try:
|
||||||
fname, outfn = render_dot(self, code, options, 'png', prefix)
|
for line in fp:
|
||||||
|
match = svg_dim_re.match(line)
|
||||||
|
if match:
|
||||||
|
dimensions = match.groups()
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
dimensions = None
|
||||||
|
finally:
|
||||||
|
fp.close()
|
||||||
|
|
||||||
|
# We need this hack to make WebKit show our object tag properly
|
||||||
|
def pt2px(x):
|
||||||
|
return int(ceil((96.0/72.0) * float(x)))
|
||||||
|
|
||||||
|
if dimensions:
|
||||||
|
style = ' width="%s" height="%s"' % tuple(map(pt2px, dimensions))
|
||||||
|
else:
|
||||||
|
style = ''
|
||||||
|
|
||||||
|
# The object tag works fine on Firefox and WebKit
|
||||||
|
# Besides it's a hack, this strategy does not mess with templates.
|
||||||
|
imgcss = imgcls and ' class="%s"' % imgcls or ''
|
||||||
|
return '<object type="image/svg+xml" data="%s"%s%s/>\n' % \
|
||||||
|
(svgref, imgcss, style)
|
||||||
|
|
||||||
|
|
||||||
|
def render_dot_html(self, node, code, options, prefix='graphviz',
|
||||||
|
imgcls=None, alt=None):
|
||||||
|
format = self.builder.config.graphviz_output_format
|
||||||
|
try:
|
||||||
|
if format not in ('png', 'svg'):
|
||||||
|
raise GraphvizError("graphviz_output_format must be one of 'png', "
|
||||||
|
"'svg', but is %r" % format)
|
||||||
|
fname, outfn = render_dot(self, code, options, format, prefix)
|
||||||
except GraphvizError, exc:
|
except GraphvizError, exc:
|
||||||
self.builder.warn('dot code %r: ' % code + str(exc))
|
self.builder.warn('dot code %r: ' % code + str(exc))
|
||||||
raise nodes.SkipNode
|
raise nodes.SkipNode
|
||||||
@ -139,23 +177,29 @@ def render_dot_html(self, node, code, options, prefix='graphviz', imgcls=None):
|
|||||||
if fname is None:
|
if fname is None:
|
||||||
self.body.append(self.encode(code))
|
self.body.append(self.encode(code))
|
||||||
else:
|
else:
|
||||||
mapfile = open(outfn + '.map', 'rb')
|
if alt is None:
|
||||||
try:
|
alt = self.encode(code).strip()
|
||||||
imgmap = mapfile.readlines()
|
if format == 'svg':
|
||||||
finally:
|
svgtag = get_svg_tag(fname, outfn, imgcls)
|
||||||
mapfile.close()
|
self.body.append(svgtag)
|
||||||
imgcss = imgcls and 'class="%s"' % imgcls or ''
|
|
||||||
if len(imgmap) == 2:
|
|
||||||
# nothing in image map (the lines are <map> and </map>)
|
|
||||||
self.body.append('<img src="%s" alt="%s" %s/>\n' %
|
|
||||||
(fname, self.encode(code).strip(), imgcss))
|
|
||||||
else:
|
else:
|
||||||
# has a map: get the name of the map and connect the parts
|
mapfile = open(outfn + '.map', 'rb')
|
||||||
mapname = mapname_re.match(imgmap[0]).group(1)
|
try:
|
||||||
self.body.append('<img src="%s" alt="%s" usemap="#%s" %s/>\n' %
|
imgmap = mapfile.readlines()
|
||||||
(fname, self.encode(code).strip(),
|
finally:
|
||||||
mapname, imgcss))
|
mapfile.close()
|
||||||
self.body.extend(imgmap)
|
imgcss = imgcls and 'class="%s"' % imgcls or ''
|
||||||
|
if len(imgmap) == 2:
|
||||||
|
# nothing in image map (the lines are <map> and </map>)
|
||||||
|
self.body.append('<img src="%s" alt="%s" %s/>\n' %
|
||||||
|
(fname, alt, imgcss))
|
||||||
|
else:
|
||||||
|
# has a map: get the name of the map and connect the parts
|
||||||
|
mapname = mapname_re.match(imgmap[0]).group(1)
|
||||||
|
self.body.append('<img src="%s" alt="%s" usemap="#%s" %s/>\n' %
|
||||||
|
(fname, alt, mapname, imgcss))
|
||||||
|
self.body.extend(imgmap)
|
||||||
|
|
||||||
self.body.append('</p>\n')
|
self.body.append('</p>\n')
|
||||||
raise nodes.SkipNode
|
raise nodes.SkipNode
|
||||||
|
|
||||||
@ -188,3 +232,4 @@ def setup(app):
|
|||||||
app.add_directive('digraph', GraphvizSimple)
|
app.add_directive('digraph', GraphvizSimple)
|
||||||
app.add_config_value('graphviz_dot', 'dot', 'html')
|
app.add_config_value('graphviz_dot', 'dot', 'html')
|
||||||
app.add_config_value('graphviz_dot_args', [], 'html')
|
app.add_config_value('graphviz_dot_args', [], 'html')
|
||||||
|
app.add_config_value('graphviz_output_format', 'png', 'html')
|
||||||
|
@ -302,7 +302,7 @@ class InheritanceDiagram(Directive):
|
|||||||
node['graph'] = graph
|
node['graph'] = graph
|
||||||
# Store the original content for use as a hash
|
# Store the original content for use as a hash
|
||||||
node['parts'] = self.options.get('parts', 0)
|
node['parts'] = self.options.get('parts', 0)
|
||||||
node['content'] = ' '.join(class_names)
|
node['content'] = ', '.join(class_names)
|
||||||
return [node]
|
return [node]
|
||||||
|
|
||||||
|
|
||||||
@ -330,7 +330,8 @@ def html_visit_inheritance_diagram(self, node):
|
|||||||
urls[child['reftitle']] = '#' + child.get('refid')
|
urls[child['reftitle']] = '#' + child.get('refid')
|
||||||
|
|
||||||
dotcode = graph.generate_dot(name, parts, urls, env=self.builder.env)
|
dotcode = graph.generate_dot(name, parts, urls, env=self.builder.env)
|
||||||
render_dot_html(self, node, dotcode, [], 'inheritance', 'inheritance')
|
render_dot_html(self, node, dotcode, [], 'inheritance', 'inheritance',
|
||||||
|
alt='Inheritance diagram of ' + node['content'])
|
||||||
raise nodes.SkipNode
|
raise nodes.SkipNode
|
||||||
|
|
||||||
|
|
||||||
|
@ -250,3 +250,11 @@ tt {
|
|||||||
th {
|
th {
|
||||||
background-color: #ede;
|
background-color: #ede;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.warning tt {
|
||||||
|
background: #efc2c2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.note tt {
|
||||||
|
background: #d6d6d6;
|
||||||
|
}
|
||||||
|
@ -445,6 +445,13 @@ def copy_static_entry(source, target, builder, context={}):
|
|||||||
shutil.copytree(source, target)
|
shutil.copytree(source, target)
|
||||||
|
|
||||||
|
|
||||||
|
def clean_astext(node):
|
||||||
|
"""Like node.astext(), but ignore images."""
|
||||||
|
node = node.deepcopy()
|
||||||
|
for img in node.traverse(docutils.nodes.image):
|
||||||
|
img['alt'] = ''
|
||||||
|
return node.astext()
|
||||||
|
|
||||||
|
|
||||||
def split_explicit_title(text):
|
def split_explicit_title(text):
|
||||||
"""Split role content into title and target, if given."""
|
"""Split role content into title and target, if given."""
|
||||||
|
@ -30,7 +30,7 @@ def checker(*suffixes, **kwds):
|
|||||||
|
|
||||||
|
|
||||||
name_mail_re = r'[\w ]+(<.*?>)?'
|
name_mail_re = r'[\w ]+(<.*?>)?'
|
||||||
copyright_re = re.compile(r'^ :copyright: Copyright 200\d(-200\d)? '
|
copyright_re = re.compile(r'^ :copyright: Copyright 200\d(-20\d\d)? '
|
||||||
r'by %s(, %s)*[,.]$' %
|
r'by %s(, %s)*[,.]$' %
|
||||||
(name_mail_re, name_mail_re))
|
(name_mail_re, name_mail_re))
|
||||||
license_re = re.compile(r" :license: (.*?).\n")
|
license_re = re.compile(r" :license: (.*?).\n")
|
||||||
|
Loading…
Reference in New Issue
Block a user