diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index f3c0d2a77..d3ade4923 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -3,3 +3,5 @@ #### Improvements 🧹 #### Bugfixes ⛑️ + +- Restricts where `near` key constant values can be used, with good error messages, instead of erroring (e.g. setting `near: top-center` on a container would cause bad layouts or error). [#538](https://github.com/terrastruct/d2/pull/538) diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 9ca373d81..86e6e63d3 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -860,6 +860,23 @@ func (c *compiler) validateNear(g *d2graph.Graph) { c.errorf(obj.Attributes.NearKey.GetRange().Start, obj.Attributes.NearKey.GetRange().End, "constant near keys can only be set on root level shapes") continue } + if !isKey && isConst && len(obj.ChildrenArray) > 0 { + c.errorf(obj.Attributes.NearKey.GetRange().Start, obj.Attributes.NearKey.GetRange().End, "constant near keys cannot be set on shapes with children") + continue + } + if !isKey && isConst { + is := false + for _, e := range g.Edges { + if e.Src == obj || e.Dst == obj { + is = true + break + } + } + if is { + c.errorf(obj.Attributes.NearKey.GetRange().Start, obj.Attributes.NearKey.GetRange().End, "constant near keys cannot be set on connected shapes") + continue + } + } } } } diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 29d99cee0..cf7283649 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -1278,6 +1278,28 @@ x -> y: { text: `x.near: txop-center `, expErr: `d2/testdata/d2compiler/TestCompile/near_bad_constant.d2:1:1: near key "txop-center" must be the absolute path to a shape or one of the following constants: top-left, top-center, top-right, center-left, center-right, bottom-left, bottom-center, bottom-right +`, + }, + { + name: "near_bad_container", + + text: `x: { + near: top-center + y +} +`, + expErr: `d2/testdata/d2compiler/TestCompile/near_bad_container.d2:1:1: constant near keys cannot be set on shapes with children +`, + }, + { + name: "near_bad_connected", + + text: `x: { + near: top-center +} +x -> y +`, + expErr: `d2/testdata/d2compiler/TestCompile/near_bad_connected.d2:1:1: constant near keys cannot be set on connected shapes `, }, { diff --git a/testdata/d2compiler/TestCompile/near_bad_connected.exp.json b/testdata/d2compiler/TestCompile/near_bad_connected.exp.json new file mode 100644 index 000000000..91e282c20 --- /dev/null +++ b/testdata/d2compiler/TestCompile/near_bad_connected.exp.json @@ -0,0 +1,12 @@ +{ + "graph": null, + "err": { + "ioerr": null, + "errs": [ + { + "range": "d2/testdata/d2compiler/TestCompile/near_bad_connected.d2,0:0:0-0:10:10", + "errmsg": "d2/testdata/d2compiler/TestCompile/near_bad_connected.d2:1:1: constant near keys cannot be set on connected shapes" + } + ] + } +} diff --git a/testdata/d2compiler/TestCompile/near_bad_container.exp.json b/testdata/d2compiler/TestCompile/near_bad_container.exp.json new file mode 100644 index 000000000..9ccaeb300 --- /dev/null +++ b/testdata/d2compiler/TestCompile/near_bad_container.exp.json @@ -0,0 +1,12 @@ +{ + "graph": null, + "err": { + "ioerr": null, + "errs": [ + { + "range": "d2/testdata/d2compiler/TestCompile/near_bad_container.d2,0:0:0-0:10:10", + "errmsg": "d2/testdata/d2compiler/TestCompile/near_bad_container.d2:1:1: constant near keys cannot be set on shapes with children" + } + ] + } +}