@@ -5,7 +5,6 @@ struct DOTFormat <: AbstractGraphFormat end
55
66function loadmg end
77function savemg end
8- function savedot end
98
109loadgraph (fn:: AbstractString , :: String , :: MGFormat ) = loadmg (fn)
1110savegraph (fn:: AbstractString , g:: AbstractMetaGraph ) = savemg (fn, g)
@@ -15,3 +14,60 @@ function savegraph(fn::AbstractString, g::AbstractMetaGraph, ::DOTFormat)
1514 savedot (fp, g)
1615 end
1716end
17+
18+ # escaping unescaped quotation marks
19+ # i.e. replacing `"`` with `\"` while leaving `\"` as is
20+ escape_quotes (s:: AbstractString ) = replace (s, r" ([^\\ ])\" " => s "\1\\\\\" " )
21+
22+ # According to the DOT language specification https://graphviz.org/doc/info/lang.html
23+ # we can quote everyhthing that's not an XML/HTML literal
24+ function quote_prop (p:: AbstractString )
25+ if occursin (r" <+.*>+$" , p)
26+ # The label is an HTML string, no additional quotes here.
27+ return p
28+ else
29+ return " \" " * escape_quotes (p) * " \" "
30+ end
31+ end
32+ # if the property value is _not_ a string it cannot be XML/HTML literal, so just put it in quotes
33+ quote_prop (p:: Any ) = " \" " * escape_quotes (string (p)) * " \" "
34+ # NOTE: down there I only quote property _values_. DOT allows quoting property _names_ too
35+ # I don't do that as long as names are Symbols and can't have spaces and commas and stuff.
36+ # That will break if someone uses a DOT keyword as a property name, as they must be quoted.
37+
38+ function savedot (io:: IO , g:: AbstractMetaGraph )
39+ if is_directed (g)
40+ write (io, " digraph G {\n " )
41+ dash = " ->"
42+ else
43+ write (io, " graph G {\n " )
44+ dash = " --"
45+ end
46+
47+ for p in props (g)
48+ write (io, " $(p[1 ]) =$(quote_prop (p[2 ])) ;\n " )
49+ end
50+
51+ for v in vertices (g)
52+ write (io, " $v " )
53+ if length (props (g, v)) > 0
54+ write (io, " [ " )
55+
56+ for p in props (g, v)
57+ write (io, " $(p[1 ]) =$(quote_prop (p[2 ])) , " )
58+ end
59+
60+ write (io, " ];" )
61+ end
62+ write (io, " \n " )
63+ end
64+
65+ for e in edges (g)
66+ write (io, " $(src (e)) $dash $(dst (e)) [ " )
67+ for p in props (g,e)
68+ write (io, " $(p[1 ]) =$(quote_prop (p[2 ])) , " )
69+ end
70+ write (io, " ]\n " )
71+ end
72+ write (io, " }\n " )
73+ end
0 commit comments