diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md index affa26527..f987ad278 100644 --- a/ci/release/changelogs/next.md +++ b/ci/release/changelogs/next.md @@ -8,6 +8,7 @@ - Sequence diagram: self-referential edges account for edge label heights [#2040](https://github.com/terrastruct/d2/pull/2040) - Sequence diagram: The spacing between self-referential edges and regular edges is uniform [#2043](https://github.com/terrastruct/d2/pull/2043) - Compiler: Error on multi-line labels in `sql_table` shapes [#2057](https://github.com/terrastruct/d2/pull/2057) +- Sequence diagram: Image shape actors can use spans and notes [#2056](https://github.com/terrastruct/d2/issues/2056) #### Bugfixes ⛑️ diff --git a/d2compiler/compile.go b/d2compiler/compile.go index e9a554e15..40813de70 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -1034,7 +1034,7 @@ func (c *compiler) validateKey(obj *d2graph.Object, f *d2ir.Field) { return } - if strings.EqualFold(obj.Shape.Value, d2target.ShapeImage) { + if strings.EqualFold(obj.Shape.Value, d2target.ShapeImage) && obj.OuterSequenceDiagram() == nil { c.errorf(f.LastRef().AST(), "image shapes cannot have children.") return } diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index 28cfd513c..037cb4ea7 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -3129,6 +3129,22 @@ y: "hello\nworld" { expErr: `d2/testdata/d2compiler/TestCompile/sql-table-header-newline.d2:3:3: shape sql_table cannot have newlines in label d2/testdata/d2compiler/TestCompile/sql-table-header-newline.d2:6:1: shape sql_table cannot have newlines in label`, }, + { + name: "sequence-diagram-icons", + text: `shape: sequence_diagram +svc_1: { + icon: https://icons.terrastruct.com/dev%2Fdocker.svg + shape: image +} + +a: A +b: B + +svc_1.t1 -> a: do with A +svc_1."think about A" +svc_1.t2 -> b: do with B +`, + }, } for _, tc := range testCases { diff --git a/testdata/d2compiler/TestCompile/sequence-diagram-icons.exp.json b/testdata/d2compiler/TestCompile/sequence-diagram-icons.exp.json new file mode 100644 index 000000000..ff10cdd9d --- /dev/null +++ b/testdata/d2compiler/TestCompile/sequence-diagram-icons.exp.json @@ -0,0 +1,910 @@ +{ + "graph": { + "name": "", + "isFolderOnly": false, + "ast": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,0:0:0-12:0:189", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,0:0:0-0:23:23", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,0:0:0-0:5:5", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,0:0:0-0:5:5", + "value": [ + { + "string": "shape", + "raw_string": "shape" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,0:7:7-0:23:23", + "value": [ + { + "string": "sequence_diagram", + "raw_string": "sequence_diagram" + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,1:0:24-4:1:104", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,1:0:24-1:5:29", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,1:0:24-1:5:29", + "value": [ + { + "string": "svc_1", + "raw_string": "svc_1" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "map": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,1:7:31-4:1:104", + "nodes": [ + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,2:2:35-2:54:87", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,2:2:35-2:6:39", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,2:2:35-2:6:39", + "value": [ + { + "string": "icon", + "raw_string": "icon" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,2:8:41-2:54:87", + "value": [ + { + "string": "https://icons.terrastruct.com/dev%2Fdocker.svg", + "raw_string": "https://icons.terrastruct.com/dev%2Fdocker.svg" + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,3:2:90-3:14:102", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,3:2:90-3:7:95", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,3:2:90-3:7:95", + "value": [ + { + "string": "shape", + "raw_string": "shape" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,3:9:97-3:14:102", + "value": [ + { + "string": "image", + "raw_string": "image" + } + ] + } + } + } + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,6:0:106-6:4:110", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,6:0:106-6:1:107", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,6:0:106-6:1:107", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,6:3:109-6:4:110", + "value": [ + { + "string": "A", + "raw_string": "A" + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,7:0:111-7:4:115", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,7:0:111-7:1:112", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,7:0:111-7:1:112", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,7:3:114-7:4:115", + "value": [ + { + "string": "B", + "raw_string": "B" + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,9:0:117-9:24:141", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,9:0:117-9:13:130", + "src": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,9:0:117-9:8:125", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,9:0:117-9:5:122", + "value": [ + { + "string": "svc_1", + "raw_string": "svc_1" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,9:6:123-9:8:125", + "value": [ + { + "string": "t1", + "raw_string": "t1" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,9:12:129-9:13:130", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,9:12:129-9:13:130", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,9:15:132-9:24:141", + "value": [ + { + "string": "do with A", + "raw_string": "do with A" + } + ] + } + } + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,10:0:142-10:21:163", + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,10:0:142-10:21:163", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,10:0:142-10:5:147", + "value": [ + { + "string": "svc_1", + "raw_string": "svc_1" + } + ] + } + }, + { + "double_quoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,10:6:148-10:21:163", + "value": [ + { + "string": "think about A", + "raw_string": "think about A" + } + ] + } + } + ] + }, + "primary": {}, + "value": {} + } + }, + { + "map_key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,11:0:164-11:24:188", + "edges": [ + { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,11:0:164-11:13:177", + "src": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,11:0:164-11:8:172", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,11:0:164-11:5:169", + "value": [ + { + "string": "svc_1", + "raw_string": "svc_1" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,11:6:170-11:8:172", + "value": [ + { + "string": "t2", + "raw_string": "t2" + } + ] + } + } + ] + }, + "src_arrow": "", + "dst": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,11:12:176-11:13:177", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,11:12:176-11:13:177", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "dst_arrow": ">" + } + ], + "primary": {}, + "value": { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,11:15:179-11:24:188", + "value": [ + { + "string": "do with B", + "raw_string": "do with B" + } + ] + } + } + } + } + ] + }, + "root": { + "id": "", + "id_val": "", + "attributes": { + "label": { + "value": "" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "sequence_diagram" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + "edges": [ + { + "index": 0, + "isCurve": false, + "src_arrow": false, + "dst_arrow": true, + "references": [ + { + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "do with A" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "index": 0, + "isCurve": false, + "src_arrow": false, + "dst_arrow": true, + "references": [ + { + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "do with B" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ], + "objects": [ + { + "id": "svc_1", + "id_val": "svc_1", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,1:0:24-1:5:29", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,1:0:24-1:5:29", + "value": [ + { + "string": "svc_1", + "raw_string": "svc_1" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,9:0:117-9:8:125", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,9:0:117-9:5:122", + "value": [ + { + "string": "svc_1", + "raw_string": "svc_1" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,9:6:123-9:8:125", + "value": [ + { + "string": "t1", + "raw_string": "t1" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,10:0:142-10:21:163", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,10:0:142-10:5:147", + "value": [ + { + "string": "svc_1", + "raw_string": "svc_1" + } + ] + } + }, + { + "double_quoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,10:6:148-10:21:163", + "value": [ + { + "string": "think about A", + "raw_string": "think about A" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,11:0:164-11:8:172", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,11:0:164-11:5:169", + "value": [ + { + "string": "svc_1", + "raw_string": "svc_1" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,11:6:170-11:8:172", + "value": [ + { + "string": "t2", + "raw_string": "t2" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "svc_1" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "icon": { + "Scheme": "https", + "Opaque": "", + "User": null, + "Host": "icons.terrastruct.com", + "Path": "/dev/docker.svg", + "RawPath": "/dev%2Fdocker.svg", + "OmitHost": false, + "ForceQuery": false, + "RawQuery": "", + "Fragment": "", + "RawFragment": "" + }, + "near_key": null, + "shape": { + "value": "image" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "a", + "id_val": "a", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,6:0:106-6:1:107", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,6:0:106-6:1:107", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,9:12:129-9:13:130", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,9:12:129-9:13:130", + "value": [ + { + "string": "a", + "raw_string": "a" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "A" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "b", + "id_val": "b", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,7:0:111-7:1:112", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,7:0:111-7:1:112", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": -1 + }, + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,11:12:176-11:13:177", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,11:12:176-11:13:177", + "value": [ + { + "string": "b", + "raw_string": "b" + } + ] + } + } + ] + }, + "key_path_index": 0, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "B" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "t1", + "id_val": "t1", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,9:0:117-9:8:125", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,9:0:117-9:5:122", + "value": [ + { + "string": "svc_1", + "raw_string": "svc_1" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,9:6:123-9:8:125", + "value": [ + { + "string": "t1", + "raw_string": "t1" + } + ] + } + } + ] + }, + "key_path_index": 1, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "t1" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "think about A", + "id_val": "think about A", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,10:0:142-10:21:163", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,10:0:142-10:5:147", + "value": [ + { + "string": "svc_1", + "raw_string": "svc_1" + } + ] + } + }, + { + "double_quoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,10:6:148-10:21:163", + "value": [ + { + "string": "think about A", + "raw_string": "think about A" + } + ] + } + } + ] + }, + "key_path_index": 1, + "map_key_edge_index": -1 + } + ], + "attributes": { + "label": { + "value": "think about A" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + }, + { + "id": "t2", + "id_val": "t2", + "references": [ + { + "key": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,11:0:164-11:8:172", + "path": [ + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,11:0:164-11:5:169", + "value": [ + { + "string": "svc_1", + "raw_string": "svc_1" + } + ] + } + }, + { + "unquoted_string": { + "range": "d2/testdata/d2compiler/TestCompile/sequence-diagram-icons.d2,11:6:170-11:8:172", + "value": [ + { + "string": "t2", + "raw_string": "t2" + } + ] + } + } + ] + }, + "key_path_index": 1, + "map_key_edge_index": 0 + } + ], + "attributes": { + "label": { + "value": "t2" + }, + "labelDimensions": { + "width": 0, + "height": 0 + }, + "style": {}, + "near_key": null, + "shape": { + "value": "rectangle" + }, + "direction": { + "value": "" + }, + "constraint": null + }, + "zIndex": 0 + } + ] + }, + "err": null +}