diff --git a/ci/release/changelogs/next.md b/ci/release/changelogs/next.md
index f3c0d2a77..8f10656d9 100644
--- a/ci/release/changelogs/next.md
+++ b/ci/release/changelogs/next.md
@@ -3,3 +3,5 @@
#### Improvements 🧹
#### Bugfixes ⛑️
+
+- Grid layout now accounts for each cell's outside labels and icons [#1624](https://github.com/terrastruct/d2/pull/1624)
diff --git a/d2graph/layout.go b/d2graph/layout.go
index 8c705b713..f1c4a7ecc 100644
--- a/d2graph/layout.go
+++ b/d2graph/layout.go
@@ -1,6 +1,7 @@
package d2graph
import (
+ "math"
"sort"
"strings"
@@ -285,6 +286,49 @@ func (obj *Object) GetModifierElementAdjustments() (dx, dy float64) {
return dx, dy
}
+func (obj *Object) GetMargin() geo.Spacing {
+ margin := geo.Spacing{}
+
+ if obj.HasLabel() && obj.LabelPosition != nil {
+ position := label.Position(*obj.LabelPosition)
+
+ labelWidth := float64(obj.LabelDimensions.Width + label.PADDING)
+ labelHeight := float64(obj.LabelDimensions.Height + label.PADDING)
+
+ switch position {
+ case label.OutsideTopLeft, label.OutsideTopCenter, label.OutsideTopRight:
+ margin.Top = labelHeight
+ case label.OutsideBottomLeft, label.OutsideBottomCenter, label.OutsideBottomRight:
+ margin.Bottom = labelHeight
+ case label.OutsideLeftTop, label.OutsideLeftMiddle, label.OutsideLeftBottom:
+ margin.Left = labelWidth
+ case label.OutsideRightTop, label.OutsideRightMiddle, label.OutsideRightBottom:
+ margin.Right = labelWidth
+ }
+ }
+
+ if obj.Icon != nil && obj.IconPosition != nil && obj.Shape.Value != d2target.ShapeImage {
+ position := label.Position(*obj.IconPosition)
+
+ iconSize := float64(d2target.MAX_ICON_SIZE + label.PADDING)
+ switch position {
+ case label.OutsideTopLeft, label.OutsideTopCenter, label.OutsideTopRight:
+ margin.Top = math.Max(margin.Top, iconSize)
+ case label.OutsideBottomLeft, label.OutsideBottomCenter, label.OutsideBottomRight:
+ margin.Bottom = math.Max(margin.Bottom, iconSize)
+ case label.OutsideLeftTop, label.OutsideLeftMiddle, label.OutsideLeftBottom:
+ margin.Left = math.Max(margin.Left, iconSize)
+ case label.OutsideRightTop, label.OutsideRightMiddle, label.OutsideRightBottom:
+ margin.Right = math.Max(margin.Right, iconSize)
+ }
+ }
+
+ dx, dy := obj.GetModifierElementAdjustments()
+ margin.Right += dx
+ margin.Top += dy
+ return margin
+}
+
func (obj *Object) ToShape() shape.Shape {
tl := obj.TopLeft
if tl == nil {
diff --git a/d2layouts/d2grid/grid_diagram.go b/d2layouts/d2grid/grid_diagram.go
index cc56e82de..281f1e46d 100644
--- a/d2layouts/d2grid/grid_diagram.go
+++ b/d2layouts/d2grid/grid_diagram.go
@@ -2,7 +2,6 @@ package d2grid
import (
"strconv"
- "strings"
"oss.terrastruct.com/d2/d2graph"
"oss.terrastruct.com/d2/lib/geo"
@@ -112,19 +111,3 @@ func (gd *gridDiagram) shift(dx, dy float64) {
e.Move(dx, dy)
}
}
-
-func (gd *gridDiagram) cleanup(obj *d2graph.Object, graph *d2graph.Graph) {
- obj.Children = make(map[string]*d2graph.Object)
- obj.ChildrenArray = make([]*d2graph.Object, 0)
-
- restore := func(parent, child *d2graph.Object) {
- parent.Children[strings.ToLower(child.ID)] = child
- parent.ChildrenArray = append(parent.ChildrenArray, child)
- graph.Objects = append(graph.Objects, child)
- }
- for _, child := range gd.objects {
- restore(obj, child)
- child.IterDescendants(restore)
- }
- graph.Edges = append(graph.Edges, gd.edges...)
-}
diff --git a/d2layouts/d2grid/layout.go b/d2layouts/d2grid/layout.go
index f2b01e183..d5c220f90 100644
--- a/d2layouts/d2grid/layout.go
+++ b/d2layouts/d2grid/layout.go
@@ -77,43 +77,6 @@ func Layout(ctx context.Context, g *d2graph.Graph) error {
}
}
- // also check for grid cells with outside top labels or icons
- // the first grid object is at the top (and always exists)
- topY := gd.objects[0].TopLeft.Y
- highestOutside := topY
- for _, o := range gd.objects {
- // we only want to compute label positions for objects at the top of the grid
- if o.TopLeft.Y > topY {
- if gd.rowDirected {
- // if the grid is rowDirected (row1, row2, etc) we can stop after finishing the first row
- break
- } else {
- // otherwise we continue until the next column
- continue
- }
- }
- if o.LabelPosition != nil {
- labelPosition := label.Position(*o.LabelPosition)
- if labelPosition.IsOutside() {
- labelTL := o.GetLabelTopLeft()
- if labelTL.Y < highestOutside {
- highestOutside = labelTL.Y
- }
- }
- }
- if o.IconPosition != nil {
- switch label.Position(*o.IconPosition) {
- case label.OutsideTopLeft, label.OutsideTopCenter, label.OutsideTopRight:
- iconSpace := float64(d2target.MAX_ICON_SIZE + label.PADDING)
- if topY-iconSpace < highestOutside {
- highestOutside = topY - iconSpace
- }
- }
- }
- }
- if highestOutside < topY {
- occupiedHeight += topY - highestOutside + 2*label.PADDING
- }
if occupiedHeight > float64(verticalPadding) {
// if the label doesn't fit within the padding, we need to add more
dy = occupiedHeight - float64(verticalPadding)
@@ -179,12 +142,18 @@ func Layout(ctx context.Context, g *d2graph.Graph) error {
func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*gridDiagram, error) {
gd := newGridDiagram(obj)
+ // to handle objects with outside labels, we adjust their dimensions before layout and
+ // after layout, we remove the label adjustment and reposition TopLeft if needed
+ revertAdjustments := gd.sizeForOutsideLabels()
+
if gd.rows != 0 && gd.columns != 0 {
gd.layoutEvenly(g, obj)
} else {
gd.layoutDynamic(g, obj)
}
+ revertAdjustments()
+
// position labels and icons
for _, o := range gd.objects {
if o.Icon != nil {
@@ -871,3 +840,31 @@ func getDistToTarget(layout [][]*d2graph.Object, targetSize float64, horizontalG
}
return totalDelta
}
+
+func (gd *gridDiagram) sizeForOutsideLabels() (revert func()) {
+ margins := make(map[*d2graph.Object]geo.Spacing)
+
+ for _, o := range gd.objects {
+ margin := o.GetMargin()
+ margins[o] = margin
+
+ o.Height += margin.Top + margin.Bottom
+ o.Width += margin.Left + margin.Right
+ }
+
+ return func() {
+ for _, o := range gd.objects {
+ margin, has := margins[o]
+ if !has {
+ continue
+ }
+
+ o.Height -= margin.Top + margin.Bottom
+ o.Width -= margin.Left + margin.Right
+
+ if margin.Left > 0 || margin.Top > 0 {
+ o.MoveWithDescendants(margin.Left, margin.Top)
+ }
+ }
+ }
+}
diff --git a/e2etests/stable_test.go b/e2etests/stable_test.go
index 517fd91f2..7174c7c46 100644
--- a/e2etests/stable_test.go
+++ b/e2etests/stable_test.go
@@ -2836,6 +2836,7 @@ y: profits {
loadFromFile(t, "simple_grid_edges"),
loadFromFile(t, "grid_nested_simple_edges"),
loadFromFile(t, "nested_diagram_types"),
+ loadFromFile(t, "grid_outside_labels"),
}
runa(t, tcs)
diff --git a/e2etests/testdata/files/grid_outside_labels.d2 b/e2etests/testdata/files/grid_outside_labels.d2
new file mode 100644
index 000000000..9f54d9234
--- /dev/null
+++ b/e2etests/testdata/files/grid_outside_labels.d2
@@ -0,0 +1,64 @@
+container: ___________________________________container____________________________________ {
+ grid-columns: 3
+ grid-gap: 20
+
+ amscd plugin: {
+ ex: |tex
+ \\begin{CD} B @>{\\text{very long label}}>> C S^{{\\mathcal{W}}_\\Lambda}\\otimes T @>j>> T\\\\ @VVV V \\end{CD}
+ |
+ }
+
+ braket plugin: {
+ style.3d: true
+ ex: |tex
+ \\bra{a}\\ket{b}
+ |
+ }
+
+ cancel plugin: {
+ ex: |tex
+ \\cancel{Culture + 5}
+ |
+ }
+
+ color plugin: {
+ icon: https://icons.terrastruct.com/essentials/profits.svg
+ icon.near: outside-right-center
+ ex: |tex
+ \\textcolor{red}{y} = \\textcolor{green}{\\sin} x
+ |
+ }
+
+ gensymb plugin: {
+ ex: |tex
+ \\lambda = 10.6\\,\\micro\\mathrm{m}
+ |
+ }
+
+ mhchem plugin: {
+ style.multiple: true
+ ex: |tex
+ \ce{SO4^2- + Ba^2+ -> BaSO4 v}
+ |
+ }
+
+ physics plugin: {
+ ex: |tex
+ \\var{F[g(x)]}
+ \\dd(\\cos\\theta)
+ |
+ }
+
+ multilines: {
+ ex: |tex
+ \\displaylines{x = a + b \\\\ y = b + c}
+ \\sum_{k=1}^{n} h_{k} \\int_{0}^{1} \\bigl(\\partial_{k} f(x_{k-1}+t h_{k} e_{k}) -\\partial_{k} f(a)\\bigr) \\,dt
+ |
+ }
+
+ asm: {
+ ex: |latex
+ \\min_{ \\mathclap{\\substack{ x \\in \\mathbb{R}^n \\ x \\geq 0 \\ Ax \\leq b }}} c^T x
+ |
+ }
+}
diff --git a/e2etests/testdata/regression/outside_grid_label_position/dagre/board.exp.json b/e2etests/testdata/regression/outside_grid_label_position/dagre/board.exp.json
index e4d63f30e..d59b3cdda 100644
--- a/e2etests/testdata/regression/outside_grid_label_position/dagre/board.exp.json
+++ b/e2etests/testdata/regression/outside_grid_label_position/dagre/board.exp.json
@@ -11,7 +11,7 @@
"y": 29
},
"width": 681,
- "height": 390,
+ "height": 404,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -52,7 +52,7 @@
"y": 70
},
"width": 621,
- "height": 319,
+ "height": 333,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -93,7 +93,7 @@
"y": 100
},
"width": 561,
- "height": 259,
+ "height": 273,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -131,7 +131,7 @@
"type": "rectangle",
"pos": {
"x": 120,
- "y": 172
+ "y": 186
},
"width": 140,
"height": 127,
@@ -172,7 +172,7 @@
"type": "rectangle",
"pos": {
"x": 150,
- "y": 202
+ "y": 216
},
"width": 80,
"height": 66,
@@ -213,7 +213,7 @@
"type": "rectangle",
"pos": {
"x": 300,
- "y": 172
+ "y": 186
},
"width": 140,
"height": 127,
@@ -254,7 +254,7 @@
"type": "rectangle",
"pos": {
"x": 330,
- "y": 202
+ "y": 216
},
"width": 80,
"height": 66,
@@ -295,7 +295,7 @@
"type": "rectangle",
"pos": {
"x": 480,
- "y": 172
+ "y": 186
},
"width": 81,
"height": 127,
diff --git a/e2etests/testdata/regression/outside_grid_label_position/dagre/sketch.exp.svg b/e2etests/testdata/regression/outside_grid_label_position/dagre/sketch.exp.svg
index ce14de299..f9f126ca0 100644
--- a/e2etests/testdata/regression/outside_grid_label_position/dagre/sketch.exp.svg
+++ b/e2etests/testdata/regression/outside_grid_label_position/dagre/sketch.exp.svg
@@ -1,16 +1,16 @@
-
\ No newline at end of file
diff --git a/e2etests/testdata/regression/outside_grid_label_position/elk/board.exp.json b/e2etests/testdata/regression/outside_grid_label_position/elk/board.exp.json
index 26f38abc9..953d15c18 100644
--- a/e2etests/testdata/regression/outside_grid_label_position/elk/board.exp.json
+++ b/e2etests/testdata/regression/outside_grid_label_position/elk/board.exp.json
@@ -11,7 +11,7 @@
"y": 12
},
"width": 841,
- "height": 498,
+ "height": 512,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -52,7 +52,7 @@
"y": 62
},
"width": 741,
- "height": 398,
+ "height": 412,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -93,7 +93,7 @@
"y": 112
},
"width": 641,
- "height": 298,
+ "height": 312,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -131,7 +131,7 @@
"type": "rectangle",
"pos": {
"x": 172,
- "y": 184
+ "y": 198
},
"width": 180,
"height": 166,
@@ -172,7 +172,7 @@
"type": "rectangle",
"pos": {
"x": 222,
- "y": 234
+ "y": 248
},
"width": 80,
"height": 66,
@@ -213,7 +213,7 @@
"type": "rectangle",
"pos": {
"x": 392,
- "y": 184
+ "y": 198
},
"width": 180,
"height": 166,
@@ -254,7 +254,7 @@
"type": "rectangle",
"pos": {
"x": 442,
- "y": 234
+ "y": 248
},
"width": 80,
"height": 66,
@@ -295,7 +295,7 @@
"type": "rectangle",
"pos": {
"x": 612,
- "y": 184
+ "y": 198
},
"width": 81,
"height": 166,
diff --git a/e2etests/testdata/regression/outside_grid_label_position/elk/sketch.exp.svg b/e2etests/testdata/regression/outside_grid_label_position/elk/sketch.exp.svg
index 33ff27a74..e46c1bd7b 100644
--- a/e2etests/testdata/regression/outside_grid_label_position/elk/sketch.exp.svg
+++ b/e2etests/testdata/regression/outside_grid_label_position/elk/sketch.exp.svg
@@ -1,16 +1,16 @@
-container1container2container3firstsecondthirdchildchild
-
+ .d2-2885429201 .fill-N1{fill:#0A0F25;}
+ .d2-2885429201 .fill-N2{fill:#676C7E;}
+ .d2-2885429201 .fill-N3{fill:#9499AB;}
+ .d2-2885429201 .fill-N4{fill:#CFD2DD;}
+ .d2-2885429201 .fill-N5{fill:#DEE1EB;}
+ .d2-2885429201 .fill-N6{fill:#EEF1F8;}
+ .d2-2885429201 .fill-N7{fill:#FFFFFF;}
+ .d2-2885429201 .fill-B1{fill:#0D32B2;}
+ .d2-2885429201 .fill-B2{fill:#0D32B2;}
+ .d2-2885429201 .fill-B3{fill:#E3E9FD;}
+ .d2-2885429201 .fill-B4{fill:#E3E9FD;}
+ .d2-2885429201 .fill-B5{fill:#EDF0FD;}
+ .d2-2885429201 .fill-B6{fill:#F7F8FE;}
+ .d2-2885429201 .fill-AA2{fill:#4A6FF3;}
+ .d2-2885429201 .fill-AA4{fill:#EDF0FD;}
+ .d2-2885429201 .fill-AA5{fill:#F7F8FE;}
+ .d2-2885429201 .fill-AB4{fill:#EDF0FD;}
+ .d2-2885429201 .fill-AB5{fill:#F7F8FE;}
+ .d2-2885429201 .stroke-N1{stroke:#0A0F25;}
+ .d2-2885429201 .stroke-N2{stroke:#676C7E;}
+ .d2-2885429201 .stroke-N3{stroke:#9499AB;}
+ .d2-2885429201 .stroke-N4{stroke:#CFD2DD;}
+ .d2-2885429201 .stroke-N5{stroke:#DEE1EB;}
+ .d2-2885429201 .stroke-N6{stroke:#EEF1F8;}
+ .d2-2885429201 .stroke-N7{stroke:#FFFFFF;}
+ .d2-2885429201 .stroke-B1{stroke:#0D32B2;}
+ .d2-2885429201 .stroke-B2{stroke:#0D32B2;}
+ .d2-2885429201 .stroke-B3{stroke:#E3E9FD;}
+ .d2-2885429201 .stroke-B4{stroke:#E3E9FD;}
+ .d2-2885429201 .stroke-B5{stroke:#EDF0FD;}
+ .d2-2885429201 .stroke-B6{stroke:#F7F8FE;}
+ .d2-2885429201 .stroke-AA2{stroke:#4A6FF3;}
+ .d2-2885429201 .stroke-AA4{stroke:#EDF0FD;}
+ .d2-2885429201 .stroke-AA5{stroke:#F7F8FE;}
+ .d2-2885429201 .stroke-AB4{stroke:#EDF0FD;}
+ .d2-2885429201 .stroke-AB5{stroke:#F7F8FE;}
+ .d2-2885429201 .background-color-N1{background-color:#0A0F25;}
+ .d2-2885429201 .background-color-N2{background-color:#676C7E;}
+ .d2-2885429201 .background-color-N3{background-color:#9499AB;}
+ .d2-2885429201 .background-color-N4{background-color:#CFD2DD;}
+ .d2-2885429201 .background-color-N5{background-color:#DEE1EB;}
+ .d2-2885429201 .background-color-N6{background-color:#EEF1F8;}
+ .d2-2885429201 .background-color-N7{background-color:#FFFFFF;}
+ .d2-2885429201 .background-color-B1{background-color:#0D32B2;}
+ .d2-2885429201 .background-color-B2{background-color:#0D32B2;}
+ .d2-2885429201 .background-color-B3{background-color:#E3E9FD;}
+ .d2-2885429201 .background-color-B4{background-color:#E3E9FD;}
+ .d2-2885429201 .background-color-B5{background-color:#EDF0FD;}
+ .d2-2885429201 .background-color-B6{background-color:#F7F8FE;}
+ .d2-2885429201 .background-color-AA2{background-color:#4A6FF3;}
+ .d2-2885429201 .background-color-AA4{background-color:#EDF0FD;}
+ .d2-2885429201 .background-color-AA5{background-color:#F7F8FE;}
+ .d2-2885429201 .background-color-AB4{background-color:#EDF0FD;}
+ .d2-2885429201 .background-color-AB5{background-color:#F7F8FE;}
+ .d2-2885429201 .color-N1{color:#0A0F25;}
+ .d2-2885429201 .color-N2{color:#676C7E;}
+ .d2-2885429201 .color-N3{color:#9499AB;}
+ .d2-2885429201 .color-N4{color:#CFD2DD;}
+ .d2-2885429201 .color-N5{color:#DEE1EB;}
+ .d2-2885429201 .color-N6{color:#EEF1F8;}
+ .d2-2885429201 .color-N7{color:#FFFFFF;}
+ .d2-2885429201 .color-B1{color:#0D32B2;}
+ .d2-2885429201 .color-B2{color:#0D32B2;}
+ .d2-2885429201 .color-B3{color:#E3E9FD;}
+ .d2-2885429201 .color-B4{color:#E3E9FD;}
+ .d2-2885429201 .color-B5{color:#EDF0FD;}
+ .d2-2885429201 .color-B6{color:#F7F8FE;}
+ .d2-2885429201 .color-AA2{color:#4A6FF3;}
+ .d2-2885429201 .color-AA4{color:#EDF0FD;}
+ .d2-2885429201 .color-AA5{color:#F7F8FE;}
+ .d2-2885429201 .color-AB4{color:#EDF0FD;}
+ .d2-2885429201 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]>container1container2container3firstsecondthirdchildchild
+
-
-
-
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/e2etests/testdata/stable/grid_icon/dagre/board.exp.json b/e2etests/testdata/stable/grid_icon/dagre/board.exp.json
index e8b5da641..e5bf4fa9e 100644
--- a/e2etests/testdata/stable/grid_icon/dagre/board.exp.json
+++ b/e2etests/testdata/stable/grid_icon/dagre/board.exp.json
@@ -14,7 +14,7 @@
"y": 0
},
"width": 364,
- "height": 417,
+ "height": 421,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -52,10 +52,10 @@
"type": "rectangle",
"pos": {
"x": 60,
- "y": 125
+ "y": 60
},
"width": 53,
- "height": 126,
+ "height": 195,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -93,7 +93,7 @@
"type": "rectangle",
"pos": {
"x": 153,
- "y": 125
+ "y": 129
},
"width": 151,
"height": 126,
@@ -146,7 +146,7 @@
"type": "rectangle",
"pos": {
"x": 183,
- "y": 155
+ "y": 159
},
"width": 91,
"height": 66,
@@ -187,7 +187,7 @@
"type": "rectangle",
"pos": {
"x": 60,
- "y": 291
+ "y": 295
},
"width": 53,
"height": 66,
@@ -228,7 +228,7 @@
"type": "rectangle",
"pos": {
"x": 153,
- "y": 291
+ "y": 295
},
"width": 151,
"height": 66,
@@ -272,7 +272,7 @@
],
"pos": {
"x": 424,
- "y": 56
+ "y": 58
},
"width": 278,
"height": 306,
@@ -325,7 +325,7 @@
"type": "rectangle",
"pos": {
"x": 489,
- "y": 130
+ "y": 132
},
"width": 53,
"height": 66,
@@ -366,7 +366,7 @@
"type": "rectangle",
"pos": {
"x": 582,
- "y": 130
+ "y": 132
},
"width": 54,
"height": 66,
@@ -407,7 +407,7 @@
"type": "rectangle",
"pos": {
"x": 489,
- "y": 236
+ "y": 238
},
"width": 53,
"height": 66,
@@ -448,7 +448,7 @@
"type": "rectangle",
"pos": {
"x": 582,
- "y": 236
+ "y": 238
},
"width": 54,
"height": 66,
@@ -492,10 +492,10 @@
],
"pos": {
"x": 762,
- "y": 3
+ "y": 10
},
"width": 433,
- "height": 412,
+ "height": 402,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -545,10 +545,10 @@
"type": "rectangle",
"pos": {
"x": 856,
- "y": 123
+ "y": 84
},
"width": 53,
- "height": 126,
+ "height": 162,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -586,7 +586,7 @@
"type": "rectangle",
"pos": {
"x": 949,
- "y": 123
+ "y": 120
},
"width": 151,
"height": 126,
@@ -627,7 +627,7 @@
"type": "rectangle",
"pos": {
"x": 979,
- "y": 153
+ "y": 150
},
"width": 91,
"height": 66,
@@ -668,7 +668,7 @@
"type": "rectangle",
"pos": {
"x": 856,
- "y": 289
+ "y": 286
},
"width": 53,
"height": 66,
@@ -709,7 +709,7 @@
"type": "rectangle",
"pos": {
"x": 949,
- "y": 289
+ "y": 286
},
"width": 151,
"height": 66,
@@ -753,10 +753,10 @@
],
"pos": {
"x": 1255,
- "y": 23
+ "y": 0
},
"width": 364,
- "height": 371,
+ "height": 421,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -794,10 +794,10 @@
"type": "rectangle",
"pos": {
"x": 1315,
- "y": 102
+ "y": 60
},
"width": 53,
- "height": 126,
+ "height": 195,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -835,7 +835,7 @@
"type": "rectangle",
"pos": {
"x": 1408,
- "y": 102
+ "y": 129
},
"width": 151,
"height": 126,
@@ -888,7 +888,7 @@
"type": "rectangle",
"pos": {
"x": 1438,
- "y": 132
+ "y": 159
},
"width": 91,
"height": 66,
@@ -929,7 +929,7 @@
"type": "rectangle",
"pos": {
"x": 1315,
- "y": 268
+ "y": 295
},
"width": 53,
"height": 66,
@@ -970,7 +970,7 @@
"type": "rectangle",
"pos": {
"x": 1408,
- "y": 268
+ "y": 295
},
"width": 151,
"height": 66,
@@ -1014,7 +1014,7 @@
],
"pos": {
"x": 1679,
- "y": 56
+ "y": 58
},
"width": 267,
"height": 306,
@@ -1067,7 +1067,7 @@
"type": "rectangle",
"pos": {
"x": 1739,
- "y": 130
+ "y": 132
},
"width": 53,
"height": 66,
@@ -1108,7 +1108,7 @@
"type": "rectangle",
"pos": {
"x": 1832,
- "y": 130
+ "y": 132
},
"width": 54,
"height": 66,
@@ -1149,7 +1149,7 @@
"type": "rectangle",
"pos": {
"x": 1739,
- "y": 236
+ "y": 238
},
"width": 53,
"height": 66,
@@ -1190,7 +1190,7 @@
"type": "rectangle",
"pos": {
"x": 1832,
- "y": 236
+ "y": 238
},
"width": 54,
"height": 66,
diff --git a/e2etests/testdata/stable/grid_icon/dagre/sketch.exp.svg b/e2etests/testdata/stable/grid_icon/dagre/sketch.exp.svg
index 619e1ea9b..37ef678d3 100644
--- a/e2etests/testdata/stable/grid_icon/dagre/sketch.exp.svg
+++ b/e2etests/testdata/stable/grid_icon/dagre/sketch.exp.svg
@@ -1,16 +1,16 @@
-grid w/ container + icongrid + icongrid + icon w/ containerabcdabcdabcdabcdabcdb childb childb child
-
+ .d2-379655365 .fill-N1{fill:#0A0F25;}
+ .d2-379655365 .fill-N2{fill:#676C7E;}
+ .d2-379655365 .fill-N3{fill:#9499AB;}
+ .d2-379655365 .fill-N4{fill:#CFD2DD;}
+ .d2-379655365 .fill-N5{fill:#DEE1EB;}
+ .d2-379655365 .fill-N6{fill:#EEF1F8;}
+ .d2-379655365 .fill-N7{fill:#FFFFFF;}
+ .d2-379655365 .fill-B1{fill:#0D32B2;}
+ .d2-379655365 .fill-B2{fill:#0D32B2;}
+ .d2-379655365 .fill-B3{fill:#E3E9FD;}
+ .d2-379655365 .fill-B4{fill:#E3E9FD;}
+ .d2-379655365 .fill-B5{fill:#EDF0FD;}
+ .d2-379655365 .fill-B6{fill:#F7F8FE;}
+ .d2-379655365 .fill-AA2{fill:#4A6FF3;}
+ .d2-379655365 .fill-AA4{fill:#EDF0FD;}
+ .d2-379655365 .fill-AA5{fill:#F7F8FE;}
+ .d2-379655365 .fill-AB4{fill:#EDF0FD;}
+ .d2-379655365 .fill-AB5{fill:#F7F8FE;}
+ .d2-379655365 .stroke-N1{stroke:#0A0F25;}
+ .d2-379655365 .stroke-N2{stroke:#676C7E;}
+ .d2-379655365 .stroke-N3{stroke:#9499AB;}
+ .d2-379655365 .stroke-N4{stroke:#CFD2DD;}
+ .d2-379655365 .stroke-N5{stroke:#DEE1EB;}
+ .d2-379655365 .stroke-N6{stroke:#EEF1F8;}
+ .d2-379655365 .stroke-N7{stroke:#FFFFFF;}
+ .d2-379655365 .stroke-B1{stroke:#0D32B2;}
+ .d2-379655365 .stroke-B2{stroke:#0D32B2;}
+ .d2-379655365 .stroke-B3{stroke:#E3E9FD;}
+ .d2-379655365 .stroke-B4{stroke:#E3E9FD;}
+ .d2-379655365 .stroke-B5{stroke:#EDF0FD;}
+ .d2-379655365 .stroke-B6{stroke:#F7F8FE;}
+ .d2-379655365 .stroke-AA2{stroke:#4A6FF3;}
+ .d2-379655365 .stroke-AA4{stroke:#EDF0FD;}
+ .d2-379655365 .stroke-AA5{stroke:#F7F8FE;}
+ .d2-379655365 .stroke-AB4{stroke:#EDF0FD;}
+ .d2-379655365 .stroke-AB5{stroke:#F7F8FE;}
+ .d2-379655365 .background-color-N1{background-color:#0A0F25;}
+ .d2-379655365 .background-color-N2{background-color:#676C7E;}
+ .d2-379655365 .background-color-N3{background-color:#9499AB;}
+ .d2-379655365 .background-color-N4{background-color:#CFD2DD;}
+ .d2-379655365 .background-color-N5{background-color:#DEE1EB;}
+ .d2-379655365 .background-color-N6{background-color:#EEF1F8;}
+ .d2-379655365 .background-color-N7{background-color:#FFFFFF;}
+ .d2-379655365 .background-color-B1{background-color:#0D32B2;}
+ .d2-379655365 .background-color-B2{background-color:#0D32B2;}
+ .d2-379655365 .background-color-B3{background-color:#E3E9FD;}
+ .d2-379655365 .background-color-B4{background-color:#E3E9FD;}
+ .d2-379655365 .background-color-B5{background-color:#EDF0FD;}
+ .d2-379655365 .background-color-B6{background-color:#F7F8FE;}
+ .d2-379655365 .background-color-AA2{background-color:#4A6FF3;}
+ .d2-379655365 .background-color-AA4{background-color:#EDF0FD;}
+ .d2-379655365 .background-color-AA5{background-color:#F7F8FE;}
+ .d2-379655365 .background-color-AB4{background-color:#EDF0FD;}
+ .d2-379655365 .background-color-AB5{background-color:#F7F8FE;}
+ .d2-379655365 .color-N1{color:#0A0F25;}
+ .d2-379655365 .color-N2{color:#676C7E;}
+ .d2-379655365 .color-N3{color:#9499AB;}
+ .d2-379655365 .color-N4{color:#CFD2DD;}
+ .d2-379655365 .color-N5{color:#DEE1EB;}
+ .d2-379655365 .color-N6{color:#EEF1F8;}
+ .d2-379655365 .color-N7{color:#FFFFFF;}
+ .d2-379655365 .color-B1{color:#0D32B2;}
+ .d2-379655365 .color-B2{color:#0D32B2;}
+ .d2-379655365 .color-B3{color:#E3E9FD;}
+ .d2-379655365 .color-B4{color:#E3E9FD;}
+ .d2-379655365 .color-B5{color:#EDF0FD;}
+ .d2-379655365 .color-B6{color:#F7F8FE;}
+ .d2-379655365 .color-AA2{color:#4A6FF3;}
+ .d2-379655365 .color-AA4{color:#EDF0FD;}
+ .d2-379655365 .color-AA5{color:#F7F8FE;}
+ .d2-379655365 .color-AB4{color:#EDF0FD;}
+ .d2-379655365 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]>grid w/ container + icongrid + icongrid + icon w/ containerabcdabcdabcdabcdabcdb childb childb child
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/e2etests/testdata/stable/grid_nested/dagre/board.exp.json b/e2etests/testdata/stable/grid_nested/dagre/board.exp.json
index 4d4abbc98..99cef9427 100644
--- a/e2etests/testdata/stable/grid_nested/dagre/board.exp.json
+++ b/e2etests/testdata/stable/grid_nested/dagre/board.exp.json
@@ -11,10 +11,10 @@
],
"pos": {
"x": 0,
- "y": 99
+ "y": 97
},
"width": 364,
- "height": 384,
+ "height": 388,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -52,10 +52,10 @@
"type": "rectangle",
"pos": {
"x": 60,
- "y": 191
+ "y": 157
},
"width": 53,
- "height": 126,
+ "height": 162,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -93,7 +93,7 @@
"type": "rectangle",
"pos": {
"x": 153,
- "y": 191
+ "y": 193
},
"width": 151,
"height": 126,
@@ -134,7 +134,7 @@
"type": "rectangle",
"pos": {
"x": 183,
- "y": 221
+ "y": 223
},
"width": 91,
"height": 66,
@@ -175,7 +175,7 @@
"type": "rectangle",
"pos": {
"x": 60,
- "y": 357
+ "y": 359
},
"width": 53,
"height": 66,
@@ -216,7 +216,7 @@
"type": "rectangle",
"pos": {
"x": 153,
- "y": 357
+ "y": 359
},
"width": 151,
"height": 66,
@@ -260,10 +260,10 @@
],
"pos": {
"x": 424,
- "y": 5
+ "y": 3
},
"width": 692,
- "height": 572,
+ "height": 576,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -301,10 +301,10 @@
"type": "rectangle",
"pos": {
"x": 484,
- "y": 97
+ "y": 63
},
"width": 53,
- "height": 314,
+ "height": 350,
"opacity": 1,
"strokeDash": 0,
"strokeWidth": 2,
@@ -342,7 +342,7 @@
"type": "rectangle",
"pos": {
"x": 577,
- "y": 97
+ "y": 99
},
"width": 479,
"height": 314,
@@ -383,7 +383,7 @@
"type": "rectangle",
"pos": {
"x": 597,
- "y": 133
+ "y": 135
},
"width": 439,
"height": 248,
@@ -424,7 +424,7 @@
"type": "rectangle",
"pos": {
"x": 617,
- "y": 164
+ "y": 166
},
"width": 186,
"height": 187,
@@ -465,7 +465,7 @@
"type": "rectangle",
"pos": {
"x": 647,
- "y": 195
+ "y": 197
},
"width": 126,
"height": 126,
@@ -506,7 +506,7 @@
"type": "rectangle",
"pos": {
"x": 677,
- "y": 225
+ "y": 227
},
"width": 66,
"height": 66,
@@ -547,7 +547,7 @@
"type": "rectangle",
"pos": {
"x": 823,
- "y": 164
+ "y": 166
},
"width": 193,
"height": 187,
@@ -588,7 +588,7 @@
"type": "rectangle",
"pos": {
"x": 853,
- "y": 195
+ "y": 197
},
"width": 133,
"height": 126,
@@ -629,7 +629,7 @@
"type": "rectangle",
"pos": {
"x": 883,
- "y": 225
+ "y": 227
},
"width": 73,
"height": 66,
@@ -670,7 +670,7 @@
"type": "rectangle",
"pos": {
"x": 484,
- "y": 451
+ "y": 453
},
"width": 53,
"height": 66,
@@ -711,7 +711,7 @@
"type": "rectangle",
"pos": {
"x": 577,
- "y": 451
+ "y": 453
},
"width": 479,
"height": 66,
diff --git a/e2etests/testdata/stable/grid_nested/dagre/sketch.exp.svg b/e2etests/testdata/stable/grid_nested/dagre/sketch.exp.svg
index 78ba506bc..c16ab304f 100644
--- a/e2etests/testdata/stable/grid_nested/dagre/sketch.exp.svg
+++ b/e2etests/testdata/stable/grid_nested/dagre/sketch.exp.svg
@@ -1,16 +1,16 @@
-grid w/ containergrid w/ nested containersgrid in gridgrid w/ grid w/ gridabcdabcdabcdabcdb childb 1abcdabcdb 2b 2aabcdb 3b 3aabcdb 4b 3aabcd
+ .d2-2055001460 .fill-N1{fill:#0A0F25;}
+ .d2-2055001460 .fill-N2{fill:#676C7E;}
+ .d2-2055001460 .fill-N3{fill:#9499AB;}
+ .d2-2055001460 .fill-N4{fill:#CFD2DD;}
+ .d2-2055001460 .fill-N5{fill:#DEE1EB;}
+ .d2-2055001460 .fill-N6{fill:#EEF1F8;}
+ .d2-2055001460 .fill-N7{fill:#FFFFFF;}
+ .d2-2055001460 .fill-B1{fill:#0D32B2;}
+ .d2-2055001460 .fill-B2{fill:#0D32B2;}
+ .d2-2055001460 .fill-B3{fill:#E3E9FD;}
+ .d2-2055001460 .fill-B4{fill:#E3E9FD;}
+ .d2-2055001460 .fill-B5{fill:#EDF0FD;}
+ .d2-2055001460 .fill-B6{fill:#F7F8FE;}
+ .d2-2055001460 .fill-AA2{fill:#4A6FF3;}
+ .d2-2055001460 .fill-AA4{fill:#EDF0FD;}
+ .d2-2055001460 .fill-AA5{fill:#F7F8FE;}
+ .d2-2055001460 .fill-AB4{fill:#EDF0FD;}
+ .d2-2055001460 .fill-AB5{fill:#F7F8FE;}
+ .d2-2055001460 .stroke-N1{stroke:#0A0F25;}
+ .d2-2055001460 .stroke-N2{stroke:#676C7E;}
+ .d2-2055001460 .stroke-N3{stroke:#9499AB;}
+ .d2-2055001460 .stroke-N4{stroke:#CFD2DD;}
+ .d2-2055001460 .stroke-N5{stroke:#DEE1EB;}
+ .d2-2055001460 .stroke-N6{stroke:#EEF1F8;}
+ .d2-2055001460 .stroke-N7{stroke:#FFFFFF;}
+ .d2-2055001460 .stroke-B1{stroke:#0D32B2;}
+ .d2-2055001460 .stroke-B2{stroke:#0D32B2;}
+ .d2-2055001460 .stroke-B3{stroke:#E3E9FD;}
+ .d2-2055001460 .stroke-B4{stroke:#E3E9FD;}
+ .d2-2055001460 .stroke-B5{stroke:#EDF0FD;}
+ .d2-2055001460 .stroke-B6{stroke:#F7F8FE;}
+ .d2-2055001460 .stroke-AA2{stroke:#4A6FF3;}
+ .d2-2055001460 .stroke-AA4{stroke:#EDF0FD;}
+ .d2-2055001460 .stroke-AA5{stroke:#F7F8FE;}
+ .d2-2055001460 .stroke-AB4{stroke:#EDF0FD;}
+ .d2-2055001460 .stroke-AB5{stroke:#F7F8FE;}
+ .d2-2055001460 .background-color-N1{background-color:#0A0F25;}
+ .d2-2055001460 .background-color-N2{background-color:#676C7E;}
+ .d2-2055001460 .background-color-N3{background-color:#9499AB;}
+ .d2-2055001460 .background-color-N4{background-color:#CFD2DD;}
+ .d2-2055001460 .background-color-N5{background-color:#DEE1EB;}
+ .d2-2055001460 .background-color-N6{background-color:#EEF1F8;}
+ .d2-2055001460 .background-color-N7{background-color:#FFFFFF;}
+ .d2-2055001460 .background-color-B1{background-color:#0D32B2;}
+ .d2-2055001460 .background-color-B2{background-color:#0D32B2;}
+ .d2-2055001460 .background-color-B3{background-color:#E3E9FD;}
+ .d2-2055001460 .background-color-B4{background-color:#E3E9FD;}
+ .d2-2055001460 .background-color-B5{background-color:#EDF0FD;}
+ .d2-2055001460 .background-color-B6{background-color:#F7F8FE;}
+ .d2-2055001460 .background-color-AA2{background-color:#4A6FF3;}
+ .d2-2055001460 .background-color-AA4{background-color:#EDF0FD;}
+ .d2-2055001460 .background-color-AA5{background-color:#F7F8FE;}
+ .d2-2055001460 .background-color-AB4{background-color:#EDF0FD;}
+ .d2-2055001460 .background-color-AB5{background-color:#F7F8FE;}
+ .d2-2055001460 .color-N1{color:#0A0F25;}
+ .d2-2055001460 .color-N2{color:#676C7E;}
+ .d2-2055001460 .color-N3{color:#9499AB;}
+ .d2-2055001460 .color-N4{color:#CFD2DD;}
+ .d2-2055001460 .color-N5{color:#DEE1EB;}
+ .d2-2055001460 .color-N6{color:#EEF1F8;}
+ .d2-2055001460 .color-N7{color:#FFFFFF;}
+ .d2-2055001460 .color-B1{color:#0D32B2;}
+ .d2-2055001460 .color-B2{color:#0D32B2;}
+ .d2-2055001460 .color-B3{color:#E3E9FD;}
+ .d2-2055001460 .color-B4{color:#E3E9FD;}
+ .d2-2055001460 .color-B5{color:#EDF0FD;}
+ .d2-2055001460 .color-B6{color:#F7F8FE;}
+ .d2-2055001460 .color-AA2{color:#4A6FF3;}
+ .d2-2055001460 .color-AA4{color:#EDF0FD;}
+ .d2-2055001460 .color-AA5{color:#F7F8FE;}
+ .d2-2055001460 .color-AB4{color:#EDF0FD;}
+ .d2-2055001460 .color-AB5{color:#F7F8FE;}.appendix text.text{fill:#0A0F25}.md{--color-fg-default:#0A0F25;--color-fg-muted:#676C7E;--color-fg-subtle:#9499AB;--color-canvas-default:#FFFFFF;--color-canvas-subtle:#EEF1F8;--color-border-default:#0D32B2;--color-border-muted:#0D32B2;--color-neutral-muted:#EEF1F8;--color-accent-fg:#0D32B2;--color-accent-emphasis:#0D32B2;--color-attention-subtle:#676C7E;--color-danger-fg:red;}.sketch-overlay-B1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B2{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-B3{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-B6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-AA4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AA5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB4{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-AB5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N1{fill:url(#streaks-darker);mix-blend-mode:lighten}.sketch-overlay-N2{fill:url(#streaks-dark);mix-blend-mode:overlay}.sketch-overlay-N3{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N4{fill:url(#streaks-normal);mix-blend-mode:color-burn}.sketch-overlay-N5{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N6{fill:url(#streaks-bright);mix-blend-mode:darken}.sketch-overlay-N7{fill:url(#streaks-bright);mix-blend-mode:darken}.light-code{display: block}.dark-code{display: none}]]>grid w/ containergrid w/ nested containersgrid in gridgrid w/ grid w/ gridabcdabcdabcdabcdb childb 1abcdabcdb 2b 2aabcdb 3b 3aabcdb 4b 3aabcd
-
-
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -118,8 +118,8 @@
-
-
+
+
@@ -128,20 +128,20 @@
-
-
+
+
-
-
+
+
-
-
+
+
diff --git a/e2etests/testdata/stable/grid_outside_labels/dagre/board.exp.json b/e2etests/testdata/stable/grid_outside_labels/dagre/board.exp.json
new file mode 100644
index 000000000..7140db237
--- /dev/null
+++ b/e2etests/testdata/stable/grid_outside_labels/dagre/board.exp.json
@@ -0,0 +1,830 @@
+{
+ "name": "",
+ "isFolderOnly": false,
+ "fontFamily": "SourceSansPro",
+ "shapes": [
+ {
+ "id": "container",
+ "type": "rectangle",
+ "pos": {
+ "x": 0,
+ "y": 0
+ },
+ "width": 1213,
+ "height": 524,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B4",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "___________________________________container____________________________________",
+ "fontSize": 28,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 1107,
+ "labelHeight": 36,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 1
+ },
+ {
+ "id": "container.amscd plugin",
+ "type": "rectangle",
+ "pos": {
+ "x": 20,
+ "y": 82
+ },
+ "width": 345,
+ "height": 132,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "amscd plugin",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 133,
+ "labelHeight": 31,
+ "labelPosition": "OUTSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.amscd plugin.ex",
+ "type": "text",
+ "pos": {
+ "x": 50,
+ "y": 112
+ },
+ "width": 285,
+ "height": 72,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\\\begin{CD} B @>{\\\\text{very long label}}>> C S^{{\\\\mathcal{W}}_\\\\Lambda}\\\\otimes T @>j>> T\\\\\\\\ @VVV V \\\\end{CD}",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 285,
+ "labelHeight": 72,
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.braket plugin",
+ "type": "rectangle",
+ "pos": {
+ "x": 20,
+ "y": 285
+ },
+ "width": 330,
+ "height": 79,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": true,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "braket plugin",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 132,
+ "labelHeight": 31,
+ "labelPosition": "OUTSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.braket plugin.ex",
+ "type": "text",
+ "pos": {
+ "x": 50,
+ "y": 315
+ },
+ "width": 37,
+ "height": 19,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\\\bra{a}\\\\ket{b}",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 37,
+ "labelHeight": 19,
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.cancel plugin",
+ "type": "rectangle",
+ "pos": {
+ "x": 20,
+ "y": 420
+ },
+ "width": 345,
+ "height": 84,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "cancel plugin",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 132,
+ "labelHeight": 31,
+ "labelPosition": "OUTSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.cancel plugin.ex",
+ "type": "text",
+ "pos": {
+ "x": 50,
+ "y": 450
+ },
+ "width": 104,
+ "height": 24,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\\\cancel{Culture + 5}",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 104,
+ "labelHeight": 24,
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.color plugin",
+ "type": "rectangle",
+ "pos": {
+ "x": 385,
+ "y": 82
+ },
+ "width": 255,
+ "height": 103,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": {
+ "Scheme": "https",
+ "Opaque": "",
+ "User": null,
+ "Host": "icons.terrastruct.com",
+ "Path": "/essentials/profits.svg",
+ "RawPath": "",
+ "OmitHost": false,
+ "ForceQuery": false,
+ "RawQuery": "",
+ "Fragment": "",
+ "RawFragment": ""
+ },
+ "iconPosition": "OUTSIDE_RIGHT_MIDDLE",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "color plugin",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 118,
+ "labelHeight": 31,
+ "labelPosition": "OUTSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.color plugin.ex",
+ "type": "text",
+ "pos": {
+ "x": 415,
+ "y": 112
+ },
+ "width": 69,
+ "height": 16,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\\\textcolor{red}{y} = \\\\textcolor{green}{\\\\sin} x",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 69,
+ "labelHeight": 16,
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.gensymb plugin",
+ "type": "rectangle",
+ "pos": {
+ "x": 385,
+ "y": 241
+ },
+ "width": 324,
+ "height": 103,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "gensymb plugin",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 158,
+ "labelHeight": 31,
+ "labelPosition": "OUTSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.gensymb plugin.ex",
+ "type": "text",
+ "pos": {
+ "x": 415,
+ "y": 271
+ },
+ "width": 96,
+ "height": 18,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\\\lambda = 10.6\\\\,\\\\micro\\\\mathrm{m}",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 96,
+ "labelHeight": 18,
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.mhchem plugin",
+ "type": "rectangle",
+ "pos": {
+ "x": 385,
+ "y": 410
+ },
+ "width": 314,
+ "height": 93,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": true,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "mhchem plugin",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 156,
+ "labelHeight": 31,
+ "labelPosition": "OUTSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.mhchem plugin.ex",
+ "type": "text",
+ "pos": {
+ "x": 415,
+ "y": 440
+ },
+ "width": 254,
+ "height": 18,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\ce{SO4^2- + Ba^2+ -> BaSO4 v}",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 254,
+ "labelHeight": 18,
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.physics plugin",
+ "type": "rectangle",
+ "pos": {
+ "x": 729,
+ "y": 82
+ },
+ "width": 464,
+ "height": 95,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "physics plugin",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 141,
+ "labelHeight": 31,
+ "labelPosition": "OUTSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.physics plugin.ex",
+ "type": "text",
+ "pos": {
+ "x": 759,
+ "y": 112
+ },
+ "width": 128,
+ "height": 19,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\\\var{F[g(x)]}\n\\\\dd(\\\\cos\\\\theta)",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 128,
+ "labelHeight": 19,
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.multilines",
+ "type": "rectangle",
+ "pos": {
+ "x": 729,
+ "y": 233
+ },
+ "width": 464,
+ "height": 112,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "multilines",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 100,
+ "labelHeight": 31,
+ "labelPosition": "OUTSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.multilines.ex",
+ "type": "text",
+ "pos": {
+ "x": 759,
+ "y": 263
+ },
+ "width": 404,
+ "height": 52,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\\\displaylines{x = a + b \\\\\\\\ y = b + c}\n\\\\sum_{k=1}^{n} h_{k} \\\\int_{0}^{1} \\\\bigl(\\\\partial_{k} f(x_{k-1}+t h_{k} e_{k}) -\\\\partial_{k} f(a)\\\\bigr) \\\\,dt",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 404,
+ "labelHeight": 52,
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.asm",
+ "type": "rectangle",
+ "pos": {
+ "x": 729,
+ "y": 401
+ },
+ "width": 464,
+ "height": 102,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "asm",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 41,
+ "labelHeight": 31,
+ "labelPosition": "OUTSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.asm.ex",
+ "type": "text",
+ "pos": {
+ "x": 759,
+ "y": 431
+ },
+ "width": 62,
+ "height": 32,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\\\min_{ \\\\mathclap{\\\\substack{ x \\\\in \\\\mathbb{R}^n \\\\ x \\\\geq 0 \\\\ Ax \\\\leq b }}} c^T x",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 62,
+ "labelHeight": 32,
+ "zIndex": 0,
+ "level": 3
+ }
+ ],
+ "connections": [],
+ "root": {
+ "id": "",
+ "type": "",
+ "pos": {
+ "x": 0,
+ "y": 0
+ },
+ "width": 0,
+ "height": 0,
+ "opacity": 0,
+ "strokeDash": 0,
+ "strokeWidth": 0,
+ "borderRadius": 0,
+ "fill": "N7",
+ "stroke": "",
+ "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/stable/grid_outside_labels/dagre/sketch.exp.svg b/e2etests/testdata/stable/grid_outside_labels/dagre/sketch.exp.svg
new file mode 100644
index 000000000..3596a8c27
--- /dev/null
+++ b/e2etests/testdata/stable/grid_outside_labels/dagre/sketch.exp.svg
@@ -0,0 +1,851 @@
+___________________________________container____________________________________amscd plugin
+
+braket plugincancel plugincolor plugingensymb pluginmhchem pluginphysics pluginmultilinesasmµ
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/e2etests/testdata/stable/grid_outside_labels/elk/board.exp.json b/e2etests/testdata/stable/grid_outside_labels/elk/board.exp.json
new file mode 100644
index 000000000..5ace04c9d
--- /dev/null
+++ b/e2etests/testdata/stable/grid_outside_labels/elk/board.exp.json
@@ -0,0 +1,830 @@
+{
+ "name": "",
+ "isFolderOnly": false,
+ "fontFamily": "SourceSansPro",
+ "shapes": [
+ {
+ "id": "container",
+ "type": "rectangle",
+ "pos": {
+ "x": 12,
+ "y": 12
+ },
+ "width": 1333,
+ "height": 536,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B4",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "___________________________________container____________________________________",
+ "fontSize": 28,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 1107,
+ "labelHeight": 36,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 1
+ },
+ {
+ "id": "container.amscd plugin",
+ "type": "rectangle",
+ "pos": {
+ "x": 32,
+ "y": 58
+ },
+ "width": 385,
+ "height": 172,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "amscd plugin",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 133,
+ "labelHeight": 31,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.amscd plugin.ex",
+ "type": "text",
+ "pos": {
+ "x": 82,
+ "y": 108
+ },
+ "width": 285,
+ "height": 72,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\\\begin{CD} B @>{\\\\text{very long label}}>> C S^{{\\\\mathcal{W}}_\\\\Lambda}\\\\otimes T @>j>> T\\\\\\\\ @VVV V \\\\end{CD}",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 285,
+ "labelHeight": 72,
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.braket plugin",
+ "type": "rectangle",
+ "pos": {
+ "x": 32,
+ "y": 265
+ },
+ "width": 370,
+ "height": 119,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": true,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "braket plugin",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 132,
+ "labelHeight": 31,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.braket plugin.ex",
+ "type": "text",
+ "pos": {
+ "x": 109,
+ "y": 315
+ },
+ "width": 37,
+ "height": 19,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\\\bra{a}\\\\ket{b}",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 37,
+ "labelHeight": 19,
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.cancel plugin",
+ "type": "rectangle",
+ "pos": {
+ "x": 32,
+ "y": 404
+ },
+ "width": 385,
+ "height": 124,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "cancel plugin",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 132,
+ "labelHeight": 31,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.cancel plugin.ex",
+ "type": "text",
+ "pos": {
+ "x": 82,
+ "y": 454
+ },
+ "width": 104,
+ "height": 24,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\\\cancel{Culture + 5}",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 104,
+ "labelHeight": 24,
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.color plugin",
+ "type": "rectangle",
+ "pos": {
+ "x": 437,
+ "y": 58
+ },
+ "width": 295,
+ "height": 148,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": {
+ "Scheme": "https",
+ "Opaque": "",
+ "User": null,
+ "Host": "icons.terrastruct.com",
+ "Path": "/essentials/profits.svg",
+ "RawPath": "",
+ "OmitHost": false,
+ "ForceQuery": false,
+ "RawQuery": "",
+ "Fragment": "",
+ "RawFragment": ""
+ },
+ "iconPosition": "OUTSIDE_RIGHT_MIDDLE",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "color plugin",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 118,
+ "labelHeight": 31,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.color plugin.ex",
+ "type": "text",
+ "pos": {
+ "x": 502,
+ "y": 124
+ },
+ "width": 69,
+ "height": 16,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\\\textcolor{red}{y} = \\\\textcolor{green}{\\\\sin} x",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 69,
+ "labelHeight": 16,
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.gensymb plugin",
+ "type": "rectangle",
+ "pos": {
+ "x": 437,
+ "y": 226
+ },
+ "width": 364,
+ "height": 139,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "gensymb plugin",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 158,
+ "labelHeight": 31,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.gensymb plugin.ex",
+ "type": "text",
+ "pos": {
+ "x": 490,
+ "y": 276
+ },
+ "width": 96,
+ "height": 18,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\\\lambda = 10.6\\\\,\\\\micro\\\\mathrm{m}",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 96,
+ "labelHeight": 18,
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.mhchem plugin",
+ "type": "rectangle",
+ "pos": {
+ "x": 437,
+ "y": 395
+ },
+ "width": 354,
+ "height": 132,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": true,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "mhchem plugin",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 156,
+ "labelHeight": 31,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.mhchem plugin.ex",
+ "type": "text",
+ "pos": {
+ "x": 487,
+ "y": 445
+ },
+ "width": 254,
+ "height": 18,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\ce{SO4^2- + Ba^2+ -> BaSO4 v}",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 254,
+ "labelHeight": 18,
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.physics plugin",
+ "type": "rectangle",
+ "pos": {
+ "x": 821,
+ "y": 58
+ },
+ "width": 504,
+ "height": 135,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "physics plugin",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 141,
+ "labelHeight": 31,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.physics plugin.ex",
+ "type": "text",
+ "pos": {
+ "x": 871,
+ "y": 108
+ },
+ "width": 128,
+ "height": 19,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\\\var{F[g(x)]}\n\\\\dd(\\\\cos\\\\theta)",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 128,
+ "labelHeight": 19,
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.multilines",
+ "type": "rectangle",
+ "pos": {
+ "x": 821,
+ "y": 213
+ },
+ "width": 504,
+ "height": 152,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "multilines",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 100,
+ "labelHeight": 31,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.multilines.ex",
+ "type": "text",
+ "pos": {
+ "x": 871,
+ "y": 263
+ },
+ "width": 404,
+ "height": 52,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\\\displaylines{x = a + b \\\\\\\\ y = b + c}\n\\\\sum_{k=1}^{n} h_{k} \\\\int_{0}^{1} \\\\bigl(\\\\partial_{k} f(x_{k-1}+t h_{k} e_{k}) -\\\\partial_{k} f(a)\\\\bigr) \\\\,dt",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 404,
+ "labelHeight": 52,
+ "zIndex": 0,
+ "level": 3
+ },
+ {
+ "id": "container.asm",
+ "type": "rectangle",
+ "pos": {
+ "x": 821,
+ "y": 385
+ },
+ "width": 504,
+ "height": 142,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "B5",
+ "stroke": "B1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "asm",
+ "fontSize": 24,
+ "fontFamily": "DEFAULT",
+ "language": "",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 41,
+ "labelHeight": 31,
+ "labelPosition": "INSIDE_TOP_CENTER",
+ "zIndex": 0,
+ "level": 2
+ },
+ {
+ "id": "container.asm.ex",
+ "type": "text",
+ "pos": {
+ "x": 871,
+ "y": 435
+ },
+ "width": 62,
+ "height": 32,
+ "opacity": 1,
+ "strokeDash": 0,
+ "strokeWidth": 2,
+ "borderRadius": 0,
+ "fill": "transparent",
+ "stroke": "N1",
+ "shadow": false,
+ "3d": false,
+ "multiple": false,
+ "double-border": false,
+ "tooltip": "",
+ "link": "",
+ "icon": null,
+ "iconPosition": "",
+ "blend": false,
+ "fields": null,
+ "methods": null,
+ "columns": null,
+ "label": "\\\\min_{ \\\\mathclap{\\\\substack{ x \\\\in \\\\mathbb{R}^n \\\\ x \\\\geq 0 \\\\ Ax \\\\leq b }}} c^T x",
+ "fontSize": 16,
+ "fontFamily": "DEFAULT",
+ "language": "latex",
+ "color": "N1",
+ "italic": false,
+ "bold": false,
+ "underline": false,
+ "labelWidth": 62,
+ "labelHeight": 32,
+ "zIndex": 0,
+ "level": 3
+ }
+ ],
+ "connections": [],
+ "root": {
+ "id": "",
+ "type": "",
+ "pos": {
+ "x": 0,
+ "y": 0
+ },
+ "width": 0,
+ "height": 0,
+ "opacity": 0,
+ "strokeDash": 0,
+ "strokeWidth": 0,
+ "borderRadius": 0,
+ "fill": "N7",
+ "stroke": "",
+ "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/stable/grid_outside_labels/elk/sketch.exp.svg b/e2etests/testdata/stable/grid_outside_labels/elk/sketch.exp.svg
new file mode 100644
index 000000000..46bd861c5
--- /dev/null
+++ b/e2etests/testdata/stable/grid_outside_labels/elk/sketch.exp.svg
@@ -0,0 +1,851 @@
+___________________________________container____________________________________amscd plugin
+
+braket plugincancel plugincolor plugingensymb pluginmhchem pluginphysics pluginmultilinesasmµ
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file