diff --git a/d2layouts/d2near/layout.go b/d2layouts/d2near/layout.go
index e05709169..85ef8ff72 100644
--- a/d2layouts/d2near/layout.go
+++ b/d2layouts/d2near/layout.go
@@ -27,12 +27,12 @@ func Layout(ctx context.Context, g *d2graph.Graph, constantNears []*d2graph.Obje
// So place the center ones first, then the later ones will consider them for bounding box
for _, processCenters := range []bool{true, false} {
for _, obj := range constantNears {
- if processCenters == strings.Contains(d2graph.Key(obj.Attributes.NearKey)[0], "center") {
+ if processCenters == strings.Contains(d2graph.Key(obj.Attributes.NearKey)[0], "-center") {
obj.TopLeft = geo.NewPoint(place(obj))
}
}
for _, obj := range constantNears {
- if processCenters == strings.Contains(d2graph.Key(obj.Attributes.NearKey)[0], "center") {
+ if processCenters == strings.Contains(d2graph.Key(obj.Attributes.NearKey)[0], "-center") {
// The z-index for constant nears does not matter, as it will not collide
g.Objects = append(g.Objects, obj)
obj.Parent.Children[obj.ID] = obj
diff --git a/d2layouts/d2sequence/layout.go b/d2layouts/d2sequence/layout.go
index 49ae00b43..14e4c6f80 100644
--- a/d2layouts/d2sequence/layout.go
+++ b/d2layouts/d2sequence/layout.go
@@ -17,43 +17,45 @@ func WithoutSequenceDiagrams(ctx context.Context, g *d2graph.Graph) (map[string]
edgesToRemove := make(map[*d2graph.Edge]struct{})
sequenceDiagrams := make(map[string]*sequenceDiagram)
- queue := make([]*d2graph.Object, 1, len(g.Objects))
- queue[0] = g.Root
- for len(queue) > 0 {
- obj := queue[0]
- queue = queue[1:]
- if len(obj.ChildrenArray) == 0 {
- continue
- }
- if obj.Attributes.Shape.Value != d2target.ShapeSequenceDiagram {
- queue = append(queue, obj.ChildrenArray...)
- continue
- }
+ if len(g.Objects) > 0 {
+ queue := make([]*d2graph.Object, 1, len(g.Objects))
+ queue[0] = g.Root
+ for len(queue) > 0 {
+ obj := queue[0]
+ queue = queue[1:]
+ if len(obj.ChildrenArray) == 0 {
+ continue
+ }
+ if obj.Attributes.Shape.Value != d2target.ShapeSequenceDiagram {
+ queue = append(queue, obj.ChildrenArray...)
+ continue
+ }
- sd, err := layoutSequenceDiagram(g, obj)
- if err != nil {
- return nil, nil, nil, err
- }
- obj.Children = make(map[string]*d2graph.Object)
- obj.ChildrenArray = nil
- obj.Box = geo.NewBox(nil, sd.getWidth()+GROUP_CONTAINER_PADDING*2, sd.getHeight()+GROUP_CONTAINER_PADDING*2)
- obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
- sequenceDiagrams[obj.AbsID()] = sd
+ sd, err := layoutSequenceDiagram(g, obj)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+ obj.Children = make(map[string]*d2graph.Object)
+ obj.ChildrenArray = nil
+ obj.Box = geo.NewBox(nil, sd.getWidth()+GROUP_CONTAINER_PADDING*2, sd.getHeight()+GROUP_CONTAINER_PADDING*2)
+ obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter))
+ sequenceDiagrams[obj.AbsID()] = sd
- for _, edge := range sd.messages {
- edgesToRemove[edge] = struct{}{}
- }
- for _, obj := range sd.actors {
- objectsToRemove[obj] = struct{}{}
- }
- for _, obj := range sd.notes {
- objectsToRemove[obj] = struct{}{}
- }
- for _, obj := range sd.groups {
- objectsToRemove[obj] = struct{}{}
- }
- for _, obj := range sd.spans {
- objectsToRemove[obj] = struct{}{}
+ for _, edge := range sd.messages {
+ edgesToRemove[edge] = struct{}{}
+ }
+ for _, obj := range sd.actors {
+ objectsToRemove[obj] = struct{}{}
+ }
+ for _, obj := range sd.notes {
+ objectsToRemove[obj] = struct{}{}
+ }
+ for _, obj := range sd.groups {
+ objectsToRemove[obj] = struct{}{}
+ }
+ for _, obj := range sd.spans {
+ objectsToRemove[obj] = struct{}{}
+ }
}
}
diff --git a/e2etests/stable_test.go b/e2etests/stable_test.go
index fb9f7399a..7ec142f3a 100644
--- a/e2etests/stable_test.go
+++ b/e2etests/stable_test.go
@@ -1815,6 +1815,20 @@ x.y -> a.b: {
style.animated: true
target-arrowhead.shape: cf-many
}
+`,
+ },
+ {
+ name: "near-alone",
+ script: `
+x: {
+ near: top-center
+}
+y: {
+ near: bottom-center
+}
+z: {
+ near: center-left
+}
`,
},
}
diff --git a/e2etests/testdata/stable/near-alone/dagre/board.exp.json b/e2etests/testdata/stable/near-alone/dagre/board.exp.json
new file mode 100644
index 000000000..dba43ee30
--- /dev/null
+++ b/e2etests/testdata/stable/near-alone/dagre/board.exp.json
@@ -0,0 +1,127 @@
+{
+ "name": "",
+ "fontFamily": "SourceSansPro",
+ "shapes": [
+ {
+ "id": "x",
+ "type": "",
+ "pos": {
+ "x": -56,
+ "y": -146
+ },
+ "width": 113,
+ "height": 126,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#F7F8FE",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "x",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": true,
+ "underline": false,
+ "labelWidth": 13,
+ "labelHeight": 26,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 1
+ },
+ {
+ "id": "y",
+ "type": "",
+ "pos": {
+ "x": -57,
+ "y": 20
+ },
+ "width": 114,
+ "height": 126,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#F7F8FE",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "y",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": true,
+ "underline": false,
+ "labelWidth": 14,
+ "labelHeight": 26,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 1
+ },
+ {
+ "id": "z",
+ "type": "",
+ "pos": {
+ "x": -189,
+ "y": 0
+ },
+ "width": 112,
+ "height": 126,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#F7F8FE",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "z",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": true,
+ "underline": false,
+ "labelWidth": 12,
+ "labelHeight": 26,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 1
+ }
+ ],
+ "connections": []
+}
diff --git a/e2etests/testdata/stable/near-alone/dagre/sketch.exp.svg b/e2etests/testdata/stable/near-alone/dagre/sketch.exp.svg
new file mode 100644
index 000000000..3944c699c
--- /dev/null
+++ b/e2etests/testdata/stable/near-alone/dagre/sketch.exp.svg
@@ -0,0 +1,52 @@
+
+
\ No newline at end of file
diff --git a/e2etests/testdata/stable/near-alone/elk/board.exp.json b/e2etests/testdata/stable/near-alone/elk/board.exp.json
new file mode 100644
index 000000000..dba43ee30
--- /dev/null
+++ b/e2etests/testdata/stable/near-alone/elk/board.exp.json
@@ -0,0 +1,127 @@
+{
+ "name": "",
+ "fontFamily": "SourceSansPro",
+ "shapes": [
+ {
+ "id": "x",
+ "type": "",
+ "pos": {
+ "x": -56,
+ "y": -146
+ },
+ "width": 113,
+ "height": 126,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#F7F8FE",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "x",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": true,
+ "underline": false,
+ "labelWidth": 13,
+ "labelHeight": 26,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 1
+ },
+ {
+ "id": "y",
+ "type": "",
+ "pos": {
+ "x": -57,
+ "y": 20
+ },
+ "width": 114,
+ "height": 126,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#F7F8FE",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "y",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": true,
+ "underline": false,
+ "labelWidth": 14,
+ "labelHeight": 26,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 1
+ },
+ {
+ "id": "z",
+ "type": "",
+ "pos": {
+ "x": -189,
+ "y": 0
+ },
+ "width": 112,
+ "height": 126,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "#F7F8FE",
+ "stroke": "#0D32B2",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "z",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "#0A0F25",
+ "italic": false,
+ "bold": true,
+ "underline": false,
+ "labelWidth": 12,
+ "labelHeight": 26,
+ "labelPosition": "INSIDE_MIDDLE_CENTER",
+ "zIndex": 0,
+ "level": 1
+ }
+ ],
+ "connections": []
+}
diff --git a/e2etests/testdata/stable/near-alone/elk/sketch.exp.svg b/e2etests/testdata/stable/near-alone/elk/sketch.exp.svg
new file mode 100644
index 000000000..3944c699c
--- /dev/null
+++ b/e2etests/testdata/stable/near-alone/elk/sketch.exp.svg
@@ -0,0 +1,52 @@
+
+
\ No newline at end of file