mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
#309: The `graphviz
` extension can now output SVG instead of PNG
images, controlled by the ``graphviz_output_format`` config value. Patch by Henrique Bastos.
This commit is contained in:
parent
82fa1f3cfe
commit
d32bd22ae7
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
|
||||||
|
3
CHANGES
3
CHANGES
@ -3,6 +3,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.
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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,44 @@ 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):
|
||||||
|
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 +176,28 @@ 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 format == 'svg':
|
||||||
try:
|
svgtag = get_svg_tag(fname, outfn, imgcls)
|
||||||
imgmap = mapfile.readlines()
|
self.body.append(svgtag)
|
||||||
finally:
|
|
||||||
mapfile.close()
|
|
||||||
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, self.encode(code).strip(), 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, self.encode(code).strip(),
|
||||||
|
mapname, imgcss))
|
||||||
|
self.body.extend(imgmap)
|
||||||
|
|
||||||
self.body.append('</p>\n')
|
self.body.append('</p>\n')
|
||||||
raise nodes.SkipNode
|
raise nodes.SkipNode
|
||||||
|
|
||||||
@ -188,3 +230,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')
|
||||||
|
Loading…
Reference in New Issue
Block a user