diff --git a/d2compiler/compile.go b/d2compiler/compile.go
index 66f6497a54..2cfd85e698 100644
--- a/d2compiler/compile.go
+++ b/d2compiler/compile.go
@@ -86,7 +86,7 @@ func compileIR(ast *d2ast.Map, m *d2ir.Map) (*d2graph.Graph, error) {
func (c *compiler) compileBoard(g *d2graph.Graph, ir *d2ir.Map) *d2graph.Graph {
ir = ir.Copy(nil).(*d2ir.Map)
- // c.preprocessSeqDiagrams(ir)
+ c.preprocessSeqDiagrams(ir)
c.compileMap(g.Root, ir)
c.setDefaultShapes(g)
if len(c.err.Errors) == 0 {
@@ -1483,23 +1483,15 @@ func isCrossEdgeGroupEdge(m *d2ir.Map, e *d2ir.Edge) bool {
return false
}
-func isEdgeGroup(n d2ir.Node) bool {
- return n.Map().EdgeCountRecursive() > 0
-}
-
-func parentSeqDiagram(n d2ir.Node) *d2ir.Map {
- for {
- m := d2ir.ParentMap(n)
- if m == nil {
- return nil
- }
- for _, f := range m.Fields {
- if f.Name.ScalarString() == "shape" && f.Name.IsUnquoted() && f.Primary_.Value.ScalarString() == d2target.ShapeSequenceDiagram {
- return m
+func isEdgeGroup(f *d2ir.Field) bool {
+ if f.Map() != nil {
+ for _, f := range f.Map().Fields {
+ if f.Name.ScalarString() == "shape" && f.Name.IsUnquoted() && f.Primary_.Value.ScalarString() == d2target.ShapeSequenceDiagramEdgeGroup {
+ return true
}
}
- n = m
}
+ return false
}
func compileConfig(ir *d2ir.Map) (*d2target.Config, error) {
diff --git a/d2layouts/d2sequence2/sequencediagram.go b/d2layouts/d2sequence2/sequencediagram.go
new file mode 100644
index 0000000000..5a75be154b
--- /dev/null
+++ b/d2layouts/d2sequence2/sequencediagram.go
@@ -0,0 +1,63 @@
+package sequencediagram
+
+import (
+ "context"
+
+ "oss.terrastruct.com/d2/d2graph"
+)
+
+/*
+Concepts:
+
+- Actor
+ - A top-level entity.
+ - Every other entity must be associated with an actor.
+- Actor Group
+ - A top level entity.
+ - If an actor is defined in an actor group, it must also be referenced as such, e.g. group.actor -> actor2
+- Message
+ - A connection between two actors.
+ - vertical-gap can be defined to specify the NEXT spacing
+- Span
+ - A child of an actor whose shape == nil.
+ - Messages may be attached directly onto a span.
+ - Spans can nest, e.g. actor.span1.span2
+ - Labels are default not shown. Must be explicitly defined to show.
+- Note
+ - A child of an actor whose shape == page.
+ - Messages are not allowed on Notes.
+- Event
+ - A child of an actor whose shape != nil && shape != page.
+ - Messages are not allowed on Events.
+- Edge Group
+ - A child of an actor whose shape == edge-group.
+ - Message inside an edge group are visually grouped together under one label.
+
+
+- configs:
+ - vars.mirror: true
+ - vars.numbered: true
+*/
+
+type SequenceDiagram struct {
+ *builder
+}
+
+// Traverse top-down vertically.
+// At each vertical step, traverse left-right horizontally
+type builder struct {
+ y int
+ x int
+}
+
+func Layout(ctx context.Context, g *d2graph.Graph) (*SequenceDiagram, error) {
+ return newSequenceDiagram(g), nil
+}
+
+func newSequenceDiagram(g *d2graph.Graph) *SequenceDiagram {
+ return &SequenceDiagram{builder: newBuilder()}
+}
+
+func newBuilder() *builder {
+ return &builder{}
+}
diff --git a/d2layouts/d2sequence2/sequencediagram_test.go b/d2layouts/d2sequence2/sequencediagram_test.go
new file mode 100644
index 0000000000..6548bba7bc
--- /dev/null
+++ b/d2layouts/d2sequence2/sequencediagram_test.go
@@ -0,0 +1,86 @@
+package sequencediagram_test
+
+import (
+ "context"
+ "strings"
+ "testing"
+
+ "oss.terrastruct.com/d2/d2compiler"
+ sequencediagram "oss.terrastruct.com/d2/d2layouts/d2sequence2"
+ "oss.terrastruct.com/d2/d2lib"
+ "oss.terrastruct.com/d2/lib/log"
+ "oss.terrastruct.com/d2/lib/textmeasure"
+ "oss.terrastruct.com/util-go/assert"
+ "oss.terrastruct.com/util-go/mapfs"
+)
+
+func TestSequenceDiagrams(t *testing.T) {
+ t.Parallel()
+
+ t.Run("basic", testBasic)
+}
+
+func testBasic(t *testing.T) {
+ t.Parallel()
+
+ tca := []testCase{
+ {
+ name: "escaped",
+ assert: func(t testing.TB, sd *sequencediagram.SequenceDiagram) {
+ assert.True(t, 1 == 1)
+ },
+ },
+ }
+
+ runa(t, tca)
+}
+
+type testCase struct {
+ name string
+ fs map[string]string
+ assert func(testing.TB, *sequencediagram.SequenceDiagram)
+ expErr string
+}
+
+func runa(t *testing.T, tca []testCase) {
+ for _, tc := range tca {
+ t.Run(tc.name, func(t *testing.T) {
+ t.Parallel()
+
+ ctx := context.Background()
+ ctx = log.WithTB(ctx, t)
+ ruler, _ := textmeasure.NewRuler()
+ fs, _ := mapfs.New(tc.fs)
+ compileOpts := &d2lib.CompileOptions{
+ Ruler: ruler,
+ FS: fs,
+ }
+ g, config, err := d2compiler.Compile(compileOpts.InputPath, strings.NewReader(tc.fs["index.d2"]), &d2compiler.CompileOptions{
+ UTF16Pos: compileOpts.UTF16Pos,
+ FS: compileOpts.FS,
+ })
+ if tc.expErr != "" {
+ assert.Error(t, err)
+ } else {
+ assert.Success(t, err)
+ }
+ if config != nil {
+ g.Data = config.Data
+ }
+ err = g.SetDimensions(nil, compileOpts.Ruler, compileOpts.FontFamily, compileOpts.MonoFontFamily)
+ if tc.expErr != "" {
+ assert.Error(t, err)
+ } else {
+ assert.Success(t, err)
+ }
+
+ sd, err := sequencediagram.Layout(ctx, g)
+ if tc.expErr != "" {
+ assert.Error(t, err)
+ } else {
+ assert.Success(t, err)
+ }
+ tc.assert(t, sd)
+ })
+ }
+}
diff --git a/d2target/d2target.go b/d2target/d2target.go
index 63fcfacbf3..5e9321763a 100644
--- a/d2target/d2target.go
+++ b/d2target/d2target.go
@@ -1048,31 +1048,32 @@ func NewPoint(x, y int) Point {
}
const (
- ShapeRectangle = "rectangle"
- ShapeSquare = "square"
- ShapePage = "page"
- ShapeParallelogram = "parallelogram"
- ShapeDocument = "document"
- ShapeCylinder = "cylinder"
- ShapeQueue = "queue"
- ShapePackage = "package"
- ShapeStep = "step"
- ShapeCallout = "callout"
- ShapeStoredData = "stored_data"
- ShapePerson = "person"
- ShapeC4Person = "c4-person"
- ShapeDiamond = "diamond"
- ShapeOval = "oval"
- ShapeCircle = "circle"
- ShapeHexagon = "hexagon"
- ShapeCloud = "cloud"
- ShapeText = "text"
- ShapeCode = "code"
- ShapeClass = "class"
- ShapeSQLTable = "sql_table"
- ShapeImage = "image"
- ShapeSequenceDiagram = "sequence_diagram"
- ShapeHierarchy = "hierarchy"
+ ShapeRectangle = "rectangle"
+ ShapeSquare = "square"
+ ShapePage = "page"
+ ShapeParallelogram = "parallelogram"
+ ShapeDocument = "document"
+ ShapeCylinder = "cylinder"
+ ShapeQueue = "queue"
+ ShapePackage = "package"
+ ShapeStep = "step"
+ ShapeCallout = "callout"
+ ShapeStoredData = "stored_data"
+ ShapePerson = "person"
+ ShapeC4Person = "c4-person"
+ ShapeDiamond = "diamond"
+ ShapeOval = "oval"
+ ShapeCircle = "circle"
+ ShapeHexagon = "hexagon"
+ ShapeCloud = "cloud"
+ ShapeText = "text"
+ ShapeCode = "code"
+ ShapeClass = "class"
+ ShapeSQLTable = "sql_table"
+ ShapeImage = "image"
+ ShapeSequenceDiagram = "sequence_diagram"
+ ShapeSequenceDiagramEdgeGroup = "edge-group"
+ ShapeHierarchy = "hierarchy"
)
var Shapes = []string{
diff --git a/e2etests/testdata/todo/sequence_diagram_ambiguous_edge_group/dagre/board.exp.json b/e2etests/testdata/todo/sequence_diagram_ambiguous_edge_group/dagre/board.exp.json
new file mode 100644
index 0000000000..94587e7209
--- /dev/null
+++ b/e2etests/testdata/todo/sequence_diagram_ambiguous_edge_group/dagre/board.exp.json
@@ -0,0 +1,548 @@
+{
+ "name": "",
+ "config": {
+ "sketch": false,
+ "themeID": 0,
+ "darkThemeID": null,
+ "pad": null,
+ "center": null,
+ "layoutEngine": null
+ },
+ "isFolderOnly": false,
+ "fontFamily": "SourceSansPro",
+ "monoFontFamily": "SourceCodePro",
+ "shapes": [
+ {
+ "id": "Office chatter",
+ "type": "sequence_diagram",
+ "pos": {
+ "x": 0,
+ "y": 0
+ },
+ "width": 371,
+ "height": 679,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 0,
+ "borderRadius": 0,
+ "fill": "N7",
+ "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": "Office chatter",
+ "fontSize": 28,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 159,
+ "labelHeight": 36,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 1
+ },
+ {
+ "id": "Office chatter.alice",
+ "type": "rectangle",
+ "pos": {
+ "x": 12,
+ "y": 88
+ },
+ "width": 100,
+ "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": "Alice",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 33,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "Office chatter.bob",
+ "type": "rectangle",
+ "pos": {
+ "x": 259,
+ "y": 88
+ },
+ "width": 100,
+ "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": "Bobby",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 43,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "Office chatter.awkward small talk",
+ "type": "rectangle",
+ "pos": {
+ "x": 10,
+ "y": 211
+ },
+ "width": 351,
+ "height": 420,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 0,
+ "borderRadius": 0,
+ "fill": "N5",
+ "stroke": "B1",
+ "animated": false,
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": true,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "awkward small talk",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 130,
+ "labelHeight": 21,
+ "labelFill": "N5",
+ "labelPosition": "INSIDE_TOP_LEFT",
+ "zIndex": 3,
+ "level": 2
+ },
+ {
+ "id": "Office chatter.awkward small talk.icebreaker attempt",
+ "type": "rectangle",
+ "pos": {
+ "x": 22,
+ "y": 422
+ },
+ "width": 327,
+ "height": 76,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 0,
+ "borderRadius": 0,
+ "fill": "N5",
+ "stroke": "B1",
+ "animated": false,
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": true,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "icebreaker attempt",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 129,
+ "labelHeight": 21,
+ "labelFill": "N5",
+ "labelPosition": "INSIDE_TOP_LEFT",
+ "zIndex": 3,
+ "level": 3
+ },
+ {
+ "id": "Office chatter.awkward small talk.unfortunate outcome",
+ "type": "rectangle",
+ "pos": {
+ "x": 22,
+ "y": 543
+ },
+ "width": 327,
+ "height": 76,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 0,
+ "borderRadius": 0,
+ "fill": "N5",
+ "stroke": "B1",
+ "animated": false,
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": true,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "unfortunate outcome",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 143,
+ "labelHeight": 21,
+ "labelFill": "N5",
+ "labelPosition": "INSIDE_TOP_LEFT",
+ "zIndex": 3,
+ "level": 3
+ }
+ ],
+ "connections": [
+ {
+ "id": "Office chatter.(alice -> bob)[1]",
+ "src": "Office chatter.alice",
+ "srcArrow": "none",
+ "dst": "Office chatter.bob",
+ "dstArrow": "triangle",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "B1",
+ "borderRadius": 10,
+ "label": "uhm, hi",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N2",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 50,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "link": "",
+ "route": [
+ {
+ "x": 62,
+ "y": 265
+ },
+ {
+ "x": 309,
+ "y": 265
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 4
+ },
+ {
+ "id": "Office chatter.(bob -> alice)[1]",
+ "src": "Office chatter.bob",
+ "srcArrow": "none",
+ "dst": "Office chatter.alice",
+ "dstArrow": "triangle",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "B1",
+ "borderRadius": 10,
+ "label": "oh, hello",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N2",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 56,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "link": "",
+ "route": [
+ {
+ "x": 309,
+ "y": 355
+ },
+ {
+ "x": 62,
+ "y": 355
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 4
+ },
+ {
+ "id": "Office chatter.(alice -> bob)[0]",
+ "src": "Office chatter.alice",
+ "srcArrow": "none",
+ "dst": "Office chatter.bob",
+ "dstArrow": "triangle",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "B1",
+ "borderRadius": 10,
+ "label": "what did you have for lunch?",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N2",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 187,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "link": "",
+ "route": [
+ {
+ "x": 62,
+ "y": 476
+ },
+ {
+ "x": 309,
+ "y": 476
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 4
+ },
+ {
+ "id": "Office chatter.(bob -> alice)[0]",
+ "src": "Office chatter.bob",
+ "srcArrow": "none",
+ "dst": "Office chatter.alice",
+ "dstArrow": "triangle",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "B1",
+ "borderRadius": 10,
+ "label": "that's personal",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N2",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 99,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "link": "",
+ "route": [
+ {
+ "x": 309,
+ "y": 597
+ },
+ {
+ "x": 62,
+ "y": 597
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 4
+ },
+ {
+ "id": "(Office chatter.alice -- )[0]",
+ "src": "Office chatter.alice",
+ "srcArrow": "none",
+ "dst": "alice-lifeline-end-3851299086",
+ "dstArrow": "none",
+ "opacity": 1,
+ "strokeDash": 6,
+ "strokeWidth": 2,
+ "stroke": "B2",
+ "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": 62,
+ "y": 154
+ },
+ {
+ "x": 62,
+ "y": 667
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 1
+ },
+ {
+ "id": "(Office chatter.bob -- )[0]",
+ "src": "Office chatter.bob",
+ "srcArrow": "none",
+ "dst": "bob-lifeline-end-3036726343",
+ "dstArrow": "none",
+ "opacity": 1,
+ "strokeDash": 6,
+ "strokeWidth": 2,
+ "stroke": "B2",
+ "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": 309,
+ "y": 154
+ },
+ {
+ "x": 309,
+ "y": 667
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 1
+ }
+ ],
+ "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/todo/sequence_diagram_ambiguous_edge_group/dagre/sketch.exp.svg b/e2etests/testdata/todo/sequence_diagram_ambiguous_edge_group/dagre/sketch.exp.svg
new file mode 100644
index 0000000000..de885b8757
--- /dev/null
+++ b/e2etests/testdata/todo/sequence_diagram_ambiguous_edge_group/dagre/sketch.exp.svg
@@ -0,0 +1,105 @@
+
\ No newline at end of file
diff --git a/e2etests/testdata/todo/sequence_diagram_ambiguous_edge_group/elk/board.exp.json b/e2etests/testdata/todo/sequence_diagram_ambiguous_edge_group/elk/board.exp.json
new file mode 100644
index 0000000000..9f3e24458a
--- /dev/null
+++ b/e2etests/testdata/todo/sequence_diagram_ambiguous_edge_group/elk/board.exp.json
@@ -0,0 +1,548 @@
+{
+ "name": "",
+ "config": {
+ "sketch": false,
+ "themeID": 0,
+ "darkThemeID": null,
+ "pad": null,
+ "center": null,
+ "layoutEngine": null
+ },
+ "isFolderOnly": false,
+ "fontFamily": "SourceSansPro",
+ "monoFontFamily": "SourceCodePro",
+ "shapes": [
+ {
+ "id": "Office chatter",
+ "type": "sequence_diagram",
+ "pos": {
+ "x": 12,
+ "y": 12
+ },
+ "width": 371,
+ "height": 679,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 0,
+ "borderRadius": 0,
+ "fill": "N7",
+ "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": "Office chatter",
+ "fontSize": 28,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 159,
+ "labelHeight": 36,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 1
+ },
+ {
+ "id": "Office chatter.alice",
+ "type": "rectangle",
+ "pos": {
+ "x": 24,
+ "y": 100
+ },
+ "width": 100,
+ "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": "Alice",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 33,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "Office chatter.bob",
+ "type": "rectangle",
+ "pos": {
+ "x": 271,
+ "y": 100
+ },
+ "width": 100,
+ "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": "Bobby",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 43,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "Office chatter.awkward small talk",
+ "type": "rectangle",
+ "pos": {
+ "x": 22,
+ "y": 223
+ },
+ "width": 351,
+ "height": 420,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 0,
+ "borderRadius": 0,
+ "fill": "N5",
+ "stroke": "B1",
+ "animated": false,
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": true,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "awkward small talk",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 130,
+ "labelHeight": 21,
+ "labelFill": "N5",
+ "labelPosition": "INSIDE_TOP_LEFT",
+ "zIndex": 3,
+ "level": 2
+ },
+ {
+ "id": "Office chatter.awkward small talk.icebreaker attempt",
+ "type": "rectangle",
+ "pos": {
+ "x": 34,
+ "y": 434
+ },
+ "width": 327,
+ "height": 76,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 0,
+ "borderRadius": 0,
+ "fill": "N5",
+ "stroke": "B1",
+ "animated": false,
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": true,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "icebreaker attempt",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 129,
+ "labelHeight": 21,
+ "labelFill": "N5",
+ "labelPosition": "INSIDE_TOP_LEFT",
+ "zIndex": 3,
+ "level": 3
+ },
+ {
+ "id": "Office chatter.awkward small talk.unfortunate outcome",
+ "type": "rectangle",
+ "pos": {
+ "x": 34,
+ "y": 555
+ },
+ "width": 327,
+ "height": 76,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 0,
+ "borderRadius": 0,
+ "fill": "N5",
+ "stroke": "B1",
+ "animated": false,
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": true,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "unfortunate outcome",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 143,
+ "labelHeight": 21,
+ "labelFill": "N5",
+ "labelPosition": "INSIDE_TOP_LEFT",
+ "zIndex": 3,
+ "level": 3
+ }
+ ],
+ "connections": [
+ {
+ "id": "Office chatter.(alice -> bob)[1]",
+ "src": "Office chatter.alice",
+ "srcArrow": "none",
+ "dst": "Office chatter.bob",
+ "dstArrow": "triangle",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "B1",
+ "borderRadius": 10,
+ "label": "uhm, hi",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N2",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 50,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "link": "",
+ "route": [
+ {
+ "x": 74,
+ "y": 277
+ },
+ {
+ "x": 321,
+ "y": 277
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 4
+ },
+ {
+ "id": "Office chatter.(bob -> alice)[1]",
+ "src": "Office chatter.bob",
+ "srcArrow": "none",
+ "dst": "Office chatter.alice",
+ "dstArrow": "triangle",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "B1",
+ "borderRadius": 10,
+ "label": "oh, hello",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N2",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 56,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "link": "",
+ "route": [
+ {
+ "x": 321,
+ "y": 367
+ },
+ {
+ "x": 74,
+ "y": 367
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 4
+ },
+ {
+ "id": "Office chatter.(alice -> bob)[0]",
+ "src": "Office chatter.alice",
+ "srcArrow": "none",
+ "dst": "Office chatter.bob",
+ "dstArrow": "triangle",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "B1",
+ "borderRadius": 10,
+ "label": "what did you have for lunch?",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N2",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 187,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "link": "",
+ "route": [
+ {
+ "x": 74,
+ "y": 488
+ },
+ {
+ "x": 321,
+ "y": 488
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 4
+ },
+ {
+ "id": "Office chatter.(bob -> alice)[0]",
+ "src": "Office chatter.bob",
+ "srcArrow": "none",
+ "dst": "Office chatter.alice",
+ "dstArrow": "triangle",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "B1",
+ "borderRadius": 10,
+ "label": "that's personal",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N2",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 99,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "link": "",
+ "route": [
+ {
+ "x": 321,
+ "y": 609
+ },
+ {
+ "x": 74,
+ "y": 609
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 4
+ },
+ {
+ "id": "(Office chatter.alice -- )[0]",
+ "src": "Office chatter.alice",
+ "srcArrow": "none",
+ "dst": "alice-lifeline-end-3851299086",
+ "dstArrow": "none",
+ "opacity": 1,
+ "strokeDash": 6,
+ "strokeWidth": 2,
+ "stroke": "B2",
+ "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": 74,
+ "y": 166
+ },
+ {
+ "x": 74,
+ "y": 679
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 1
+ },
+ {
+ "id": "(Office chatter.bob -- )[0]",
+ "src": "Office chatter.bob",
+ "srcArrow": "none",
+ "dst": "bob-lifeline-end-3036726343",
+ "dstArrow": "none",
+ "opacity": 1,
+ "strokeDash": 6,
+ "strokeWidth": 2,
+ "stroke": "B2",
+ "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": 321,
+ "y": 166
+ },
+ {
+ "x": 321,
+ "y": 679
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 1
+ }
+ ],
+ "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/todo/sequence_diagram_ambiguous_edge_group/elk/sketch.exp.svg b/e2etests/testdata/todo/sequence_diagram_ambiguous_edge_group/elk/sketch.exp.svg
new file mode 100644
index 0000000000..730257a971
--- /dev/null
+++ b/e2etests/testdata/todo/sequence_diagram_ambiguous_edge_group/elk/sketch.exp.svg
@@ -0,0 +1,105 @@
+Office chatterAliceBobbyawkward small talkicebreaker attemptunfortunate outcome uhm, hioh, hellowhat did you have for lunch?that's personal
+
+
+
+
+
+
\ No newline at end of file
diff --git a/e2etests/todo_test.go b/e2etests/todo_test.go
index d6fa346ca6..c94a091a6a 100644
--- a/e2etests/todo_test.go
+++ b/e2etests/todo_test.go
@@ -165,7 +165,6 @@ small code: |go
`,
},
{
- // issue https://github.com/terrastruct/d2/issues/748
name: "sequence_diagram_edge_group_span_field",
script: `
Office chatter: {
@@ -187,8 +186,6 @@ Office chatter: {
`,
},
{
- // issue https://github.com/terrastruct/d2/issues/748
- skip: true,
name: "sequence_diagram_ambiguous_edge_group",
script: `
Office chatter: {
@@ -196,6 +193,7 @@ Office chatter: {
alice: Alice
bob: Bobby
awkward small talk: {
+ shape: edge-group
awkward small talk.ok
alice -> bob: uhm, hi
bob -> alice: oh, hello