diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 520d7ca04..640c949b4 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -5198,20 +5198,21 @@ y.link: https://google.com }, }, { - name: "exists-filter", + name: "leaf-filter", run: func(t *testing.T) { g, _ := assertCompile(t, ` -**.style.fill: red { +**: { &leaf: false + style.fill: red } a.b.c `, ``) assert.Equal(t, "a", g.Objects[0].ID) assert.Equal(t, "red", g.Objects[0].Attributes.Style.Fill.Value) - assert.Equal(t, "b", g.Objects[1].Attributes.Style.Fill.Value) + assert.Equal(t, "b", g.Objects[1].ID) assert.Equal(t, "red", g.Objects[1].Attributes.Style.Fill.Value) - assert.Equal(t, "c", g.Objects[2].Attributes.Style.Fill.Value) - assert.NotEqual(t, "red", g.Objects[2].Attributes.Style.Fill.Value) + assert.Equal(t, "c", g.Objects[2].ID) + assert.Equal(t, (*d2graph.Scalar)(nil), g.Objects[2].Attributes.Style.Fill) }, }, { diff --git a/d2ir/compile.go b/d2ir/compile.go index fe28a1c1b..57acd3bb2 100644 --- a/d2ir/compile.go +++ b/d2ir/compile.go @@ -750,6 +750,17 @@ func (c *compiler) ampersandFilter(refctx *RefContext) bool { }, } return c._ampersandFilter(f, refctx) + case "leaf": + raw := refctx.Key.Value.ScalarBox().Unbox().ScalarString() + boolVal, err := strconv.ParseBool(raw) + if err != nil { + c.errorf(refctx.Key, `&leaf must be "true" or "false", got %q`, raw) + return false + } + + f := refctx.ScopeMap.Parent().(*Field) + isLeaf := f.Map() == nil || !f.Map().IsContainer() + return isLeaf == boolVal case "label": f := &Field{} n := refctx.ScopeMap.Parent() diff --git a/testdata/d2compiler/TestCompile2/globs/leaf-filter.exp.json b/testdata/d2compiler/TestCompile2/globs/leaf-filter.exp.json new file mode 100644 index 000000000..cfb785772 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/globs/leaf-filter.exp.json @@ -0,0 +1,399 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,0:0:0-6:0:48", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,1:0:1-4:1:41", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,1:0:1-1:2:3", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,1:0:1-1:2:3", + "value": [ + { + "string": "**", + "raw_string": "**" + } + ], + "pattern": [ + "*", + "", + "*" + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,1:4:5-4:1:41", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,2:2:9-2:14:21", + "ampersand": true, + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,2:3:10-2:7:14", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,2:3:10-2:7:14", + "value": [ + { + "string": "leaf", + "raw_string": "leaf" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "boolean": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,2:9:16-2:14:21", + "value": false + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,3:2:24-3:17:39", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,3:2:24-3:12:34", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,3:2:24-3:7:29", + "value": [ + { + "string": "style", + "raw_string": "style" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,3:8:30-3:12:34", + "value": [ + { + "string": "fill", + "raw_string": "fill" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,3:14:36-3:17:39", + "value": [ + { + "string": "red", + "raw_string": "red" + } + ] + } + } + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:0:42-5:5:47", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:0:42-5:5:47", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:0:42-5:1:43", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:2:44-5:3:45", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:4:46-5:5:47", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": null, + "objects": [ + { + "id": "a", + "id_val": "a", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:0:42-5:5:47", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:0:42-5:1:43", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:2:44-5:3:45", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:4:46-5:5:47", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "a" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": { + "fill": { + "value": "red" + } + }, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "b", + "id_val": "b", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:0:42-5:5:47", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:0:42-5:1:43", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:2:44-5:3:45", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:4:46-5:5:47", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "key_path_index": 1, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "b" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": { + "fill": { + "value": "red" + } + }, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "c", + "id_val": "c", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:0:42-5:5:47", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:0:42-5:1:43", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:2:44-5:3:45", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/leaf-filter.d2,5:4:46-5:5:47", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "key_path_index": 2, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "c" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": null +}