diff --git a/d2layouts/d2sequence/sequence_diagram.go b/d2layouts/d2sequence/sequence_diagram.go
index 1058d6037..053694d1a 100644
--- a/d2layouts/d2sequence/sequence_diagram.go
+++ b/d2layouts/d2sequence/sequence_diagram.go
@@ -471,7 +471,17 @@ func (sd *sequenceDiagram) routeMessages() error {
isFromDescendant := strings.HasPrefix(message.Src.AbsID(), message.Dst.AbsID()+".")
isSelfMessage := message.Src == message.Dst
- if isSelfMessage || isToDescendant || isFromDescendant {
+ currSrc := message.Src
+ for !currSrc.Parent.IsSequenceDiagram() {
+ currSrc = currSrc.Parent
+ }
+ currDst := message.Dst
+ for !currDst.Parent.IsSequenceDiagram() {
+ currDst = currDst.Parent
+ }
+ isToSibling := currSrc == currDst
+
+ if isSelfMessage || isToDescendant || isFromDescendant || isToSibling {
midX := startX + SELF_MESSAGE_HORIZONTAL_TRAVEL
endY := startY + MIN_MESSAGE_DISTANCE
message.Route = []*geo.Point{
diff --git a/e2etests/stable_test.go b/e2etests/stable_test.go
index 90ce50f94..b7f34a5cd 100644
--- a/e2etests/stable_test.go
+++ b/e2etests/stable_test.go
@@ -1840,6 +1840,18 @@ x: {
y: {
style.border-radius: 10
}
+`,
+ },
+ {
+ name: "sequence-inter-span-self",
+ script: `
+shape: sequence_diagram
+a: A
+b: B
+
+a.sp1 -> b: foo
+a.sp1 -> a.sp2: redirect
+a.sp2 -> b: bar
`,
},
}
diff --git a/e2etests/testdata/stable/sequence-inter-span-self/dagre/board.exp.json b/e2etests/testdata/stable/sequence-inter-span-self/dagre/board.exp.json
new file mode 100644
index 000000000..69b32bf01
--- /dev/null
+++ b/e2etests/testdata/stable/sequence-inter-span-self/dagre/board.exp.json
@@ -0,0 +1,369 @@
+{
+ "name": "",
+ "fontFamily": "SourceSansPro",
+ "shapes": [
+ {
+ "id": "a",
+ "type": "",
+ "pos": {
+ "x": 24,
+ "y": 74
+ },
+ "width": 150,
+ "height": 126,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#EDF0FD",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "A",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 14,
+ "labelHeight": 26,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 1
+ },
+ {
+ "id": "b",
+ "type": "",
+ "pos": {
+ "x": 274,
+ "y": 74
+ },
+ "width": 150,
+ "height": 126,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#EDF0FD",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "B",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 13,
+ "labelHeight": 26,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 1
+ },
+ {
+ "id": "a.sp1",
+ "type": "rectangle",
+ "pos": {
+ "x": 93,
+ "y": 314
+ },
+ "width": 12,
+ "height": 162,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#E3E9FD",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 29,
+ "labelHeight": 26,
+ "zIndex": 2,
+ "level": 2
+ },
+ {
+ "id": "a.sp2",
+ "type": "rectangle",
+ "pos": {
+ "x": 93,
+ "y": 524
+ },
+ "width": 12,
+ "height": 82,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#E3E9FD",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 29,
+ "labelHeight": 26,
+ "zIndex": 2,
+ "level": 2
+ }
+ ],
+ "connections": [
+ {
+ "id": "(a.sp1 -> b)[0]",
+ "src": "a.sp1",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "b",
+ "dstArrow": "triangle",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "foo",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 21,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 105,
+ "y": 330
+ },
+ {
+ "x": 349,
+ "y": 330
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 4
+ },
+ {
+ "id": "a.(sp1 -> sp2)[0]",
+ "src": "a.sp1",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "a.sp2",
+ "dstArrow": "triangle",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "redirect",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 52,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 105,
+ "y": 460
+ },
+ {
+ "x": 199,
+ "y": 460
+ },
+ {
+ "x": 199,
+ "y": 540
+ },
+ {
+ "x": 105,
+ "y": 540
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 4
+ },
+ {
+ "id": "(a.sp2 -> b)[0]",
+ "src": "a.sp2",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "b",
+ "dstArrow": "triangle",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "bar",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 25,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 105,
+ "y": 590
+ },
+ {
+ "x": 349,
+ "y": 590
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 4
+ },
+ {
+ "id": "(a -- )[0]",
+ "src": "a",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "a-lifeline-end-2251863791",
+ "dstArrow": "none",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 6,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 0,
+ "labelHeight": 0,
+ "labelPosition": "",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 99,
+ "y": 200
+ },
+ {
+ "x": 99,
+ "y": 720
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 1
+ },
+ {
+ "id": "(b -- )[0]",
+ "src": "b",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "b-lifeline-end-668380428",
+ "dstArrow": "none",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 6,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 0,
+ "labelHeight": 0,
+ "labelPosition": "",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 349,
+ "y": 200
+ },
+ {
+ "x": 349,
+ "y": 720
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 1
+ }
+ ]
+}
diff --git a/e2etests/testdata/stable/sequence-inter-span-self/dagre/sketch.exp.svg b/e2etests/testdata/stable/sequence-inter-span-self/dagre/sketch.exp.svg
new file mode 100644
index 000000000..db270ba18
--- /dev/null
+++ b/e2etests/testdata/stable/sequence-inter-span-self/dagre/sketch.exp.svg
@@ -0,0 +1,61 @@
+
+
\ No newline at end of file
diff --git a/e2etests/testdata/stable/sequence-inter-span-self/elk/board.exp.json b/e2etests/testdata/stable/sequence-inter-span-self/elk/board.exp.json
new file mode 100644
index 000000000..69b32bf01
--- /dev/null
+++ b/e2etests/testdata/stable/sequence-inter-span-self/elk/board.exp.json
@@ -0,0 +1,369 @@
+{
+ "name": "",
+ "fontFamily": "SourceSansPro",
+ "shapes": [
+ {
+ "id": "a",
+ "type": "",
+ "pos": {
+ "x": 24,
+ "y": 74
+ },
+ "width": 150,
+ "height": 126,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#EDF0FD",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "A",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 14,
+ "labelHeight": 26,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 1
+ },
+ {
+ "id": "b",
+ "type": "",
+ "pos": {
+ "x": 274,
+ "y": 74
+ },
+ "width": 150,
+ "height": 126,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#EDF0FD",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "B",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 13,
+ "labelHeight": 26,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 1
+ },
+ {
+ "id": "a.sp1",
+ "type": "rectangle",
+ "pos": {
+ "x": 93,
+ "y": 314
+ },
+ "width": 12,
+ "height": 162,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#E3E9FD",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 29,
+ "labelHeight": 26,
+ "zIndex": 2,
+ "level": 2
+ },
+ {
+ "id": "a.sp2",
+ "type": "rectangle",
+ "pos": {
+ "x": 93,
+ "y": 524
+ },
+ "width": 12,
+ "height": 82,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#E3E9FD",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 29,
+ "labelHeight": 26,
+ "zIndex": 2,
+ "level": 2
+ }
+ ],
+ "connections": [
+ {
+ "id": "(a.sp1 -> b)[0]",
+ "src": "a.sp1",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "b",
+ "dstArrow": "triangle",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "foo",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 21,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 105,
+ "y": 330
+ },
+ {
+ "x": 349,
+ "y": 330
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 4
+ },
+ {
+ "id": "a.(sp1 -> sp2)[0]",
+ "src": "a.sp1",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "a.sp2",
+ "dstArrow": "triangle",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "redirect",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 52,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 105,
+ "y": 460
+ },
+ {
+ "x": 199,
+ "y": 460
+ },
+ {
+ "x": 199,
+ "y": 540
+ },
+ {
+ "x": 105,
+ "y": 540
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 4
+ },
+ {
+ "id": "(a.sp2 -> b)[0]",
+ "src": "a.sp2",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "b",
+ "dstArrow": "triangle",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "bar",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 25,
+ "labelHeight": 21,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 105,
+ "y": 590
+ },
+ {
+ "x": 349,
+ "y": 590
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 4
+ },
+ {
+ "id": "(a -- )[0]",
+ "src": "a",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "a-lifeline-end-2251863791",
+ "dstArrow": "none",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 6,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 0,
+ "labelHeight": 0,
+ "labelPosition": "",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 99,
+ "y": 200
+ },
+ {
+ "x": 99,
+ "y": 720
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 1
+ },
+ {
+ "id": "(b -- )[0]",
+ "src": "b",
+ "srcArrow": "none",
+ "srcLabel": "",
+ "dst": "b-lifeline-end-668380428",
+ "dstArrow": "none",
+ "dstLabel": "",
+ "opacity": 1,
+ "strokeDash": 6,
+ "strokeWidth": 2,
+ "stroke": "#0D32B2",
+ "label": "",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#676C7E",
+ "italic": true,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 0,
+ "labelHeight": 0,
+ "labelPosition": "",
+ "labelPercentage": 0,
+ "route": [
+ {
+ "x": 349,
+ "y": 200
+ },
+ {
+ "x": 349,
+ "y": 720
+ }
+ ],
+ "animated": false,
+ "tooltip": "",
+ "icon": null,
+ "zIndex": 1
+ }
+ ]
+}
diff --git a/e2etests/testdata/stable/sequence-inter-span-self/elk/sketch.exp.svg b/e2etests/testdata/stable/sequence-inter-span-self/elk/sketch.exp.svg
new file mode 100644
index 000000000..db270ba18
--- /dev/null
+++ b/e2etests/testdata/stable/sequence-inter-span-self/elk/sketch.exp.svg
@@ -0,0 +1,61 @@
+
+
\ No newline at end of file