Clean the SVG emitted by graphviz to permit CSS styling

This commit is contained in:
Benjamin Dauvergne 2011-06-14 16:47:08 +02:00 committed by Frédéric Péters
parent b5ed62aba2
commit 876a95b893
2 changed files with 93 additions and 3 deletions

View File

@ -18,6 +18,8 @@ import time
from StringIO import StringIO
from subprocess import Popen, PIPE
import textwrap
import xml.etree.ElementTree as etree
import re
from quixote import redirect, get_publisher
from quixote.directory import Directory
@ -33,6 +35,56 @@ from wcs.formdata import Evolution
from wcs.admin.forms import ET, indent
def svg(tag):
return '{http://www.w3.org/2000/svg}%s' % tag
def xlink(tag):
return '{http://www.w3.org/1999/xlink}%s' % tag
TITLE = svg('title')
POLYGON = svg('polygon')
XLINK_TITLE = xlink('title')
def remove_tag(node, tag):
for child in node:
if child.tag == tag:
node.remove(child)
def remove_attribute(node, att):
if att in node.attrib:
del node.attrib[att]
def remove_style(node, top):
remove_tag(node, TITLE)
for child in node:
remove_attribute(child, XLINK_TITLE)
style = child.get('style', None)
# Beware ! HACK ! salmon is matched and converted to class="page-subject"
if style:
m = re.search('(?:stroke|fill):salmon', style)
if m:
top.set('class', top.get('class','') + ' page-subject')
remove_attribute(child, 'style')
remove_style(child, top)
def graphviz_post_treatment(content):
''' Remove all svg:title and top-level svg:polygon nodes, remove style
attributes and xlink:title attributes.
If a color style is set to a name matching class-\w+, set the second
part on as class selector on the top level svg:g element.
'''
tree = etree.fromstring(content)
for root in tree:
remove_tag(root, TITLE)
# remove_tag(root, POLYGON)
for child in root:
remove_style(child, child)
return etree.tostring(tree)
def graphviz(workflow, url_prefix='', select=None, svg=True,
include=False):
out = StringIO()
@ -61,7 +113,7 @@ def graphviz(workflow, url_prefix='', select=None, svg=True,
label = label.replace('\n', '\\n')
print >>out, '[label="%s"' % label,
if select == '%s-%s' % (i, item.id):
print >>out, ',color=salmon,fontcolor=salmon'
print >>out, ',color=salmon'
print >>out, ',URL="%s%s"]' % (url_prefix, url)
print >>out, '}'
out = out.getvalue()
@ -69,8 +121,13 @@ def graphviz(workflow, url_prefix='', select=None, svg=True,
process = Popen(['dot', '-Tsvg', '/dev/stdin'], stdin=PIPE, stdout=PIPE)
out, err = process.communicate(out)
if include:
i = out.index('<svg')
out = out[i:]
out = graphviz_post_treatment(out)
# It seems webkit refuse to accept SVG when using its proper namespace,
# and xlink namespace prefix must be xlink: to be acceptable
out = out.replace('ns0:', '')
out = out.replace('xmlns:ns0', 'xmlns:svg')
out = out.replace('ns1:', 'xlink:')
out = out.replace(':ns1', ':xlink')
return out

View File

@ -657,3 +657,36 @@ h3 span.change {
font-size: small;
font-weight: normal;
}
/* Styling for workflow graphs */
svg .node polygon {
stroke:black;
fill:#EEE;
}
svg .node path {
fill:none;
stroke: black;
}
svg .edge path {
fill:none;
stroke: black;
}
svg .edge polygon {
stroke: black;
}
svg text {
font-family: sans-serif;
font-size: 9.00pt;
}
svg .page-subject.edge text {
fill: #028;
}
svg .page-subject polygon {
fill: #028;
stroke: #028;
}
svg .page-subject path {
stroke: #028;
}