Wrap graphviz diagrams in <div class="graphviz">

The graphviz extension is modified to wrap the `<img>` and `<object>`
tags it creates for diagrams in the png and svg formats in an additional
`<div class="graphviz">...</div>` tag. This allows to apply additional
CSS styling to the the diagrams that cannot be applied to `<img>` and
`<object>` directly. Most notably,

    div.graphviz {
      overflow: auto;
    }

would be a useful style that the standard themes might consider.

In any case, it would allow users to add custom CSS code to their
project that gets around the problems with inheritance-diagrams
discussed in https://github.com/sphinx-doc/sphinx/issues/4865

The tests for the `grahviz` and `inheritance_diagram` have been modified
to test for the presence of the additional `<div>` tag.

Closes #4865
This commit is contained in:
Michael Goerz 2018-04-20 02:10:30 -04:00
parent 96c5605374
commit b689fb1c12
3 changed files with 27 additions and 19 deletions

View File

@ -290,21 +290,25 @@ def render_dot_html(self, node, code, options, prefix='graphviz',
self.body.append('<div align="%s" class="align-%s">' %
(node['align'], node['align']))
if format == 'svg':
svgtag = '''<object data="%s" type="image/svg+xml">
<p class="warning">%s</p></object>\n''' % (fname, alt)
svgtag = '''<div class="graphviz"><object data="%s" type="image/svg+xml">
<p class="warning">%s</p></object></div>\n''' % (fname, alt)
self.body.append(svgtag)
else:
with codecs.open(outfn + '.map', 'r', encoding='utf-8') as mapfile: # type: ignore
imgmap = ClickableMapDefinition(outfn + '.map', mapfile.read(), dot=code)
if imgmap.clickable:
# has a map
self.body.append('<img src="%s" alt="%s" usemap="#%s" %s/>\n' %
self.body.append('<div class="graphviz">')
self.body.append('<img src="%s" alt="%s" usemap="#%s" %s/>' %
(fname, alt, imgmap.id, imgcss))
self.body.append('</div>\n')
self.body.append(imgmap.generate_clickable_map())
else:
# nothing in image map
self.body.append('<img src="%s" alt="%s" %s/>\n' %
self.body.append('<div class="graphviz">')
self.body.append('<img src="%s" alt="%s" %s/>' %
(fname, alt, imgcss))
self.body.append('</div>\n')
if 'align' in node:
self.body.append('</div>\n')

View File

@ -22,24 +22,26 @@ def test_graphviz_png_html(app, status, warning):
app.builder.build_all()
content = (app.outdir / 'index.html').text()
html = (r'<div class="figure" .*?>\s*<img .*?/>\s*<p class="caption">'
html = (r'<div class="figure" .*?>\s*'
r'<div class="graphviz"><img .*?/></div>\s*<p class="caption">'
r'<span class="caption-text">caption of graph</span>.*</p>\s*</div>')
assert re.search(html, content, re.S)
html = 'Hello <img .*?/>\n graphviz world'
html = 'Hello <div class="graphviz"><img .*?/></div>\n graphviz world'
assert re.search(html, content, re.S)
html = '<img src=".*?" alt="digraph {\n bar -&gt; baz\n}" />'
assert re.search(html, content, re.M)
html = (r'<div class="figure align-right" .*?>\s*<img .*?/>\s*<p class="caption">'
html = (r'<div class="figure align-right" .*?>\s*'
r'<div class="graphviz"><img .*?/></div>\s*<p class="caption">'
r'<span class="caption-text">on right</span>.*</p>\s*</div>')
assert re.search(html, content, re.S)
html = (r'<div align=\"center\" class=\"align-center\">'
r'<img src=\".*\.png\" alt=\"digraph foo {\n'
r'<div class="graphviz"><img src=\".*\.png\" alt=\"digraph foo {\n'
r'centered\n'
r'}\" />\n</div>')
r'}\" /></div>\n</div>')
assert re.search(html, content, re.S)
@ -52,34 +54,34 @@ def test_graphviz_svg_html(app, status, warning):
content = (app.outdir / 'index.html').text()
html = (r'<div class=\"figure\" .*?>\n'
r'<object data=\".*\.svg\".*>\n'
r'<div class="graphviz"><object data=\".*\.svg\".*>\n'
r'\s+<p class=\"warning\">digraph foo {\n'
r'bar -&gt; baz\n'
r'}</p></object>\n'
r'}</p></object></div>\n'
r'<p class=\"caption\"><span class=\"caption-text\">'
r'caption of graph</span>.*</p>\n</div>')
assert re.search(html, content, re.S)
html = (r'Hello <object.*>\n'
r'\s+<p class=\"warning\">graph</p></object>\n'
html = (r'Hello <div class="graphviz"><object.*>\n'
r'\s+<p class=\"warning\">graph</p></object></div>\n'
r' graphviz world')
assert re.search(html, content, re.S)
html = (r'<div class=\"figure align-right\" .*\>\n'
r'<object data=\".*\.svg\".*>\n'
r'<div class="graphviz"><object data=\".*\.svg\".*>\n'
r'\s+<p class=\"warning\">digraph bar {\n'
r'foo -&gt; bar\n'
r'}</p></object>\n'
r'}</p></object></div>\n'
r'<p class=\"caption\"><span class=\"caption-text\">'
r'on right</span>.*</p>\n'
r'</div>')
assert re.search(html, content, re.S)
html = (r'<div align=\"center\" class=\"align-center\">'
r'<object data=\".*\.svg\".*>\n'
r'<div class="graphviz"><object data=\".*\.svg\".*>\n'
r'\s+<p class=\"warning\">digraph foo {\n'
r'centered\n'
r'}</p></object>\n'
r'}</p></object></div>\n'
r'</div>')
assert re.search(html, content, re.S)

View File

@ -25,8 +25,9 @@ def test_inheritance_diagram_html(app, status, warning):
content = (app.outdir / 'index.html').text()
pattern = ('<div class="figure" id="id1">\n'
'<div class="graphviz">'
'<img src="_images/inheritance-\\w+.png" alt="Inheritance diagram of test.Foo" '
'class="inheritance"/>\n<p class="caption"><span class="caption-text">'
'class="inheritance"/></div>\n<p class="caption"><span class="caption-text">'
'Test Foo!</span><a class="headerlink" href="#id1" '
'title="Permalink to this image">\xb6</a></p>')
assert re.search(pattern, content, re.M)
@ -62,8 +63,9 @@ def test_inheritance_diagram_latex_alias(app, status, warning):
content = (app.outdir / 'index.html').text()
pattern = ('<div class="figure" id="id1">\n'
'<div class="graphviz">'
'<img src="_images/inheritance-\\w+.png" alt="Inheritance diagram of test.Foo" '
'class="inheritance"/>\n<p class="caption"><span class="caption-text">'
'class="inheritance"/></div>\n<p class="caption"><span class="caption-text">'
'Test Foo!</span><a class="headerlink" href="#id1" '
'title="Permalink to this image">\xb6</a></p>')
assert re.search(pattern, content, re.M)