diff --git a/d2compiler/compile.go b/d2compiler/compile.go index 3bc0f26d1..df5efd7cd 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -285,6 +285,24 @@ func (c *compiler) compileReserved(attrs *d2graph.Attributes, f *d2ir.Field) { attrs.Height = &d2graph.Scalar{} attrs.Height.Value = scalar.ScalarString() attrs.Height.MapKey = f.LastPrimaryKey() + case "top": + _, err := strconv.Atoi(scalar.ScalarString()) + if err != nil { + c.errorf(scalar, "non-integer top %#v: %s", scalar.ScalarString(), err) + return + } + attrs.Top = &d2graph.Scalar{} + attrs.Top.Value = scalar.ScalarString() + attrs.Top.MapKey = f.LastPrimaryKey() + case "left": + _, err := strconv.Atoi(scalar.ScalarString()) + if err != nil { + c.errorf(scalar, "non-integer left %#v: %s", scalar.ScalarString(), err) + return + } + attrs.Left = &d2graph.Scalar{} + attrs.Left.Value = scalar.ScalarString() + attrs.Left.MapKey = f.LastPrimaryKey() case "link": attrs.Link = scalar.ScalarString() case "direction": @@ -364,6 +382,10 @@ func compileStyleFieldInit(attrs *d2graph.Attributes, f *d2ir.Field) { attrs.Width = &d2graph.Scalar{MapKey: f.LastPrimaryKey()} case "height": attrs.Height = &d2graph.Scalar{MapKey: f.LastPrimaryKey()} + case "top": + attrs.Top = &d2graph.Scalar{MapKey: f.LastPrimaryKey()} + case "left": + attrs.Left = &d2graph.Scalar{MapKey: f.LastPrimaryKey()} case "double-border": attrs.Style.DoubleBorder = &d2graph.Scalar{MapKey: f.LastPrimaryKey()} } diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index fa238a2c5..537cec457 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -86,7 +86,6 @@ x: { } }, }, - { name: "dimensions_on_nonimage", @@ -114,6 +113,17 @@ x: { } }, }, + { + name: "positions", + text: `hey: { + top: 200 + left: 230 +} +`, + assertions: func(t *testing.T, g *d2graph.Graph) { + tassert.Equal(t, "200", g.Objects[0].Attributes.Top.Value) + }, + }, { name: "equal_dimensions_on_circle", diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index 1300289d6..30bdedcbf 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -98,10 +98,12 @@ type Attributes struct { Tooltip string `json:"tooltip,omitempty"` Link string `json:"link,omitempty"` - // Only applicable for images right now Width *Scalar `json:"width,omitempty"` Height *Scalar `json:"height,omitempty"` + Top *Scalar `json:"top,omitempty"` + Left *Scalar `json:"left,omitempty"` + // TODO consider separate Attributes struct for shape-specific and edge-specific // Shapes only NearKey *d2ast.KeyPath `json:"near_key"` @@ -1442,6 +1444,8 @@ var SimpleReservedKeywords = map[string]struct{}{ "width": {}, "height": {}, "direction": {}, + "top": {}, + "left": {}, } // ReservedKeywordHolders are reserved keywords that are meaningless on its own and exist solely to hold a set of reserved keywords diff --git a/e2etests/stable_test.go b/e2etests/stable_test.go index a95a58450..a2d38b57f 100644 --- a/e2etests/stable_test.go +++ b/e2etests/stable_test.go @@ -165,9 +165,9 @@ d -> g.e -> f -> g -> d.h }, { name: "one_three_one_container", - script: `top.start -> a -top.start -> b -top.start -> c + script: `top2.start -> a +top2.start -> b +top2.start -> c a -> bottom.end b -> bottom.end c -> bottom.end @@ -1576,13 +1576,13 @@ container: { icon: https://icons.terrastruct.com/essentials/004-picture.svg } - left: { + left2: { root: { shape: image icon: https://icons.terrastruct.com/essentials/004-picture.svg } inner: { - left: { + left2: { shape: image icon: https://icons.terrastruct.com/essentials/004-picture.svg } @@ -1591,8 +1591,8 @@ container: { icon: https://icons.terrastruct.com/essentials/004-picture.svg } } - root -> inner.left: { - label: to inner left + root -> inner.left2: { + label: to inner left2 } root -> inner.right: { label: to inner right @@ -1605,7 +1605,7 @@ container: { icon: https://icons.terrastruct.com/essentials/004-picture.svg } inner: { - left: { + left2: { shape: image icon: https://icons.terrastruct.com/essentials/004-picture.svg } @@ -1614,16 +1614,16 @@ container: { icon: https://icons.terrastruct.com/essentials/004-picture.svg } } - root -> inner.left: { - label: to inner left + root -> inner.left2: { + label: to inner left2 } root -> inner.right: { label: to inner right } } - root -> left.root: { - label: to left container root + root -> left2.root: { + label: to left2 container root } root -> right.root: { diff --git a/e2etests/testdata/stable/one_three_one_container/dagre/board.exp.json b/e2etests/testdata/stable/one_three_one_container/dagre/board.exp.json index 3dd278592..7be26b11e 100644 --- a/e2etests/testdata/stable/one_three_one_container/dagre/board.exp.json +++ b/e2etests/testdata/stable/one_three_one_container/dagre/board.exp.json @@ -3,7 +3,7 @@ "fontFamily": "SourceSansPro", "shapes": [ { - "id": "top", + "id": "top2", "type": "rectangle", "pos": { "x": 0, @@ -29,7 +29,7 @@ "fields": null, "methods": null, "columns": null, - "label": "top", + "label": "top2", "fontSize": 28, "fontFamily": "DEFAULT", "language": "", @@ -37,14 +37,14 @@ "italic": false, "bold": false, "underline": false, - "labelWidth": 40, + "labelWidth": 54, "labelHeight": 36, "labelPosition": "OUTSIDE_TOP_CENTER", "zIndex": 0, "level": 1 }, { - "id": "top.start", + "id": "top2.start", "type": "rectangle", "pos": { "x": 123, @@ -292,8 +292,8 @@ ], "connections": [ { - "id": "(top.start -> a)[0]", - "src": "top.start", + "id": "(top2.start -> a)[0]", + "src": "top2.start", "srcArrow": "none", "srcLabel": "", "dst": "a", @@ -340,8 +340,8 @@ "zIndex": 0 }, { - "id": "(top.start -> b)[0]", - "src": "top.start", + "id": "(top2.start -> b)[0]", + "src": "top2.start", "srcArrow": "none", "srcLabel": "", "dst": "b", @@ -388,8 +388,8 @@ "zIndex": 0 }, { - "id": "(top.start -> c)[0]", - "src": "top.start", + "id": "(top2.start -> c)[0]", + "src": "top2.start", "srcArrow": "none", "srcLabel": "", "dst": "c", diff --git a/e2etests/testdata/stable/one_three_one_container/dagre/sketch.exp.svg b/e2etests/testdata/stable/one_three_one_container/dagre/sketch.exp.svg index c5bbec41f..614384cb9 100644 --- a/e2etests/testdata/stable/one_three_one_container/dagre/sketch.exp.svg +++ b/e2etests/testdata/stable/one_three_one_container/dagre/sketch.exp.svg @@ -39,7 +39,7 @@ width="530" height="800" viewBox="-102 -100 530 800">