diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index fa5f12f07..0855902f0 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -1351,6 +1351,17 @@ y -> x.style b`, g.Objects[0].Attributes.Label.Value) }, }, + { + name: "unescaped_id_cr", + + text: `b\rb`, + assertions: func(t *testing.T, g *d2graph.Graph) { + if len(g.Objects) != 1 { + t.Fatal(g.Objects) + } + assert.String(t, "b\rb", g.Objects[0].Attributes.Label.Value) + }, + }, { name: "class_style", diff --git a/d2layouts/d2dagrelayout/layout.go b/d2layouts/d2dagrelayout/layout.go index c984dc2e2..cd2e44d21 100644 --- a/d2layouts/d2dagrelayout/layout.go +++ b/d2layouts/d2dagrelayout/layout.go @@ -259,15 +259,20 @@ func setGraphAttrs(attrs dagreGraphAttrs) string { ) } +func escapeID(id string) string { + return strings.ReplaceAll(id, "\r", "\\r") +} + func generateAddNodeLine(id string, width, height int) string { + id = escapeID(id) return fmt.Sprintf("g.setNode(`%s`, { id: `%s`, width: %d, height: %d });\n", id, id, width, height) } func generateAddParentLine(childID, parentID string) string { - return fmt.Sprintf("g.setParent(`%s`, `%s`);\n", childID, parentID) + return fmt.Sprintf("g.setParent(`%s`, `%s`);\n", escapeID(childID), escapeID(parentID)) } func generateAddEdgeLine(fromID, toID, edgeID string) string { // in dagre v is from, w is to, name is to uniquely identify - return fmt.Sprintf("g.setEdge({v:`%s`, w:`%s`, name:`%s` });\n", fromID, toID, edgeID) + return fmt.Sprintf("g.setEdge({v:`%s`, w:`%s`, name:`%s` });\n", escapeID(fromID), escapeID(toID), escapeID(edgeID)) } diff --git a/e2etests/regression_test.go b/e2etests/regression_test.go index 4db509e55..fc0f6c7c7 100644 --- a/e2etests/regression_test.go +++ b/e2etests/regression_test.go @@ -7,8 +7,12 @@ import ( func testRegression(t *testing.T) { tcs := []testCase{ { - name: "dagre_id_with_newline", - script: `ninety\nnine`, + name: "dagre_id_with_newline", + script: ` +ninety\nnine +eighty\reight +seventy\r\nseven +`, }, }