Escape double quotes, replace center-chars to left-aligns, and add tests (#557)
diff --git a/internal/graph/dotgraph.go b/internal/graph/dotgraph.go
index 09debfb..cde648f 100644
--- a/internal/graph/dotgraph.go
+++ b/internal/graph/dotgraph.go
@@ -127,7 +127,7 @@
}
title := labels[0]
fmt.Fprintf(b, `subgraph cluster_L { "%s" [shape=box fontsize=16`, title)
- fmt.Fprintf(b, ` label="%s\l"`, strings.Join(labels, `\l`))
+ fmt.Fprintf(b, ` label="%s\l"`, strings.Join(escapeForDot(labels), `\l`))
if b.config.LegendURL != "" {
fmt.Fprintf(b, ` URL="%s" target="_blank"`, b.config.LegendURL)
}
@@ -472,3 +472,14 @@
}
return b
}
+
+// escapeForDot escapes double quotes and backslashes, and replaces Graphviz's
+// "center" character (\n) with a left-justified character.
+// See https://graphviz.org/doc/info/attrs.html#k:escString for more info.
+func escapeForDot(in []string) []string {
+ var out = make([]string, len(in))
+ for i := range in {
+ out[i] = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(in[i], `\`, `\\`), `"`, `\"`), "\n", `\l`)
+ }
+ return out
+}
diff --git a/internal/graph/dotgraph_test.go b/internal/graph/dotgraph_test.go
index b8368b8..4232efa 100644
--- a/internal/graph/dotgraph_test.go
+++ b/internal/graph/dotgraph_test.go
@@ -178,7 +178,7 @@
}
c := &DotConfig{
Title: "testtitle",
- Labels: []string{"label1", "label2"},
+ Labels: []string{"label1", "label2", `label3: "foo"`},
Total: 100,
FormatValue: func(v int64) string {
return strconv.FormatInt(v, 10)
@@ -326,6 +326,46 @@
}
}
+func TestEscapeForDot(t *testing.T) {
+ for _, tc := range []struct {
+ desc string
+ input []string
+ want []string
+ }{
+ {
+ desc: "with multiple doubles quotes",
+ input: []string{`label: "foo" and "bar"`},
+ want: []string{`label: \"foo\" and \"bar\"`},
+ },
+ {
+ desc: "with graphviz center line character",
+ input: []string{"label: foo \n bar"},
+ want: []string{`label: foo \l bar`},
+ },
+ {
+ desc: "with two backslashes",
+ input: []string{`label: \\`},
+ want: []string{`label: \\\\`},
+ },
+ {
+ desc: "with two double quotes together",
+ input: []string{`label: ""`},
+ want: []string{`label: \"\"`},
+ },
+ {
+ desc: "with multiple labels",
+ input: []string{`label1: "foo"`, `label2: "bar"`},
+ want: []string{`label1: \"foo\"`, `label2: \"bar\"`},
+ },
+ } {
+ t.Run(tc.desc, func(t *testing.T) {
+ if got := escapeForDot(tc.input); !reflect.DeepEqual(got, tc.want) {
+ t.Errorf("escapeForDot(%s) = %s, want %s", tc.input, got, tc.want)
+ }
+ })
+ }
+}
+
func tagString(t []*Tag) string {
var ret []string
for _, s := range t {
diff --git a/internal/graph/testdata/compose1.dot b/internal/graph/testdata/compose1.dot
index da349a4..a0842ee 100644
--- a/internal/graph/testdata/compose1.dot
+++ b/internal/graph/testdata/compose1.dot
@@ -1,6 +1,6 @@
digraph "testtitle" {
node [style=filled fillcolor="#f8f8f8"]
-subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\l" tooltip="testtitle"] }
+subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\llabel3: \"foo\"\l" tooltip="testtitle"] }
N1 [label="src\n10 (10.00%)\nof 25 (25.00%)" id="node1" fontsize=22 shape=box tooltip="src (25)" color="#b23c00" fillcolor="#edddd5"]
N2 [label="dest\n15 (15.00%)\nof 25 (25.00%)" id="node2" fontsize=24 shape=box tooltip="dest (25)" color="#b23c00" fillcolor="#edddd5"]
N1 -> N2 [label=" 10" weight=11 color="#b28559" tooltip="src -> dest (10)" labeltooltip="src -> dest (10)"]
diff --git a/internal/graph/testdata/compose2.dot b/internal/graph/testdata/compose2.dot
index 0c1a6eb..44c2aec 100644
--- a/internal/graph/testdata/compose2.dot
+++ b/internal/graph/testdata/compose2.dot
@@ -1,6 +1,6 @@
digraph "testtitle" {
node [style=filled fillcolor="#f8f8f8"]
-subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\l" tooltip="testtitle"] }
+subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\llabel3: \"foo\"\l" tooltip="testtitle"] }
N1 [label="SRC10 (10.00%)\nof 25 (25.00%)" id="node1" fontsize=24 shape=folder tooltip="src (25)" color="#b23c00" fillcolor="#edddd5" style="bold,filled" peripheries=2 URL="www.google.com" target="_blank"]
N2 [label="dest\n0 of 25 (25.00%)" id="node2" fontsize=8 shape=box tooltip="dest (25)" color="#b23c00" fillcolor="#edddd5"]
N1 -> N2 [label=" 10" weight=11 color="#b28559" tooltip="src -> dest (10)" labeltooltip="src -> dest (10)"]
diff --git a/internal/graph/testdata/compose3.dot b/internal/graph/testdata/compose3.dot
index 1b878b7..f22ad9f 100644
--- a/internal/graph/testdata/compose3.dot
+++ b/internal/graph/testdata/compose3.dot
@@ -1,6 +1,6 @@
digraph "testtitle" {
node [style=filled fillcolor="#f8f8f8"]
-subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\l" tooltip="testtitle"] }
+subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\llabel3: \"foo\"\l" tooltip="testtitle"] }
N1 [label="src\n10 (10.00%)\nof 25 (25.00%)" id="node1" fontsize=22 shape=box tooltip="src (25)" color="#b23c00" fillcolor="#edddd5"]
N1_0 [label = "tag1" id="N1_0" fontsize=8 shape=box3d tooltip="10"]
N1 -> N1_0 [label=" 10" weight=100 tooltip="10" labeltooltip="10"]
diff --git a/internal/graph/testdata/compose4.dot b/internal/graph/testdata/compose4.dot
index 302da8c..ed770d1 100644
--- a/internal/graph/testdata/compose4.dot
+++ b/internal/graph/testdata/compose4.dot
@@ -1,4 +1,4 @@
digraph "testtitle" {
node [style=filled fillcolor="#f8f8f8"]
-subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\l" tooltip="testtitle"] }
+subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\llabel3: \"foo\"\l" tooltip="testtitle"] }
}
diff --git a/internal/graph/testdata/compose5.dot b/internal/graph/testdata/compose5.dot
index 8876e33..3f2285c 100644
--- a/internal/graph/testdata/compose5.dot
+++ b/internal/graph/testdata/compose5.dot
@@ -1,6 +1,6 @@
digraph "testtitle" {
node [style=filled fillcolor="#f8f8f8"]
-subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\l" tooltip="testtitle"] }
+subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\llabel3: \"foo\"\l" tooltip="testtitle"] }
N1 [label="src\n10 (10.00%)\nof 25 (25.00%)" id="node1" fontsize=22 shape=box tooltip="src (25)" color="#b23c00" fillcolor="#edddd5"]
N1_0 [label = "tag1" id="N1_0" fontsize=8 shape=box3d tooltip="10"]
N1 -> N1_0 [label=" 10" weight=100 tooltip="10" labeltooltip="10"]
diff --git a/internal/graph/testdata/compose6.dot b/internal/graph/testdata/compose6.dot
index cf88439..1dfc3fe 100644
--- a/internal/graph/testdata/compose6.dot
+++ b/internal/graph/testdata/compose6.dot
@@ -1,6 +1,6 @@
digraph "testtitle" {
node [style=filled fillcolor="#f8f8f8"]
-subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\l" URL="http://example.com" target="_blank" tooltip="testtitle"] }
+subgraph cluster_L { "label1" [shape=box fontsize=16 label="label1\llabel2\llabel3: \"foo\"\l" URL="http://example.com" target="_blank" tooltip="testtitle"] }
N1 [label="src\n10 (10.00%)\nof 25 (25.00%)" id="node1" fontsize=22 shape=box tooltip="src (25)" color="#b23c00" fillcolor="#edddd5"]
N2 [label="dest\n15 (15.00%)\nof 25 (25.00%)" id="node2" fontsize=24 shape=box tooltip="dest (25)" color="#b23c00" fillcolor="#edddd5"]
N1 -> N2 [label=" 10" weight=11 color="#b28559" tooltip="src -> dest (10)" labeltooltip="src -> dest (10)"]
diff --git a/internal/report/report.go b/internal/report/report.go
index a345208..bc5685d 100644
--- a/internal/report/report.go
+++ b/internal/report/report.go
@@ -1207,7 +1207,7 @@
// Help new users understand the graph.
// A new line is intentionally added here to better show this message.
if fullHeaders {
- label = append(label, "\\lSee https://git.io/JfYMW for how to read the graph")
+ label = append(label, "\nSee https://git.io/JfYMW for how to read the graph")
}
return label