From 4a6ab032e710f1292bb1ecd577c0dc9900e8dcf0 Mon Sep 17 00:00:00 2001 From: melsonic Date: Wed, 16 Apr 2025 00:49:12 +0530 Subject: [PATCH 01/18] validate gradient color stops --- d2compiler/compile_test.go | 8 ++++++++ lib/color/gradient.go | 13 ++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 702295099..57568e279 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -3929,6 +3929,14 @@ svc_1.t2 -> b: do with B tassert.Equal(t, "d2/testdata/d2compiler/TestCompile/meow.d2", g.Layers[0].Layers[0].AST.Range.Path) }, }, + { + name: "invalid_gradient_color_stop", + text: ` + x + x.style.fill: "linear-gradient(#ggg, #000)" + `, + expErr: `d2/testdata/d2compiler/TestCompile/invalid_gradient_color_stop.d2:3:19: expected "fill" to be a valid named color ("orange"), a hex code ("#f0ff3a"), or a gradient ("linear-gradient(red, blue)")`, + }, } for _, tc := range testCases { diff --git a/lib/color/gradient.go b/lib/color/gradient.go index 51dbde637..7aae4d0f4 100644 --- a/lib/color/gradient.go +++ b/lib/color/gradient.go @@ -9,6 +9,8 @@ import ( "regexp" "strconv" "strings" + + "github.com/mazznoer/csscolorparser" ) type Gradient struct { @@ -241,10 +243,15 @@ func UniqueGradientID(cssGradient string) string { return "grad-" + hash } -var GradientRegex = regexp.MustCompile(`^(linear|radial)-gradient\((.+)\)$`) - func IsGradient(color string) bool { - return GradientRegex.MatchString(color) + gradient, err := ParseGradient(color) + for _, colorStop := range gradient.ColorStops { + _, err = csscolorparser.Parse(colorStop.Color) + if err != nil { + break + } + } + return err == nil } var URLGradientID = regexp.MustCompile(`^url\('#grad-[a-f0-9]{40}'\)$`) From 1c41fd472ed6f79b4157635abbcd8f8215b9a4f7 Mon Sep 17 00:00:00 2001 From: melsonic Date: Wed, 16 Apr 2025 01:03:23 +0530 Subject: [PATCH 02/18] update next.md --- ci/release/changelogs/next.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index 4a04e7e04..8cf883cff 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -21,6 +21,7 @@ - Compiler: - `link`s can be set to root path, e.g. `/xyz`. [#2357](https://github.com/terrastruct/d2/issues/2357) - When importing a file, attempt resolving substitutions at the imported file scope first [#2482](https://github.com/terrastruct/d2/pull/2482) + - validate gradient color stops. [#2492](https://github.com/terrastruct/d2/pull/2492) - Parser: - impose max key length. It's almost certainly a mistake if an ID gets too long, e.g. missing quotes [#2465](https://github.com/terrastruct/d2/pull/2465) - Render: From 9f66199777641ced6778d944e91a2e6834b6476b Mon Sep 17 00:00:00 2001 From: melsonic Date: Wed, 16 Apr 2025 01:03:52 +0530 Subject: [PATCH 03/18] add test .exp file --- .../TestCompile/invalid_gradient_color_stop.exp.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 testdata/d2compiler/TestCompile/invalid_gradient_color_stop.exp.json diff --git a/testdata/d2compiler/TestCompile/invalid_gradient_color_stop.exp.json b/testdata/d2compiler/TestCompile/invalid_gradient_color_stop.exp.json new file mode 100644 index 000000000..49f1fffea --- /dev/null +++ b/testdata/d2compiler/TestCompile/invalid_gradient_color_stop.exp.json @@ -0,0 +1,11 @@ +{ + "graph": null, + "err": { + "errs": [ + { + "range": "d2/testdata/d2compiler/TestCompile/invalid_gradient_color_stop.d2,2:18:25-2:47:54", + "errmsg": "d2/testdata/d2compiler/TestCompile/invalid_gradient_color_stop.d2:3:19: expected \"fill\" to be a valid named color (\"orange\"), a hex code (\"#f0ff3a\"), or a gradient (\"linear-gradient(red, blue)\")" + } + ] + } +} From 5457b02e699d9c78bf9209866bb4790fe73b1624 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Wed, 16 Apr 2025 05:41:09 -0700 Subject: [PATCH 04/18] d2ir: fix imported glob leaf filter --- d2compiler/compile_test.go | 27 ++ d2ir/compile.go | 2 +- d2ir/d2ir.go | 20 +- d2ir/import.go | 47 +++ .../imported-glob-leaf-filter.exp.json | 307 ++++++++++++++++++ 5 files changed, 399 insertions(+), 4 deletions(-) create mode 100644 testdata/d2compiler/TestCompile/imported-glob-leaf-filter.exp.json diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 702295099..61123712b 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -1726,6 +1726,33 @@ k expErr: `d2/testdata/d2compiler/TestCompile/composite-glob-filter.d2:3:3: glob filters cannot be composites d2/testdata/d2compiler/TestCompile/composite-glob-filter.d2:3:3: glob filters cannot be composites`, }, + { + name: "imported-glob-leaf-filter", + + text: ` +***: { + &leaf: true + style: { + font-size: 30 + } +} +a: { + ...@x +} +`, + files: map[string]string{ + "x.d2": ` +b +`, + }, + assertions: func(t *testing.T, g *d2graph.Graph) { + assert.Equal(t, 2, len(g.Objects)) + assert.Equal(t, "b", g.Objects[0].Label.Value) + assert.Equal(t, "a", g.Objects[1].Label.Value) + assert.Equal(t, "30", g.Objects[0].Style.FontSize.Value) + assert.Equal(t, (*d2graph.Scalar)(nil), g.Objects[1].Style.FontSize) + }, + }, { name: "import-nested-var", diff --git a/d2ir/compile.go b/d2ir/compile.go index 91c0739e8..6467fef1a 100644 --- a/d2ir/compile.go +++ b/d2ir/compile.go @@ -981,7 +981,7 @@ func (c *compiler) _ampersandPropertyFilter(propName string, value string, node c.errorf(key, `&leaf must be "true" or "false", got %q`, value) return false } - isLeaf := node.Map() == nil || !node.Map().IsContainer() + isLeaf := node.Map() == nil || !c.IsContainer(node.Map()) return isLeaf == boolVal case "connected": boolVal, err := strconv.ParseBool(value) diff --git a/d2ir/d2ir.go b/d2ir/d2ir.go index 290e679de..d336d7894 100644 --- a/d2ir/d2ir.go +++ b/d2ir/d2ir.go @@ -705,7 +705,7 @@ func (m *Map) FieldCountRecursive() int { return acc } -func (m *Map) IsContainer() bool { +func (c *compiler) IsContainer(m *Map) bool { if m == nil { return false } @@ -714,6 +714,20 @@ func (m *Map) IsContainer() bool { for _, ref := range f.References { if ref.Primary() && ref.Context_.Key != nil && ref.Context_.Key.Value.Map != nil { for _, n := range ref.Context_.Key.Value.Map.Nodes { + if n.MapKey == nil { + if n.Import != nil { + impn, ok := c.peekImport(n.Import) + if ok { + for _, f := range impn.Fields { + _, isReserved := d2ast.ReservedKeywords[f.Name.ScalarString()] + if !(isReserved && f.Name.IsUnquoted()) { + return true + } + } + } + } + continue + } if len(n.MapKey.Edges) > 0 { return true } @@ -1333,7 +1347,7 @@ func (m *Map) createEdge(eid *EdgeID, refctx *RefContext, gctx *globContext, c * if refctx.Edge.Src.HasMultiGlob() { // If src has a double glob we only select leafs, those without children. - if src.Map().IsContainer() { + if c.IsContainer(src.Map()) { continue } if NodeBoardKind(src) != "" || ParentBoard(src) != ParentBoard(dst) { @@ -1342,7 +1356,7 @@ func (m *Map) createEdge(eid *EdgeID, refctx *RefContext, gctx *globContext, c * } if refctx.Edge.Dst.HasMultiGlob() { // If dst has a double glob we only select leafs, those without children. - if dst.Map().IsContainer() { + if c.IsContainer(dst.Map()) { continue } if NodeBoardKind(dst) != "" || ParentBoard(src) != ParentBoard(dst) { diff --git a/d2ir/import.go b/d2ir/import.go index 2d6630203..dff3edbee 100644 --- a/d2ir/import.go +++ b/d2ir/import.go @@ -124,6 +124,53 @@ func (c *compiler) __import(imp *d2ast.Import) (*Map, bool) { return ir, true } +func (c *compiler) peekImport(imp *d2ast.Import) (*Map, bool) { + impPath := imp.PathWithPre() + if impPath == "" && imp.Range != (d2ast.Range{}) { + return nil, false + } + + if len(c.importStack) > 0 { + if path.Ext(impPath) != ".d2" { + impPath += ".d2" + } + + if !filepath.IsAbs(impPath) { + impPath = path.Join(path.Dir(c.importStack[len(c.importStack)-1]), impPath) + } + } + + var f fs.File + var err error + if c.fs == nil { + f, err = os.Open(impPath) + } else { + f, err = c.fs.Open(impPath) + } + if err != nil { + return nil, false + } + defer f.Close() + + // Use a separate parse error to avoid polluting the main one + localErr := &d2parser.ParseError{} + ast, err := d2parser.Parse(impPath, f, &d2parser.ParseOptions{ + UTF16Pos: c.utf16Pos, + ParseError: localErr, + }) + if err != nil { + return nil, false + } + + ir := &Map{} + ir.initRoot() + ir.parent.(*Field).References[0].Context_.Scope = ast + + c.compileMap(ir, ast, ast) + + return ir, true +} + func nilScopeMap(n Node) { switch n := n.(type) { case *Map: diff --git a/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.exp.json b/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.exp.json new file mode 100644 index 000000000..410f77b04 --- /dev/null +++ b/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.exp.json @@ -0,0 +1,307 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,0:0:0-10:0:71", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,1:0:1-6:1:56", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,1:0:1-1:3:4", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,1:0:1-1:3:4", + "value": [ + { + "string": "***", + "raw_string": "***" + } + ], + "pattern": [ + "*", + "", + "*", + "", + "*" + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,1:5:6-6:1:56", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,2:2:10-2:13:21", + "ampersand": true, + "key": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,2:3:11-2:7:15", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,2:3:11-2:7:15", + "value": [ + { + "string": "leaf", + "raw_string": "leaf" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "boolean": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,2:9:17-2:13:21", + "value": true + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,3:2:24-5:3:54", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,3:2:24-3:7:29", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,3:2:24-3:7:29", + "value": [ + { + "string": "style", + "raw_string": "style" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,3:9:31-5:3:54", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,4:4:37-4:17:50", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,4:4:37-4:13:46", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,4:4:37-4:13:46", + "value": [ + { + "string": "font-size", + "raw_string": "font-size" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "number": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,4:15:48-4:17:50", + "raw": "30", + "value": "30" + } + } + } + } + ] + } + } + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,7:0:57-9:1:70", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,7:0:57-7:1:58", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,7:0:57-7:1:58", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,7:3:60-9:1:70", + "nodes": [ + { + "import": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,8:1:63-8:6:68", + "spread": true, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,8:5:67-8:6:68", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "b", + "id_val": "b", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/x.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/x.d2,1:0:1-1:1:2", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "b" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": { + "fontSize": { + "value": "30" + } + }, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "a", + "id_val": "a", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,7:0:57-7:1:58", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/imported-glob-leaf-filter.d2,7:0:57-7:1:58", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "a" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": null +} From 630d5f1adf46f8ac6ba5560def5267d6b82b09c1 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Wed, 16 Apr 2025 05:42:25 -0700 Subject: [PATCH 05/18] next --- ci/release/changelogs/next.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index 4a04e7e04..843d8c331 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -38,6 +38,7 @@ - fixes panic when classes were mixed with layers incorrectly [#2448](https://github.com/terrastruct/d2/pull/2448) - fixes panic when gradient colors are used in sketch mode [#2481](https://github.com/terrastruct/d2/pull/2487) - fixes panic using glob ampersand filters with composite values [#2489](https://github.com/terrastruct/d2/pull/2489) + - fixes leaf ampersand filter when used with imports [#2494](https://github.com/terrastruct/d2/pull/2494) - Formatter: - fixes substitutions in quotes surrounded by text [#2462](https://github.com/terrastruct/d2/pull/2462) - CLI: fetch and render remote images of mimetype octet-stream correctly [#2370](https://github.com/terrastruct/d2/pull/2370) From 909eeb00afca58a712fd0a750073fe40a2756d16 Mon Sep 17 00:00:00 2001 From: melsonic Date: Fri, 18 Apr 2025 21:22:07 +0530 Subject: [PATCH 06/18] update gradient color stop validity check --- lib/color/color.go | 14 +++++++++++++- lib/color/gradient.go | 13 +++---------- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/color/color.go b/lib/color/color.go index 7417a2b9d..95a15520a 100644 --- a/lib/color/color.go +++ b/lib/color/color.go @@ -512,7 +512,19 @@ var NamedColors = []string{ var ColorHexRegex = regexp.MustCompile(`^#(([0-9a-fA-F]{2}){3}|([0-9a-fA-F]){3})$`) func ValidColor(color string) bool { - if !go2.Contains(NamedColors, strings.ToLower(color)) && !ColorHexRegex.MatchString(color) && !IsGradient(color) { + + if IsGradient(color) { + gradient, err := ParseGradient(color) + for _, colorStop := range gradient.ColorStops { + _, err = csscolorparser.Parse(colorStop.Color) + if err != nil { + break + } + } + return err == nil + } + + if !go2.Contains(NamedColors, strings.ToLower(color)) && !ColorHexRegex.MatchString(color) { return false } diff --git a/lib/color/gradient.go b/lib/color/gradient.go index 7aae4d0f4..51dbde637 100644 --- a/lib/color/gradient.go +++ b/lib/color/gradient.go @@ -9,8 +9,6 @@ import ( "regexp" "strconv" "strings" - - "github.com/mazznoer/csscolorparser" ) type Gradient struct { @@ -243,15 +241,10 @@ func UniqueGradientID(cssGradient string) string { return "grad-" + hash } +var GradientRegex = regexp.MustCompile(`^(linear|radial)-gradient\((.+)\)$`) + func IsGradient(color string) bool { - gradient, err := ParseGradient(color) - for _, colorStop := range gradient.ColorStops { - _, err = csscolorparser.Parse(colorStop.Color) - if err != nil { - break - } - } - return err == nil + return GradientRegex.MatchString(color) } var URLGradientID = regexp.MustCompile(`^url\('#grad-[a-f0-9]{40}'\)$`) From 01e9a44fdfd8274e49b3eb82cb61db878b2522f1 Mon Sep 17 00:00:00 2001 From: melsonic Date: Mon, 21 Apr 2025 22:38:15 +0530 Subject: [PATCH 07/18] change err check flow --- lib/color/color.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/color/color.go b/lib/color/color.go index 95a15520a..701cc0b3d 100644 --- a/lib/color/color.go +++ b/lib/color/color.go @@ -512,19 +512,18 @@ var NamedColors = []string{ var ColorHexRegex = regexp.MustCompile(`^#(([0-9a-fA-F]{2}){3}|([0-9a-fA-F]){3})$`) func ValidColor(color string) bool { - if IsGradient(color) { gradient, err := ParseGradient(color) + if err != nil { + return false + } for _, colorStop := range gradient.ColorStops { _, err = csscolorparser.Parse(colorStop.Color) if err != nil { - break + return false } } - return err == nil - } - - if !go2.Contains(NamedColors, strings.ToLower(color)) && !ColorHexRegex.MatchString(color) { + } else if !go2.Contains(NamedColors, strings.ToLower(color)) && !ColorHexRegex.MatchString(color) { return false } From 5648c863a4f86d2d369979928af216d64b90357f Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Sun, 27 Apr 2025 09:20:11 -0600 Subject: [PATCH 08/18] d2oracle: fix setting in multiple layers --- d2compiler/compile.go | 85 +- d2oracle/edit_test.go | 34 + d2oracle/get.go | 64 +- .../TestSet/set-style-in-layer.exp.json | 726 ++++++++++++++++++ 4 files changed, 823 insertions(+), 86 deletions(-) create mode 100644 testdata/d2oracle/TestSet/set-style-in-layer.exp.json diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 651238afe..c7030146b 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -208,55 +208,48 @@ func findFieldAST(ast *d2ast.Map, f *d2ir.Field) *d2ast.Map { curr = d2ir.ParentField(curr) } - currAST := ast - for len(path) > 0 { - head := path[0] - found := false - for _, n := range currAST.Nodes { - if n.MapKey == nil { - continue - } - if n.MapKey.Key == nil { - continue - } - if len(n.MapKey.Key.Path) != 1 { - continue - } - head2 := n.MapKey.Key.Path[0].Unbox().ScalarString() - if head == head2 { - currAST = n.MapKey.Value.Map - // The BaseAST is only used for making edits to the AST (through d2oracle) - // If there's no Map for a given board, either it's an empty layer or set to an import - // Either way, in order to make edits, it needs to be expanded into a Map to add lines to - if currAST == nil { - n.MapKey.Value.Map = &d2ast.Map{ - Range: d2ast.MakeRange(",1:0:0-1:0:0"), - } - if n.MapKey.Value.Import != nil { - imp := &d2ast.Import{ - Range: d2ast.MakeRange(",1:0:0-1:0:0"), - Spread: true, - Pre: n.MapKey.Value.Import.Pre, - Path: n.MapKey.Value.Import.Path, - } - n.MapKey.Value.Map.Nodes = append(n.MapKey.Value.Map.Nodes, d2ast.MapNodeBox{ - Import: imp, - }) + return _findFieldAST(ast, path) +} - } - currAST = n.MapKey.Value.Map - } - found = true - break - } - } - if !found { - return nil - } - path = path[1:] +func _findFieldAST(ast *d2ast.Map, path []string) *d2ast.Map { + if len(path) == 0 { + return ast } - return currAST + head := path[0] + remainingPath := path[1:] + + for i := range ast.Nodes { + if ast.Nodes[i].MapKey == nil || ast.Nodes[i].MapKey.Key == nil || len(ast.Nodes[i].MapKey.Key.Path) != 1 { + continue + } + + head2 := ast.Nodes[i].MapKey.Key.Path[0].Unbox().ScalarString() + if head == head2 { + if ast.Nodes[i].MapKey.Value.Map == nil { + ast.Nodes[i].MapKey.Value.Map = &d2ast.Map{ + Range: d2ast.MakeRange(",1:0:0-1:0:0"), + } + if ast.Nodes[i].MapKey.Value.Import != nil { + imp := &d2ast.Import{ + Range: d2ast.MakeRange(",1:0:0-1:0:0"), + Spread: true, + Pre: ast.Nodes[i].MapKey.Value.Import.Pre, + Path: ast.Nodes[i].MapKey.Value.Import.Path, + } + ast.Nodes[i].MapKey.Value.Map.Nodes = append(ast.Nodes[i].MapKey.Value.Map.Nodes, d2ast.MapNodeBox{ + Import: imp, + }) + } + } + + if result := _findFieldAST(ast.Nodes[i].MapKey.Value.Map, remainingPath); result != nil { + return result + } + } + } + + return nil } type compiler struct { diff --git a/d2oracle/edit_test.go b/d2oracle/edit_test.go index 9e6466568..94d103615 100644 --- a/d2oracle/edit_test.go +++ b/d2oracle/edit_test.go @@ -2775,6 +2775,40 @@ scenarios: { Metricbeat.style.stroke: red } } +`, + }, + { + name: "set-style-in-layer", + text: `hey + +layers: { + k: { + b: {style.stroke: "#969db4"} + } +} + +layers: { + x: { + y + } +} +`, + boardPath: []string{"x"}, + key: `y.style.fill`, + value: go2.Pointer(`#ff0000`), + exp: `hey + +layers: { + k: { + b: {style.stroke: "#969db4"} + } +} + +layers: { + x: { + y: {style.fill: "#ff0000"} + } +} `, }, } diff --git a/d2oracle/get.go b/d2oracle/get.go index c39e88469..15df0767a 100644 --- a/d2oracle/get.go +++ b/d2oracle/get.go @@ -48,51 +48,35 @@ func ReplaceBoardNode(ast, ast2 *d2ast.Map, boardPath []string) bool { return false } - findMap := func(root *d2ast.Map, name string) *d2ast.Map { - for _, n := range root.Nodes { - if n.MapKey != nil && n.MapKey.Key != nil && n.MapKey.Key.Path[0].Unbox().ScalarString() == name { - return n.MapKey.Value.Map - } - } - return nil - } + return replaceBoardNodeInMap(ast, ast2, boardPath, "layers") || + replaceBoardNodeInMap(ast, ast2, boardPath, "scenarios") || + replaceBoardNodeInMap(ast, ast2, boardPath, "steps") +} - layersMap := findMap(ast, "layers") - scenariosMap := findMap(ast, "scenarios") - stepsMap := findMap(ast, "steps") +func replaceBoardNodeInMap(ast, ast2 *d2ast.Map, boardPath []string, boardType string) bool { + var matches []*d2ast.Map - if layersMap != nil { - m := findMap(layersMap, boardPath[0]) - if m != nil { - if len(boardPath) > 1 { - return ReplaceBoardNode(m, ast2, boardPath[1:]) - } else { - m.Nodes = ast2.Nodes - return true - } + for _, n := range ast.Nodes { + if n.MapKey != nil && n.MapKey.Key != nil && + n.MapKey.Key.Path[0].Unbox().ScalarString() == boardType && + n.MapKey.Value.Map != nil { + matches = append(matches, n.MapKey.Value.Map) } } - if scenariosMap != nil { - m := findMap(scenariosMap, boardPath[0]) - if m != nil { - if len(boardPath) > 1 { - return ReplaceBoardNode(m, ast2, boardPath[1:]) - } else { - m.Nodes = ast2.Nodes - return true - } - } - } - - if stepsMap != nil { - m := findMap(stepsMap, boardPath[0]) - if m != nil { - if len(boardPath) > 1 { - return ReplaceBoardNode(m, ast2, boardPath[1:]) - } else { - m.Nodes = ast2.Nodes - return true + for _, boardMap := range matches { + for _, n := range boardMap.Nodes { + if n.MapKey != nil && n.MapKey.Key != nil && + n.MapKey.Key.Path[0].Unbox().ScalarString() == boardPath[0] && + n.MapKey.Value.Map != nil { + if len(boardPath) > 1 { + if ReplaceBoardNode(n.MapKey.Value.Map, ast2, boardPath[1:]) { + return true + } + } else { + n.MapKey.Value.Map.Nodes = ast2.Nodes + return true + } } } } diff --git a/testdata/d2oracle/TestSet/set-style-in-layer.exp.json b/testdata/d2oracle/TestSet/set-style-in-layer.exp.json new file mode 100644 index 000000000..73d98726c --- /dev/null +++ b/testdata/d2oracle/TestSet/set-style-in-layer.exp.json @@ -0,0 +1,726 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,0:0:0-13:0:116", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,0:0:0-0:3:3", + "key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,0:0:0-0:3:3", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,0:0:0-0:3:3", + "value": [ + { + "string": "hey", + "raw_string": "hey" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,2:0:5-6:1:60", + "key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,2:0:5-2:6:11", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,2:0:5-2:6:11", + "value": [ + { + "string": "layers", + "raw_string": "layers" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,2:8:13-6:1:60", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,3:2:17-5:3:58", + "key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,3:2:17-3:3:18", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,3:2:17-3:3:18", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,3:5:20-5:3:58", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,4:4:26-4:32:54", + "key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,4:4:26-4:5:27", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,4:4:26-4:5:27", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,4:7:29-4:32:54", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,4:8:30-4:31:53", + "key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,4:8:30-4:20:42", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,4:8:30-4:13:35", + "value": [ + { + "string": "style", + "raw_string": "style" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,4:14:36-4:20:42", + "value": [ + { + "string": "stroke", + "raw_string": "stroke" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "double_quoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,4:22:44-4:31:53", + "value": [ + { + "string": "#969db4", + "raw_string": "#969db4" + } + ] + } + } + } + } + ] + } + } + } + } + ] + } + } + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,8:0:62-12:1:115", + "key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,8:0:62-8:6:68", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,8:0:62-8:6:68", + "value": [ + { + "string": "layers", + "raw_string": "layers" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,8:8:70-12:1:115", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,9:2:74-11:3:113", + "key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,9:2:74-9:3:75", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,9:2:74-9:3:75", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,9:5:77-11:3:113", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,10:4:83-10:30:109", + "key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,10:4:83-10:5:84", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,10:4:83-10:5:84", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,10:7:86-10:30:109", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,10:8:87-10:29:108", + "key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,10:8:87-10:18:97", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,10:8:87-10:13:92", + "value": [ + { + "string": "style", + "raw_string": "style" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,10:14:93-10:18:97", + "value": [ + { + "string": "fill", + "raw_string": "fill" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "double_quoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,10:20:99-10:29:108", + "value": [ + { + "string": "#ff0000", + "raw_string": "#ff0000" + } + ] + } + } + } + } + ] + } + } + } + } + ] + } + } + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "hey", + "id_val": "hey", + "references": [ + { + "key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,0:0:0-0:3:3", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,0:0:0-0:3:3", + "value": [ + { + "string": "hey", + "raw_string": "hey" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "hey" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ], + "layers": [ + { + "name": "k", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,0:0:0-1:0:0", + "nodes": [ + { + "map_key": { + "range": ",0:0:0-0:0:0", + "key": { + "range": ",0:0:0-0:0:0", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,4:4:26-4:5:27", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": ",1:0:0-2:0:0", + "nodes": [ + { + "map_key": { + "range": ",0:0:0-0:0:0", + "key": { + "range": ",0:0:0-0:0:0", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,4:8:30-4:13:35", + "value": [ + { + "string": "style", + "raw_string": "style" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": ",1:0:0-2:0:0", + "nodes": [ + { + "map_key": { + "range": ",0:0:0-0:0:0", + "key": { + "range": ",0:0:0-0:0:0", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,4:14:36-4:20:42", + "value": [ + { + "string": "stroke", + "raw_string": "stroke" + } + ] + } + } + ] + }, + "primary": { + "double_quoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,4:22:44-4:31:53", + "value": [ + { + "string": "#969db4", + "raw_string": "#969db4" + } + ] + } + }, + "value": {} + } + } + ] + } + } + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "b", + "id_val": "b", + "references": [ + { + "key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,4:4:26-4:5:27", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,4:4:26-4:5:27", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "b" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": { + "stroke": { + "value": "#969db4" + } + }, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + { + "name": "x", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,0:0:0-1:0:0", + "nodes": [ + { + "map_key": { + "range": ",0:0:0-0:0:0", + "key": { + "range": ",0:0:0-0:0:0", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,10:4:83-10:5:84", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": ",1:0:0-2:0:0", + "nodes": [ + { + "map_key": { + "range": ",0:0:0-0:0:0", + "key": { + "range": ",0:0:0-0:0:0", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,10:8:87-10:13:92", + "value": [ + { + "string": "style", + "raw_string": "style" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": ",1:0:0-2:0:0", + "nodes": [ + { + "map_key": { + "range": ",0:0:0-0:0:0", + "key": { + "range": ",0:0:0-0:0:0", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,10:14:93-10:18:97", + "value": [ + { + "string": "fill", + "raw_string": "fill" + } + ] + } + } + ] + }, + "primary": { + "double_quoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,10:20:99-10:29:108", + "value": [ + { + "string": "#ff0000", + "raw_string": "#ff0000" + } + ] + } + }, + "value": {} + } + } + ] + } + } + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,10:4:83-10:5:84", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2oracle/TestSet/set-style-in-layer.d2,10:4:83-10:5:84", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": { + "fill": { + "value": "#ff0000" + } + }, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + } + ] + }, + "err": "" +} From 42358c2b081d43e64ddddbdf1423a016d80c033b Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Tue, 29 Apr 2025 09:40:45 -0600 Subject: [PATCH 09/18] d2oracle: UpdateImport --- d2oracle/edit.go | 103 +++++ d2oracle/edit_test.go | 201 +++++++++ .../TestUpdateImport/mixed_imports.exp.json | 397 +++++++++++++++++ .../multiple_imports.exp.json | 416 ++++++++++++++++++ .../TestUpdateImport/nested_import.exp.json | 337 ++++++++++++++ .../no_matching_import.exp.json | 262 +++++++++++ .../TestUpdateImport/remove_import.exp.json | 177 ++++++++ .../remove_nested_import.exp.json | 252 +++++++++++ .../remove_spread_import.exp.json | 177 ++++++++ .../TestUpdateImport/update_import.exp.json | 262 +++++++++++ .../update_import_with_dir.exp.json | 262 +++++++++++ .../update_spread_import.exp.json | 243 ++++++++++ 12 files changed, 3089 insertions(+) create mode 100644 testdata/d2oracle/TestUpdateImport/mixed_imports.exp.json create mode 100644 testdata/d2oracle/TestUpdateImport/multiple_imports.exp.json create mode 100644 testdata/d2oracle/TestUpdateImport/nested_import.exp.json create mode 100644 testdata/d2oracle/TestUpdateImport/no_matching_import.exp.json create mode 100644 testdata/d2oracle/TestUpdateImport/remove_import.exp.json create mode 100644 testdata/d2oracle/TestUpdateImport/remove_nested_import.exp.json create mode 100644 testdata/d2oracle/TestUpdateImport/remove_spread_import.exp.json create mode 100644 testdata/d2oracle/TestUpdateImport/update_import.exp.json create mode 100644 testdata/d2oracle/TestUpdateImport/update_import_with_dir.exp.json create mode 100644 testdata/d2oracle/TestUpdateImport/update_spread_import.exp.json diff --git a/d2oracle/edit.go b/d2oracle/edit.go index 6256403d4..18447fed9 100644 --- a/d2oracle/edit.go +++ b/d2oracle/edit.go @@ -3324,3 +3324,106 @@ func filterReservedPath(path []*d2ast.StringBox) (filtered []*d2ast.StringBox) { } return } + +func UpdateImport(g *d2graph.Graph, boardPath []string, path string, newPath *string) (_ *d2graph.Graph, err error) { + if newPath == nil { + defer xdefer.Errorf(&err, "failed to remove import %#v", path) + } else { + defer xdefer.Errorf(&err, "failed to update import from %#v to %#v", path, *newPath) + } + + boardG := g + baseAST := g.AST + + if len(boardPath) > 0 { + // When compiling a nested board, we can read from boardG but only write to baseBoardG + boardG = GetBoardGraph(g, boardPath) + if boardG == nil { + return nil, fmt.Errorf("board %v not found", boardPath) + } + // TODO beter name + baseAST = boardG.BaseAST + if baseAST == nil { + return nil, fmt.Errorf("board %v cannot be modified through this file", boardPath) + } + } + + _updateImport(boardG, baseAST, path, newPath) + + if len(boardPath) > 0 { + replaced := ReplaceBoardNode(g.AST, baseAST, boardPath) + if !replaced { + return nil, fmt.Errorf("board %v AST not found", boardPath) + } + } + + return recompile(g) +} + +func _updateImport(g *d2graph.Graph, m *d2ast.Map, oldPath string, newPath *string) { + for i := 0; i < len(m.Nodes); i++ { + node := m.Nodes[i] + + if node.Import != nil { + if node.Import.PathWithPre() == oldPath { + if newPath == nil { + if node.Import.Spread { + m.Nodes = append(m.Nodes[:i], m.Nodes[i+1:]...) + i-- + } else { + node.Import = nil + } + } else { + updateImportPath(node.Import, *newPath) + } + continue + } + } + + if node.MapKey != nil { + if node.MapKey.Value.Import != nil { + if node.MapKey.Value.Import.PathWithPre() == oldPath { + if newPath == nil { + if node.MapKey.Value.Import.Spread && node.MapKey.Value.Map == nil { + m.Nodes = append(m.Nodes[:i], m.Nodes[i+1:]...) + i-- + } else { + node.MapKey.Value.Import = nil + } + } else { + updateImportPath(node.MapKey.Value.Import, *newPath) + } + } + } + + primaryImport := node.MapKey.Primary.Unbox() + if primaryImport != nil { + value, ok := primaryImport.(d2ast.Value) + if ok { + importBox := d2ast.MakeValueBox(value) + if importBox.Import != nil && importBox.Import.PathWithPre() == oldPath { + if newPath == nil { + node.MapKey.Primary = d2ast.ScalarBox{} + } else { + updateImportPath(importBox.Import, *newPath) + } + } + } + } + + if node.MapKey.Value.Map != nil { + _updateImport(g, node.MapKey.Value.Map, oldPath, newPath) + } + } + } +} + +func updateImportPath(imp *d2ast.Import, newPath string) { + if len(imp.Path) > 0 { + imp.Path[0] = d2ast.MakeValueBox(d2ast.RawString(newPath, true)).StringBox() + } else { + imp.Path = []*d2ast.StringBox{ + d2ast.MakeValueBox(d2ast.RawString(newPath, true)).StringBox(), + } + } +} diff --git a/d2oracle/edit_test.go b/d2oracle/edit_test.go index 94d103615..e860d558c 100644 --- a/d2oracle/edit_test.go +++ b/d2oracle/edit_test.go @@ -9597,3 +9597,204 @@ scenarios: { }) } } + +func TestUpdateImport(t *testing.T) { + t.Parallel() + + testCases := []struct { + name string + boardPath []string + text string + fsTexts map[string]string + path string + newPath *string + + expErr string + exp string + assertions func(t *testing.T, g *d2graph.Graph) + }{ + { + name: "remove_import", + text: `x: @meow +y +`, + fsTexts: map[string]string{ + "meow.d2": "k", + }, + path: "meow", + newPath: nil, + exp: `x +y +`, + }, + { + name: "remove_spread_import", + text: `x +...@meow +y`, + fsTexts: map[string]string{ + "meow.d2": "k", + }, + path: "meow", + newPath: nil, + exp: `x + +y +`, + }, + { + name: "update_import", + text: `x: @meow +y +`, + fsTexts: map[string]string{ + "meow.d2": "k", + "woof.d2": "k", + }, + path: "meow", + newPath: go2.Pointer("woof"), + exp: `x: @woof +y +`, + }, + { + name: "update_import_with_dir", + text: `x: @foo/meow +y +`, + fsTexts: map[string]string{ + "foo/meow.d2": "k", + "bar/woof.d2": "k", + }, + path: "foo/meow", + newPath: go2.Pointer("bar/woof"), + exp: `x: @bar/woof +y +`, + }, + { + name: "update_spread_import", + text: `x +...@meow +y +`, + fsTexts: map[string]string{ + "meow.d2": "k", + "woof.d2": "k", + }, + path: "meow", + newPath: go2.Pointer("woof"), + exp: `x +...@woof +y +`, + }, + { + name: "no_matching_import", + text: `x: @cat +y +`, + fsTexts: map[string]string{ + "cat.d2": "k", + }, + path: "meow", + newPath: go2.Pointer("woof"), + exp: `x: @cat +y +`, + }, + { + name: "nested_import", + text: `container: { + x: @meow + y +} +`, + fsTexts: map[string]string{ + "meow.d2": "k", + "woof.d2": "k", + }, + path: "meow", + newPath: go2.Pointer("woof"), + exp: `container: { + x: @woof + y +} +`, + }, + { + name: "remove_nested_import", + text: `container: { + x: @meow + y +} +`, + fsTexts: map[string]string{ + "meow.d2": "k", + }, + path: "meow", + newPath: nil, + exp: `container: { + x + y +} +`, + }, + { + name: "multiple_imports", + text: `x: @meow +y: @meow +z +`, + fsTexts: map[string]string{ + "meow.d2": "k", + "woof.d2": "k", + }, + path: "meow", + newPath: go2.Pointer("woof"), + exp: `x: @woof +y: @woof +z +`, + }, + { + name: "mixed_imports", + text: `x: @meow +y +...@meow +z +`, + fsTexts: map[string]string{ + "meow.d2": "k", + "woof.d2": "k", + }, + path: "meow", + newPath: go2.Pointer("woof"), + exp: `x: @woof +y +...@woof +z +`, + }, + } + + for _, tc := range testCases { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + + et := editTest{ + text: tc.text, + fsTexts: tc.fsTexts, + testFunc: func(g *d2graph.Graph) (*d2graph.Graph, error) { + return d2oracle.UpdateImport(g, tc.boardPath, tc.path, tc.newPath) + }, + + exp: tc.exp, + expErr: tc.expErr, + assertions: tc.assertions, + } + et.run(t) + }) + } +} diff --git a/testdata/d2oracle/TestUpdateImport/mixed_imports.exp.json b/testdata/d2oracle/TestUpdateImport/mixed_imports.exp.json new file mode 100644 index 000000000..89ddf2f9f --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/mixed_imports.exp.json @@ -0,0 +1,397 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-4:0:22", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-0:8:8", + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "import": { + "range": "index.d2,0:3:3-0:8:8", + "spread": false, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:4:4-0:8:8", + "value": [ + { + "string": "woof", + "raw_string": "woof" + } + ] + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "index.d2,1:0:9-1:1:10", + "key": { + "range": "index.d2,1:0:9-1:1:10", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:9-1:1:10", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "import": { + "range": "index.d2,2:0:11-2:8:19", + "spread": true, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:4:15-2:8:19", + "value": [ + { + "string": "woof", + "raw_string": "woof" + } + ] + } + } + ] + } + }, + { + "map_key": { + "range": "index.d2,3:0:20-3:1:21", + "key": { + "range": "index.d2,3:0:20-3:1:21", + "path": [ + { + "unquoted_string": { + "range": "index.d2,3:0:20-3:1:21", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "index.d2,1:0:9-1:1:10", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:9-1:1:10", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "z", + "id_val": "z", + "references": [ + { + "key": { + "range": "index.d2,3:0:20-3:1:21", + "path": [ + { + "unquoted_string": { + "range": "index.d2,3:0:20-3:1:21", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "z" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": "" +} diff --git a/testdata/d2oracle/TestUpdateImport/multiple_imports.exp.json b/testdata/d2oracle/TestUpdateImport/multiple_imports.exp.json new file mode 100644 index 000000000..837aae868 --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/multiple_imports.exp.json @@ -0,0 +1,416 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-3:0:20", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-0:8:8", + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "import": { + "range": "index.d2,0:3:3-0:8:8", + "spread": false, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:4:4-0:8:8", + "value": [ + { + "string": "woof", + "raw_string": "woof" + } + ] + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "index.d2,1:0:9-1:8:17", + "key": { + "range": "index.d2,1:0:9-1:1:10", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:9-1:1:10", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "import": { + "range": "index.d2,1:3:12-1:8:17", + "spread": false, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:4:13-1:8:17", + "value": [ + { + "string": "woof", + "raw_string": "woof" + } + ] + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "index.d2,2:0:18-2:1:19", + "key": { + "range": "index.d2,2:0:18-2:1:19", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:18-2:1:19", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "index.d2,1:0:9-1:1:10", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:9-1:1:10", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "index.d2,1:0:9-1:1:10", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:9-1:1:10", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "z", + "id_val": "z", + "references": [ + { + "key": { + "range": "index.d2,2:0:18-2:1:19", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:18-2:1:19", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "z" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": "" +} diff --git a/testdata/d2oracle/TestUpdateImport/nested_import.exp.json b/testdata/d2oracle/TestUpdateImport/nested_import.exp.json new file mode 100644 index 000000000..e4b2e89a8 --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/nested_import.exp.json @@ -0,0 +1,337 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-4:0:30", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-3:1:29", + "key": { + "range": "index.d2,0:0:0-0:9:9", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:9:9", + "value": [ + { + "string": "container", + "raw_string": "container" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "index.d2,0:11:11-3:1:29", + "nodes": [ + { + "map_key": { + "range": "index.d2,1:2:15-1:10:23", + "key": { + "range": "index.d2,1:2:15-1:3:16", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:2:15-1:3:16", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "import": { + "range": "index.d2,1:5:18-1:10:23", + "spread": false, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:6:19-1:10:23", + "value": [ + { + "string": "woof", + "raw_string": "woof" + } + ] + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "index.d2,2:2:26-2:3:27", + "key": { + "range": "index.d2,2:2:26-2:3:27", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:2:26-2:3:27", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "container", + "id_val": "container", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:9:9", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:9:9", + "value": [ + { + "string": "container", + "raw_string": "container" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "container" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,1:2:15-1:3:16", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:2:15-1:3:16", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "index.d2,1:2:15-1:3:16", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:2:15-1:3:16", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "index.d2,2:2:26-2:3:27", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:2:26-2:3:27", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": "" +} diff --git a/testdata/d2oracle/TestUpdateImport/no_matching_import.exp.json b/testdata/d2oracle/TestUpdateImport/no_matching_import.exp.json new file mode 100644 index 000000000..2acfaef4d --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/no_matching_import.exp.json @@ -0,0 +1,262 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-2:0:10", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-0:7:7", + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "import": { + "range": "index.d2,0:3:3-0:7:7", + "spread": false, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:4:4-0:7:7", + "value": [ + { + "string": "cat", + "raw_string": "cat" + } + ] + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "index.d2,1:0:8-1:1:9", + "key": { + "range": "index.d2,1:0:8-1:1:9", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:8-1:1:9", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "cat.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "cat.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "index.d2,1:0:8-1:1:9", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:8-1:1:9", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": "" +} diff --git a/testdata/d2oracle/TestUpdateImport/remove_import.exp.json b/testdata/d2oracle/TestUpdateImport/remove_import.exp.json new file mode 100644 index 000000000..be88e94da --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/remove_import.exp.json @@ -0,0 +1,177 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-2:0:4", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-0:1:1", + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "index.d2,1:0:2-1:1:3", + "key": { + "range": "index.d2,1:0:2-1:1:3", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:2-1:1:3", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "index.d2,1:0:2-1:1:3", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:2-1:1:3", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": "" +} diff --git a/testdata/d2oracle/TestUpdateImport/remove_nested_import.exp.json b/testdata/d2oracle/TestUpdateImport/remove_nested_import.exp.json new file mode 100644 index 000000000..6c4cb9a55 --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/remove_nested_import.exp.json @@ -0,0 +1,252 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-4:0:23", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-3:1:22", + "key": { + "range": "index.d2,0:0:0-0:9:9", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:9:9", + "value": [ + { + "string": "container", + "raw_string": "container" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "index.d2,0:11:11-3:1:22", + "nodes": [ + { + "map_key": { + "range": "index.d2,1:2:15-1:3:16", + "key": { + "range": "index.d2,1:2:15-1:3:16", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:2:15-1:3:16", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "index.d2,2:2:19-2:3:20", + "key": { + "range": "index.d2,2:2:19-2:3:20", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:2:19-2:3:20", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "container", + "id_val": "container", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:9:9", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:9:9", + "value": [ + { + "string": "container", + "raw_string": "container" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "container" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,1:2:15-1:3:16", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:2:15-1:3:16", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "index.d2,2:2:19-2:3:20", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:2:19-2:3:20", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": "" +} diff --git a/testdata/d2oracle/TestUpdateImport/remove_spread_import.exp.json b/testdata/d2oracle/TestUpdateImport/remove_spread_import.exp.json new file mode 100644 index 000000000..24487fde6 --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/remove_spread_import.exp.json @@ -0,0 +1,177 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-3:0:5", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-0:1:1", + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "index.d2,2:0:3-2:1:4", + "key": { + "range": "index.d2,2:0:3-2:1:4", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:3-2:1:4", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "index.d2,2:0:3-2:1:4", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:3-2:1:4", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": "" +} diff --git a/testdata/d2oracle/TestUpdateImport/update_import.exp.json b/testdata/d2oracle/TestUpdateImport/update_import.exp.json new file mode 100644 index 000000000..69194c8b0 --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/update_import.exp.json @@ -0,0 +1,262 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-2:0:11", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-0:8:8", + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "import": { + "range": "index.d2,0:3:3-0:8:8", + "spread": false, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:4:4-0:8:8", + "value": [ + { + "string": "woof", + "raw_string": "woof" + } + ] + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "index.d2,1:0:9-1:1:10", + "key": { + "range": "index.d2,1:0:9-1:1:10", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:9-1:1:10", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "index.d2,1:0:9-1:1:10", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:9-1:1:10", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": "" +} diff --git a/testdata/d2oracle/TestUpdateImport/update_import_with_dir.exp.json b/testdata/d2oracle/TestUpdateImport/update_import_with_dir.exp.json new file mode 100644 index 000000000..ef6720216 --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/update_import_with_dir.exp.json @@ -0,0 +1,262 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-2:0:15", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-0:12:12", + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "import": { + "range": "index.d2,0:3:3-0:12:12", + "spread": false, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:4:4-0:12:12", + "value": [ + { + "string": "bar/woof", + "raw_string": "bar/woof" + } + ] + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "index.d2,1:0:13-1:1:14", + "key": { + "range": "index.d2,1:0:13-1:1:14", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:13-1:1:14", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "bar/woof.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "bar/woof.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "index.d2,1:0:13-1:1:14", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:13-1:1:14", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": "" +} diff --git a/testdata/d2oracle/TestUpdateImport/update_spread_import.exp.json b/testdata/d2oracle/TestUpdateImport/update_spread_import.exp.json new file mode 100644 index 000000000..daec0b4aa --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/update_spread_import.exp.json @@ -0,0 +1,243 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-3:0:13", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-0:1:1", + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "import": { + "range": "index.d2,1:0:2-1:8:10", + "spread": true, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:4:6-1:8:10", + "value": [ + { + "string": "woof", + "raw_string": "woof" + } + ] + } + } + ] + } + }, + { + "map_key": { + "range": "index.d2,2:0:11-2:1:12", + "key": { + "range": "index.d2,2:0:11-2:1:12", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:11-2:1:12", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "index.d2,2:0:11-2:1:12", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:11-2:1:12", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": "" +} From 5ba60f24a8e73e9ff2344880d5e36741596a6a55 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Tue, 29 Apr 2025 09:50:39 -0600 Subject: [PATCH 10/18] add layers tests --- d2oracle/edit_test.go | 50 +++ .../TestUpdateImport/in_layer.exp.json | 410 ++++++++++++++++++ .../TestUpdateImport/layer_import.exp.json | 293 +++++++++++++ 3 files changed, 753 insertions(+) create mode 100644 testdata/d2oracle/TestUpdateImport/in_layer.exp.json create mode 100644 testdata/d2oracle/TestUpdateImport/layer_import.exp.json diff --git a/d2oracle/edit_test.go b/d2oracle/edit_test.go index e860d558c..d17c3919e 100644 --- a/d2oracle/edit_test.go +++ b/d2oracle/edit_test.go @@ -9774,6 +9774,56 @@ z y ...@woof z +`, + }, + { + name: "in_layer", + text: `x + +layers: { + y: { + z: @meow + } +} +`, + fsTexts: map[string]string{ + "meow.d2": "k", + "woof.d2": "k", + }, + path: "meow", + newPath: go2.Pointer("woof"), + exp: `x + +layers: { + y: { + z: @woof + } +} +`, + }, + { + name: "layer_import", + text: `x + +layers: { + y: { + ...@meow + } +} +`, + fsTexts: map[string]string{ + "meow.d2": "k", + "woof.d2": "k", + }, + path: "meow", + newPath: go2.Pointer("woof"), + exp: `x + +layers: { + y: { + ...@woof + } +} `, }, } diff --git a/testdata/d2oracle/TestUpdateImport/in_layer.exp.json b/testdata/d2oracle/TestUpdateImport/in_layer.exp.json new file mode 100644 index 000000000..e66d31063 --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/in_layer.exp.json @@ -0,0 +1,410 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-7:0:39", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-0:1:1", + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "index.d2,2:0:3-6:1:38", + "key": { + "range": "index.d2,2:0:3-2:6:9", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:3-2:6:9", + "value": [ + { + "string": "layers", + "raw_string": "layers" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "index.d2,2:8:11-6:1:38", + "nodes": [ + { + "map_key": { + "range": "index.d2,3:2:15-5:3:36", + "key": { + "range": "index.d2,3:2:15-3:3:16", + "path": [ + { + "unquoted_string": { + "range": "index.d2,3:2:15-3:3:16", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "index.d2,3:5:18-5:3:36", + "nodes": [ + { + "map_key": { + "range": "index.d2,4:4:24-4:12:32", + "key": { + "range": "index.d2,4:4:24-4:5:25", + "path": [ + { + "unquoted_string": { + "range": "index.d2,4:4:24-4:5:25", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "import": { + "range": "index.d2,4:7:27-4:12:32", + "spread": false, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,4:8:28-4:12:32", + "value": [ + { + "string": "woof", + "raw_string": "woof" + } + ] + } + } + ] + } + } + } + } + ] + } + } + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ], + "layers": [ + { + "name": "y", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-1:0:0", + "nodes": [ + { + "map_key": { + "range": ",0:0:0-0:0:0", + "key": { + "range": ",0:0:0-0:0:0", + "path": [ + { + "unquoted_string": { + "range": "index.d2,4:4:24-4:5:25", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": ",1:0:0-2:0:0", + "nodes": [ + { + "map_key": { + "range": ",0:0:0-0:0:0", + "key": { + "range": ",0:0:0-0:0:0", + "path": [ + { + "unquoted_string": { + "range": "woof.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "z", + "id_val": "z", + "references": [ + { + "key": { + "range": "index.d2,4:4:24-4:5:25", + "path": [ + { + "unquoted_string": { + "range": "index.d2,4:4:24-4:5:25", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "index.d2,4:4:24-4:5:25", + "path": [ + { + "unquoted_string": { + "range": "index.d2,4:4:24-4:5:25", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "z" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + } + ] + }, + "err": "" +} diff --git a/testdata/d2oracle/TestUpdateImport/layer_import.exp.json b/testdata/d2oracle/TestUpdateImport/layer_import.exp.json new file mode 100644 index 000000000..b1f35b938 --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/layer_import.exp.json @@ -0,0 +1,293 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-7:0:39", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-0:1:1", + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "index.d2,2:0:3-6:1:38", + "key": { + "range": "index.d2,2:0:3-2:6:9", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:3-2:6:9", + "value": [ + { + "string": "layers", + "raw_string": "layers" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "index.d2,2:8:11-6:1:38", + "nodes": [ + { + "map_key": { + "range": "index.d2,3:2:15-5:3:36", + "key": { + "range": "index.d2,3:2:15-3:3:16", + "path": [ + { + "unquoted_string": { + "range": "index.d2,3:2:15-3:3:16", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "index.d2,3:5:18-5:3:36", + "nodes": [ + { + "import": { + "range": "index.d2,4:4:24-4:12:32", + "spread": true, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,4:8:28-4:12:32", + "value": [ + { + "string": "woof", + "raw_string": "woof" + } + ] + } + } + ] + } + } + ] + } + } + } + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ], + "layers": [ + { + "name": "y", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-1:0:0", + "nodes": [ + { + "map_key": { + "range": ",0:0:0-0:0:0", + "key": { + "range": ",0:0:0-0:0:0", + "path": [ + { + "unquoted_string": { + "range": "woof.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + } + ] + }, + "err": "" +} From ba78c3bacc5ab67b8953f624be2abbc2f6862053 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Wed, 30 Apr 2025 09:08:58 -0600 Subject: [PATCH 11/18] d2oracle.UpdateImport: support directory updates --- d2oracle/edit.go | 41 +- d2oracle/edit_test.go | 55 +++ .../remove_directory_import.exp.json | 246 +++++++++++ .../update_deep_directory_paths.exp.json | 416 ++++++++++++++++++ .../update_directory_import.exp.json | 416 ++++++++++++++++++ 5 files changed, 1165 insertions(+), 9 deletions(-) create mode 100644 testdata/d2oracle/TestUpdateImport/remove_directory_import.exp.json create mode 100644 testdata/d2oracle/TestUpdateImport/update_deep_directory_paths.exp.json create mode 100644 testdata/d2oracle/TestUpdateImport/update_directory_import.exp.json diff --git a/d2oracle/edit.go b/d2oracle/edit.go index 18447fed9..06a8c0ac9 100644 --- a/d2oracle/edit.go +++ b/d2oracle/edit.go @@ -3365,7 +3365,8 @@ func _updateImport(g *d2graph.Graph, m *d2ast.Map, oldPath string, newPath *stri node := m.Nodes[i] if node.Import != nil { - if node.Import.PathWithPre() == oldPath { + importPath := node.Import.PathWithPre() + if matchesImportPath(importPath, oldPath) { if newPath == nil { if node.Import.Spread { m.Nodes = append(m.Nodes[:i], m.Nodes[i+1:]...) @@ -3374,7 +3375,7 @@ func _updateImport(g *d2graph.Graph, m *d2ast.Map, oldPath string, newPath *stri node.Import = nil } } else { - updateImportPath(node.Import, *newPath) + updateImportPath(node.Import, getNewImportPath(importPath, oldPath, *newPath)) } continue } @@ -3382,7 +3383,8 @@ func _updateImport(g *d2graph.Graph, m *d2ast.Map, oldPath string, newPath *stri if node.MapKey != nil { if node.MapKey.Value.Import != nil { - if node.MapKey.Value.Import.PathWithPre() == oldPath { + importPath := node.MapKey.Value.Import.PathWithPre() + if matchesImportPath(importPath, oldPath) { if newPath == nil { if node.MapKey.Value.Import.Spread && node.MapKey.Value.Map == nil { m.Nodes = append(m.Nodes[:i], m.Nodes[i+1:]...) @@ -3391,7 +3393,7 @@ func _updateImport(g *d2graph.Graph, m *d2ast.Map, oldPath string, newPath *stri node.MapKey.Value.Import = nil } } else { - updateImportPath(node.MapKey.Value.Import, *newPath) + updateImportPath(node.MapKey.Value.Import, getNewImportPath(importPath, oldPath, *newPath)) } } } @@ -3401,11 +3403,14 @@ func _updateImport(g *d2graph.Graph, m *d2ast.Map, oldPath string, newPath *stri value, ok := primaryImport.(d2ast.Value) if ok { importBox := d2ast.MakeValueBox(value) - if importBox.Import != nil && importBox.Import.PathWithPre() == oldPath { - if newPath == nil { - node.MapKey.Primary = d2ast.ScalarBox{} - } else { - updateImportPath(importBox.Import, *newPath) + if importBox.Import != nil { + importPath := importBox.Import.PathWithPre() + if matchesImportPath(importPath, oldPath) { + if newPath == nil { + node.MapKey.Primary = d2ast.ScalarBox{} + } else { + updateImportPath(importBox.Import, getNewImportPath(importPath, oldPath, *newPath)) + } } } } @@ -3427,3 +3432,21 @@ func updateImportPath(imp *d2ast.Import, newPath string) { } } } + +func matchesImportPath(importPath, oldPath string) bool { + isDir := strings.HasSuffix(oldPath, "/") + if isDir { + return strings.HasPrefix(importPath, oldPath) + } + return importPath == oldPath +} + +func getNewImportPath(importPath, oldPath, newPath string) string { + isOldDir := strings.HasSuffix(oldPath, "/") + isNewDir := strings.HasSuffix(newPath, "/") + if isOldDir && isNewDir { + relPath := importPath[len(oldPath):] + return newPath + relPath + } + return newPath +} diff --git a/d2oracle/edit_test.go b/d2oracle/edit_test.go index d17c3919e..7a022f355 100644 --- a/d2oracle/edit_test.go +++ b/d2oracle/edit_test.go @@ -9824,6 +9824,61 @@ layers: { ...@woof } } +`, + }, + { + name: "update_directory_import", + text: `x: @foo/bar +y: @foo/baz +z +`, + fsTexts: map[string]string{ + "foo/bar.d2": "k", + "foo/baz.d2": "k", + "woof/bar.d2": "k", + "woof/baz.d2": "k", + }, + path: "foo/", + newPath: go2.Pointer("woof/"), + exp: `x: @woof/bar +y: @woof/baz +z +`, + }, + { + name: "remove_directory_import", + text: `x: @foo/bar +y: @foo/baz +z +`, + fsTexts: map[string]string{ + "foo/bar.d2": "k", + "foo/baz.d2": "k", + }, + path: "foo/", + newPath: nil, + exp: `x +y +z +`, + }, + { + name: "update_deep_directory_paths", + text: `x: @foo/bar/baz +y: @foo/qux/quux +z +`, + fsTexts: map[string]string{ + "foo/bar/baz.d2": "k", + "foo/qux/quux.d2": "k", + "woof/bar/baz.d2": "k", + "woof/qux/quux.d2": "k", + }, + path: "foo/", + newPath: go2.Pointer("woof/"), + exp: `x: @woof/bar/baz +y: @woof/qux/quux +z `, }, } diff --git a/testdata/d2oracle/TestUpdateImport/remove_directory_import.exp.json b/testdata/d2oracle/TestUpdateImport/remove_directory_import.exp.json new file mode 100644 index 000000000..2183e42b6 --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/remove_directory_import.exp.json @@ -0,0 +1,246 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-3:0:6", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-0:1:1", + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "index.d2,1:0:2-1:1:3", + "key": { + "range": "index.d2,1:0:2-1:1:3", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:2-1:1:3", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "index.d2,2:0:4-2:1:5", + "key": { + "range": "index.d2,2:0:4-2:1:5", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:4-2:1:5", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "index.d2,1:0:2-1:1:3", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:2-1:1:3", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "z", + "id_val": "z", + "references": [ + { + "key": { + "range": "index.d2,2:0:4-2:1:5", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:4-2:1:5", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "z" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": "" +} diff --git a/testdata/d2oracle/TestUpdateImport/update_deep_directory_paths.exp.json b/testdata/d2oracle/TestUpdateImport/update_deep_directory_paths.exp.json new file mode 100644 index 000000000..629973701 --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/update_deep_directory_paths.exp.json @@ -0,0 +1,416 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-3:0:37", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-0:16:16", + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "import": { + "range": "index.d2,0:3:3-0:16:16", + "spread": false, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:4:4-0:16:16", + "value": [ + { + "string": "woof/bar/baz", + "raw_string": "woof/bar/baz" + } + ] + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "index.d2,1:0:17-1:17:34", + "key": { + "range": "index.d2,1:0:17-1:1:18", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:17-1:1:18", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "import": { + "range": "index.d2,1:3:20-1:17:34", + "spread": false, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:4:21-1:17:34", + "value": [ + { + "string": "woof/qux/quux", + "raw_string": "woof/qux/quux" + } + ] + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "index.d2,2:0:35-2:1:36", + "key": { + "range": "index.d2,2:0:35-2:1:36", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:35-2:1:36", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof/bar/baz.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof/bar/baz.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof/qux/quux.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof/qux/quux.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "index.d2,1:0:17-1:1:18", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:17-1:1:18", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "index.d2,1:0:17-1:1:18", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:17-1:1:18", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "z", + "id_val": "z", + "references": [ + { + "key": { + "range": "index.d2,2:0:35-2:1:36", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:35-2:1:36", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "z" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": "" +} diff --git a/testdata/d2oracle/TestUpdateImport/update_directory_import.exp.json b/testdata/d2oracle/TestUpdateImport/update_directory_import.exp.json new file mode 100644 index 000000000..26b681263 --- /dev/null +++ b/testdata/d2oracle/TestUpdateImport/update_directory_import.exp.json @@ -0,0 +1,416 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "index.d2,0:0:0-3:0:28", + "nodes": [ + { + "map_key": { + "range": "index.d2,0:0:0-0:12:12", + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "import": { + "range": "index.d2,0:3:3-0:12:12", + "spread": false, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:4:4-0:12:12", + "value": [ + { + "string": "woof/bar", + "raw_string": "woof/bar" + } + ] + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "index.d2,1:0:13-1:12:25", + "key": { + "range": "index.d2,1:0:13-1:1:14", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:13-1:1:14", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "import": { + "range": "index.d2,1:3:16-1:12:25", + "spread": false, + "pre": "", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:4:17-1:12:25", + "value": [ + { + "string": "woof/baz", + "raw_string": "woof/baz" + } + ] + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "index.d2,2:0:26-2:1:27", + "key": { + "range": "index.d2,2:0:26-2:1:27", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:26-2:1:27", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "x", + "id_val": "x", + "references": [ + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "index.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "index.d2,0:0:0-0:1:1", + "value": [ + { + "string": "x", + "raw_string": "x" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "x" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof/bar.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof/bar.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "k", + "id_val": "k", + "references": [ + { + "key": { + "range": "woof/baz.d2,0:0:0-0:1:1", + "path": [ + { + "unquoted_string": { + "range": "woof/baz.d2,0:0:0-0:1:1", + "value": [ + { + "string": "k", + "raw_string": "k" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "k" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "y", + "id_val": "y", + "references": [ + { + "key": { + "range": "index.d2,1:0:13-1:1:14", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:13-1:1:14", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "index.d2,1:0:13-1:1:14", + "path": [ + { + "unquoted_string": { + "range": "index.d2,1:0:13-1:1:14", + "value": [ + { + "string": "y", + "raw_string": "y" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "y" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "z", + "id_val": "z", + "references": [ + { + "key": { + "range": "index.d2,2:0:26-2:1:27", + "path": [ + { + "unquoted_string": { + "range": "index.d2,2:0:26-2:1:27", + "value": [ + { + "string": "z", + "raw_string": "z" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "z" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "iconStyle": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": "" +} From e9040e88e68ce9f218fb0044aad7332b77b667f3 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Wed, 30 Apr 2025 10:43:17 -0600 Subject: [PATCH 12/18] Update next.md --- ci/release/changelogs/next.md | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index 1ede35ee1..b1828ca77 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -1,15 +1,19 @@ #### Features ๐Ÿš€ -- Icons: connections can include icons [#12](https://github.com/terrastruct/d2/issues/12) -- Syntax: `suspend`/`unsuspend` to define models and instantiate them [#2394](https://github.com/terrastruct/d2/pull/2394) +- Icons: + - connections can include icons [#12](https://github.com/terrastruct/d2/issues/12) +- Syntax: + - `suspend`/`unsuspend` to define models and instantiate them [#2394](https://github.com/terrastruct/d2/pull/2394) - Globs: - support for filtering edges based on properties of endpoint nodes (e.g., `&src.style.fill: blue`) [#2395](https://github.com/terrastruct/d2/pull/2395) - `level` filter implemented [#2473](https://github.com/terrastruct/d2/pull/2473) - Render: - markdown, latex, and code can be used as object labels [#2204](https://github.com/terrastruct/d2/pull/2204) - `shape: c4-person` to render a person shape like what the C4 model prescribes [#2397](https://github.com/terrastruct/d2/pull/2397) -- Icons: border-radius should work on icon [#2409](https://github.com/terrastruct/d2/issues/2409) -- Diagram legends are implemented [#2416](https://github.com/terrastruct/d2/pull/2416) +- Icons: + - border-radius should work on icon [#2409](https://github.com/terrastruct/d2/issues/2409) +- Misc: + - Diagram legends are implemented [#2416](https://github.com/terrastruct/d2/pull/2416) #### Improvements ๐Ÿงน @@ -42,12 +46,13 @@ - fixes leaf ampersand filter when used with imports [#2494](https://github.com/terrastruct/d2/pull/2494) - Formatter: - fixes substitutions in quotes surrounded by text [#2462](https://github.com/terrastruct/d2/pull/2462) -- CLI: fetch and render remote images of mimetype octet-stream correctly [#2370](https://github.com/terrastruct/d2/pull/2370) +- CLI: + - fetch and render remote images of mimetype octet-stream correctly [#2370](https://github.com/terrastruct/d2/pull/2370) - Composition: - spread importing scenarios/steps was not inheriting correctly [#2460](https://github.com/terrastruct/d2/pull/2460) - imported fields were not merging with current fields/edges [#2464](https://github.com/terrastruct/d2/pull/2464) -- Markdown: fixes nested var substitutions not working [#2456](https://github.com/terrastruct/d2/pull/2456) -- d2js: handle unicode characters [#2393](https://github.com/terrastruct/d2/pull/2393) +- Markdown: + - fixes nested var substitutions not working [#2456](https://github.com/terrastruct/d2/pull/2456) --- From f648622dcfaac3a99b31c413fb7160f3b2d54d5d Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Wed, 30 Apr 2025 11:21:07 -0600 Subject: [PATCH 13/18] d2oracle: update signature of UpdateImport --- d2oracle/edit.go | 34 +++++-------------- d2oracle/edit_test.go | 77 ++++--------------------------------------- 2 files changed, 14 insertions(+), 97 deletions(-) diff --git a/d2oracle/edit.go b/d2oracle/edit.go index 06a8c0ac9..a06784ef3 100644 --- a/d2oracle/edit.go +++ b/d2oracle/edit.go @@ -3325,42 +3325,24 @@ func filterReservedPath(path []*d2ast.StringBox) (filtered []*d2ast.StringBox) { return } -func UpdateImport(g *d2graph.Graph, boardPath []string, path string, newPath *string) (_ *d2graph.Graph, err error) { +func UpdateImport(dsl, path string, newPath *string) (_ string, err error) { if newPath == nil { defer xdefer.Errorf(&err, "failed to remove import %#v", path) } else { defer xdefer.Errorf(&err, "failed to update import from %#v to %#v", path, *newPath) } - boardG := g - baseAST := g.AST - - if len(boardPath) > 0 { - // When compiling a nested board, we can read from boardG but only write to baseBoardG - boardG = GetBoardGraph(g, boardPath) - if boardG == nil { - return nil, fmt.Errorf("board %v not found", boardPath) - } - // TODO beter name - baseAST = boardG.BaseAST - if baseAST == nil { - return nil, fmt.Errorf("board %v cannot be modified through this file", boardPath) - } + ast, err := d2parser.Parse("", strings.NewReader(dsl), nil) + if err != nil { + return "", err } - _updateImport(boardG, baseAST, path, newPath) + _updateImport(ast, path, newPath) - if len(boardPath) > 0 { - replaced := ReplaceBoardNode(g.AST, baseAST, boardPath) - if !replaced { - return nil, fmt.Errorf("board %v AST not found", boardPath) - } - } - - return recompile(g) + return d2format.Format(ast), nil } -func _updateImport(g *d2graph.Graph, m *d2ast.Map, oldPath string, newPath *string) { +func _updateImport(m *d2ast.Map, oldPath string, newPath *string) { for i := 0; i < len(m.Nodes); i++ { node := m.Nodes[i] @@ -3417,7 +3399,7 @@ func _updateImport(g *d2graph.Graph, m *d2ast.Map, oldPath string, newPath *stri } if node.MapKey.Value.Map != nil { - _updateImport(g, node.MapKey.Value.Map, oldPath, newPath) + _updateImport(node.MapKey.Value.Map, oldPath, newPath) } } } diff --git a/d2oracle/edit_test.go b/d2oracle/edit_test.go index 7a022f355..275e34bab 100644 --- a/d2oracle/edit_test.go +++ b/d2oracle/edit_test.go @@ -9618,9 +9618,6 @@ func TestUpdateImport(t *testing.T) { text: `x: @meow y `, - fsTexts: map[string]string{ - "meow.d2": "k", - }, path: "meow", newPath: nil, exp: `x @@ -9632,9 +9629,6 @@ y text: `x ...@meow y`, - fsTexts: map[string]string{ - "meow.d2": "k", - }, path: "meow", newPath: nil, exp: `x @@ -9647,10 +9641,6 @@ y text: `x: @meow y `, - fsTexts: map[string]string{ - "meow.d2": "k", - "woof.d2": "k", - }, path: "meow", newPath: go2.Pointer("woof"), exp: `x: @woof @@ -9662,10 +9652,6 @@ y text: `x: @foo/meow y `, - fsTexts: map[string]string{ - "foo/meow.d2": "k", - "bar/woof.d2": "k", - }, path: "foo/meow", newPath: go2.Pointer("bar/woof"), exp: `x: @bar/woof @@ -9678,10 +9664,6 @@ y ...@meow y `, - fsTexts: map[string]string{ - "meow.d2": "k", - "woof.d2": "k", - }, path: "meow", newPath: go2.Pointer("woof"), exp: `x @@ -9694,9 +9676,6 @@ y text: `x: @cat y `, - fsTexts: map[string]string{ - "cat.d2": "k", - }, path: "meow", newPath: go2.Pointer("woof"), exp: `x: @cat @@ -9710,10 +9689,6 @@ y y } `, - fsTexts: map[string]string{ - "meow.d2": "k", - "woof.d2": "k", - }, path: "meow", newPath: go2.Pointer("woof"), exp: `container: { @@ -9729,9 +9704,6 @@ y y } `, - fsTexts: map[string]string{ - "meow.d2": "k", - }, path: "meow", newPath: nil, exp: `container: { @@ -9746,10 +9718,6 @@ y y: @meow z `, - fsTexts: map[string]string{ - "meow.d2": "k", - "woof.d2": "k", - }, path: "meow", newPath: go2.Pointer("woof"), exp: `x: @woof @@ -9764,10 +9732,6 @@ y ...@meow z `, - fsTexts: map[string]string{ - "meow.d2": "k", - "woof.d2": "k", - }, path: "meow", newPath: go2.Pointer("woof"), exp: `x: @woof @@ -9786,10 +9750,6 @@ layers: { } } `, - fsTexts: map[string]string{ - "meow.d2": "k", - "woof.d2": "k", - }, path: "meow", newPath: go2.Pointer("woof"), exp: `x @@ -9811,10 +9771,6 @@ layers: { } } `, - fsTexts: map[string]string{ - "meow.d2": "k", - "woof.d2": "k", - }, path: "meow", newPath: go2.Pointer("woof"), exp: `x @@ -9832,12 +9788,6 @@ layers: { y: @foo/baz z `, - fsTexts: map[string]string{ - "foo/bar.d2": "k", - "foo/baz.d2": "k", - "woof/bar.d2": "k", - "woof/baz.d2": "k", - }, path: "foo/", newPath: go2.Pointer("woof/"), exp: `x: @woof/bar @@ -9851,10 +9801,6 @@ z y: @foo/baz z `, - fsTexts: map[string]string{ - "foo/bar.d2": "k", - "foo/baz.d2": "k", - }, path: "foo/", newPath: nil, exp: `x @@ -9868,12 +9814,6 @@ z y: @foo/qux/quux z `, - fsTexts: map[string]string{ - "foo/bar/baz.d2": "k", - "foo/qux/quux.d2": "k", - "woof/bar/baz.d2": "k", - "woof/qux/quux.d2": "k", - }, path: "foo/", newPath: go2.Pointer("woof/"), exp: `x: @woof/bar/baz @@ -9888,18 +9828,13 @@ z t.Run(tc.name, func(t *testing.T) { t.Parallel() - et := editTest{ - text: tc.text, - fsTexts: tc.fsTexts, - testFunc: func(g *d2graph.Graph) (*d2graph.Graph, error) { - return d2oracle.UpdateImport(g, tc.boardPath, tc.path, tc.newPath) - }, - - exp: tc.exp, - expErr: tc.expErr, - assertions: tc.assertions, + got, err := d2oracle.UpdateImport(tc.text, tc.path, tc.newPath) + if err != nil { + t.Fatal(err) + } + if got != tc.exp { + t.Fatalf("tc.exp != newText:\n%s", got) } - et.run(t) }) } } From e954ba07112564fee20a7c29f7dfcfb041cd87af Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Thu, 1 May 2025 12:05:36 -0600 Subject: [PATCH 14/18] handle relative paths for updating imports --- d2oracle/edit.go | 32 +++++++++++++++++++++++++++---- d2oracle/edit_test.go | 44 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 4 deletions(-) diff --git a/d2oracle/edit.go b/d2oracle/edit.go index a06784ef3..bdb548548 100644 --- a/d2oracle/edit.go +++ b/d2oracle/edit.go @@ -3406,11 +3406,35 @@ func _updateImport(m *d2ast.Map, oldPath string, newPath *string) { } func updateImportPath(imp *d2ast.Import, newPath string) { - if len(imp.Path) > 0 { - imp.Path[0] = d2ast.MakeValueBox(d2ast.RawString(newPath, true)).StringBox() - } else { + var pre string + pathPart := newPath + + for i, r := range newPath { + if r != '.' && r != '/' { + pre = newPath[:i] + pathPart = newPath[i:] + break + } + } + + if pre == "" && len(newPath) > 0 && (newPath[0] == '.' || newPath[0] == '/') { + pre = newPath + pathPart = "" + } + + imp.Pre = pre + + if pathPart != "" { + if len(imp.Path) > 0 { + imp.Path[0] = d2ast.MakeValueBox(d2ast.RawString(pathPart, true)).StringBox() + } else { + imp.Path = []*d2ast.StringBox{ + d2ast.MakeValueBox(d2ast.RawString(pathPart, true)).StringBox(), + } + } + } else if len(imp.Path) == 0 { imp.Path = []*d2ast.StringBox{ - d2ast.MakeValueBox(d2ast.RawString(newPath, true)).StringBox(), + d2ast.MakeValueBox(d2ast.RawString("", true)).StringBox(), } } } diff --git a/d2oracle/edit_test.go b/d2oracle/edit_test.go index 275e34bab..c7e8db0ec 100644 --- a/d2oracle/edit_test.go +++ b/d2oracle/edit_test.go @@ -9819,6 +9819,50 @@ z exp: `x: @woof/bar/baz y: @woof/qux/quux z +`, + }, + { + name: "update_relative_import-1", + text: `x: @../meow +y +`, + path: "../meow", + newPath: go2.Pointer("../woof"), + exp: `x: @../woof +y +`, + }, + { + name: "update_relative_import-2", + text: `x: @../meow +y +`, + path: "../meow", + newPath: go2.Pointer("woof"), + exp: `x: @woof +y +`, + }, + { + name: "update_relative_import-3", + text: `x: @../meow +y +`, + path: "../meow", + newPath: go2.Pointer("../meow/woof"), + exp: `x: @../meow/woof +y +`, + }, + { + name: "update_relative_import-4", + text: `x: @../meow +y +`, + path: "../meow", + newPath: go2.Pointer("../g/woof"), + exp: `x: @../g/woof +y `, }, } From d2696c5feeb110d885433140d62f1b38fdfbb910 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Thu, 1 May 2025 16:13:16 -0600 Subject: [PATCH 15/18] bump version --- lib/version/version.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/version/version.go b/lib/version/version.go index a22fd34c2..cf82936fd 100644 --- a/lib/version/version.go +++ b/lib/version/version.go @@ -3,7 +3,7 @@ package version import "regexp" // Pre-built binaries will have version set correctly during build time. -var Version = "v0.6.9-HEAD" +var Version = "v0.7.0-HEAD" func OnlyNumbers() string { re, err := regexp.Compile("[0-9]+.[0-9]+.[0-9]+") From 355f97794a862008091bab098f4a89852f05baa3 Mon Sep 17 00:00:00 2001 From: Alexander Wang Date: Thu, 1 May 2025 16:17:17 -0600 Subject: [PATCH 16/18] ta --- .../testdata/all_shapes/sketch.exp.svg | 2 +- .../testdata/all_shapes_dark/sketch.exp.svg | 2 +- .../d2sketch/testdata/animated/sketch.exp.svg | 2 +- .../testdata/animated_dark/sketch.exp.svg | 2 +- .../testdata/arrowheads/sketch.exp.svg | 2 +- .../testdata/arrowheads_dark/sketch.exp.svg | 2 +- .../d2sketch/testdata/basic/sketch.exp.svg | 2 +- .../testdata/basic_dark/sketch.exp.svg | 2 +- .../testdata/child_to_child/sketch.exp.svg | 2 +- .../child_to_child_dark/sketch.exp.svg | 2 +- .../d2sketch/testdata/class/sketch.exp.svg | 2 +- .../sketch.exp.svg | 2 +- .../testdata/class_dark/sketch.exp.svg | 2 +- .../connection-style-fill/sketch.exp.svg | 2 +- .../testdata/connection_label/sketch.exp.svg | 2 +- .../connection_label_dark/sketch.exp.svg | 2 +- .../testdata/crows_feet/sketch.exp.svg | 2 +- .../testdata/crows_feet_dark/sketch.exp.svg | 2 +- .../d2sketch/testdata/dots-3d/sketch.exp.svg | 2 +- .../d2sketch/testdata/dots-all/sketch.exp.svg | 2 +- .../testdata/dots-multiple/sketch.exp.svg | 2 +- .../testdata/dots-real/sketch.exp.svg | 2 +- .../testdata/double-border/sketch.exp.svg | 2 +- .../testdata/elk_corners/sketch.exp.svg | 2 +- .../long_arrowhead_label/sketch.exp.svg | 2 +- .../d2sketch/testdata/opacity/sketch.exp.svg | 2 +- .../testdata/opacity_dark/sketch.exp.svg | 2 +- .../d2sketch/testdata/overlay/sketch.exp.svg | 2 +- .../testdata/paper-real/sketch.exp.svg | 2 +- .../testdata/root-fill/sketch.exp.svg | 2 +- .../testdata/sql_tables/sketch.exp.svg | 2 +- .../testdata/sql_tables_dark/sketch.exp.svg | 2 +- .../d2sketch/testdata/terminal/sketch.exp.svg | 2 +- .../sketch.exp.svg | 2 +- .../d2sketch/testdata/twitter/sketch.exp.svg | 2 +- .../testdata/twitter_dark/sketch.exp.svg | 2 +- .../testdata/unfilled_triangle/sketch.exp.svg | 2 +- .../diagram_wider_than_tooltip/sketch.exp.svg | 2 +- .../testdata/internal-links/sketch.exp.svg | 2 +- .../appendix/testdata/links/sketch.exp.svg | 2 +- .../testdata/links_dark/sketch.exp.svg | 2 +- .../testdata/tooltip_fill/sketch.exp.svg | 2 +- .../tooltip_wider_than_diagram/sketch.exp.svg | 2 +- .../testdata/all_shapes/dark_theme.exp.svg | 2 +- .../testdata/animated/dark_theme.exp.svg | 2 +- .../testdata/arrowheads/dark_theme.exp.svg | 2 +- .../testdata/basic/dark_theme.exp.svg | 2 +- .../child_to_child/dark_theme.exp.svg | 2 +- .../testdata/class/dark_theme.exp.svg | 2 +- .../testdata/code/dark_theme.exp.svg | 2 +- .../connection_label/dark_theme.exp.svg | 2 +- .../testdata/opacity/dark_theme.exp.svg | 2 +- .../testdata/overlay/dark_theme.exp.svg | 2 +- .../testdata/sql_tables/dark_theme.exp.svg | 2 +- .../testdata/twitter/dark_theme.exp.svg | 2 +- .../testdata/TestCLI_E2E/abspath.exp.svg | 2 +- .../testdata/TestCLI_E2E/animation.exp.svg | 2 +- .../board_import/hello-world-x-y.exp.svg | 2 +- .../board_import/hello-world-x.exp.svg | 2 +- .../board_import/hello-world.exp.svg | 2 +- .../testdata/TestCLI_E2E/center.exp.svg | 2 +- .../TestCLI_E2E/chain_icon_import.exp.svg | 2 +- .../testdata/TestCLI_E2E/chain_import.exp.svg | 2 +- .../testdata/TestCLI_E2E/empty-base.exp.svg | 2 +- .../TestCLI_E2E/hello_world_png.exp.png | Bin 15128 -> 15128 bytes .../TestCLI_E2E/hello_world_png_pad.exp.png | Bin 73268 -> 73268 bytes .../hello_world_png_sketch.exp.png | Bin 21343 -> 21343 bytes .../testdata/TestCLI_E2E/import.exp.svg | 2 +- .../TestCLI_E2E/import_icon_relative.exp.svg | 2 +- .../TestCLI_E2E/import_spread_nested.exp.svg | 2 +- .../testdata/TestCLI_E2E/import_vars.exp.svg | 2 +- .../TestCLI_E2E/layer-link/index.exp.svg | 2 +- .../TestCLI_E2E/layer-link/test2.exp.svg | 2 +- .../TestCLI_E2E/multiboard/life/index.exp.svg | 2 +- .../multiboard/life/layers/broker.exp.svg | 2 +- .../multiboard/life/layers/core.exp.svg | 2 +- .../multiboard/life/layers/stocks.exp.svg | 2 +- .../multiboard/life/scenarios/why.exp.svg | 2 +- .../multiboard/life_index_d2/index.exp.svg | 2 +- .../life_index_d2/layers/broker.exp.svg | 2 +- .../life_index_d2/layers/core.exp.svg | 2 +- .../life_index_d2/layers/stocks.exp.svg | 2 +- .../life_index_d2/scenarios/why.exp.svg | 2 +- .../TestCLI_E2E/pptx-theme-overrides.exp.pptx | Bin 35186 -> 35186 bytes .../TestCLI_E2E/sequence-layer/index.exp.svg | 2 +- .../TestCLI_E2E/sequence-layer/seq.exp.svg | 2 +- .../sequence-spread-layer/index.exp.svg | 2 +- .../sequence-spread-layer/seq.exp.svg | 2 +- .../testdata/TestCLI_E2E/stdin.exp.svg | 2 +- .../testdata/TestCLI_E2E/target-b.exp.svg | 2 +- .../TestCLI_E2E/target-nested-index.exp.svg | 2 +- .../TestCLI_E2E/target-nested-index2.exp.svg | 2 +- .../target-nested-with-special-chars.exp.svg | 2 +- .../testdata/TestCLI_E2E/target-root.exp.svg | 2 +- .../TestCLI_E2E/theme-override.exp.svg | 2 +- .../TestCLI_E2E/vars-animation.exp.svg | 2 +- .../testdata/TestCLI_E2E/vars-config.exp.svg | 2 +- .../testdata/TestCLI_E2E/with-font.exp.svg | 2 +- .../measured/empty-class/dagre/sketch.exp.svg | 2 +- .../measured/empty-shape/dagre/sketch.exp.svg | 2 +- .../empty-sql_table/dagre/sketch.exp.svg | 2 +- .../testdata/patterns/3d/dagre/sketch.exp.svg | 2 +- .../patterns/all_shapes/dagre/sketch.exp.svg | 2 +- .../patterns/multiple/dagre/sketch.exp.svg | 2 +- .../patterns/paper/dagre/sketch.exp.svg | 2 +- .../patterns/real-lines/dagre/sketch.exp.svg | 2 +- .../patterns/real/dagre/sketch.exp.svg | 2 +- .../root-dots-with-fill/dagre/sketch.exp.svg | 2 +- .../patterns/root-dots/dagre/sketch.exp.svg | 2 +- .../patterns/shape/dagre/sketch.exp.svg | 2 +- .../ampersand-escape/dagre/sketch.exp.svg | 2 +- .../ampersand-escape/elk/sketch.exp.svg | 2 +- .../arrowhead_font_color/dagre/sketch.exp.svg | 2 +- .../arrowhead_font_color/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../bold_edge_label/dagre/sketch.exp.svg | 2 +- .../bold_edge_label/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../cloud_shaped_grid/dagre/sketch.exp.svg | 2 +- .../cloud_shaped_grid/elk/sketch.exp.svg | 2 +- .../code_font_size/dagre/sketch.exp.svg | 2 +- .../code_font_size/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../code_leading_newlines/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../code_trailing_newlines/elk/sketch.exp.svg | 2 +- .../cylinder_grid_label/dagre/sketch.exp.svg | 2 +- .../cylinder_grid_label/elk/sketch.exp.svg | 2 +- .../dagre-disconnect/dagre/sketch.exp.svg | 2 +- .../dagre-disconnect/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../dagre_broken_arrowhead/elk/sketch.exp.svg | 2 +- .../dagre_child_id_id/dagre/sketch.exp.svg | 2 +- .../dagre_child_id_id/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre_special_ids/dagre/sketch.exp.svg | 2 +- .../dagre_special_ids/elk/sketch.exp.svg | 2 +- .../disclaimer/dagre/sketch.exp.svg | 2 +- .../regression/disclaimer/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../elk_alignment/dagre/sketch.exp.svg | 2 +- .../elk_alignment/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../elk_loop_panic/dagre/sketch.exp.svg | 2 +- .../elk_loop_panic/elk/sketch.exp.svg | 2 +- .../regression/elk_order/dagre/sketch.exp.svg | 2 +- .../regression/elk_order/elk/sketch.exp.svg | 2 +- .../empty_class_height/dagre/sketch.exp.svg | 2 +- .../empty_class_height/elk/sketch.exp.svg | 2 +- .../empty_nested_grid/dagre/sketch.exp.svg | 2 +- .../empty_nested_grid/elk/sketch.exp.svg | 2 +- .../empty_sequence/dagre/sketch.exp.svg | 2 +- .../empty_sequence/elk/sketch.exp.svg | 2 +- .../glob_dimensions/dagre/sketch.exp.svg | 2 +- .../glob_dimensions/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../grid_in_constant_near/elk/sketch.exp.svg | 2 +- .../regression/grid_oom/dagre/sketch.exp.svg | 2 +- .../regression/grid_oom/elk/sketch.exp.svg | 2 +- .../grid_panic/dagre/sketch.exp.svg | 2 +- .../regression/grid_panic/elk/sketch.exp.svg | 2 +- .../grid_rows_gap_bug/dagre/sketch.exp.svg | 2 +- .../grid_rows_gap_bug/elk/sketch.exp.svg | 2 +- .../grid_with_latex/dagre/sketch.exp.svg | 2 +- .../grid_with_latex/elk/sketch.exp.svg | 2 +- .../regression/hex-fill/dagre/sketch.exp.svg | 2 +- .../regression/hex-fill/elk/sketch.exp.svg | 2 +- .../icons_on_top/dagre/sketch.exp.svg | 2 +- .../icons_on_top/elk/sketch.exp.svg | 2 +- .../just-width/dagre/sketch.exp.svg | 2 +- .../regression/just-width/elk/sketch.exp.svg | 2 +- .../link_with_ampersand/dagre/sketch.exp.svg | 2 +- .../link_with_ampersand/elk/sketch.exp.svg | 2 +- .../long_arrowhead_label/dagre/sketch.exp.svg | 2 +- .../long_arrowhead_label/elk/sketch.exp.svg | 2 +- .../md_font_weight/dagre/sketch.exp.svg | 2 +- .../md_font_weight/elk/sketch.exp.svg | 2 +- .../md_h1_li_li/dagre/sketch.exp.svg | 2 +- .../regression/md_h1_li_li/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../nested_layout_bug/dagre/sketch.exp.svg | 2 +- .../nested_layout_bug/elk/sketch.exp.svg | 2 +- .../nested_steps/dagre/sketch.exp.svg | 2 +- .../nested_steps/elk/sketch.exp.svg | 2 +- .../regression/no-lexer/dagre/sketch.exp.svg | 2 +- .../regression/no-lexer/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../opacity-on-label/dagre/sketch.exp.svg | 2 +- .../opacity-on-label/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../overlapping-edge-label/elk/sketch.exp.svg | 2 +- .../query_param_escape/dagre/sketch.exp.svg | 2 +- .../query_param_escape/elk/sketch.exp.svg | 2 +- .../root-container/dagre/sketch.exp.svg | 2 +- .../root-container/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../regression/slow_grid/dagre/sketch.exp.svg | 2 +- .../regression/slow_grid/elk/sketch.exp.svg | 2 +- .../sql_table_overflow/dagre/sketch.exp.svg | 2 +- .../sql_table_overflow/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../unconnected/dagre/sketch.exp.svg | 2 +- .../regression/unconnected/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../root/border-radius/dagre/sketch.exp.svg | 2 +- .../root/border-radius/elk/sketch.exp.svg | 2 +- .../root/double-border/dagre/sketch.exp.svg | 2 +- .../root/double-border/elk/sketch.exp.svg | 2 +- .../even-stroke-width/dagre/sketch.exp.svg | 2 +- .../root/even-stroke-width/elk/sketch.exp.svg | 2 +- .../testdata/root/fill/dagre/sketch.exp.svg | 2 +- .../testdata/root/fill/elk/sketch.exp.svg | 2 +- .../root/stroke-dash/dagre/sketch.exp.svg | 2 +- .../root/stroke-dash/elk/sketch.exp.svg | 2 +- .../root/stroke-no-width/dagre/sketch.exp.svg | 2 +- .../root/stroke-no-width/elk/sketch.exp.svg | 2 +- .../root/stroke-width/dagre/sketch.exp.svg | 2 +- .../root/stroke-width/elk/sketch.exp.svg | 2 +- .../sanity/1_to_2/dagre/sketch.exp.svg | 2 +- .../testdata/sanity/1_to_2/elk/sketch.exp.svg | 2 +- .../sanity/basic/dagre/sketch.exp.svg | 2 +- .../testdata/sanity/basic/elk/sketch.exp.svg | 2 +- .../child_to_child/dagre/sketch.exp.svg | 2 +- .../sanity/child_to_child/elk/sketch.exp.svg | 2 +- .../connection_label/dagre/sketch.exp.svg | 2 +- .../connection_label/elk/sketch.exp.svg | 2 +- .../sanity/empty/dagre/sketch.exp.svg | 2 +- .../testdata/sanity/empty/elk/sketch.exp.svg | 2 +- .../3d_fill_and_stroke/dagre/sketch.exp.svg | 2 +- .../3d_fill_and_stroke/elk/sketch.exp.svg | 2 +- .../stable/all_shapes/dagre/sketch.exp.svg | 2 +- .../stable/all_shapes/elk/sketch.exp.svg | 2 +- .../all_shapes_link/dagre/sketch.exp.svg | 2 +- .../stable/all_shapes_link/elk/sketch.exp.svg | 2 +- .../all_shapes_multiple/dagre/sketch.exp.svg | 2 +- .../all_shapes_multiple/elk/sketch.exp.svg | 2 +- .../all_shapes_shadow/dagre/sketch.exp.svg | 2 +- .../all_shapes_shadow/elk/sketch.exp.svg | 2 +- .../stable/animated/dagre/sketch.exp.svg | 2 +- .../stable/animated/elk/sketch.exp.svg | 2 +- .../stable/array-classes/dagre/sketch.exp.svg | 2 +- .../stable/array-classes/elk/sketch.exp.svg | 2 +- .../arrowhead_adjustment/dagre/sketch.exp.svg | 2 +- .../arrowhead_adjustment/elk/sketch.exp.svg | 2 +- .../arrowhead_labels/dagre/sketch.exp.svg | 2 +- .../arrowhead_labels/elk/sketch.exp.svg | 2 +- .../arrowhead_scaling/dagre/sketch.exp.svg | 2 +- .../arrowhead_scaling/elk/sketch.exp.svg | 2 +- .../basic-tooltips/dagre/sketch.exp.svg | 2 +- .../stable/basic-tooltips/elk/sketch.exp.svg | 2 +- .../stable/binary_tree/dagre/sketch.exp.svg | 2 +- .../stable/binary_tree/elk/sketch.exp.svg | 2 +- .../stable/bold-mono/dagre/sketch.exp.svg | 2 +- .../stable/bold-mono/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../stable/border-radius/dagre/sketch.exp.svg | 2 +- .../stable/border-radius/elk/sketch.exp.svg | 2 +- .../stable/box_arrowhead/dagre/sketch.exp.svg | 2 +- .../stable/box_arrowhead/elk/sketch.exp.svg | 2 +- .../testdata/stable/br/dagre/sketch.exp.svg | 2 +- .../testdata/stable/br/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../stable/chaos2/dagre/sketch.exp.svg | 2 +- .../testdata/stable/chaos2/elk/sketch.exp.svg | 2 +- .../circle_arrowhead/dagre/sketch.exp.svg | 2 +- .../circle_arrowhead/elk/sketch.exp.svg | 2 +- .../circular_dependency/dagre/sketch.exp.svg | 2 +- .../circular_dependency/elk/sketch.exp.svg | 2 +- .../stable/class/dagre/sketch.exp.svg | 2 +- .../testdata/stable/class/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../stable/classes/dagre/sketch.exp.svg | 2 +- .../stable/classes/elk/sketch.exp.svg | 2 +- .../stable/code_snippet/dagre/sketch.exp.svg | 2 +- .../stable/code_snippet/elk/sketch.exp.svg | 2 +- .../complex-layers/dagre/sketch.exp.svg | 2 +- .../stable/complex-layers/elk/sketch.exp.svg | 2 +- .../connected_container/dagre/sketch.exp.svg | 2 +- .../connected_container/elk/sketch.exp.svg | 2 +- .../constant_near_stress/dagre/sketch.exp.svg | 2 +- .../constant_near_stress/elk/sketch.exp.svg | 2 +- .../constant_near_title/dagre/sketch.exp.svg | 2 +- .../constant_near_title/elk/sketch.exp.svg | 2 +- .../container_edges/dagre/sketch.exp.svg | 2 +- .../stable/container_edges/elk/sketch.exp.svg | 2 +- .../crow_foot_arrowhead/dagre/sketch.exp.svg | 2 +- .../crow_foot_arrowhead/elk/sketch.exp.svg | 2 +- .../stable/cycle-order/dagre/sketch.exp.svg | 2 +- .../stable/cycle-order/elk/sketch.exp.svg | 2 +- .../stable/dagger_grid/dagre/sketch.exp.svg | 2 +- .../stable/dagger_grid/elk/sketch.exp.svg | 2 +- .../dagre-container/dagre/sketch.exp.svg | 2 +- .../stable/dagre-container/elk/sketch.exp.svg | 2 +- .../stable/dagre_spacing/dagre/sketch.exp.svg | 2 +- .../stable/dagre_spacing/elk/sketch.exp.svg | 2 +- .../dagre_spacing_right/dagre/sketch.exp.svg | 2 +- .../dagre_spacing_right/elk/sketch.exp.svg | 2 +- .../stable/dense/dagre/sketch.exp.svg | 2 +- .../testdata/stable/dense/elk/sketch.exp.svg | 2 +- .../different_subgraphs/dagre/sketch.exp.svg | 2 +- .../different_subgraphs/elk/sketch.exp.svg | 2 +- .../stable/direction/dagre/sketch.exp.svg | 2 +- .../stable/direction/elk/sketch.exp.svg | 2 +- .../edge-label-overflow/dagre/sketch.exp.svg | 2 +- .../edge-label-overflow/elk/sketch.exp.svg | 2 +- .../elk_border_radius/dagre/sketch.exp.svg | 2 +- .../elk_border_radius/elk/sketch.exp.svg | 2 +- .../elk_container_height/dagre/sketch.exp.svg | 2 +- .../elk_container_height/elk/sketch.exp.svg | 2 +- .../stable/elk_shim/dagre/sketch.exp.svg | 2 +- .../stable/elk_shim/elk/sketch.exp.svg | 2 +- .../stable/ent2d2_basic/dagre/sketch.exp.svg | 2 +- .../stable/ent2d2_basic/elk/sketch.exp.svg | 2 +- .../stable/ent2d2_right/dagre/sketch.exp.svg | 2 +- .../stable/ent2d2_right/elk/sketch.exp.svg | 2 +- .../executive_grid/dagre/sketch.exp.svg | 2 +- .../stable/executive_grid/elk/sketch.exp.svg | 2 +- .../stable/font_colors/dagre/sketch.exp.svg | 2 +- .../stable/font_colors/elk/sketch.exp.svg | 2 +- .../stable/font_sizes/dagre/sketch.exp.svg | 2 +- .../stable/font_sizes/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../giant_markdown_test/dagre/sketch.exp.svg | 2 +- .../giant_markdown_test/elk/sketch.exp.svg | 2 +- .../stable/grid_animated/dagre/sketch.exp.svg | 2 +- .../stable/grid_animated/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../grid_edge_across_cell/elk/sketch.exp.svg | 2 +- .../stable/grid_even/dagre/sketch.exp.svg | 2 +- .../stable/grid_even/elk/sketch.exp.svg | 2 +- .../stable/grid_gap/dagre/sketch.exp.svg | 2 +- .../stable/grid_gap/elk/sketch.exp.svg | 2 +- .../stable/grid_icon/dagre/sketch.exp.svg | 2 +- .../stable/grid_icon/elk/sketch.exp.svg | 2 +- .../grid_label_positions/dagre/sketch.exp.svg | 2 +- .../grid_label_positions/elk/sketch.exp.svg | 2 +- .../grid_large_checkered/dagre/sketch.exp.svg | 2 +- .../grid_large_checkered/elk/sketch.exp.svg | 2 +- .../stable/grid_nested/dagre/sketch.exp.svg | 2 +- .../stable/grid_nested/elk/sketch.exp.svg | 2 +- .../grid_nested_gap0/dagre/sketch.exp.svg | 2 +- .../grid_nested_gap0/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../grid_outside_labels/dagre/sketch.exp.svg | 2 +- .../grid_outside_labels/elk/sketch.exp.svg | 2 +- .../stable/grid_tests/dagre/sketch.exp.svg | 2 +- .../stable/grid_tests/elk/sketch.exp.svg | 2 +- .../stable/hexagon_3d/dagre/sketch.exp.svg | 2 +- .../stable/hexagon_3d/elk/sketch.exp.svg | 2 +- .../testdata/stable/hr/dagre/sketch.exp.svg | 2 +- .../testdata/stable/hr/elk/sketch.exp.svg | 2 +- .../icon-containers/dagre/sketch.exp.svg | 2 +- .../stable/icon-containers/elk/sketch.exp.svg | 2 +- .../stable/icon-label/dagre/sketch.exp.svg | 2 +- .../stable/icon-label/elk/sketch.exp.svg | 2 +- .../icon_positions/dagre/sketch.exp.svg | 2 +- .../stable/icon_positions/elk/sketch.exp.svg | 2 +- .../stable/images/dagre/sketch.exp.svg | 2 +- .../testdata/stable/images/elk/sketch.exp.svg | 2 +- .../stable/investigate/dagre/sketch.exp.svg | 2 +- .../stable/investigate/elk/sketch.exp.svg | 2 +- .../stable/label-near/dagre/sketch.exp.svg | 2 +- .../stable/label-near/elk/sketch.exp.svg | 2 +- .../label_positions/dagre/sketch.exp.svg | 2 +- .../stable/label_positions/elk/sketch.exp.svg | 2 +- .../stable/large_arch/dagre/sketch.exp.svg | 2 +- .../stable/large_arch/elk/sketch.exp.svg | 2 +- .../stable/latex/dagre/sketch.exp.svg | 2 +- .../testdata/stable/latex/elk/sketch.exp.svg | 2 +- .../legend_with_near_key/dagre/sketch.exp.svg | 2 +- .../legend_with_near_key/elk/sketch.exp.svg | 2 +- .../testdata/stable/li1/dagre/sketch.exp.svg | 2 +- .../testdata/stable/li1/elk/sketch.exp.svg | 2 +- .../testdata/stable/li2/dagre/sketch.exp.svg | 2 +- .../testdata/stable/li2/elk/sketch.exp.svg | 2 +- .../testdata/stable/li3/dagre/sketch.exp.svg | 2 +- .../testdata/stable/li3/elk/sketch.exp.svg | 2 +- .../testdata/stable/li4/dagre/sketch.exp.svg | 2 +- .../testdata/stable/li4/elk/sketch.exp.svg | 2 +- .../stable/links/dagre/sketch.exp.svg | 2 +- .../testdata/stable/links/elk/sketch.exp.svg | 2 +- .../stable/lone_h1/dagre/sketch.exp.svg | 2 +- .../stable/lone_h1/elk/sketch.exp.svg | 2 +- .../stable/markdown/dagre/sketch.exp.svg | 2 +- .../stable/markdown/elk/sketch.exp.svg | 2 +- .../markdown_stroke_fill/dagre/sketch.exp.svg | 2 +- .../markdown_stroke_fill/elk/sketch.exp.svg | 2 +- .../md_2space_newline/dagre/sketch.exp.svg | 2 +- .../md_2space_newline/elk/sketch.exp.svg | 2 +- .../md_backslash_newline/dagre/sketch.exp.svg | 2 +- .../md_backslash_newline/elk/sketch.exp.svg | 2 +- .../md_code_block_fenced/dagre/sketch.exp.svg | 2 +- .../md_code_block_fenced/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../md_code_block_indented/elk/sketch.exp.svg | 2 +- .../md_code_inline/dagre/sketch.exp.svg | 2 +- .../stable/md_code_inline/elk/sketch.exp.svg | 2 +- .../md_fontsize_10/dagre/sketch.exp.svg | 2 +- .../stable/md_fontsize_10/elk/sketch.exp.svg | 2 +- .../stable/md_mixed/dagre/sketch.exp.svg | 2 +- .../stable/md_mixed/elk/sketch.exp.svg | 2 +- .../stable/mono-edge/dagre/sketch.exp.svg | 2 +- .../stable/mono-edge/elk/sketch.exp.svg | 2 +- .../stable/mono-font/dagre/sketch.exp.svg | 2 +- .../stable/mono-font/elk/sketch.exp.svg | 2 +- .../multiline_text/dagre/sketch.exp.svg | 2 +- .../stable/multiline_text/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../multiple_box_selection/elk/sketch.exp.svg | 2 +- .../multiple_offset/dagre/sketch.exp.svg | 2 +- .../stable/multiple_offset/elk/sketch.exp.svg | 2 +- .../multiple_offset_left/dagre/sketch.exp.svg | 2 +- .../multiple_offset_left/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../multiple_person_label/elk/sketch.exp.svg | 2 +- .../multiple_trees/dagre/sketch.exp.svg | 2 +- .../stable/multiple_trees/elk/sketch.exp.svg | 2 +- .../stable/n22_e32/dagre/sketch.exp.svg | 2 +- .../stable/n22_e32/elk/sketch.exp.svg | 2 +- .../stable/near-alone/dagre/sketch.exp.svg | 2 +- .../stable/near-alone/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../nested_diagram_types/dagre/sketch.exp.svg | 2 +- .../nested_diagram_types/elk/sketch.exp.svg | 2 +- .../nested_shape_labels/dagre/sketch.exp.svg | 2 +- .../nested_shape_labels/elk/sketch.exp.svg | 2 +- .../stable/nesting_power/dagre/sketch.exp.svg | 2 +- .../stable/nesting_power/elk/sketch.exp.svg | 2 +- .../number_connections/dagre/sketch.exp.svg | 2 +- .../number_connections/elk/sketch.exp.svg | 2 +- .../one_container_loop/dagre/sketch.exp.svg | 2 +- .../one_container_loop/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../outside_bottom_labels/elk/sketch.exp.svg | 2 +- .../stable/ovals/dagre/sketch.exp.svg | 2 +- .../testdata/stable/ovals/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../testdata/stable/p/dagre/sketch.exp.svg | 2 +- e2etests/testdata/stable/p/elk/sketch.exp.svg | 2 +- .../stable/people/dagre/sketch.exp.svg | 2 +- .../testdata/stable/people/elk/sketch.exp.svg | 2 +- .../testdata/stable/pre/dagre/sketch.exp.svg | 2 +- .../testdata/stable/pre/elk/sketch.exp.svg | 2 +- .../self-referencing/dagre/sketch.exp.svg | 2 +- .../self-referencing/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../sequence_diagram_note/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../sequence_diagram_real/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../sequence_diagram_span/elk/sketch.exp.svg | 2 +- .../sequence_diagrams/dagre/sketch.exp.svg | 2 +- .../sequence_diagrams/elk/sketch.exp.svg | 2 +- .../shebang-codeblock/dagre/sketch.exp.svg | 2 +- .../shebang-codeblock/elk/sketch.exp.svg | 2 +- .../simple_grid_edges/dagre/sketch.exp.svg | 2 +- .../simple_grid_edges/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../stable/sql_tables/dagre/sketch.exp.svg | 2 +- .../stable/sql_tables/elk/sketch.exp.svg | 2 +- .../stable/square_3d/dagre/sketch.exp.svg | 2 +- .../stable/square_3d/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../stable/stylish/dagre/sketch.exp.svg | 2 +- .../stable/stylish/elk/sketch.exp.svg | 2 +- .../stable/teleport_grid/dagre/sketch.exp.svg | 2 +- .../stable/teleport_grid/elk/sketch.exp.svg | 2 +- .../text_font_sizes/dagre/sketch.exp.svg | 2 +- .../stable/text_font_sizes/elk/sketch.exp.svg | 2 +- .../transparent_3d/dagre/sketch.exp.svg | 2 +- .../stable/transparent_3d/elk/sketch.exp.svg | 2 +- .../unfilled_triangle/dagre/sketch.exp.svg | 2 +- .../unfilled_triangle/elk/sketch.exp.svg | 2 +- .../unnamed_only_height/dagre/sketch.exp.svg | 2 +- .../unnamed_only_height/elk/sketch.exp.svg | 2 +- .../unnamed_only_width/dagre/sketch.exp.svg | 2 +- .../unnamed_only_width/elk/sketch.exp.svg | 2 +- .../stable/us_map/dagre/sketch.exp.svg | 2 +- .../testdata/stable/us_map/elk/sketch.exp.svg | 2 +- .../themes/3d-sides/dagre/sketch.exp.svg | 2 +- .../themes/3d-sides/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../themes/origami/dagre/sketch.exp.svg | 2 +- .../themes/origami/elk/sketch.exp.svg | 2 +- .../themes/terminal/dagre/sketch.exp.svg | 2 +- .../themes/terminal/elk/sketch.exp.svg | 2 +- .../terminal_grayscale/dagre/sketch.exp.svg | 2 +- .../terminal_grayscale/elk/sketch.exp.svg | 2 +- .../container_icon_label/dagre/sketch.exp.svg | 2 +- .../container_icon_label/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../shape_set_width_height/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../c4-person-label/dagre/sketch.exp.svg | 2 +- .../txtar/c4-person-label/elk/sketch.exp.svg | 2 +- .../c4-person-shape/dagre/sketch.exp.svg | 2 +- .../txtar/c4-person-shape/elk/sketch.exp.svg | 2 +- .../connection-icons/dagre/sketch.exp.svg | 2 +- .../txtar/connection-icons/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../connection-style-fill/elk/sketch.exp.svg | 2 +- .../connection-underline/dagre/sketch.exp.svg | 2 +- .../connection-underline/elk/sketch.exp.svg | 2 +- .../txtar/dark-theme-md/dagre/sketch.exp.svg | 2 +- .../txtar/dark-theme-md/elk/sketch.exp.svg | 2 +- .../txtar/elk-title-near/dagre/sketch.exp.svg | 2 +- .../txtar/elk-title-near/elk/sketch.exp.svg | 2 +- .../txtar/extended-ascii/dagre/sketch.exp.svg | 2 +- .../txtar/extended-ascii/elk/sketch.exp.svg | 2 +- .../txtar/gradient/dagre/sketch.exp.svg | 2 +- .../txtar/gradient/elk/sketch.exp.svg | 2 +- .../txtar/icon-style/dagre/sketch.exp.svg | 2 +- .../txtar/icon-style/elk/sketch.exp.svg | 2 +- .../txtar/legend/dagre/sketch.exp.svg | 2 +- .../testdata/txtar/legend/elk/sketch.exp.svg | 2 +- .../link-on-connections/dagre/sketch.exp.svg | 2 +- .../link-on-connections/elk/sketch.exp.svg | 2 +- .../txtar/md-label/dagre/sketch.exp.svg | 2 +- .../txtar/md-label/elk/sketch.exp.svg | 2 +- .../txtar/md-tables/dagre/sketch.exp.svg | 2 +- .../txtar/md-tables/elk/sketch.exp.svg | 2 +- .../txtar/model-view/dagre/sketch.exp.svg | 2 +- .../txtar/model-view/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../txtar/none-fill/dagre/sketch.exp.svg | 2 +- .../txtar/none-fill/elk/sketch.exp.svg | 2 +- .../txtar/note-overlap/dagre/sketch.exp.svg | 2 +- .../txtar/note-overlap/elk/sketch.exp.svg | 2 +- .../opacity-zero-route/dagre/sketch.exp.svg | 2 +- .../opacity-zero-route/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../sequence-bounding-box/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../sequence-fontsize/dagre/sketch.exp.svg | 2 +- .../sequence-fontsize/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../txtar/shape-animate/dagre/sketch.exp.svg | 2 +- .../txtar/shape-animate/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../single-backslash-latex/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../small-c4-person/dagre/sketch.exp.svg | 2 +- .../txtar/small-c4-person/elk/sketch.exp.svg | 2 +- .../sql-casing-panic/dagre/sketch.exp.svg | 2 +- .../txtar/sql-casing-panic/elk/sketch.exp.svg | 2 +- .../txtar/sql-icon/dagre/sketch.exp.svg | 2 +- .../txtar/sql-icon/elk/sketch.exp.svg | 2 +- .../sql-table-reserved/dagre/sketch.exp.svg | 2 +- .../sql-table-reserved/elk/sketch.exp.svg | 2 +- .../theme-overrides/dagre/sketch.exp.svg | 2 +- .../txtar/theme-overrides/elk/sketch.exp.svg | 2 +- .../txtar/unicode/dagre/sketch.exp.svg | 2 +- .../testdata/txtar/unicode/elk/sketch.exp.svg | 2 +- .../var_in_markdown/dagre/sketch.exp.svg | 2 +- .../txtar/var_in_markdown/elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../dagre/sketch.exp.svg | 2 +- .../elk/sketch.exp.svg | 2 +- .../unicode/chinese/dagre/sketch.exp.svg | 2 +- .../unicode/chinese/elk/sketch.exp.svg | 2 +- .../unicode/emojis/dagre/sketch.exp.svg | 2 +- .../unicode/emojis/elk/sketch.exp.svg | 2 +- .../japanese-basic/dagre/sketch.exp.svg | 2 +- .../unicode/japanese-basic/elk/sketch.exp.svg | 2 +- .../japanese-full/dagre/sketch.exp.svg | 2 +- .../unicode/japanese-full/elk/sketch.exp.svg | 2 +- .../japanese-mixed/dagre/sketch.exp.svg | 2 +- .../unicode/japanese-mixed/elk/sketch.exp.svg | 2 +- .../unicode/korean/dagre/sketch.exp.svg | 2 +- .../unicode/korean/elk/sketch.exp.svg | 2 +- .../mixed-language-2/dagre/sketch.exp.svg | 2 +- .../mixed-language-2/elk/sketch.exp.svg | 2 +- .../mixed-language/dagre/sketch.exp.svg | 2 +- .../unicode/mixed-language/elk/sketch.exp.svg | 2 +- .../unicode/with-style/dagre/sketch.exp.svg | 2 +- .../unicode/with-style/elk/sketch.exp.svg | 2 +- 676 files changed, 672 insertions(+), 672 deletions(-) diff --git a/d2renderers/d2sketch/testdata/all_shapes/sketch.exp.svg b/d2renderers/d2sketch/testdata/all_shapes/sketch.exp.svg index daba1652f..a07f5b49f 100644 --- a/d2renderers/d2sketch/testdata/all_shapes/sketch.exp.svg +++ b/d2renderers/d2sketch/testdata/all_shapes/sketch.exp.svg @@ -1,4 +1,4 @@ -