Clean the SVG emitted by graphviz to permit CSS styling
This commit is contained in:
parent
b5ed62aba2
commit
876a95b893
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue