diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index 63cd026c6..9092a7ff6 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -1,6 +1,7 @@ #### 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) #### Improvements ๐Ÿงน diff --git a/d2ast/d2ast.go b/d2ast/d2ast.go index b0e9386e9..807b7c93c 100644 --- a/d2ast/d2ast.go +++ b/d2ast/d2ast.go @@ -56,6 +56,7 @@ var _ Node = &Comment{} var _ Node = &BlockComment{} var _ Node = &Null{} +var _ Node = &Suspension{} var _ Node = &Boolean{} var _ Node = &Number{} var _ Node = &UnquotedString{} @@ -329,6 +330,7 @@ type Scalar interface { // See String for rest. var _ Scalar = &Null{} +var _ Scalar = &Suspension{} var _ Scalar = &Boolean{} var _ Scalar = &Number{} @@ -349,6 +351,7 @@ var _ String = &BlockString{} func (c *Comment) node() {} func (c *BlockComment) node() {} func (n *Null) node() {} +func (n *Suspension) node() {} func (b *Boolean) node() {} func (n *Number) node() {} func (s *UnquotedString) node() {} @@ -367,6 +370,7 @@ func (i *EdgeIndex) node() {} func (c *Comment) Type() string { return "comment" } func (c *BlockComment) Type() string { return "block comment" } func (n *Null) Type() string { return "null" } +func (n *Suspension) Type() string { return "suspension" } func (b *Boolean) Type() string { return "boolean" } func (n *Number) Type() string { return "number" } func (s *UnquotedString) Type() string { return "unquoted string" } @@ -385,6 +389,7 @@ func (i *EdgeIndex) Type() string { return "edge index" } func (c *Comment) GetRange() Range { return c.Range } func (c *BlockComment) GetRange() Range { return c.Range } func (n *Null) GetRange() Range { return n.Range } +func (n *Suspension) GetRange() Range { return n.Range } func (b *Boolean) GetRange() Range { return b.Range } func (n *Number) GetRange() Range { return n.Range } func (s *UnquotedString) GetRange() Range { return s.Range } @@ -409,6 +414,7 @@ func (i *Import) mapNode() {} func (c *Comment) arrayNode() {} func (c *BlockComment) arrayNode() {} func (n *Null) arrayNode() {} +func (n *Suspension) arrayNode() {} func (b *Boolean) arrayNode() {} func (n *Number) arrayNode() {} func (s *UnquotedString) arrayNode() {} @@ -421,6 +427,7 @@ func (a *Array) arrayNode() {} func (m *Map) arrayNode() {} func (n *Null) value() {} +func (n *Suspension) value() {} func (b *Boolean) value() {} func (n *Number) value() {} func (s *UnquotedString) value() {} @@ -432,6 +439,7 @@ func (m *Map) value() {} func (i *Import) value() {} func (n *Null) scalar() {} +func (n *Suspension) scalar() {} func (b *Boolean) scalar() {} func (n *Number) scalar() {} func (s *UnquotedString) scalar() {} @@ -442,6 +450,7 @@ func (s *BlockString) scalar() {} func (c *Comment) Children() []Node { return nil } func (c *BlockComment) Children() []Node { return nil } func (n *Null) Children() []Node { return nil } +func (n *Suspension) Children() []Node { return nil } func (b *Boolean) Children() []Node { return nil } func (n *Number) Children() []Node { return nil } func (s *SingleQuotedString) Children() []Node { return nil } @@ -573,9 +582,10 @@ func Walk(node Node, fn func(Node) bool) { } // TODO: mistake, move into parse.go -func (n *Null) ScalarString() string { return "" } -func (b *Boolean) ScalarString() string { return strconv.FormatBool(b.Value) } -func (n *Number) ScalarString() string { return n.Raw } +func (n *Null) ScalarString() string { return "" } +func (n *Suspension) ScalarString() string { return "" } +func (b *Boolean) ScalarString() string { return strconv.FormatBool(b.Value) } +func (n *Number) ScalarString() string { return n.Raw } func (s *UnquotedString) ScalarString() string { if len(s.Value) == 0 { return "" @@ -631,6 +641,11 @@ type Null struct { Range Range `json:"range"` } +type Suspension struct { + Range Range `json:"range"` + Value bool `json:"value"` +} + type Boolean struct { Range Range `json:"range"` Value bool `json:"value"` @@ -1369,6 +1384,7 @@ func (ab ArrayNodeBox) Unbox() ArrayNode { // ValueBox is used to box Value for JSON persistence. type ValueBox struct { Null *Null `json:"null,omitempty"` + Suspension *Suspension `json:"suspension,omitempty"` Boolean *Boolean `json:"boolean,omitempty"` Number *Number `json:"number,omitempty"` UnquotedString *UnquotedString `json:"unquoted_string,omitempty"` @@ -1384,6 +1400,8 @@ func (vb ValueBox) Unbox() Value { switch { case vb.Null != nil: return vb.Null + case vb.Suspension != nil: + return vb.Suspension case vb.Boolean != nil: return vb.Boolean case vb.Number != nil: @@ -1412,6 +1430,8 @@ func MakeValueBox(v Value) ValueBox { switch v := v.(type) { case *Null: vb.Null = v + case *Suspension: + vb.Suspension = v case *Boolean: vb.Boolean = v case *Number: @@ -1437,6 +1457,7 @@ func MakeValueBox(v Value) ValueBox { func (vb ValueBox) ScalarBox() ScalarBox { var sb ScalarBox sb.Null = vb.Null + sb.Suspension = vb.Suspension sb.Boolean = vb.Boolean sb.Number = vb.Number sb.UnquotedString = vb.UnquotedString @@ -1459,6 +1480,7 @@ func (vb ValueBox) StringBox() *StringBox { // TODO: implement ScalarString() type ScalarBox struct { Null *Null `json:"null,omitempty"` + Suspension *Suspension `json:"suspension,omitempty"` Boolean *Boolean `json:"boolean,omitempty"` Number *Number `json:"number,omitempty"` UnquotedString *UnquotedString `json:"unquoted_string,omitempty"` @@ -1471,6 +1493,8 @@ func (sb ScalarBox) Unbox() Scalar { switch { case sb.Null != nil: return sb.Null + case sb.Suspension != nil: + return sb.Suspension case sb.Boolean != nil: return sb.Boolean case sb.Number != nil: @@ -1559,7 +1583,7 @@ func RawString(s string, inKey bool) String { return &SingleQuotedString{Value: s} } } - } else if s == "null" || strings.ContainsAny(s, UnquotedValueSpecials) { + } else if s == "null" || s == "suspend" || s == "unsuspend" || strings.ContainsAny(s, UnquotedValueSpecials) { if !strings.ContainsRune(s, '"') && !strings.ContainsRune(s, '$') { return FlatDoubleQuotedString(s) } diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 5928cd164..cabe05031 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -5471,6 +5471,34 @@ a.width: 339 assert.Equal(t, 5, len(g.Objects)) }, }, + { + name: "suspension-lazy", + run: func(t *testing.T) { + g, _ := assertCompile(t, ` +a -> b +c +**: suspend +(** -> **)[*]: suspend +d +`, ``) + assert.Equal(t, 1, len(g.Objects)) + }, + }, + { + name: "suspension-quotes", + run: func(t *testing.T) { + g, _ := assertCompile(t, ` +a -> b +c +**: suspend +(** -> **)[*]: suspend +d: "suspend" +d -> d: "suspend" +`, ``) + assert.Equal(t, 1, len(g.Objects)) + assert.Equal(t, 1, len(g.Edges)) + }, + }, } for _, tc := range tca { diff --git a/d2ir/compile.go b/d2ir/compile.go index 668bc9190..5e1647ea0 100644 --- a/d2ir/compile.go +++ b/d2ir/compile.go @@ -81,6 +81,7 @@ func Compile(ast *d2ast.Map, opts *CompileOptions) (*Map, []string, error) { c.compileMap(m, ast, ast) c.compileSubstitutions(m, nil) c.overlayClasses(m) + m.removeSuspendedFields() if !c.err.Empty() { return nil, nil, c.err } @@ -866,6 +867,17 @@ func (c *compiler) _compileField(f *Field, refctx *RefContext) { } } + if len(refctx.Key.Edges) == 0 && (refctx.Key.Primary.Suspension != nil || refctx.Key.Value.Suspension != nil) { + if !c.lazyGlobBeingApplied { + if refctx.Key.Primary.Suspension != nil { + f.suspended = refctx.Key.Primary.Suspension.Value + } else { + f.suspended = refctx.Key.Value.Suspension.Value + } + } + return + } + if refctx.Key.Primary.Unbox() != nil { if c.ignoreLazyGlob(f) { return @@ -1164,6 +1176,17 @@ func (c *compiler) _compileEdges(refctx *RefContext) { refctx.ScopeMap.DeleteEdge(e.ID) continue } + + if refctx.Key.Primary.Suspension != nil || refctx.Key.Value.Suspension != nil { + if !c.lazyGlobBeingApplied { + if refctx.Key.Primary.Suspension != nil { + e.suspended = refctx.Key.Primary.Suspension.Value + } else { + e.suspended = refctx.Key.Value.Suspension.Value + } + } + } + e.References = append(e.References, &EdgeReference{ Context_: refctx, DueToGlob_: len(c.globRefContextStack) > 0, @@ -1289,3 +1312,39 @@ func (c *compiler) compileArray(dst *Array, a *d2ast.Array, scopeAST *d2ast.Map) dst.Values = append(dst.Values, irv) } } + +func (m *Map) removeSuspendedFields() { + if m == nil { + return + } + + for _, f := range m.Fields { + if f.Map() != nil { + f.Map().removeSuspendedFields() + } + } + + for i := len(m.Fields) - 1; i >= 0; i-- { + if m.Fields[i].Name == nil { + continue + } + _, isReserved := d2ast.ReservedKeywords[m.Fields[i].Name.ScalarString()] + if isReserved { + continue + } + if m.Fields[i].suspended { + m.DeleteField(m.Fields[i].Name.ScalarString()) + } + } + + for _, e := range m.Edges { + if e.Map() != nil { + e.Map().removeSuspendedFields() + } + } + for i := len(m.Edges) - 1; i >= 0; i-- { + if m.Edges[i].suspended { + m.DeleteEdge(m.Edges[i].ID) + } + } +} diff --git a/d2ir/d2ir.go b/d2ir/d2ir.go index d5d014515..4ea360b92 100644 --- a/d2ir/d2ir.go +++ b/d2ir/d2ir.go @@ -318,6 +318,7 @@ type Field struct { // *Map. parent Node importAST d2ast.Node + suspended bool Name d2ast.String `json:"name"` @@ -488,6 +489,7 @@ type Edge struct { // *Map parent Node importAST d2ast.Node + suspended bool ID *EdgeID `json:"edge_id"` diff --git a/d2parser/parse.go b/d2parser/parse.go index 3eb500484..e9d57b0ec 100644 --- a/d2parser/parse.go +++ b/d2parser/parse.go @@ -1668,6 +1668,20 @@ func (p *parser) parseValue() d2ast.ValueBox { } return box } + if strings.EqualFold(s.ScalarString(), "suspend") { + box.Suspension = &d2ast.Suspension{ + Range: s.Range, + Value: true, + } + return box + } + if strings.EqualFold(s.ScalarString(), "unsuspend") { + box.Suspension = &d2ast.Suspension{ + Range: s.Range, + Value: false, + } + return box + } if strings.EqualFold(s.ScalarString(), "true") { box.Boolean = &d2ast.Boolean{ diff --git a/e2etests/testdata/txtar/model-view/dagre/board.exp.json b/e2etests/testdata/txtar/model-view/dagre/board.exp.json new file mode 100644 index 000000000..901a987f6 --- /dev/null +++ b/e2etests/testdata/txtar/model-view/dagre/board.exp.json @@ -0,0 +1,322 @@ +{ + "name": "", + "config": { + "sketch": false, + "themeID": 0, + "darkThemeID": null, + "pad": null, + "center": null, + "layoutEngine": null + }, + "isFolderOnly": false, + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "user", + "type": "rectangle", + "pos": { + "x": 0, + "y": 50 + }, + "width": 77, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "blue", + "stroke": "B1", + "animated": false, + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "user", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 32, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "softwareSystem", + "type": "rectangle", + "pos": { + "x": 127, + "y": 20 + }, + "width": 331, + "height": 126, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "animated": false, + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "softwareSystem", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 188, + "labelHeight": 36, + "labelPosition": "OUTSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "softwareSystem.serviceA", + "type": "rectangle", + "classes": [ + "ok" + ], + "pos": { + "x": 157, + "y": 50 + }, + "width": 106, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "animated": false, + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "serviceA", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 61, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "softwareSystem.serviceC", + "type": "rectangle", + "classes": [ + "ok" + ], + "pos": { + "x": 323, + "y": 50 + }, + "width": 105, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "animated": false, + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "serviceC", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 60, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "externalSystem", + "type": "rectangle", + "pos": { + "x": 297, + "y": 266 + }, + "width": 157, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "animated": false, + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "externalSystem", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 112, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(softwareSystem -> externalSystem)[0]", + "src": "softwareSystem", + "srcArrow": "none", + "dst": "externalSystem", + "dstArrow": "triangle", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "B1", + "borderRadius": 10, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N2", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "link": "", + "route": [ + { + "x": 375.5, + "y": 146 + }, + { + "x": 375.5, + "y": 202 + }, + { + "x": 375.5, + "y": 226 + }, + { + "x": 375.5, + "y": 266 + } + ], + "isCurve": true, + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ], + "root": { + "id": "", + "type": "", + "pos": { + "x": 0, + "y": 0 + }, + "width": 0, + "height": 0, + "opacity": 0, + "strokeDash": 0, + "strokeWidth": 0, + "borderRadius": 0, + "fill": "N7", + "stroke": "", + "animated": false, + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 0 + } +} diff --git a/e2etests/testdata/txtar/model-view/dagre/sketch.exp.svg b/e2etests/testdata/txtar/model-view/dagre/sketch.exp.svg new file mode 100644 index 000000000..8773ebf93 --- /dev/null +++ b/e2etests/testdata/txtar/model-view/dagre/sketch.exp.svg @@ -0,0 +1,106 @@ +usersoftwareSystemexternalSystemserviceAserviceC + + + + + + + \ No newline at end of file diff --git a/e2etests/testdata/txtar/model-view/elk/board.exp.json b/e2etests/testdata/txtar/model-view/elk/board.exp.json new file mode 100644 index 000000000..7a2d1c3a2 --- /dev/null +++ b/e2etests/testdata/txtar/model-view/elk/board.exp.json @@ -0,0 +1,313 @@ +{ + "name": "", + "config": { + "sketch": false, + "themeID": 0, + "darkThemeID": null, + "pad": null, + "center": null, + "layoutEngine": null + }, + "isFolderOnly": false, + "fontFamily": "SourceSansPro", + "shapes": [ + { + "id": "user", + "type": "rectangle", + "pos": { + "x": 12, + "y": 62 + }, + "width": 77, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "blue", + "stroke": "B1", + "animated": false, + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "user", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 32, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "softwareSystem", + "type": "rectangle", + "pos": { + "x": 109, + "y": 12 + }, + "width": 331, + "height": 166, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B4", + "stroke": "B1", + "animated": false, + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "softwareSystem", + "fontSize": 28, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 188, + "labelHeight": 36, + "labelPosition": "INSIDE_TOP_CENTER", + "zIndex": 0, + "level": 1 + }, + { + "id": "softwareSystem.serviceA", + "type": "rectangle", + "classes": [ + "ok" + ], + "pos": { + "x": 159, + "y": 62 + }, + "width": 106, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "animated": false, + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "serviceA", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 61, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "softwareSystem.serviceC", + "type": "rectangle", + "classes": [ + "ok" + ], + "pos": { + "x": 285, + "y": 62 + }, + "width": 105, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B5", + "stroke": "B1", + "animated": false, + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "serviceC", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 60, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 2 + }, + { + "id": "externalSystem", + "type": "rectangle", + "pos": { + "x": 196, + "y": 248 + }, + "width": 157, + "height": 66, + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "borderRadius": 0, + "fill": "B6", + "stroke": "B1", + "animated": false, + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "externalSystem", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N1", + "italic": false, + "bold": true, + "underline": false, + "labelWidth": 112, + "labelHeight": 21, + "labelPosition": "INSIDE_MIDDLE_CENTER", + "zIndex": 0, + "level": 1 + } + ], + "connections": [ + { + "id": "(softwareSystem -> externalSystem)[0]", + "src": "softwareSystem", + "srcArrow": "none", + "dst": "externalSystem", + "dstArrow": "triangle", + "opacity": 1, + "strokeDash": 0, + "strokeWidth": 2, + "stroke": "B1", + "borderRadius": 10, + "label": "", + "fontSize": 16, + "fontFamily": "DEFAULT", + "language": "", + "color": "N2", + "italic": true, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "labelPosition": "", + "labelPercentage": 0, + "link": "", + "route": [ + { + "x": 274.5, + "y": 178 + }, + { + "x": 274.5, + "y": 248 + } + ], + "animated": false, + "tooltip": "", + "icon": null, + "zIndex": 0 + } + ], + "root": { + "id": "", + "type": "", + "pos": { + "x": 0, + "y": 0 + }, + "width": 0, + "height": 0, + "opacity": 0, + "strokeDash": 0, + "strokeWidth": 0, + "borderRadius": 0, + "fill": "N7", + "stroke": "", + "animated": false, + "shadow": false, + "3d": false, + "multiple": false, + "double-border": false, + "tooltip": "", + "link": "", + "icon": null, + "iconPosition": "", + "blend": false, + "fields": null, + "methods": null, + "columns": null, + "label": "", + "fontSize": 0, + "fontFamily": "", + "language": "", + "color": "", + "italic": false, + "bold": false, + "underline": false, + "labelWidth": 0, + "labelHeight": 0, + "zIndex": 0, + "level": 0 + } +} diff --git a/e2etests/testdata/txtar/model-view/elk/sketch.exp.svg b/e2etests/testdata/txtar/model-view/elk/sketch.exp.svg new file mode 100644 index 000000000..890eccd04 --- /dev/null +++ b/e2etests/testdata/txtar/model-view/elk/sketch.exp.svg @@ -0,0 +1,106 @@ +usersoftwareSystemexternalSystemserviceAserviceC + + + + + + + \ No newline at end of file diff --git a/e2etests/txtar.txt b/e2etests/txtar.txt index fcc6a7619..c4be32876 100644 --- a/e2etests/txtar.txt +++ b/e2etests/txtar.txt @@ -775,3 +775,33 @@ a -> b: hello { b -> c: { icon: https://icons.terrastruct.com/essentials%2F213-alarm.svg } + +-- model-view -- +# Models +user.style.fill: blue +softwareSystem: { + serviceA.class: ok + serviceB + serviceC.class: ok + serviceD + + serviceA -> serviceB + serviceA -> serviceD + serviceC -> serviceB +} +externalSystem +user -> softwareSystem +softwareSystem -> externalSystem + +# Clear models +**: suspend +(** -> **)[*]: suspend + +# Include all top-level objects +*: unsuspend +# Include all objects with a certain class +**: unsuspend { + &class: ok +} +# Include all connections/objects connected to an object +(** -> externalSystem)[*]: unsuspend diff --git a/testdata/d2compiler/TestCompile2/globs/suspension-lazy.exp.json b/testdata/d2compiler/TestCompile2/globs/suspension-lazy.exp.json new file mode 100644 index 000000000..78d2710a9 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/globs/suspension-lazy.exp.json @@ -0,0 +1,274 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,0:0:0-6:0:47", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,1:0:1-1:6:7", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,1:0:1-1:6:7", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,1:5:6-1:6:7", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,1:5:6-1:6:7", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,2:0:8-2:1:9", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,2:0:8-2:1:9", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,2:0:8-2:1:9", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,3:0:10-3:11:21", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,3:0:10-3:2:12", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,3:0:10-3:2:12", + "value": [ + { + "string": "**", + "raw_string": "**" + } + ], + "pattern": [ + "*", + "", + "*" + ] + } + } + ] + }, + "primary": {}, + "value": { + "suspension": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,3:4:14-3:11:21", + "value": true + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,4:0:22-4:22:44", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,4:1:23-4:9:31", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,4:1:23-4:3:25", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,4:1:23-4:3:25", + "value": [ + { + "string": "**", + "raw_string": "**" + } + ], + "pattern": [ + "*", + "", + "*" + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,4:7:29-4:9:31", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,4:7:29-4:9:31", + "value": [ + { + "string": "**", + "raw_string": "**" + } + ], + "pattern": [ + "*", + "", + "*" + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "edge_index": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,4:10:32-4:13:35", + "int": null, + "glob": true + }, + "primary": {}, + "value": { + "suspension": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,4:15:37-4:22:44", + "value": true + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,5:0:45-5:1:46", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,5:0:45-5:1:46", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,5:0:45-5:1:46", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "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": "d", + "id_val": "d", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,5:0:45-5:1:46", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-lazy.d2,5:0:45-5:1:46", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "d" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": null +} diff --git a/testdata/d2compiler/TestCompile2/globs/suspension-quotes.exp.json b/testdata/d2compiler/TestCompile2/globs/suspension-quotes.exp.json new file mode 100644 index 000000000..f025e00fa --- /dev/null +++ b/testdata/d2compiler/TestCompile2/globs/suspension-quotes.exp.json @@ -0,0 +1,414 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,0:0:0-7:0:76", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,1:0:1-1:6:7", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,1:0:1-1:6:7", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,1:5:6-1:6:7", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,1:5:6-1:6:7", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,2:0:8-2:1:9", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,2:0:8-2:1:9", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,2:0:8-2:1:9", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,3:0:10-3:11:21", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,3:0:10-3:2:12", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,3:0:10-3:2:12", + "value": [ + { + "string": "**", + "raw_string": "**" + } + ], + "pattern": [ + "*", + "", + "*" + ] + } + } + ] + }, + "primary": {}, + "value": { + "suspension": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,3:4:14-3:11:21", + "value": true + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,4:0:22-4:22:44", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,4:1:23-4:9:31", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,4:1:23-4:3:25", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,4:1:23-4:3:25", + "value": [ + { + "string": "**", + "raw_string": "**" + } + ], + "pattern": [ + "*", + "", + "*" + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,4:7:29-4:9:31", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,4:7:29-4:9:31", + "value": [ + { + "string": "**", + "raw_string": "**" + } + ], + "pattern": [ + "*", + "", + "*" + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "edge_index": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,4:10:32-4:13:35", + "int": null, + "glob": true + }, + "primary": {}, + "value": { + "suspension": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,4:15:37-4:22:44", + "value": true + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,5:0:45-5:12:57", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,5:0:45-5:1:46", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,5:0:45-5:1:46", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "double_quoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,5:3:48-5:12:57", + "value": [ + { + "string": "suspend", + "raw_string": "suspend" + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,6:0:58-6:17:75", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,6:0:58-6:6:64", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,6:0:58-6:1:59", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,6:0:58-6:1:59", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,6:5:63-6:6:64", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,6:5:63-6:6:64", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "primary": {}, + "value": { + "double_quoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,6:8:66-6:17:75", + "value": [ + { + "string": "suspend", + "raw_string": "suspend" + } + ] + } + } + } + } + ] + }, + "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": [ + { + "index": 0, + "isCurve": false, + "src_arrow": false, + "dst_arrow": true, + "references": [ + { + "map_key_edge_index": 0 + }, + { + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "suspend" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ], + "objects": [ + { + "id": "d", + "id_val": "d", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,5:0:45-5:1:46", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,5:0:45-5:1:46", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,6:0:58-6:1:59", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,6:0:58-6:1:59", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,6:5:63-6:6:64", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-quotes.d2,6:5:63-6:6:64", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "suspend" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": null +} diff --git a/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.exp.json b/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.exp.json new file mode 100644 index 000000000..a312d2fa8 --- /dev/null +++ b/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.exp.json @@ -0,0 +1,341 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,0:0:0-9:0:108", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,1:0:1-1:6:7", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,1:0:1-1:6:7", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,1:0:1-1:1:2", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,1:0:1-1:1:2", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,1:5:6-1:6:7", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,1:5:6-1:6:7", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,2:0:8-2:1:9", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,2:0:8-2:1:9", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,2:0:8-2:1:9", + "value": [ + { + "string": "c", + "raw_string": "c" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,3:0:10-3:11:21", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,3:0:10-3:2:12", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,3:0:10-3:2:12", + "value": [ + { + "string": "**", + "raw_string": "**" + } + ], + "pattern": [ + "*", + "", + "*" + ] + } + } + ] + }, + "primary": {}, + "value": { + "suspension": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,3:4:14-3:11:21", + "value": true + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,4:0:22-4:22:44", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,4:1:23-4:9:31", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,4:1:23-4:3:25", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,4:1:23-4:3:25", + "value": [ + { + "string": "**", + "raw_string": "**" + } + ], + "pattern": [ + "*", + "", + "*" + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,4:7:29-4:9:31", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,4:7:29-4:9:31", + "value": [ + { + "string": "**", + "raw_string": "**" + } + ], + "pattern": [ + "*", + "", + "*" + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "edge_index": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,4:10:32-4:13:35", + "int": null, + "glob": true + }, + "primary": {}, + "value": { + "suspension": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,4:15:37-4:22:44", + "value": true + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,5:0:45-5:1:46", + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,5:0:45-5:1:46", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,5:0:45-5:1:46", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "comment": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,7:0:48-7:37:85", + "value": "Also restores the objects connected" + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,8:0:86-8:21:107", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,8:1:87-8:8:94", + "src": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,8:1:87-8:3:89", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,8:1:87-8:3:89", + "value": [ + { + "string": "**", + "raw_string": "**" + } + ], + "pattern": [ + "*", + "", + "*" + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,8:7:93-8:8:94", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,8:7:93-8:8:94", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "edge_index": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,8:9:95-8:12:98", + "int": null, + "glob": true + }, + "primary": {}, + "value": { + "suspension": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,8:14:100-8:21:107", + "value": false + } + } + } + } + ] + }, + "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": "d", + "id_val": "d", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,5:0:45-5:1:46", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile2/globs/suspension-restore-edge.d2,5:0:45-5:1:46", + "value": [ + { + "string": "d", + "raw_string": "d" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "d" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": null +}