diff --git a/d2compiler/compile.go b/d2compiler/compile.go index fc3b1bfec..84f7ba0b1 100644 --- a/d2compiler/compile.go +++ b/d2compiler/compile.go @@ -150,7 +150,7 @@ func (c *compiler) compileMap(obj *d2graph.Object, m *d2ir.Map) { c.compileField(obj, f) } - switch obj.Attributes.Shape.Value { + switch obj.Shape.Value { case d2target.ShapeClass: c.compileClass(obj) case d2target.ShapeSQLTable: @@ -191,25 +191,25 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) { } return } else if isReserved { - c.compileReserved(obj.Attributes, f) + c.compileReserved(&obj.Attributes, f) return } else if f.Name == "style" { if f.Map() == nil { return } - c.compileStyle(obj.Attributes, f.Map()) - if obj.Attributes.Style.Animated != nil { - c.errorf(obj.Attributes.Style.Animated.MapKey, `key "animated" can only be applied to edges`) + c.compileStyle(&obj.Attributes, f.Map()) + if obj.Style.Animated != nil { + c.errorf(obj.Style.Animated.MapKey, `key "animated" can only be applied to edges`) } return } if obj.Parent != nil { - if obj.Parent.Attributes.Shape.Value == d2target.ShapeSQLTable { + if obj.Parent.Shape.Value == d2target.ShapeSQLTable { c.errorf(f.LastRef().AST(), "sql_table columns cannot have children") return } - if obj.Parent.Attributes.Shape.Value == d2target.ShapeClass { + if obj.Parent.Shape.Value == d2target.ShapeClass { c.errorf(f.LastRef().AST(), "class fields cannot have children") return } @@ -217,14 +217,14 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) { obj = obj.EnsureChild(d2graphIDA([]string{f.Name})) if f.Primary() != nil { - c.compileLabel(obj.Attributes, f) + c.compileLabel(&obj.Attributes, f) } if f.Map() != nil { c.compileMap(obj, f.Map()) } - if obj.Attributes.Label.MapKey == nil { - obj.Attributes.Label.MapKey = f.LastPrimaryKey() + if obj.Label.MapKey == nil { + obj.Label.MapKey = f.LastPrimaryKey() } for _, fr := range f.References { if fr.Primary() { @@ -337,18 +337,18 @@ func (c *compiler) compileReserved(attrs *d2graph.Attributes, f *d2ir.Field) { c.errorf(scalar, "non-integer width %#v: %s", scalar.ScalarString(), err) return } - attrs.Width = &d2graph.Scalar{} - attrs.Width.Value = scalar.ScalarString() - attrs.Width.MapKey = f.LastPrimaryKey() + attrs.WidthAttr = &d2graph.Scalar{} + attrs.WidthAttr.Value = scalar.ScalarString() + attrs.WidthAttr.MapKey = f.LastPrimaryKey() case "height": _, err := strconv.Atoi(scalar.ScalarString()) if err != nil { c.errorf(scalar, "non-integer height %#v: %s", scalar.ScalarString(), err) return } - attrs.Height = &d2graph.Scalar{} - attrs.Height.Value = scalar.ScalarString() - attrs.Height.MapKey = f.LastPrimaryKey() + attrs.HeightAttr = &d2graph.Scalar{} + attrs.HeightAttr.Value = scalar.ScalarString() + attrs.HeightAttr.MapKey = f.LastPrimaryKey() case "top": v, err := strconv.Atoi(scalar.ScalarString()) if err != nil { @@ -530,9 +530,9 @@ func compileStyleFieldInit(attrs *d2graph.Attributes, f *d2ir.Field) { case "filled": attrs.Style.Filled = &d2graph.Scalar{MapKey: f.LastPrimaryKey()} case "width": - attrs.Width = &d2graph.Scalar{MapKey: f.LastPrimaryKey()} + attrs.WidthAttr = &d2graph.Scalar{MapKey: f.LastPrimaryKey()} case "height": - attrs.Height = &d2graph.Scalar{MapKey: f.LastPrimaryKey()} + attrs.HeightAttr = &d2graph.Scalar{MapKey: f.LastPrimaryKey()} case "top": attrs.Top = &d2graph.Scalar{MapKey: f.LastPrimaryKey()} case "left": @@ -552,13 +552,13 @@ func (c *compiler) compileEdge(obj *d2graph.Object, e *d2ir.Edge) { } if e.Primary() != nil { - c.compileLabel(edge.Attributes, e) + c.compileLabel(&edge.Attributes, e) } if e.Map() != nil { c.compileEdgeMap(edge, e.Map()) } - edge.Attributes.Label.MapKey = e.LastPrimaryKey() + edge.Label.MapKey = e.LastPrimaryKey() for _, er := range e.References { scopeObjIDA := d2ir.BoardIDA(er.Context.ScopeMap) scopeObj := edge.Src.Graph.Root.EnsureChildIDVal(scopeObjIDA) @@ -604,13 +604,13 @@ func (c *compiler) compileEdgeField(edge *d2graph.Edge, f *d2ir.Field) { } _, isReserved := d2graph.SimpleReservedKeywords[keyword] if isReserved { - c.compileReserved(edge.Attributes, f) + c.compileReserved(&edge.Attributes, f) return } else if f.Name == "style" { if f.Map() == nil { return } - c.compileStyle(edge.Attributes, f.Map()) + c.compileStyle(&edge.Attributes, f.Map()) return } @@ -686,7 +686,7 @@ func (c *compiler) compileClass(obj *d2graph.Object) { } if !strings.Contains(f.IDVal, "(") { - typ := f.Attributes.Label.Value + typ := f.Label.Value if typ == f.IDVal { typ = "" } @@ -698,7 +698,7 @@ func (c *compiler) compileClass(obj *d2graph.Object) { } else { // TODO: Not great, AST should easily allow specifying alternate primary field // as an explicit label should change the name. - returnType := f.Attributes.Label.Value + returnType := f.Label.Value if returnType == f.IDVal { returnType = "void" } @@ -725,7 +725,7 @@ func (c *compiler) compileClass(obj *d2graph.Object) { func (c *compiler) compileSQLTable(obj *d2graph.Object) { obj.SQLTable = &d2target.SQLTable{} for _, col := range obj.ChildrenArray { - typ := col.Attributes.Label.Value + typ := col.Label.Value if typ == col.IDVal { // Not great, AST should easily allow specifying alternate primary field // as an explicit label should change the name. @@ -735,8 +735,8 @@ func (c *compiler) compileSQLTable(obj *d2graph.Object) { Name: d2target.Text{Label: col.IDVal}, Type: d2target.Text{Label: typ}, } - if col.Attributes.Constraint.Value != "" { - d2Col.Constraint = col.Attributes.Constraint.Value + if col.Constraint.Value != "" { + d2Col.Constraint = col.Constraint.Value } obj.SQLTable.Columns = append(obj.SQLTable.Columns, d2Col) } @@ -766,35 +766,35 @@ func (c *compiler) validateKey(obj *d2graph.Object, f *d2ir.Field) { keyword := strings.ToLower(f.Name) _, isReserved := d2graph.ReservedKeywords[keyword] if isReserved { - switch obj.Attributes.Shape.Value { + switch obj.Shape.Value { case d2target.ShapeCircle, d2target.ShapeSquare: - checkEqual := (keyword == "width" && obj.Attributes.Height != nil) || (keyword == "height" && obj.Attributes.Width != nil) - if checkEqual && obj.Attributes.Width.Value != obj.Attributes.Height.Value { - c.errorf(f.LastPrimaryKey(), "width and height must be equal for %s shapes", obj.Attributes.Shape.Value) + checkEqual := (keyword == "width" && obj.HeightAttr != nil) || (keyword == "height" && obj.WidthAttr != nil) + if checkEqual && obj.WidthAttr.Value != obj.HeightAttr.Value { + c.errorf(f.LastPrimaryKey(), "width and height must be equal for %s shapes", obj.Shape.Value) } } switch f.Name { case "style": - if obj.Attributes.Style.ThreeDee != nil { - if !strings.EqualFold(obj.Attributes.Shape.Value, d2target.ShapeSquare) && !strings.EqualFold(obj.Attributes.Shape.Value, d2target.ShapeRectangle) && !strings.EqualFold(obj.Attributes.Shape.Value, d2target.ShapeHexagon) { - c.errorf(obj.Attributes.Style.ThreeDee.MapKey, `key "3d" can only be applied to squares, rectangles, and hexagons`) + if obj.Style.ThreeDee != nil { + if !strings.EqualFold(obj.Shape.Value, d2target.ShapeSquare) && !strings.EqualFold(obj.Shape.Value, d2target.ShapeRectangle) && !strings.EqualFold(obj.Shape.Value, d2target.ShapeHexagon) { + c.errorf(obj.Style.ThreeDee.MapKey, `key "3d" can only be applied to squares, rectangles, and hexagons`) } } - if obj.Attributes.Style.DoubleBorder != nil { - if obj.Attributes.Shape.Value != "" && obj.Attributes.Shape.Value != d2target.ShapeSquare && obj.Attributes.Shape.Value != d2target.ShapeRectangle && obj.Attributes.Shape.Value != d2target.ShapeCircle && obj.Attributes.Shape.Value != d2target.ShapeOval { - c.errorf(obj.Attributes.Style.DoubleBorder.MapKey, `key "double-border" can only be applied to squares, rectangles, circles, ovals`) + if obj.Style.DoubleBorder != nil { + if obj.Shape.Value != "" && obj.Shape.Value != d2target.ShapeSquare && obj.Shape.Value != d2target.ShapeRectangle && obj.Shape.Value != d2target.ShapeCircle && obj.Shape.Value != d2target.ShapeOval { + c.errorf(obj.Style.DoubleBorder.MapKey, `key "double-border" can only be applied to squares, rectangles, circles, ovals`) } } case "shape": - if obj.Attributes.Shape.Value == d2target.ShapeImage && obj.Attributes.Icon == nil { + if obj.Shape.Value == d2target.ShapeImage && obj.Icon == nil { c.errorf(f.LastPrimaryKey(), `image shape must include an "icon" field`) } - in := d2target.IsShape(obj.Attributes.Shape.Value) - _, arrowheadIn := d2target.Arrowheads[obj.Attributes.Shape.Value] + in := d2target.IsShape(obj.Shape.Value) + _, arrowheadIn := d2target.Arrowheads[obj.Shape.Value] if !in && arrowheadIn { - c.errorf(f.LastPrimaryKey(), fmt.Sprintf(`invalid shape, can only set "%s" for arrowheads`, obj.Attributes.Shape.Value)) + c.errorf(f.LastPrimaryKey(), fmt.Sprintf(`invalid shape, can only set "%s" for arrowheads`, obj.Shape.Value)) } case "grid-rows", "grid-columns", "grid-gap", "vertical-gap", "horizontal-gap": for _, child := range obj.ChildrenArray { @@ -807,7 +807,7 @@ func (c *compiler) validateKey(obj *d2graph.Object, f *d2ir.Field) { return } - if obj.Attributes.Shape.Value == d2target.ShapeImage { + if obj.Shape.Value == d2target.ShapeImage { c.errorf(f.LastRef().AST(), "image shapes cannot have children.") return } @@ -820,9 +820,9 @@ func (c *compiler) validateKey(obj *d2graph.Object, f *d2ir.Field) { func (c *compiler) validateNear(g *d2graph.Graph) { for _, obj := range g.Objects { - if obj.Attributes.NearKey != nil { - nearObj, isKey := g.Root.HasChild(d2graph.Key(obj.Attributes.NearKey)) - _, isConst := d2graph.NearConstants[d2graph.Key(obj.Attributes.NearKey)[0]] + if obj.NearKey != nil { + nearObj, isKey := g.Root.HasChild(d2graph.Key(obj.NearKey)) + _, isConst := d2graph.NearConstants[d2graph.Key(obj.NearKey)[0]] if isKey { // Doesn't make sense to set near to an ancestor or descendant nearIsAncestor := false @@ -833,7 +833,7 @@ func (c *compiler) validateNear(g *d2graph.Graph) { } } if nearIsAncestor { - c.errorf(obj.Attributes.NearKey, "near keys cannot be set to an ancestor") + c.errorf(obj.NearKey, "near keys cannot be set to an ancestor") continue } nearIsDescendant := false @@ -844,27 +844,27 @@ func (c *compiler) validateNear(g *d2graph.Graph) { } } if nearIsDescendant { - c.errorf(obj.Attributes.NearKey, "near keys cannot be set to an descendant") + c.errorf(obj.NearKey, "near keys cannot be set to an descendant") continue } if nearObj.OuterSequenceDiagram() != nil { - c.errorf(obj.Attributes.NearKey, "near keys cannot be set to an object within sequence diagrams") + c.errorf(obj.NearKey, "near keys cannot be set to an object within sequence diagrams") continue } - if nearObj.Attributes.NearKey != nil { - _, nearObjNearIsConst := d2graph.NearConstants[d2graph.Key(nearObj.Attributes.NearKey)[0]] + if nearObj.NearKey != nil { + _, nearObjNearIsConst := d2graph.NearConstants[d2graph.Key(nearObj.NearKey)[0]] if nearObjNearIsConst { - c.errorf(obj.Attributes.NearKey, "near keys cannot be set to an object with a constant near key") + c.errorf(obj.NearKey, "near keys cannot be set to an object with a constant near key") continue } } } else if isConst { if obj.Parent != g.Root { - c.errorf(obj.Attributes.NearKey, "constant near keys can only be set on root level shapes") + c.errorf(obj.NearKey, "constant near keys can only be set on root level shapes") continue } } else { - c.errorf(obj.Attributes.NearKey, "near key %#v must be the absolute path to a shape or one of the following constants: %s", d2format.Format(obj.Attributes.NearKey), strings.Join(d2graph.NearConstantsArray, ", ")) + c.errorf(obj.NearKey, "near key %#v must be the absolute path to a shape or one of the following constants: %s", d2format.Format(obj.NearKey), strings.Join(d2graph.NearConstantsArray, ", ")) continue } } @@ -877,10 +877,10 @@ func (c *compiler) validateNear(g *d2graph.Graph) { var isSrcNearConst, isDstNearConst bool if srcNearContainer != nil { - _, isSrcNearConst = d2graph.NearConstants[d2graph.Key(srcNearContainer.Attributes.NearKey)[0]] + _, isSrcNearConst = d2graph.NearConstants[d2graph.Key(srcNearContainer.NearKey)[0]] } if dstNearContainer != nil { - _, isDstNearConst = d2graph.NearConstants[d2graph.Key(dstNearContainer.Attributes.NearKey)[0]] + _, isDstNearConst = d2graph.NearConstants[d2graph.Key(dstNearContainer.NearKey)[0]] } if (isSrcNearConst || isDstNearConst) && srcNearContainer != dstNearContainer { @@ -905,11 +905,11 @@ func (c *compiler) validateEdges(g *d2graph.Graph) { func (c *compiler) validateBoardLinks(g *d2graph.Graph) { for _, obj := range g.Objects { - if obj.Attributes.Link == nil { + if obj.Link == nil { continue } - linkKey, err := d2parser.ParseKey(obj.Attributes.Link.Value) + linkKey, err := d2parser.ParseKey(obj.Link.Value) if err != nil { continue } @@ -919,7 +919,7 @@ func (c *compiler) validateBoardLinks(g *d2graph.Graph) { } if !hasBoard(g.RootBoard(), linkKey.IDA()) { - c.errorf(obj.Attributes.Link.MapKey, "linked board not found") + c.errorf(obj.Link.MapKey, "linked board not found") continue } } diff --git a/d2compiler/compile_test.go b/d2compiler/compile_test.go index c5750ff88..4079ddfb8 100644 --- a/d2compiler/compile_test.go +++ b/d2compiler/compile_test.go @@ -43,8 +43,8 @@ x: { t.Fatalf("expected g.Objects[0].ID to be x: %#v", g.Objects[0]) } - if g.Objects[0].Attributes.Shape.Value != d2target.ShapeCircle { - t.Fatalf("expected g.Objects[0].Attributes.Shape.Value to be circle: %#v", g.Objects[0].Attributes.Shape.Value) + if g.Objects[0].Shape.Value != d2target.ShapeCircle { + t.Fatalf("expected g.Objects[0].Shape.Value to be circle: %#v", g.Objects[0].Shape.Value) } }, @@ -65,8 +65,8 @@ x: { t.Fatalf("expected g.Objects[0].ID to be x: %#v", g.Objects[0]) } - if g.Objects[0].Attributes.Style.Opacity.Value != "0.4" { - t.Fatalf("expected g.Objects[0].Attributes.Style.Opacity.Value to be 0.4: %#v", g.Objects[0].Attributes.Style.Opacity.Value) + if g.Objects[0].Style.Opacity.Value != "0.4" { + t.Fatalf("expected g.Objects[0].Style.Opacity.Value to be 0.4: %#v", g.Objects[0].Style.Opacity.Value) } }, @@ -102,14 +102,14 @@ x: { if g.Objects[0].ID != "hey" { t.Fatalf("expected g.Objects[0].ID to be 'hey': %#v", g.Objects[0]) } - if g.Objects[0].Attributes.Shape.Value != d2target.ShapeHexagon { - t.Fatalf("expected g.Objects[0].Attributes.Shape.Value to be hexagon: %#v", g.Objects[0].Attributes.Shape.Value) + if g.Objects[0].Shape.Value != d2target.ShapeHexagon { + t.Fatalf("expected g.Objects[0].Shape.Value to be hexagon: %#v", g.Objects[0].Shape.Value) } - if g.Objects[0].Attributes.Width.Value != "200" { - t.Fatalf("expected g.Objects[0].Attributes.Width.Value to be 200: %#v", g.Objects[0].Attributes.Width.Value) + if g.Objects[0].WidthAttr.Value != "200" { + t.Fatalf("expected g.Objects[0].Width.Value to be 200: %#v", g.Objects[0].WidthAttr.Value) } - if g.Objects[0].Attributes.Height.Value != "230" { - t.Fatalf("expected g.Objects[0].Attributes.Height.Value to be 230: %#v", g.Objects[0].Attributes.Height.Value) + if g.Objects[0].HeightAttr.Value != "230" { + t.Fatalf("expected g.Objects[0].Height.Value to be 230: %#v", g.Objects[0].HeightAttr.Value) } }, }, @@ -121,7 +121,7 @@ x: { } `, assertions: func(t *testing.T, g *d2graph.Graph) { - tassert.Equal(t, "200", g.Objects[0].Attributes.Top.Value) + tassert.Equal(t, "200", g.Objects[0].Top.Value) }, }, { @@ -160,13 +160,13 @@ d2/testdata/d2compiler/TestCompile/equal_dimensions_on_circle.d2:4:2: width and if g.Objects[0].ID != "hey" { t.Fatalf("expected ID to be 'hey': %#v", g.Objects[0]) } - if g.Objects[0].Attributes.Shape.Value != d2target.ShapeCircle { - t.Fatalf("expected Attributes.Shape.Value to be circle: %#v", g.Objects[0].Attributes.Shape.Value) + if g.Objects[0].Shape.Value != d2target.ShapeCircle { + t.Fatalf("expected Attributes.Shape.Value to be circle: %#v", g.Objects[0].Shape.Value) } - if g.Objects[0].Attributes.Width != nil { - t.Fatalf("expected Attributes.Width to be nil: %#v", g.Objects[0].Attributes.Width) + if g.Objects[0].WidthAttr != nil { + t.Fatalf("expected Attributes.Width to be nil: %#v", g.Objects[0].WidthAttr) } - if g.Objects[0].Attributes.Height == nil { + if g.Objects[0].HeightAttr == nil { t.Fatalf("Attributes.Height is nil") } }, @@ -237,7 +237,7 @@ containers: { } `, assertions: func(t *testing.T, g *d2graph.Graph) { - if g.Objects[0].Attributes.Icon == nil { + if g.Objects[0].Icon == nil { t.Fatal("Attribute icon is nil") } }, @@ -326,7 +326,7 @@ containers: { if len(g.Objects) != 1 { t.Fatalf("expected 1 objects: %#v", g.Objects) } - if g.Objects[0].Attributes.Style.StrokeWidth.Value != "0" { + if g.Objects[0].Style.StrokeWidth.Value != "0" { t.Fatalf("unexpected") } }, @@ -442,8 +442,8 @@ y: "But it's real. And if it's real it can be affected ... we may not be able" if len(g.Root.ChildrenArray) != 2 { t.Fatalf("expected 2 objects at the root: %#v", len(g.Root.ChildrenArray)) } - if g.Objects[1].Attributes.Label.Value != "But it's real. And if it's real it can be affected ... we may not be able" { - t.Fatalf("expected g.Objects[1].Label.Value to be last value: %#v", g.Objects[1].Attributes.Label.Value) + if g.Objects[1].Label.Value != "But it's real. And if it's real it can be affected ... we may not be able" { + t.Fatalf("expected g.Objects[1].Label.Value to be last value: %#v", g.Objects[1].Label.Value) } }, }, @@ -470,8 +470,8 @@ x: { if len(g.Root.ChildrenArray) != 2 { t.Fatalf("expected 2 objects at the root: %#v", len(g.Root.ChildrenArray)) } - if g.Objects[0].Attributes.Label.Value != "All we are given is possibilities -- to make ourselves one thing or another." { - t.Fatalf("expected g.Objects[0].Label.Value to be last value: %#v", g.Objects[0].Attributes.Label.Value) + if g.Objects[0].Label.Value != "All we are given is possibilities -- to make ourselves one thing or another." { + t.Fatalf("expected g.Objects[0].Label.Value to be last value: %#v", g.Objects[0].Label.Value) } }, }, @@ -626,11 +626,11 @@ x: { if g.Edges[1].Dst.ID != "b" { t.Fatalf("expected g.Edges[1].Dst.ID to be b: %#v", g.Edges[1]) } - if g.Edges[0].Attributes.Label.Value != "Can you imagine how life could be improved if we could do away with" { - t.Fatalf("unexpected g.Edges[0].Label: %#v", g.Edges[0].Attributes.Label) + if g.Edges[0].Label.Value != "Can you imagine how life could be improved if we could do away with" { + t.Fatalf("unexpected g.Edges[0].Label: %#v", g.Edges[0].Label) } - if g.Edges[1].Attributes.Label.Value != "Well, it's garish, ugly, and derelicts have used it for a toilet." { - t.Fatalf("unexpected g.Edges[1].Label: %#v", g.Edges[1].Attributes.Label) + if g.Edges[1].Label.Value != "Well, it's garish, ugly, and derelicts have used it for a toilet." { + t.Fatalf("unexpected g.Edges[1].Label: %#v", g.Edges[1].Label) } }, }, @@ -656,8 +656,8 @@ x: { if g.Edges[0].Dst.ID != "b" { t.Fatalf("expected g.Edges[0].Dst.ID to be b: %#v", g.Edges[0]) } - if g.Edges[0].Attributes.Label.Value != "Well, it's garish, ugly, and derelicts have used it for a toilet." { - t.Fatalf("unexpected g.Edges[0].Label: %#v", g.Edges[0].Attributes.Label) + if g.Edges[0].Label.Value != "Well, it's garish, ugly, and derelicts have used it for a toilet." { + t.Fatalf("unexpected g.Edges[0].Label: %#v", g.Edges[0].Label) } }, }, @@ -756,11 +756,11 @@ x -> y -> z: "The kids will love our inflatable slides" t.Fatalf("expected g.Edges[1].Dst.ID to be y: %#v", g.Edges[1]) } - if g.Edges[0].Attributes.Label.Value != "The kids will love our inflatable slides" { - t.Fatalf("unexpected g.Edges[0].Attributes.Label: %#v", g.Edges[0].Attributes.Label.Value) + if g.Edges[0].Label.Value != "The kids will love our inflatable slides" { + t.Fatalf("unexpected g.Edges[0].Label: %#v", g.Edges[0].Label.Value) } - if g.Edges[1].Attributes.Label.Value != "The kids will love our inflatable slides" { - t.Fatalf("unexpected g.Edges[1].Attributes.Label: %#v", g.Edges[1].Attributes.Label.Value) + if g.Edges[1].Label.Value != "The kids will love our inflatable slides" { + t.Fatalf("unexpected g.Edges[1].Label: %#v", g.Edges[1].Label.Value) } }, }, @@ -797,8 +797,8 @@ x -> y: one if !g.Edges[0].DstArrow { t.Fatalf("expected g.Edges[0].DstArrow to be true: %#v", g.Edges[0].DstArrow) } - if g.Edges[0].Attributes.Label.Value != "two" { - t.Fatalf("expected g.Edges[0].Attributes.Label to be two: %#v", g.Edges[0].Attributes.Label) + if g.Edges[0].Label.Value != "two" { + t.Fatalf("expected g.Edges[0].Label to be two: %#v", g.Edges[0].Label) } }, }, @@ -840,8 +840,8 @@ b: { if !g.Edges[0].DstArrow { t.Fatalf("expected g.Edges[0].DstArrow to be true: %#v", g.Edges[0].DstArrow) } - if g.Edges[0].Attributes.Label.Value != "two" { - t.Fatalf("expected g.Edges[0].Attributes.Label to be two: %#v", g.Edges[0].Attributes.Label) + if g.Edges[0].Label.Value != "two" { + t.Fatalf("expected g.Edges[0].Label to be two: %#v", g.Edges[0].Label) } }, }, @@ -883,8 +883,8 @@ b.(x -> y)[0]: two if !g.Edges[0].DstArrow { t.Fatalf("expected g.Edges[0].DstArrow to be true: %#v", g.Edges[0].DstArrow) } - if g.Edges[0].Attributes.Label.Value != "two" { - t.Fatalf("expected g.Edges[0].Attributes.Label to be two: %#v", g.Edges[0].Attributes.Label) + if g.Edges[0].Label.Value != "two" { + t.Fatalf("expected g.Edges[0].Label to be two: %#v", g.Edges[0].Label) } }, }, @@ -936,8 +936,8 @@ x -> y: { if g.Edges[0].Dst.ID != "y" { t.Fatalf("expected g.Edges[0].Dst.ID to be y: %#v", g.Edges[0]) } - if g.Edges[0].Attributes.Label.Value != "Space: the final frontier. These are the voyages of the starship Enterprise." { - t.Fatalf("unexpected g.Edges[0].Attributes.Label.Value : %#v", g.Edges[0].Attributes.Label.Value) + if g.Edges[0].Label.Value != "Space: the final frontier. These are the voyages of the starship Enterprise." { + t.Fatalf("unexpected g.Edges[0].Label.Value : %#v", g.Edges[0].Label.Value) } }, }, @@ -950,8 +950,8 @@ x -> y: { if len(g.Edges) != 1 { t.Fatalf("expected 1 edge: %#v", g.Edges) } - if g.Edges[0].Attributes.Label.Value != "asdf" { - t.Fatalf("unexpected g.Edges[0].Attributes.Label.Value : %#v", g.Edges[0].Attributes.Label.Value) + if g.Edges[0].Label.Value != "asdf" { + t.Fatalf("unexpected g.Edges[0].Label.Value : %#v", g.Edges[0].Label.Value) } }, }, @@ -972,7 +972,7 @@ x -> y: { t.Fatalf("expected 2 objects: %#v", g.Objects) } assert.String(t, "diamond", g.Edges[0].SrcArrowhead.Shape.Value) - assert.String(t, "", g.Edges[0].Attributes.Shape.Value) + assert.String(t, "", g.Edges[0].Shape.Value) // Make sure the DSL didn't change. this is a regression test where it did exp := `x -> y: { source-arrowhead: { @@ -1025,9 +1025,9 @@ x -> y: { assert.String(t, "Reisner's Rule of Conceptual Inertia", g.Edges[0].SrcArrowhead.Label.Value) assert.String(t, "QOTD", g.Edges[0].DstArrowhead.Label.Value) assert.String(t, "true", g.Edges[0].DstArrowhead.Style.Filled.Value) - assert.String(t, "", g.Edges[0].Attributes.Shape.Value) - assert.String(t, "", g.Edges[0].Attributes.Label.Value) - assert.JSON(t, nil, g.Edges[0].Attributes.Style.Filled) + assert.String(t, "", g.Edges[0].Shape.Value) + assert.String(t, "", g.Edges[0].Label.Value) + assert.JSON(t, nil, g.Edges[0].Style.Filled) }, }, { @@ -1044,7 +1044,7 @@ x -> y: { t.Fatalf("expected 2 objects: %#v", g.Objects) } assert.String(t, "diamond", g.Edges[0].SrcArrowhead.Shape.Value) - assert.String(t, "", g.Edges[0].Attributes.Shape.Value) + assert.String(t, "", g.Edges[0].Shape.Value) }, }, { @@ -1061,7 +1061,7 @@ x -> y: { t.Fatalf("expected 2 objects: %#v", g.Objects) } assert.String(t, "triangle", g.Edges[0].SrcArrowhead.Shape.Value) - assert.String(t, "", g.Edges[0].Attributes.Shape.Value) + assert.String(t, "", g.Edges[0].Shape.Value) }, }, { @@ -1087,7 +1087,7 @@ x -> y: { t.Fatalf("expected 2 objects: %#v", g.Objects) } assert.String(t, "yo", g.Edges[0].SrcArrowhead.Label.Value) - assert.String(t, "", g.Edges[0].Attributes.Label.Value) + assert.String(t, "", g.Edges[0].Label.Value) }, }, { @@ -1106,7 +1106,7 @@ x -> y: { t.Fatalf("expected 2 objects: %#v", g.Objects) } assert.String(t, "diamond", g.Edges[0].SrcArrowhead.Shape.Value) - assert.String(t, "", g.Edges[0].Attributes.Shape.Value) + assert.String(t, "", g.Edges[0].Shape.Value) }, }, { @@ -1128,7 +1128,7 @@ x -> y: { } assert.String(t, "diamond", g.Edges[0].SrcArrowhead.Shape.Value) assert.String(t, "diamond", g.Edges[0].DstArrowhead.Shape.Value) - assert.String(t, "", g.Edges[0].Attributes.Shape.Value) + assert.String(t, "", g.Edges[0].Shape.Value) }, }, { @@ -1143,8 +1143,8 @@ x -> y: { if len(g.Edges) != 1 { t.Fatalf("expected 1 edge: %#v", g.Edges) } - if g.Edges[0].Attributes.Style.Animated.Value != "true" { - t.Fatalf("Edges[0].Attributes.Style.Animated.Value: %#v", g.Edges[0].Attributes.Style.Animated.Value) + if g.Edges[0].Style.Animated.Value != "true" { + t.Fatalf("Edges[0].Style.Animated.Value: %#v", g.Edges[0].Style.Animated.Value) } }, }, @@ -1201,11 +1201,11 @@ x -> y -> z: { if len(g.Edges) != 2 { t.Fatalf("expected 2 edge: %#v", g.Edges) } - if g.Edges[0].Attributes.Label.Value != "Space: the final frontier. These are the voyages of the starship Enterprise." { - t.Fatalf("unexpected g.Edges[0].Attributes.Label.Value : %#v", g.Edges[0].Attributes.Label.Value) + if g.Edges[0].Label.Value != "Space: the final frontier. These are the voyages of the starship Enterprise." { + t.Fatalf("unexpected g.Edges[0].Label.Value : %#v", g.Edges[0].Label.Value) } - if g.Edges[1].Attributes.Label.Value != "Space: the final frontier. These are the voyages of the starship Enterprise." { - t.Fatalf("unexpected g.Edges[0].Attributes.Label.Value : %#v", g.Edges[1].Attributes.Label.Value) + if g.Edges[1].Label.Value != "Space: the final frontier. These are the voyages of the starship Enterprise." { + t.Fatalf("unexpected g.Edges[0].Label.Value : %#v", g.Edges[1].Label.Value) } }, }, @@ -1226,8 +1226,8 @@ x -> y if len(g.Edges) != 1 { t.Fatalf("expected 1 edge: %#v", g.Edges) } - if g.Edges[0].Attributes.Label.Value != "Space: the final frontier. These are the voyages of the starship Enterprise." { - t.Fatalf("unexpected g.Edges[0].Attributes.Label.Value : %#v", g.Edges[0].Attributes.Label.Value) + if g.Edges[0].Label.Value != "Space: the final frontier. These are the voyages of the starship Enterprise." { + t.Fatalf("unexpected g.Edges[0].Label.Value : %#v", g.Edges[0].Label.Value) } }, }, @@ -1249,8 +1249,8 @@ x -> y: { if len(g.Edges) != 1 { t.Fatalf("expected 1 edge: %#v", g.Edges) } - if g.Edges[0].Attributes.Style.Opacity.Value != "0.4" { - t.Fatalf("unexpected g.Edges[0].Attributes.Style.Opacity.Value: %#v", g.Edges[0].Attributes.Style.Opacity.Value) + if g.Edges[0].Style.Opacity.Value != "0.4" { + t.Fatalf("unexpected g.Edges[0].Style.Opacity.Value: %#v", g.Edges[0].Style.Opacity.Value) } }, }, @@ -1270,11 +1270,11 @@ x -> y: { if len(g.Edges) != 1 { t.Fatalf("expected 1 edge: %#v", g.Edges) } - if g.Edges[0].Attributes.Style.Opacity.Value != "0.4" { - t.Fatalf("unexpected g.Edges[0].Attributes.Style.Opacity.Value: %#v", g.Edges[0].Attributes.Style.Opacity.Value) + if g.Edges[0].Style.Opacity.Value != "0.4" { + t.Fatalf("unexpected g.Edges[0].Style.Opacity.Value: %#v", g.Edges[0].Style.Opacity.Value) } - if g.Edges[0].Attributes.Label.Value != "" { - t.Fatalf("unexpected g.Edges[0].Attributes.Label.Value : %#v", g.Edges[0].Attributes.Label.Value) + if g.Edges[0].Label.Value != "" { + t.Fatalf("unexpected g.Edges[0].Label.Value : %#v", g.Edges[0].Label.Value) } }, }, @@ -1293,11 +1293,11 @@ x -> y if len(g.Edges) != 1 { t.Fatalf("expected 1 edge: %#v", g.Edges) } - if g.Edges[0].Attributes.Style.Opacity.Value != "0.4" { - t.Fatalf("unexpected g.Edges[0].Attributes.Style.Opacity.Value: %#v", g.Edges[0].Attributes.Style.Opacity.Value) + if g.Edges[0].Style.Opacity.Value != "0.4" { + t.Fatalf("unexpected g.Edges[0].Style.Opacity.Value: %#v", g.Edges[0].Style.Opacity.Value) } - if g.Edges[0].Attributes.Label.Value != "" { - t.Fatalf("unexpected g.Edges[0].Attributes.Label.Value : %#v", g.Edges[0].Attributes.Label.Value) + if g.Edges[0].Label.Value != "" { + t.Fatalf("unexpected g.Edges[0].Label.Value : %#v", g.Edges[0].Label.Value) } }, }, @@ -1317,11 +1317,11 @@ x -> y if len(g.Edges) != 1 { t.Fatalf("expected 1 edge: %#v", g.Edges) } - if g.Edges[0].Attributes.Style.Opacity.Value != "0.4" { - t.Fatalf("unexpected g.Edges[0].Attributes.Style.Opacity.Value: %#v", g.Edges[0].Attributes.Style.Opacity.Value) + if g.Edges[0].Style.Opacity.Value != "0.4" { + t.Fatalf("unexpected g.Edges[0].Style.Opacity.Value: %#v", g.Edges[0].Style.Opacity.Value) } - if g.Edges[0].Attributes.Label.Value != "" { - t.Fatalf("unexpected g.Edges[0].Attributes.Label.Value : %#v", g.Edges[0].Attributes.Label.Value) + if g.Edges[0].Label.Value != "" { + t.Fatalf("unexpected g.Edges[0].Label.Value : %#v", g.Edges[0].Label.Value) } }, }, @@ -1342,11 +1342,11 @@ x.(a -> b)[0].style.opacity: 0.4 if len(g.Edges) != 1 { t.Fatalf("expected 1 edge: %#v", g.Edges) } - if g.Edges[0].Attributes.Style.Opacity.Value != "0.4" { - t.Fatalf("unexpected g.Edges[0].Attributes.Style.Opacity.Value: %#v", g.Edges[0].Attributes.Style.Opacity.Value) + if g.Edges[0].Style.Opacity.Value != "0.4" { + t.Fatalf("unexpected g.Edges[0].Style.Opacity.Value: %#v", g.Edges[0].Style.Opacity.Value) } - if g.Edges[0].Attributes.Label.Value != "" { - t.Fatalf("unexpected g.Edges[0].Attributes.Label.Value : %#v", g.Edges[0].Attributes.Label.Value) + if g.Edges[0].Label.Value != "" { + t.Fatalf("unexpected g.Edges[0].Label.Value : %#v", g.Edges[0].Label.Value) } }, }, @@ -1367,11 +1367,11 @@ x: { if len(g.Edges) != 1 { t.Fatalf("expected 1 edge: %#v", g.Edges) } - if g.Edges[0].Attributes.Style.Opacity.Value != "0.4" { - t.Fatalf("unexpected g.Edges[0].Attributes.Style.Opacity.Value: %#v", g.Edges[0].Attributes.Style.Opacity.Value) + if g.Edges[0].Style.Opacity.Value != "0.4" { + t.Fatalf("unexpected g.Edges[0].Style.Opacity.Value: %#v", g.Edges[0].Style.Opacity.Value) } - if g.Edges[0].Attributes.Label.Value != "" { - t.Fatalf("unexpected g.Edges[0].Attributes.Label.Value : %#v", g.Edges[0].Attributes.Label.Value) + if g.Edges[0].Label.Value != "" { + t.Fatalf("unexpected g.Edges[0].Label.Value : %#v", g.Edges[0].Label.Value) } }, }, @@ -1396,11 +1396,11 @@ x: { if len(g.Edges) != 1 { t.Fatalf("expected 1 edge: %#v", g.Edges) } - if g.Edges[0].Attributes.Style.Opacity.Value != "0.4" { - t.Fatalf("unexpected g.Edges[0].Attributes.Style.Opacity.Value: %#v", g.Edges[0].Attributes.Style.Opacity.Value) + if g.Edges[0].Style.Opacity.Value != "0.4" { + t.Fatalf("unexpected g.Edges[0].Style.Opacity.Value: %#v", g.Edges[0].Style.Opacity.Value) } - if g.Edges[0].Attributes.Label.Value != "" { - t.Fatalf("unexpected g.Edges[0].Attributes.Label.Value : %#v", g.Edges[0].Attributes.Label.Value) + if g.Edges[0].Label.Value != "" { + t.Fatalf("unexpected g.Edges[0].Label.Value : %#v", g.Edges[0].Label.Value) } }, }, @@ -1423,11 +1423,11 @@ x: { if len(g.Edges) != 1 { t.Fatalf("expected 1 edge: %#v", g.Edges) } - if g.Edges[0].Attributes.Style.Opacity.Value != "0.4" { - t.Fatalf("unexpected g.Edges[0].Attributes.Style.Opacity.Value: %#v", g.Edges[0].Attributes.Style.Opacity.Value) + if g.Edges[0].Style.Opacity.Value != "0.4" { + t.Fatalf("unexpected g.Edges[0].Style.Opacity.Value: %#v", g.Edges[0].Style.Opacity.Value) } - if g.Edges[0].Attributes.Label.Value != "" { - t.Fatalf("unexpected g.Edges[0].Attributes.Label.Value : %#v", g.Edges[0].Attributes.Label.Value) + if g.Edges[0].Label.Value != "" { + t.Fatalf("unexpected g.Edges[0].Label.Value : %#v", g.Edges[0].Label.Value) } }, }, @@ -1452,8 +1452,8 @@ x -> y: { if len(g.Objects) != 1 { t.Fatal(g.Objects) } - if g.Objects[0].Attributes.Link.Value != "https://google.com" { - t.Fatal(g.Objects[0].Attributes.Link.Value) + if g.Objects[0].Link.Value != "https://google.com" { + t.Fatal(g.Objects[0].Link.Value) } }, }, @@ -1465,8 +1465,8 @@ x -> y: { t.Fatal(g.Objects) } - if g.Objects[0].Attributes.Tooltip.Value != "https://google.com" { - t.Fatal(g.Objects[0].Attributes.Tooltip.Value) + if g.Objects[0].Tooltip.Value != "https://google.com" { + t.Fatal(g.Objects[0].Tooltip.Value) } }, }, @@ -1482,12 +1482,12 @@ x -> y: { if len(g.Objects) != 1 { t.Fatal(g.Objects) } - if g.Objects[0].Attributes.Link.Value != "https://google.com" { - t.Fatal(g.Objects[0].Attributes.Link.Value) + if g.Objects[0].Link.Value != "https://google.com" { + t.Fatal(g.Objects[0].Link.Value) } - if g.Objects[0].Attributes.Tooltip.Value != "hello world" { - t.Fatal(g.Objects[0].Attributes.Tooltip.Value) + if g.Objects[0].Tooltip.Value != "hello world" { + t.Fatal(g.Objects[0].Tooltip.Value) } }, }, @@ -1517,8 +1517,8 @@ b: { if len(g.Objects) != 1 { t.Fatal(g.Objects) } - if g.Objects[0].Attributes.Link.Value != "Overview.Untitled board 7.zzzzz" { - t.Fatal(g.Objects[0].Attributes.Link.Value) + if g.Objects[0].Link.Value != "Overview.Untitled board 7.zzzzz" { + t.Fatal(g.Objects[0].Link.Value) } }, }, @@ -1603,20 +1603,20 @@ y if len(g.Objects) != 2 { t.Fatal(g.Objects) } - if g.Objects[0].Attributes.NearKey == nil { + if g.Objects[0].NearKey == nil { t.Fatal("missing near key") } - if g.Objects[0].Attributes.Icon.Path != "orange" { - t.Fatal(g.Objects[0].Attributes.Icon) + if g.Objects[0].Icon.Path != "orange" { + t.Fatal(g.Objects[0].Icon) } - if g.Objects[0].Attributes.Style.Opacity.Value != "0.5" { - t.Fatal(g.Objects[0].Attributes.Style.Opacity) + if g.Objects[0].Style.Opacity.Value != "0.5" { + t.Fatal(g.Objects[0].Style.Opacity) } - if g.Objects[0].Attributes.Style.Stroke.Value != "red" { - t.Fatal(g.Objects[0].Attributes.Style.Stroke) + if g.Objects[0].Style.Stroke.Value != "red" { + t.Fatal(g.Objects[0].Style.Stroke) } - if g.Objects[0].Attributes.Style.Fill.Value != "green" { - t.Fatal(g.Objects[0].Attributes.Style.Fill) + if g.Objects[0].Style.Fill.Value != "green" { + t.Fatal(g.Objects[0].Style.Fill) } }, }, @@ -1696,7 +1696,7 @@ y -> x.style } assert.String(t, `"b\nb"`, g.Objects[0].ID) assert.String(t, `b -b`, g.Objects[0].Attributes.Label.Value) +b`, g.Objects[0].Label.Value) }, }, { @@ -1708,7 +1708,7 @@ b`, g.Objects[0].Attributes.Label.Value) t.Fatal(g.Objects) } assert.String(t, "b\rb", g.Objects[0].ID) - assert.String(t, "b\rb", g.Objects[0].Attributes.Label.Value) + assert.String(t, "b\rb", g.Objects[0].Label.Value) }, }, { @@ -1730,8 +1730,8 @@ b`, g.Objects[0].Attributes.Label.Value) if len(g.Objects[0].Class.Methods) != 0 { t.Fatal(len(g.Objects[0].Class.Methods)) } - if g.Objects[0].Attributes.Style.Opacity.Value != "0.4" { - t.Fatal(g.Objects[0].Attributes.Style.Opacity.Value) + if g.Objects[0].Style.Opacity.Value != "0.4" { + t.Fatal(g.Objects[0].Style.Opacity.Value) } }, }, @@ -1751,8 +1751,8 @@ b`, g.Objects[0].Attributes.Label.Value) if len(g.Objects[0].SQLTable.Columns) != 1 { t.Fatal(len(g.Objects[0].SQLTable.Columns)) } - if g.Objects[0].Attributes.Style.Opacity.Value != "0.4" { - t.Fatal(g.Objects[0].Attributes.Style.Opacity.Value) + if g.Objects[0].Style.Opacity.Value != "0.4" { + t.Fatal(g.Objects[0].Style.Opacity.Value) } }, }, @@ -1775,8 +1775,8 @@ b`, g.Objects[0].Attributes.Label.Value) if len(g.Objects[0].SQLTable.Columns) != 1 { t.Fatal(len(g.Objects[0].SQLTable.Columns)) } - if g.Objects[0].Attributes.Style.Opacity.Value != "0.4" { - t.Fatal(g.Objects[0].Attributes.Style.Opacity.Value) + if g.Objects[0].Style.Opacity.Value != "0.4" { + t.Fatal(g.Objects[0].Style.Opacity.Value) } }, }, @@ -1796,7 +1796,7 @@ x.y -> a.b: { } `, assertions: func(t *testing.T, g *d2graph.Graph) { - tassert.Equal(t, "true", g.Edges[0].Attributes.Style.Animated.Value) + tassert.Equal(t, "true", g.Edges[0].Style.Animated.Value) }, }, { @@ -1901,7 +1901,7 @@ dst.id <-> src.dst_id } `, assertions: func(t *testing.T, g *d2graph.Graph) { - assert.String(t, "sequence_diagram", g.Objects[0].Attributes.Shape.Value) + assert.String(t, "sequence_diagram", g.Objects[0].Shape.Value) }, }, { @@ -1948,7 +1948,7 @@ b text: `shape: sequence_diagram `, assertions: func(t *testing.T, g *d2graph.Graph) { - assert.String(t, "sequence_diagram", g.Root.Attributes.Shape.Value) + assert.String(t, "sequence_diagram", g.Root.Shape.Value) }, }, { @@ -2028,7 +2028,7 @@ ok: { text: `direction: right`, assertions: func(t *testing.T, g *d2graph.Graph) { - assert.String(t, "right", g.Root.Attributes.Direction.Value) + assert.String(t, "right", g.Root.Direction.Value) }, }, { @@ -2036,7 +2036,7 @@ ok: { text: `x`, assertions: func(t *testing.T, g *d2graph.Graph) { - assert.String(t, "", g.Objects[0].Attributes.Direction.Value) + assert.String(t, "", g.Objects[0].Direction.Value) }, }, { @@ -2046,7 +2046,7 @@ ok: { direction: left }`, assertions: func(t *testing.T, g *d2graph.Graph) { - assert.String(t, "left", g.Objects[0].Attributes.Direction.Value) + assert.String(t, "left", g.Objects[0].Direction.Value) }, }, { @@ -2057,7 +2057,7 @@ ok: { constraint: BIZ }`, assertions: func(t *testing.T, g *d2graph.Graph) { - assert.String(t, "bar", g.Objects[0].Attributes.Label.Value) + assert.String(t, "bar", g.Objects[0].Label.Value) }, }, { @@ -2151,7 +2151,7 @@ layers: { } }`, assertions: func(t *testing.T, g *d2graph.Graph) { - tassert.Equal(t, "root.layers.x", g.Objects[0].Attributes.Link.Value) + tassert.Equal(t, "root.layers.x", g.Objects[0].Link.Value) }, }, { @@ -2171,8 +2171,8 @@ scenarios: { } }`, assertions: func(t *testing.T, g *d2graph.Graph) { - tassert.Equal(t, "root.layers.cat", g.Objects[0].Attributes.Link.Value) - tassert.Equal(t, "root.layers.cat", g.Scenarios[0].Objects[0].Attributes.Link.Value) + tassert.Equal(t, "root.layers.cat", g.Objects[0].Link.Value) + tassert.Equal(t, "root.layers.cat", g.Scenarios[0].Objects[0].Link.Value) }, }, { @@ -2205,7 +2205,7 @@ layers: { } }`, assertions: func(t *testing.T, g *d2graph.Graph) { - tassert.Equal(t, "root.layers.x.layers.x", g.Objects[0].Attributes.Link.Value) + tassert.Equal(t, "root.layers.x.layers.x", g.Objects[0].Link.Value) }, }, { @@ -2219,7 +2219,7 @@ layers: { } }`, assertions: func(t *testing.T, g *d2graph.Graph) { - tassert.Equal(t, "root.layers.x", g.Objects[1].Attributes.Link.Value) + tassert.Equal(t, "root.layers.x", g.Objects[1].Link.Value) }, }, { @@ -2237,9 +2237,9 @@ layers: { } }`, assertions: func(t *testing.T, g *d2graph.Graph) { - tassert.NotNil(t, g.Layers[0].Layers[0].Objects[0].Attributes.Link.Value) - tassert.Equal(t, "root.layers.x", g.Layers[0].Layers[0].Objects[0].Attributes.Link.Value) - tassert.Equal(t, "root.layers.x", g.Layers[0].Layers[0].Objects[1].Attributes.Link.Value) + tassert.NotNil(t, g.Layers[0].Layers[0].Objects[0].Link.Value) + tassert.Equal(t, "root.layers.x", g.Layers[0].Layers[0].Objects[0].Link.Value) + tassert.Equal(t, "root.layers.x", g.Layers[0].Layers[0].Objects[1].Link.Value) }, }, { @@ -2289,7 +2289,7 @@ obj { } `, assertions: func(t *testing.T, g *d2graph.Graph) { - tassert.Equal(t, "200", g.Objects[0].Attributes.GridRows.Value) + tassert.Equal(t, "200", g.Objects[0].GridRows.Value) }, }, { @@ -2362,16 +2362,16 @@ nostar -> 1star: { class: path } `, assertions: func(t *testing.T, g *d2graph.Graph) { tassert.Equal(t, 3, len(g.Objects)) - tassert.Equal(t, "dragon_ball", g.Objects[0].Attributes.Classes[0]) - tassert.Equal(t, "", g.Objects[0].Attributes.Label.Value) + tassert.Equal(t, "dragon_ball", g.Objects[0].Classes[0]) + tassert.Equal(t, "", g.Objects[0].Label.Value) // Class field overrides primary - tassert.Equal(t, "", g.Objects[1].Attributes.Label.Value) - tassert.Equal(t, "**", g.Objects[2].Attributes.Label.Value) - tassert.Equal(t, "orange", g.Objects[0].Attributes.Style.Fill.Value) - tassert.Equal(t, "red", g.Objects[1].Attributes.Style.Fill.Value) + tassert.Equal(t, "", g.Objects[1].Label.Value) + tassert.Equal(t, "**", g.Objects[2].Label.Value) + tassert.Equal(t, "orange", g.Objects[0].Style.Fill.Value) + tassert.Equal(t, "red", g.Objects[1].Style.Fill.Value) - tassert.Equal(t, "4", g.Edges[0].Attributes.Style.StrokeWidth.Value) - tassert.Equal(t, "then", g.Edges[0].Attributes.Label.Value) + tassert.Equal(t, "4", g.Edges[0].Style.StrokeWidth.Value) + tassert.Equal(t, "then", g.Edges[0].Label.Value) }, }, { @@ -2386,7 +2386,7 @@ classes.x.shape: diamond `, assertions: func(t *testing.T, g *d2graph.Graph) { tassert.Equal(t, 1, len(g.Objects)) - tassert.Equal(t, "diamond", g.Objects[0].Attributes.Shape.Value) + tassert.Equal(t, "diamond", g.Objects[0].Shape.Value) }, }, { diff --git a/d2exporter/export.go b/d2exporter/export.go index 671527be3..8f8a398f1 100644 --- a/d2exporter/export.go +++ b/d2exporter/export.go @@ -42,10 +42,10 @@ func Export(ctx context.Context, g *d2graph.Graph, fontFamily *d2fonts.FontFamil func applyTheme(shape *d2target.Shape, obj *d2graph.Object, theme *d2themes.Theme) { shape.Stroke = obj.GetStroke(shape.StrokeDash) shape.Fill = obj.GetFill() - if obj.Attributes.Shape.Value == d2target.ShapeText { + if obj.Shape.Value == d2target.ShapeText { shape.Color = color.N1 } - if obj.Attributes.Shape.Value == d2target.ShapeSQLTable || obj.Attributes.Shape.Value == d2target.ShapeClass { + if obj.Shape.Value == d2target.ShapeSQLTable || obj.Shape.Value == d2target.ShapeClass { shape.PrimaryAccentColor = color.B2 shape.SecondaryAccentColor = color.AA2 shape.NeutralAccentColor = color.N2 @@ -72,64 +72,64 @@ func applyTheme(shape *d2target.Shape, obj *d2graph.Object, theme *d2themes.Them } func applyStyles(shape *d2target.Shape, obj *d2graph.Object) { - if obj.Attributes.Style.Opacity != nil { - shape.Opacity, _ = strconv.ParseFloat(obj.Attributes.Style.Opacity.Value, 64) + if obj.Style.Opacity != nil { + shape.Opacity, _ = strconv.ParseFloat(obj.Style.Opacity.Value, 64) } - if obj.Attributes.Style.StrokeDash != nil { - shape.StrokeDash, _ = strconv.ParseFloat(obj.Attributes.Style.StrokeDash.Value, 64) + if obj.Style.StrokeDash != nil { + shape.StrokeDash, _ = strconv.ParseFloat(obj.Style.StrokeDash.Value, 64) } - if obj.Attributes.Style.Fill != nil { - shape.Fill = obj.Attributes.Style.Fill.Value - } else if obj.Attributes.Shape.Value == d2target.ShapeText { + if obj.Style.Fill != nil { + shape.Fill = obj.Style.Fill.Value + } else if obj.Shape.Value == d2target.ShapeText { shape.Fill = "transparent" } - if obj.Attributes.Style.FillPattern != nil { - shape.FillPattern = obj.Attributes.Style.FillPattern.Value + if obj.Style.FillPattern != nil { + shape.FillPattern = obj.Style.FillPattern.Value } - if obj.Attributes.Style.Stroke != nil { - shape.Stroke = obj.Attributes.Style.Stroke.Value + if obj.Style.Stroke != nil { + shape.Stroke = obj.Style.Stroke.Value } - if obj.Attributes.Style.StrokeWidth != nil { - shape.StrokeWidth, _ = strconv.Atoi(obj.Attributes.Style.StrokeWidth.Value) + if obj.Style.StrokeWidth != nil { + shape.StrokeWidth, _ = strconv.Atoi(obj.Style.StrokeWidth.Value) } - if obj.Attributes.Style.Shadow != nil { - shape.Shadow, _ = strconv.ParseBool(obj.Attributes.Style.Shadow.Value) + if obj.Style.Shadow != nil { + shape.Shadow, _ = strconv.ParseBool(obj.Style.Shadow.Value) } - if obj.Attributes.Style.ThreeDee != nil { - shape.ThreeDee, _ = strconv.ParseBool(obj.Attributes.Style.ThreeDee.Value) + if obj.Style.ThreeDee != nil { + shape.ThreeDee, _ = strconv.ParseBool(obj.Style.ThreeDee.Value) } - if obj.Attributes.Style.Multiple != nil { - shape.Multiple, _ = strconv.ParseBool(obj.Attributes.Style.Multiple.Value) + if obj.Style.Multiple != nil { + shape.Multiple, _ = strconv.ParseBool(obj.Style.Multiple.Value) } - if obj.Attributes.Style.BorderRadius != nil { - shape.BorderRadius, _ = strconv.Atoi(obj.Attributes.Style.BorderRadius.Value) + if obj.Style.BorderRadius != nil { + shape.BorderRadius, _ = strconv.Atoi(obj.Style.BorderRadius.Value) } - if obj.Attributes.Style.FontColor != nil { - shape.Color = obj.Attributes.Style.FontColor.Value + if obj.Style.FontColor != nil { + shape.Color = obj.Style.FontColor.Value } - if obj.Attributes.Style.Italic != nil { - shape.Italic, _ = strconv.ParseBool(obj.Attributes.Style.Italic.Value) + if obj.Style.Italic != nil { + shape.Italic, _ = strconv.ParseBool(obj.Style.Italic.Value) } - if obj.Attributes.Style.Bold != nil { - shape.Bold, _ = strconv.ParseBool(obj.Attributes.Style.Bold.Value) + if obj.Style.Bold != nil { + shape.Bold, _ = strconv.ParseBool(obj.Style.Bold.Value) } - if obj.Attributes.Style.Underline != nil { - shape.Underline, _ = strconv.ParseBool(obj.Attributes.Style.Underline.Value) + if obj.Style.Underline != nil { + shape.Underline, _ = strconv.ParseBool(obj.Style.Underline.Value) } - if obj.Attributes.Style.Font != nil { - shape.FontFamily = obj.Attributes.Style.Font.Value + if obj.Style.Font != nil { + shape.FontFamily = obj.Style.Font.Value } - if obj.Attributes.Style.DoubleBorder != nil { - shape.DoubleBorder, _ = strconv.ParseBool(obj.Attributes.Style.DoubleBorder.Value) + if obj.Style.DoubleBorder != nil { + shape.DoubleBorder, _ = strconv.ParseBool(obj.Style.DoubleBorder.Value) } } func toShape(obj *d2graph.Object, theme *d2themes.Theme) d2target.Shape { shape := d2target.BaseShape() - shape.SetType(obj.Attributes.Shape.Value) + shape.SetType(obj.Shape.Value) shape.ID = obj.AbsID() - shape.Classes = obj.Attributes.Classes + shape.Classes = obj.Classes shape.ZIndex = obj.ZIndex shape.Level = int(obj.Level()) shape.Pos = d2target.NewPoint(int(obj.TopLeft.X), int(obj.TopLeft.Y)) @@ -155,10 +155,10 @@ func toShape(obj *d2graph.Object, theme *d2themes.Theme) d2target.Shape { shape.Color = text.GetColor(shape.Italic) applyStyles(shape, obj) - switch obj.Attributes.Shape.Value { + switch obj.Shape.Value { case d2target.ShapeCode, d2target.ShapeText: - shape.Language = obj.Attributes.Language - shape.Label = obj.Attributes.Label.Value + shape.Language = obj.Language + shape.Label = obj.Label.Value case d2target.ShapeClass: shape.Class = *obj.Class // The label is the header for classes and tables, which is set in client to be 4 px larger than the object's set font size @@ -178,13 +178,13 @@ func toShape(obj *d2graph.Object, theme *d2themes.Theme) d2target.Shape { } } - if obj.Attributes.Tooltip != nil { - shape.Tooltip = obj.Attributes.Tooltip.Value + if obj.Tooltip != nil { + shape.Tooltip = obj.Tooltip.Value } - if obj.Attributes.Link != nil { - shape.Link = obj.Attributes.Link.Value + if obj.Link != nil { + shape.Link = obj.Link.Value } - shape.Icon = obj.Attributes.Icon + shape.Icon = obj.Icon if obj.IconPosition != nil { shape.IconPosition = *obj.IconPosition } @@ -195,7 +195,7 @@ func toShape(obj *d2graph.Object, theme *d2themes.Theme) d2target.Shape { func toConnection(edge *d2graph.Edge, theme *d2themes.Theme) d2target.Connection { connection := d2target.BaseConnection() connection.ID = edge.AbsID() - connection.Classes = edge.Attributes.Classes + connection.Classes = edge.Classes connection.ZIndex = edge.ZIndex text := edge.Text() @@ -236,60 +236,60 @@ func toConnection(edge *d2graph.Edge, theme *d2themes.Theme) d2target.Connection if theme != nil && theme.SpecialRules.NoCornerRadius { connection.BorderRadius = 0 } - if edge.Attributes.Style.BorderRadius != nil { - connection.BorderRadius, _ = strconv.ParseFloat(edge.Attributes.Style.BorderRadius.Value, 64) + if edge.Style.BorderRadius != nil { + connection.BorderRadius, _ = strconv.ParseFloat(edge.Style.BorderRadius.Value, 64) } - if edge.Attributes.Style.Opacity != nil { - connection.Opacity, _ = strconv.ParseFloat(edge.Attributes.Style.Opacity.Value, 64) + if edge.Style.Opacity != nil { + connection.Opacity, _ = strconv.ParseFloat(edge.Style.Opacity.Value, 64) } - if edge.Attributes.Style.StrokeDash != nil { - connection.StrokeDash, _ = strconv.ParseFloat(edge.Attributes.Style.StrokeDash.Value, 64) + if edge.Style.StrokeDash != nil { + connection.StrokeDash, _ = strconv.ParseFloat(edge.Style.StrokeDash.Value, 64) } connection.Stroke = edge.GetStroke(connection.StrokeDash) - if edge.Attributes.Style.Stroke != nil { - connection.Stroke = edge.Attributes.Style.Stroke.Value + if edge.Style.Stroke != nil { + connection.Stroke = edge.Style.Stroke.Value } - if edge.Attributes.Style.StrokeWidth != nil { - connection.StrokeWidth, _ = strconv.Atoi(edge.Attributes.Style.StrokeWidth.Value) + if edge.Style.StrokeWidth != nil { + connection.StrokeWidth, _ = strconv.Atoi(edge.Style.StrokeWidth.Value) } - if edge.Attributes.Style.Fill != nil { - connection.Fill = edge.Attributes.Style.Fill.Value + if edge.Style.Fill != nil { + connection.Fill = edge.Style.Fill.Value } connection.FontSize = text.FontSize - if edge.Attributes.Style.FontSize != nil { - connection.FontSize, _ = strconv.Atoi(edge.Attributes.Style.FontSize.Value) + if edge.Style.FontSize != nil { + connection.FontSize, _ = strconv.Atoi(edge.Style.FontSize.Value) } - if edge.Attributes.Style.Animated != nil { - connection.Animated, _ = strconv.ParseBool(edge.Attributes.Style.Animated.Value) + if edge.Style.Animated != nil { + connection.Animated, _ = strconv.ParseBool(edge.Style.Animated.Value) } - if edge.Attributes.Tooltip != nil { - connection.Tooltip = edge.Attributes.Tooltip.Value + if edge.Tooltip != nil { + connection.Tooltip = edge.Tooltip.Value } - connection.Icon = edge.Attributes.Icon + connection.Icon = edge.Icon - if edge.Attributes.Style.Italic != nil { - connection.Italic, _ = strconv.ParseBool(edge.Attributes.Style.Italic.Value) + if edge.Style.Italic != nil { + connection.Italic, _ = strconv.ParseBool(edge.Style.Italic.Value) } connection.Color = text.GetColor(connection.Italic) - if edge.Attributes.Style.FontColor != nil { - connection.Color = edge.Attributes.Style.FontColor.Value + if edge.Style.FontColor != nil { + connection.Color = edge.Style.FontColor.Value } - if edge.Attributes.Style.Bold != nil { - connection.Bold, _ = strconv.ParseBool(edge.Attributes.Style.Bold.Value) + if edge.Style.Bold != nil { + connection.Bold, _ = strconv.ParseBool(edge.Style.Bold.Value) } if theme != nil && theme.SpecialRules.Mono { connection.FontFamily = "mono" } - if edge.Attributes.Style.Font != nil { - connection.FontFamily = edge.Attributes.Style.Font.Value + if edge.Style.Font != nil { + connection.FontFamily = edge.Style.Font.Value } connection.Label = text.Text connection.LabelWidth = text.Dimensions.Width diff --git a/d2graph/d2graph.go b/d2graph/d2graph.go index 24fed011e..d37351ce8 100644 --- a/d2graph/d2graph.go +++ b/d2graph/d2graph.go @@ -56,10 +56,9 @@ type Graph struct { func NewGraph() *Graph { d := &Graph{} d.Root = &Object{ - Graph: d, - Parent: nil, - Children: make(map[string]*Object), - Attributes: &Attributes{}, + Graph: d, + Parent: nil, + Children: make(map[string]*Object), } return d } @@ -90,11 +89,10 @@ type Object struct { // IDVal: yes'" // // ID allows joining on . naively and construct a valid D2 key path - ID string `json:"id"` - IDVal string `json:"id_val"` - Map *d2ast.Map `json:"-"` - LabelDimensions d2target.TextDimensions `json:"label_dimensions"` - References []Reference `json:"references,omitempty"` + ID string `json:"id"` + IDVal string `json:"id_val"` + Map *d2ast.Map `json:"-"` + References []Reference `json:"references,omitempty"` *geo.Box `json:"box,omitempty"` LabelPosition *string `json:"labelPosition,omitempty"` @@ -106,20 +104,22 @@ type Object struct { Children map[string]*Object `json:"-"` ChildrenArray []*Object `json:"-"` - Attributes *Attributes `json:"attributes,omitempty"` + Attributes `json:"attributes"` ZIndex int `json:"zIndex"` } type Attributes struct { - Label Scalar `json:"label"` + Label Scalar `json:"label"` + LabelDimensions d2target.TextDimensions `json:"labelDimensions"` + Style Style `json:"style"` Icon *url.URL `json:"icon,omitempty"` Tooltip *Scalar `json:"tooltip,omitempty"` Link *Scalar `json:"link,omitempty"` - Width *Scalar `json:"width,omitempty"` - Height *Scalar `json:"height,omitempty"` + WidthAttr *Scalar `json:"width,omitempty"` + HeightAttr *Scalar `json:"height,omitempty"` Top *Scalar `json:"top,omitempty"` Left *Scalar `json:"left,omitempty"` @@ -412,7 +412,7 @@ func (l ContainerLevel) LabelSize() int { func (obj *Object) GetFill() string { level := int(obj.Level()) - shape := obj.Attributes.Shape.Value + shape := obj.Shape.Value if strings.EqualFold(shape, d2target.ShapeSQLTable) || strings.EqualFold(shape, d2target.ShapeClass) { return color.N1 @@ -491,7 +491,7 @@ func (obj *Object) GetFill() string { } func (obj *Object) GetStroke(dashGapSize interface{}) string { - shape := obj.Attributes.Shape.Value + shape := obj.Shape.Value if strings.EqualFold(shape, d2target.ShapeCode) || strings.EqualFold(shape, d2target.ShapeText) { return color.N1 @@ -518,10 +518,10 @@ func (obj *Object) IsContainer() bool { } func (obj *Object) HasOutsideBottomLabel() bool { - if obj == nil || obj.Attributes == nil { + if obj == nil { return false } - switch obj.Attributes.Shape.Value { + switch obj.Shape.Value { case d2target.ShapeImage, d2target.ShapePerson: return true default: @@ -530,14 +530,14 @@ func (obj *Object) HasOutsideBottomLabel() bool { } func (obj *Object) HasLabel() bool { - if obj == nil || obj.Attributes == nil { + if obj == nil { return false } - switch obj.Attributes.Shape.Value { + switch obj.Shape.Value { case d2target.ShapeText, d2target.ShapeClass, d2target.ShapeSQLTable, d2target.ShapeCode: return false default: - return obj.Attributes.Label.Value != "" + return obj.Label.Value != "" } } @@ -556,12 +556,12 @@ func (obj *Object) AbsIDArray() []string { } func (obj *Object) Text() *d2target.MText { - isBold := !obj.IsContainer() && obj.Attributes.Shape.Value != "text" + isBold := !obj.IsContainer() && obj.Shape.Value != "text" isItalic := false - if obj.Attributes.Style.Bold != nil && obj.Attributes.Style.Bold.Value == "true" { + if obj.Style.Bold != nil && obj.Style.Bold.Value == "true" { isBold = true } - if obj.Attributes.Style.Italic != nil && obj.Attributes.Style.Italic.Value == "true" { + if obj.Style.Italic != nil && obj.Style.Italic.Value == "true" { isItalic = true } fontSize := d2fonts.FONT_SIZE_M @@ -571,14 +571,14 @@ func (obj *Object) Text() *d2target.MText { } if obj.OuterSequenceDiagram() == nil { - if obj.IsContainer() && obj.Attributes.Shape.Value != "text" { + if obj.IsContainer() && obj.Shape.Value != "text" { fontSize = obj.Level().LabelSize() } } else { isBold = false } - if obj.Attributes.Style.FontSize != nil { - fontSize, _ = strconv.Atoi(obj.Attributes.Style.FontSize.Value) + if obj.Style.FontSize != nil { + fontSize, _ = strconv.Atoi(obj.Style.FontSize.Value) } // Class and Table objects have Label set to header if obj.Class != nil || obj.SQLTable != nil { @@ -588,12 +588,12 @@ func (obj *Object) Text() *d2target.MText { isBold = false } return &d2target.MText{ - Text: obj.Attributes.Label.Value, + Text: obj.Label.Value, FontSize: fontSize, IsBold: isBold, IsItalic: isItalic, - Language: obj.Attributes.Language, - Shape: obj.Attributes.Shape.Value, + Language: obj.Language, + Shape: obj.Shape.Value, Dimensions: obj.LabelDimensions, } @@ -608,7 +608,7 @@ func (obj *Object) newObject(id string) *Object { child := &Object{ ID: id, IDVal: idval, - Attributes: &Attributes{ + Attributes: Attributes{ Label: Scalar{ Value: idval, }, @@ -786,7 +786,7 @@ func (obj *Object) FindEdges(mk *d2ast.Key) ([]*Edge, bool) { func (obj *Object) ensureChildEdge(ida []string) *Object { for i := range ida { - switch obj.Attributes.Shape.Value { + switch obj.Shape.Value { case d2target.ShapeClass, d2target.ShapeSQLTable: // This will only be called for connecting edges where we want to truncate to the // container. @@ -865,23 +865,23 @@ func (obj *Object) AppendReferences(ida []string, ref Reference, unresolvedObj * } func (obj *Object) GetLabelSize(mtexts []*d2target.MText, ruler *textmeasure.Ruler, fontFamily *d2fonts.FontFamily) (*d2target.TextDimensions, error) { - shapeType := strings.ToLower(obj.Attributes.Shape.Value) + shapeType := strings.ToLower(obj.Shape.Value) - if obj.Attributes.Style.Font != nil { - f := d2fonts.D2_FONT_TO_FAMILY[obj.Attributes.Style.Font.Value] + if obj.Style.Font != nil { + f := d2fonts.D2_FONT_TO_FAMILY[obj.Style.Font.Value] fontFamily = &f } var dims *d2target.TextDimensions switch shapeType { case d2target.ShapeText: - if obj.Attributes.Language == "latex" { + if obj.Language == "latex" { width, height, err := d2latex.Measure(obj.Text().Text) if err != nil { return nil, err } dims = d2target.NewTextDimensions(width, height) - } else if obj.Attributes.Language != "" { + } else if obj.Language != "" { var err error dims, err = getMarkdownDimensions(mtexts, ruler, obj.Text(), fontFamily) if err != nil { @@ -898,7 +898,7 @@ func (obj *Object) GetLabelSize(mtexts []*d2target.MText, ruler *textmeasure.Rul dims = GetTextDimensions(mtexts, ruler, obj.Text(), fontFamily) } - if shapeType == d2target.ShapeSQLTable && obj.Attributes.Label.Value == "" { + if shapeType == d2target.ShapeSQLTable && obj.Label.Value == "" { // measure with placeholder text to determine height placeholder := *obj.Text() placeholder.Text = "Table" @@ -927,7 +927,7 @@ func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.R labelDims.Height += INNER_LABEL_PADDING } - switch strings.ToLower(obj.Attributes.Shape.Value) { + switch strings.ToLower(obj.Shape.Value) { default: return d2target.NewTextDimensions(labelDims.Width, labelDims.Height), nil @@ -938,8 +938,8 @@ func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.R maxWidth := go2.Max(12, labelDims.Width) fontSize := d2fonts.FONT_SIZE_L - if obj.Attributes.Style.FontSize != nil { - fontSize, _ = strconv.Atoi(obj.Attributes.Style.FontSize.Value) + if obj.Style.FontSize != nil { + fontSize, _ = strconv.Atoi(obj.Style.FontSize.Value) } for _, f := range obj.Class.Fields { @@ -984,8 +984,8 @@ func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.R constraintWidth := 0 colFontSize := d2fonts.FONT_SIZE_L - if obj.Attributes.Style.FontSize != nil { - colFontSize, _ = strconv.Atoi(obj.Attributes.Style.FontSize.Value) + if obj.Style.FontSize != nil { + colFontSize, _ = strconv.Atoi(obj.Style.FontSize.Value) } for i := range obj.SQLTable.Columns { @@ -1031,7 +1031,7 @@ func (obj *Object) GetDefaultSize(mtexts []*d2target.MText, ruler *textmeasure.R func (obj *Object) OuterNearContainer() *Object { for obj != nil { - if obj.Attributes.NearKey != nil { + if obj.NearKey != nil { return obj } obj = obj.Parent @@ -1048,9 +1048,8 @@ type Edge struct { SrcTableColumnIndex *int `json:"srcTableColumnIndex,omitempty"` DstTableColumnIndex *int `json:"dstTableColumnIndex,omitempty"` - LabelDimensions d2target.TextDimensions `json:"label_dimensions"` - LabelPosition *string `json:"labelPosition,omitempty"` - LabelPercentage *float64 `json:"labelPercentage,omitempty"` + LabelPosition *string `json:"labelPosition,omitempty"` + LabelPercentage *float64 `json:"labelPercentage,omitempty"` IsCurve bool `json:"isCurve"` Route []*geo.Point `json:"route,omitempty"` @@ -1064,7 +1063,7 @@ type Edge struct { DstArrowhead *Attributes `json:"dstArrowhead,omitempty"` References []EdgeReference `json:"references,omitempty"` - Attributes *Attributes `json:"attributes,omitempty"` + Attributes `json:"attributes,omitempty"` ZIndex int `json:"zIndex"` } @@ -1104,15 +1103,15 @@ func (e *Edge) ArrowString() string { func (e *Edge) Text() *d2target.MText { fontSize := d2fonts.FONT_SIZE_M - if e.Attributes.Style.FontSize != nil { - fontSize, _ = strconv.Atoi(e.Attributes.Style.FontSize.Value) + if e.Style.FontSize != nil { + fontSize, _ = strconv.Atoi(e.Style.FontSize.Value) } isBold := false - if e.Attributes.Style.Bold != nil { - isBold, _ = strconv.ParseBool(e.Attributes.Style.Bold.Value) + if e.Style.Bold != nil { + isBold, _ = strconv.ParseBool(e.Style.Bold.Value) } return &d2target.MText{ - Text: e.Attributes.Label.Value, + Text: e.Label.Value, FontSize: fontSize, IsBold: isBold, IsItalic: true, @@ -1160,7 +1159,7 @@ func (obj *Object) Connect(srcID, dstID []string, srcArrow, dstArrow bool, label } e := &Edge{ - Attributes: &Attributes{ + Attributes: Attributes{ Label: Scalar{ Value: label, }, @@ -1179,7 +1178,7 @@ func (obj *Object) Connect(srcID, dstID []string, srcArrow, dstArrow bool, label } func addSQLTableColumnIndices(e *Edge, srcID, dstID []string, obj, src, dst *Object) { - if src.Attributes.Shape.Value == d2target.ShapeSQLTable { + if src.Shape.Value == d2target.ShapeSQLTable { if src == dst { // Ignore edge to column inside table. return @@ -1197,7 +1196,7 @@ func addSQLTableColumnIndices(e *Edge, srcID, dstID []string, obj, src, dst *Obj } } } - if dst.Attributes.Shape.Value == d2target.ShapeSQLTable { + if dst.Shape.Value == d2target.ShapeSQLTable { objAbsID := obj.AbsIDArray() dstAbsID := dst.AbsIDArray() if len(objAbsID)+len(dstID) > len(dstAbsID) { @@ -1344,16 +1343,16 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler var desiredWidth int var desiredHeight int - if obj.Attributes.Width != nil { - desiredWidth, _ = strconv.Atoi(obj.Attributes.Width.Value) + if obj.WidthAttr != nil { + desiredWidth, _ = strconv.Atoi(obj.WidthAttr.Value) } - if obj.Attributes.Height != nil { - desiredHeight, _ = strconv.Atoi(obj.Attributes.Height.Value) + if obj.HeightAttr != nil { + desiredHeight, _ = strconv.Atoi(obj.HeightAttr.Value) } - dslShape := strings.ToLower(obj.Attributes.Shape.Value) + dslShape := strings.ToLower(obj.Shape.Value) - if obj.Attributes.Label.Value == "" && + if obj.Label.Value == "" && dslShape != d2target.ShapeImage && dslShape != d2target.ShapeSQLTable && dslShape != d2target.ShapeClass { @@ -1379,12 +1378,12 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler continue } - if g.Theme != nil && g.Theme.SpecialRules.CapsLock && !strings.EqualFold(obj.Attributes.Shape.Value, d2target.ShapeCode) { - if obj.Attributes.Language != "latex" && !obj.Attributes.Style.NoneTextTransform() { - obj.Attributes.Label.Value = strings.ToUpper(obj.Attributes.Label.Value) + if g.Theme != nil && g.Theme.SpecialRules.CapsLock && !strings.EqualFold(obj.Shape.Value, d2target.ShapeCode) { + if obj.Language != "latex" && !obj.Style.NoneTextTransform() { + obj.Label.Value = strings.ToUpper(obj.Label.Value) } } - obj.Attributes.ApplyTextTransform() + obj.ApplyTextTransform() labelDims, err := obj.GetLabelSize(mtexts, ruler, fontFamily) if err != nil { @@ -1394,7 +1393,7 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler // if there is a desired width or height, fit to content box without inner label padding for smallest minimum size withInnerLabelPadding := desiredWidth == 0 && desiredHeight == 0 && - dslShape != d2target.ShapeText && obj.Attributes.Label.Value != "" + dslShape != d2target.ShapeText && obj.Label.Value != "" defaultDims, err := obj.GetDefaultSize(mtexts, ruler, fontFamily, *labelDims, withInnerLabelPadding) if err != nil { return err @@ -1426,7 +1425,7 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler } // give shapes with icons extra padding to fit their label - if obj.Attributes.Icon != nil { + if obj.Icon != nil { labelHeight := float64(labelDims.Height + INNER_LABEL_PADDING) // Evenly pad enough to fit label above icon if desiredWidth == 0 { @@ -1440,10 +1439,10 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler switch shapeType { case shape.TABLE_TYPE, shape.CLASS_TYPE, shape.CODE_TYPE, shape.IMAGE_TYPE: default: - if obj.Attributes.Link != nil { + if obj.Link != nil { paddingX += 32 } - if obj.Attributes.Tooltip != nil { + if obj.Tooltip != nil { paddingX += 32 } } @@ -1489,18 +1488,18 @@ func (g *Graph) SetDimensions(mtexts []*d2target.MText, ruler *textmeasure.Ruler edge.MinHeight += dims.Height + 5 } - if edge.Attributes.Label.Value == "" { + if edge.Label.Value == "" { continue } - if g.Theme != nil && g.Theme.SpecialRules.CapsLock && !edge.Attributes.Style.NoneTextTransform() { - edge.Attributes.Label.Value = strings.ToUpper(edge.Attributes.Label.Value) + if g.Theme != nil && g.Theme.SpecialRules.CapsLock && !edge.Style.NoneTextTransform() { + edge.Label.Value = strings.ToUpper(edge.Label.Value) } - edge.Attributes.ApplyTextTransform() + edge.ApplyTextTransform() usedFont := fontFamily - if edge.Attributes.Style.Font != nil { - f := d2fonts.D2_FONT_TO_FAMILY[edge.Attributes.Style.Font.Value] + if edge.Style.Font != nil { + f := d2fonts.D2_FONT_TO_FAMILY[edge.Style.Font.Value] usedFont = &f } @@ -1522,11 +1521,11 @@ func (g *Graph) Texts() []*d2target.MText { capsLock := g.Theme != nil && g.Theme.SpecialRules.CapsLock for _, obj := range g.Objects { - if obj.Attributes.Label.Value != "" { - obj.Attributes.ApplyTextTransform() + if obj.Label.Value != "" { + obj.ApplyTextTransform() text := obj.Text() - if capsLock && !strings.EqualFold(obj.Attributes.Shape.Value, d2target.ShapeCode) { - if obj.Attributes.Language != "latex" && !obj.Attributes.Style.NoneTextTransform() { + if capsLock && !strings.EqualFold(obj.Shape.Value, d2target.ShapeCode) { + if obj.Language != "latex" && !obj.Style.NoneTextTransform() { text.Text = strings.ToUpper(text.Text) } } @@ -1534,8 +1533,8 @@ func (g *Graph) Texts() []*d2target.MText { } if obj.Class != nil { fontSize := d2fonts.FONT_SIZE_L - if obj.Attributes.Style.FontSize != nil { - fontSize, _ = strconv.Atoi(obj.Attributes.Style.FontSize.Value) + if obj.Style.FontSize != nil { + fontSize, _ = strconv.Atoi(obj.Style.FontSize.Value) } for _, field := range obj.Class.Fields { texts = appendTextDedup(texts, field.Text(fontSize)) @@ -1545,8 +1544,8 @@ func (g *Graph) Texts() []*d2target.MText { } } else if obj.SQLTable != nil { colFontSize := d2fonts.FONT_SIZE_L - if obj.Attributes.Style.FontSize != nil { - colFontSize, _ = strconv.Atoi(obj.Attributes.Style.FontSize.Value) + if obj.Style.FontSize != nil { + colFontSize, _ = strconv.Atoi(obj.Style.FontSize.Value) } for _, column := range obj.SQLTable.Columns { for _, t := range column.Texts(colFontSize) { @@ -1556,10 +1555,10 @@ func (g *Graph) Texts() []*d2target.MText { } } for _, edge := range g.Edges { - if edge.Attributes.Label.Value != "" { - edge.Attributes.ApplyTextTransform() + if edge.Label.Value != "" { + edge.ApplyTextTransform() text := edge.Text() - if capsLock && !edge.Attributes.Style.NoneTextTransform() { + if capsLock && !edge.Style.NoneTextTransform() { text.Text = strings.ToUpper(text.Text) } texts = appendTextDedup(texts, text) diff --git a/d2graph/grid_diagram.go b/d2graph/grid_diagram.go index 6c40667a5..b6968e8d4 100644 --- a/d2graph/grid_diagram.go +++ b/d2graph/grid_diagram.go @@ -1,8 +1,8 @@ package d2graph func (obj *Object) IsGridDiagram() bool { - return obj != nil && obj.Attributes != nil && - (obj.Attributes.GridRows != nil || obj.Attributes.GridColumns != nil) + return obj != nil && + (obj.GridRows != nil || obj.GridColumns != nil) } func (obj *Object) ClosestGridDiagram() *Object { diff --git a/d2graph/seqdiagram.go b/d2graph/seqdiagram.go index b9cddac8d..3cd2cf171 100644 --- a/d2graph/seqdiagram.go +++ b/d2graph/seqdiagram.go @@ -3,7 +3,7 @@ package d2graph import "oss.terrastruct.com/d2/d2target" func (obj *Object) IsSequenceDiagram() bool { - return obj != nil && obj.Attributes != nil && obj.Attributes.Shape.Value == d2target.ShapeSequenceDiagram + return obj != nil && obj.Shape.Value == d2target.ShapeSequenceDiagram } func (obj *Object) OuterSequenceDiagram() *Object { diff --git a/d2graph/serde.go b/d2graph/serde.go index 7f9657808..126fec2f3 100644 --- a/d2graph/serde.go +++ b/d2graph/serde.go @@ -265,73 +265,51 @@ func CompareSerializedObject(obj, other *Object) error { } } - if obj.Attributes != nil && other.Attributes == nil { - return fmt.Errorf("other should have attributes") - } else if obj.Attributes == nil && other.Attributes != nil { - return fmt.Errorf("other should not have attributes") - } else if obj.Attributes != nil { - if d2target.IsShape(obj.Attributes.Shape.Value) != d2target.IsShape(other.Attributes.Shape.Value) { - return fmt.Errorf( - "shapes differ: obj=%s, other=%s", - obj.Attributes.Shape.Value, - other.Attributes.Shape.Value, - ) - } - - if obj.Attributes.Icon == nil && other.Attributes.Icon != nil { - return fmt.Errorf("other does not have an icon") - } else if obj.Attributes.Icon != nil && other.Attributes.Icon == nil { - return fmt.Errorf("obj does not have an icon") - } - - if obj.Attributes.Direction.Value != other.Attributes.Direction.Value { - return fmt.Errorf( - "directions differ: obj=%s, other=%s", - obj.Attributes.Direction.Value, - other.Attributes.Direction.Value, - ) - } - - if obj.Attributes.Label.Value != other.Attributes.Label.Value { - return fmt.Errorf( - "labels differ: obj=%s, other=%s", - obj.Attributes.Label.Value, - other.Attributes.Label.Value, - ) - } - - if obj.Attributes.NearKey != nil { - if other.Attributes.NearKey == nil { - return fmt.Errorf("other does not have near") - } - objKey := strings.Join(Key(obj.Attributes.NearKey), ".") - deserKey := strings.Join(Key(other.Attributes.NearKey), ".") - if objKey != deserKey { - return fmt.Errorf( - "near differs: obj=%s, other=%s", - objKey, - deserKey, - ) - } - } else if other.Attributes.NearKey != nil { - return fmt.Errorf("other should not have near") - } + if d2target.IsShape(obj.Shape.Value) != d2target.IsShape(other.Shape.Value) { + return fmt.Errorf( + "shapes differ: obj=%s, other=%s", + obj.Shape.Value, + other.Shape.Value, + ) } - if obj.SQLTable == nil && other.SQLTable != nil { - return fmt.Errorf("other is not a sql table") - } else if obj.SQLTable != nil && other.SQLTable == nil { - return fmt.Errorf("obj is not a sql table") + if obj.Icon == nil && other.Icon != nil { + return fmt.Errorf("other does not have an icon") + } else if obj.Icon != nil && other.Icon == nil { + return fmt.Errorf("obj does not have an icon") } - if obj.SQLTable != nil { - if len(obj.SQLTable.Columns) != len(other.SQLTable.Columns) { + if obj.Direction.Value != other.Direction.Value { + return fmt.Errorf( + "directions differ: obj=%s, other=%s", + obj.Direction.Value, + other.Direction.Value, + ) + } + + if obj.Label.Value != other.Label.Value { + return fmt.Errorf( + "labels differ: obj=%s, other=%s", + obj.Label.Value, + other.Label.Value, + ) + } + + if obj.NearKey != nil { + if other.NearKey == nil { + return fmt.Errorf("other does not have near") + } + objKey := strings.Join(Key(obj.NearKey), ".") + deserKey := strings.Join(Key(other.NearKey), ".") + if objKey != deserKey { return fmt.Errorf( - "table columns count differ: obj=%d, other=%d", - len(obj.SQLTable.Columns), - len(other.SQLTable.Columns), + "near differs: obj=%s, other=%s", + objKey, + deserKey, ) } + } else if other.NearKey != nil { + return fmt.Errorf("other should not have near") } if obj.LabelDimensions.Width != other.LabelDimensions.Width { @@ -350,6 +328,22 @@ func CompareSerializedObject(obj, other *Object) error { ) } + if obj.SQLTable == nil && other.SQLTable != nil { + return fmt.Errorf("other is not a sql table") + } else if obj.SQLTable != nil && other.SQLTable == nil { + return fmt.Errorf("obj is not a sql table") + } + + if obj.SQLTable != nil { + if len(obj.SQLTable.Columns) != len(other.SQLTable.Columns) { + return fmt.Errorf( + "table columns count differ: obj=%d, other=%d", + len(obj.SQLTable.Columns), + len(other.SQLTable.Columns), + ) + } + } + return nil } @@ -410,11 +404,11 @@ func CompareSerializedEdge(edge, other *Edge) error { ) } - if edge.Attributes.Label.Value != other.Attributes.Label.Value { + if edge.Label.Value != other.Label.Value { return fmt.Errorf( "labels differ: edge=%s, other=%s", - edge.Attributes.Label.Value, - other.Attributes.Label.Value, + edge.Label.Value, + other.Label.Value, ) } diff --git a/d2layouts/d2dagrelayout/layout.go b/d2layouts/d2dagrelayout/layout.go index 468414c58..b4c26c655 100644 --- a/d2layouts/d2dagrelayout/layout.go +++ b/d2layouts/d2dagrelayout/layout.go @@ -93,7 +93,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err }, } isHorizontal := false - switch g.Root.Attributes.Direction.Value { + switch g.Root.Direction.Value { case "down": rootAttrs.rankdir = "TB" case "right": @@ -118,9 +118,9 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err maxContainerLabelHeight = go2.Max(maxContainerLabelHeight, obj.LabelDimensions.Height+label.PADDING) } - if obj.Attributes.Icon != nil && obj.Attributes.Shape.Value != d2target.ShapeImage { + if obj.Icon != nil && obj.Shape.Value != d2target.ShapeImage { contentBox := geo.NewBox(geo.NewPoint(0, 0), float64(obj.Width), float64(obj.Height)) - shapeType := d2target.DSL_SHAPE_TO_SHAPE_TYPE[obj.Attributes.Shape.Value] + shapeType := d2target.DSL_SHAPE_TO_SHAPE_TYPE[obj.Shape.Value] s := shape.NewShape(shapeType, contentBox) iconSize := d2target.GetIconSize(s.GetInnerBox(), string(label.InsideTopLeft)) // Since dagre container labels are pushed up, we don't want a child container to collide @@ -161,7 +161,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err height := obj.Height if obj.HasLabel() { - if obj.HasOutsideBottomLabel() || obj.Attributes.Icon != nil { + if obj.HasOutsideBottomLabel() || obj.Icon != nil { height += float64(obj.LabelDimensions.Height) + label.PADDING } if len(obj.ChildrenArray) > 0 { @@ -189,7 +189,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err // We want to leave some gap between multiple edges if numEdges > 1 { - switch g.Root.Attributes.Direction.Value { + switch g.Root.Direction.Value { case "down", "up", "": width += EDGE_LABEL_GAP case "left", "right": @@ -242,13 +242,13 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err obj.LabelPosition = go2.Pointer(string(label.OutsideBottomCenter)) // remove the extra height we added to the node when passing to dagre obj.Height -= float64(obj.LabelDimensions.Height) + label.PADDING - } else if obj.Attributes.Icon != nil { + } else if obj.Icon != nil { obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) } else { obj.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) } } - if obj.Attributes.Icon != nil { + if obj.Icon != nil { if len(obj.ChildrenArray) > 0 { obj.IconPosition = go2.Pointer(string(label.OutsideTopLeft)) obj.LabelPosition = go2.Pointer(string(label.OutsideTopRight)) @@ -453,15 +453,15 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err } } - srcShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Src.Attributes.Shape.Value)], edge.Src.Box) - dstShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Dst.Attributes.Shape.Value)], edge.Dst.Box) + srcShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Src.Shape.Value)], edge.Src.Box) + dstShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Dst.Shape.Value)], edge.Dst.Box) // trace the edge to the specific shape's border points[startIndex] = shape.TraceToShapeBorder(srcShape, start, points[startIndex+1]) // if an edge to a container runs into its label, stop the edge at the label instead overlapsContainerLabel := false - if edge.Dst.IsContainer() && edge.Dst.Attributes.Label.Value != "" && !dstShape.Is(shape.TEXT_TYPE) { + if edge.Dst.IsContainer() && edge.Dst.Label.Value != "" && !dstShape.Is(shape.TEXT_TYPE) { // assumes LabelPosition, LabelWidth, LabelHeight are all set if there is a label labelWidth := float64(edge.Dst.LabelDimensions.Width) labelHeight := float64(edge.Dst.LabelDimensions.Height) @@ -514,7 +514,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err edge.Route = path // compile needs to assign edge label positions - if edge.Attributes.Label.Value != "" { + if edge.Label.Value != "" { edge.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) } } diff --git a/d2layouts/d2elklayout/layout.go b/d2layouts/d2elklayout/layout.go index 30475bf2a..1f21f3d08 100644 --- a/d2layouts/d2elklayout/layout.go +++ b/d2layouts/d2elklayout/layout.go @@ -159,7 +159,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err }, }, } - switch g.Root.Attributes.Direction.Value { + switch g.Root.Direction.Value { case "down": elkGraph.LayoutOptions.Direction = "DOWN" case "up": @@ -198,7 +198,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err } } if incoming >= 2 || outgoing >= 2 { - switch g.Root.Attributes.Direction.Value { + switch g.Root.Direction.Value { case "right", "left": obj.Height = math.Max(obj.Height, math.Max(incoming, outgoing)*port_spacing) default: @@ -209,7 +209,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err height := obj.Height width := obj.Width if obj.HasLabel() { - if obj.HasOutsideBottomLabel() || obj.Attributes.Icon != nil { + if obj.HasOutsideBottomLabel() || obj.Icon != nil { height += float64(obj.LabelDimensions.Height) + label.PADDING } width = go2.Max(width, float64(obj.LabelDimensions.Width)) @@ -256,7 +256,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err n.Height += 100 + float64(labelHeight) n.Width += 100 contentBox := geo.NewBox(geo.NewPoint(0, 0), float64(n.Width), float64(n.Height)) - shapeType := d2target.DSL_SHAPE_TO_SHAPE_TYPE[obj.Attributes.Shape.Value] + shapeType := d2target.DSL_SHAPE_TO_SHAPE_TYPE[obj.Shape.Value] s := shape.NewShape(shapeType, contentBox) paddingTop := n.Height - s.GetInnerBox().Height @@ -264,7 +264,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err n.Width -= 100 iconHeight := 0 - if obj.Attributes.Icon != nil && obj.Attributes.Shape.Value != d2target.ShapeImage { + if obj.Icon != nil && obj.Shape.Value != d2target.ShapeImage { iconHeight = d2target.GetIconSize(s.GetInnerBox(), string(label.InsideTopLeft)) + label.PADDING*2 } @@ -283,7 +283,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err if obj.HasLabel() { n.Labels = append(n.Labels, &ELKLabel{ - Text: obj.Attributes.Label.Value, + Text: obj.Label.Value, Width: float64(obj.LabelDimensions.Width), Height: float64(obj.LabelDimensions.Height), }) @@ -303,9 +303,9 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err Sources: []string{edge.Src.AbsID()}, Targets: []string{edge.Dst.AbsID()}, } - if edge.Attributes.Label.Value != "" { + if edge.Label.Value != "" { e.Labels = append(e.Labels, &ELKLabel{ - Text: edge.Attributes.Label.Value, + Text: edge.Label.Value, Width: float64(edge.LabelDimensions.Width), Height: float64(edge.LabelDimensions.Height), LayoutOptions: &elkOpts{ @@ -397,13 +397,13 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err } else if obj.HasOutsideBottomLabel() { obj.LabelPosition = go2.Pointer(string(label.OutsideBottomCenter)) obj.Height -= float64(obj.LabelDimensions.Height) + label.PADDING - } else if obj.Attributes.Icon != nil { + } else if obj.Icon != nil { obj.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) } else { obj.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) } } - if obj.Attributes.Icon != nil { + if obj.Icon != nil { if len(obj.ChildrenArray) > 0 { obj.IconPosition = go2.Pointer(string(label.InsideTopLeft)) obj.LabelPosition = go2.Pointer(string(label.InsideTopRight)) @@ -444,14 +444,14 @@ func Layout(ctx context.Context, g *d2graph.Graph, opts *ConfigurableOpts) (err } startIndex, endIndex := 0, len(points)-1 - srcShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Src.Attributes.Shape.Value)], edge.Src.Box) - dstShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Dst.Attributes.Shape.Value)], edge.Dst.Box) + srcShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Src.Shape.Value)], edge.Src.Box) + dstShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(edge.Dst.Shape.Value)], edge.Dst.Box) // trace the edge to the specific shape's border points[startIndex] = shape.TraceToShapeBorder(srcShape, points[startIndex], points[startIndex+1]) points[endIndex] = shape.TraceToShapeBorder(dstShape, points[endIndex], points[endIndex-1]) - if edge.Attributes.Label.Value != "" { + if edge.Label.Value != "" { edge.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) } @@ -519,7 +519,7 @@ func deleteBends(g *d2graph.Graph) { newStart = geo.NewPoint(end.X, start.Y) } - endpointShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(endpoint.Attributes.Shape.Value)], endpoint.Box) + endpointShape := shape.NewShape(d2target.DSL_SHAPE_TO_SHAPE_TYPE[strings.ToLower(endpoint.Shape.Value)], endpoint.Box) newStart = shape.TraceToShapeBorder(endpointShape, newStart, end) // Check that the new segment doesn't collide with anything new diff --git a/d2layouts/d2grid/grid_diagram.go b/d2layouts/d2grid/grid_diagram.go index 5e404db73..c8b0c28a3 100644 --- a/d2layouts/d2grid/grid_diagram.go +++ b/d2layouts/d2grid/grid_diagram.go @@ -32,11 +32,11 @@ func newGridDiagram(root *d2graph.Object) *gridDiagram { horizontalGap: DEFAULT_GAP, } - if root.Attributes.GridRows != nil { - gd.rows, _ = strconv.Atoi(root.Attributes.GridRows.Value) + if root.GridRows != nil { + gd.rows, _ = strconv.Atoi(root.GridRows.Value) } - if root.Attributes.GridColumns != nil { - gd.columns, _ = strconv.Atoi(root.Attributes.GridColumns.Value) + if root.GridColumns != nil { + gd.columns, _ = strconv.Atoi(root.GridColumns.Value) } if gd.rows != 0 && gd.columns != 0 { @@ -47,7 +47,7 @@ func newGridDiagram(root *d2graph.Object) *gridDiagram { // . │ g h i │ │ c f i │ // . └───────┘ └───────┘ // if keyword rows is first, make it row-directed, if columns is first it is column-directed - if root.Attributes.GridRows.MapKey.Range.Before(root.Attributes.GridColumns.MapKey.Range) { + if root.GridRows.MapKey.Range.Before(root.GridColumns.MapKey.Range) { gd.rowDirected = true } @@ -84,15 +84,15 @@ func newGridDiagram(root *d2graph.Object) *gridDiagram { } // grid gap sets both, but can be overridden - if root.Attributes.GridGap != nil { - gd.verticalGap, _ = strconv.Atoi(root.Attributes.GridGap.Value) + if root.GridGap != nil { + gd.verticalGap, _ = strconv.Atoi(root.GridGap.Value) gd.horizontalGap = gd.verticalGap } - if root.Attributes.VerticalGap != nil { - gd.verticalGap, _ = strconv.Atoi(root.Attributes.VerticalGap.Value) + if root.VerticalGap != nil { + gd.verticalGap, _ = strconv.Atoi(root.VerticalGap.Value) } - if root.Attributes.HorizontalGap != nil { - gd.horizontalGap, _ = strconv.Atoi(root.Attributes.HorizontalGap.Value) + if root.HorizontalGap != nil { + gd.horizontalGap, _ = strconv.Atoi(root.HorizontalGap.Value) } return &gd diff --git a/d2layouts/d2grid/layout.go b/d2layouts/d2grid/layout.go index 6650bd2c7..7d0834edd 100644 --- a/d2layouts/d2grid/layout.go +++ b/d2layouts/d2grid/layout.go @@ -123,7 +123,7 @@ func layoutGrid(g *d2graph.Graph, obj *d2graph.Object) (*gridDiagram, error) { // position labels and icons for _, o := range gd.objects { - if o.Attributes.Icon != nil { + if o.Icon != nil { o.LabelPosition = go2.Pointer(string(label.InsideTopCenter)) o.IconPosition = go2.Pointer(string(label.InsideMiddleCenter)) } else { diff --git a/d2layouts/d2near/layout.go b/d2layouts/d2near/layout.go index e8c577522..342f75eac 100644 --- a/d2layouts/d2near/layout.go +++ b/d2layouts/d2near/layout.go @@ -33,7 +33,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, constantNearGraphs []*d2graph for _, processCenters := range []bool{true, false} { for _, tempGraph := range constantNearGraphs { obj := tempGraph.Root.ChildrenArray[0] - if processCenters == strings.Contains(d2graph.Key(obj.Attributes.NearKey)[0], "-center") { + if processCenters == strings.Contains(d2graph.Key(obj.NearKey)[0], "-center") { prevX, prevY := obj.TopLeft.X, obj.TopLeft.Y obj.TopLeft = geo.NewPoint(place(obj)) dx, dy := obj.TopLeft.X-prevX, obj.TopLeft.Y-prevY @@ -56,7 +56,7 @@ func Layout(ctx context.Context, g *d2graph.Graph, constantNearGraphs []*d2graph } for _, tempGraph := range constantNearGraphs { obj := tempGraph.Root.ChildrenArray[0] - if processCenters == strings.Contains(d2graph.Key(obj.Attributes.NearKey)[0], "-center") { + if processCenters == strings.Contains(d2graph.Key(obj.NearKey)[0], "-center") { // The z-index for constant nears does not matter, as it will not collide g.Objects = append(g.Objects, tempGraph.Objects...) if obj.Parent.Children == nil { @@ -78,7 +78,7 @@ func place(obj *d2graph.Object) (float64, float64) { w := br.X - tl.X h := br.Y - tl.Y - nearKeyStr := d2graph.Key(obj.Attributes.NearKey)[0] + nearKeyStr := d2graph.Key(obj.NearKey)[0] var x, y float64 switch nearKeyStr { case "top-left": @@ -139,14 +139,14 @@ func place(obj *d2graph.Object) (float64, float64) { func WithoutConstantNears(ctx context.Context, g *d2graph.Graph) (constantNearGraphs []*d2graph.Graph) { for i := 0; i < len(g.Objects); i++ { obj := g.Objects[i] - if obj.Attributes.NearKey == nil { + if obj.NearKey == nil { continue } - _, isKey := g.Root.HasChild(d2graph.Key(obj.Attributes.NearKey)) + _, isKey := g.Root.HasChild(d2graph.Key(obj.NearKey)) if isKey { continue } - _, isConst := d2graph.NearConstants[d2graph.Key(obj.Attributes.NearKey)[0]] + _, isConst := d2graph.NearConstants[d2graph.Key(obj.NearKey)[0]] if isConst { descendantObjects, edges := pluckObjAndEdges(g, obj) @@ -217,10 +217,10 @@ func boundingBox(g *d2graph.Graph) (tl, br *geo.Point) { y2 := math.Inf(-1) for _, obj := range g.Objects { - if obj.Attributes.NearKey != nil { + if obj.NearKey != nil { // Top left should not be MORE top than top-center // But it should go more left if top-center label extends beyond bounds of diagram - switch d2graph.Key(obj.Attributes.NearKey)[0] { + switch d2graph.Key(obj.NearKey)[0] { case "top-center", "bottom-center": x1 = math.Min(x1, obj.TopLeft.X) x2 = math.Max(x2, obj.TopLeft.X+obj.Width) @@ -236,7 +236,7 @@ func boundingBox(g *d2graph.Graph) (tl, br *geo.Point) { y1 = math.Min(y1, obj.TopLeft.Y) x2 = math.Max(x2, obj.TopLeft.X+obj.Width) y2 = math.Max(y2, obj.TopLeft.Y+obj.Height) - if obj.Attributes.Label.Value != "" && obj.LabelPosition != nil { + if obj.Label.Value != "" && obj.LabelPosition != nil { labelPosition := label.Position(*obj.LabelPosition) if labelPosition.IsOutside() { labelTL := labelPosition.GetPointOnBox(obj.Box, label.PADDING, float64(obj.LabelDimensions.Width), float64(obj.LabelDimensions.Height)) diff --git a/d2layouts/d2sequence/layout.go b/d2layouts/d2sequence/layout.go index 0da870f19..24427914b 100644 --- a/d2layouts/d2sequence/layout.go +++ b/d2layouts/d2sequence/layout.go @@ -54,7 +54,7 @@ func WithoutSequenceDiagrams(ctx context.Context, g *d2graph.Graph) (map[string] if len(obj.ChildrenArray) == 0 { continue } - if obj.Attributes.Shape.Value != d2target.ShapeSequenceDiagram { + if obj.Shape.Value != d2target.ShapeSequenceDiagram { queue = append(queue, obj.ChildrenArray...) continue } diff --git a/d2layouts/d2sequence/layout_test.go b/d2layouts/d2sequence/layout_test.go index 8be43712d..6fe39ce9e 100644 --- a/d2layouts/d2sequence/layout_test.go +++ b/d2layouts/d2sequence/layout_test.go @@ -180,7 +180,7 @@ b -> a.t2` g, err := d2compiler.Compile("", strings.NewReader(input), nil) assert.Nil(t, err) - g.Root.Attributes.Shape = d2graph.Scalar{Value: d2target.ShapeSequenceDiagram} + g.Root.Shape = d2graph.Scalar{Value: d2target.ShapeSequenceDiagram} a, has := g.Root.HasChild([]string{"a"}) assert.True(t, has) @@ -217,14 +217,14 @@ b -> a.t2` }) // check properties - assert.Equal(t, strings.ToLower(shape.PERSON_TYPE), strings.ToLower(a.Attributes.Shape.Value)) + assert.Equal(t, strings.ToLower(shape.PERSON_TYPE), strings.ToLower(a.Shape.Value)) - if a_t1.Attributes.Label.Value != "" { - t.Fatalf("expected no label for span, got %s", a_t1.Attributes.Label.Value) + if a_t1.Label.Value != "" { + t.Fatalf("expected no label for span, got %s", a_t1.Label.Value) } - if a_t1.Attributes.Shape.Value != shape.SQUARE_TYPE { - t.Fatalf("expected square shape for span, got %s", a_t1.Attributes.Shape.Value) + if a_t1.Shape.Value != shape.SQUARE_TYPE { + t.Fatalf("expected square shape for span, got %s", a_t1.Shape.Value) } if a_t1.Height != b_t1.Height { @@ -323,7 +323,7 @@ container -> c: edge 1 c := g.Root.EnsureChild([]string{"c"}) c.Box = geo.NewBox(nil, 100, 100) - c.Attributes.Shape = d2graph.Scalar{Value: d2target.ShapeSquare} + c.Shape = d2graph.Scalar{Value: d2target.ShapeSquare} layoutFn := func(ctx context.Context, g *d2graph.Graph) error { if len(g.Objects) != 2 { @@ -378,7 +378,7 @@ container -> c: edge 1 func TestSelfEdges(t *testing.T) { g := d2graph.NewGraph() - g.Root.Attributes.Shape = d2graph.Scalar{Value: d2target.ShapeSequenceDiagram} + g.Root.Shape = d2graph.Scalar{Value: d2target.ShapeSequenceDiagram} n1 := g.Root.EnsureChild([]string{"n1"}) n1.Box = geo.NewBox(nil, 100, 100) @@ -387,7 +387,7 @@ func TestSelfEdges(t *testing.T) { Src: n1, Dst: n1, Index: 0, - Attributes: &d2graph.Attributes{ + Attributes: d2graph.Attributes{ Label: d2graph.Scalar{Value: "left to right"}, }, }, @@ -414,10 +414,10 @@ func TestSelfEdges(t *testing.T) { func TestSequenceToDescendant(t *testing.T) { g := d2graph.NewGraph() - g.Root.Attributes.Shape = d2graph.Scalar{Value: d2target.ShapeSequenceDiagram} + g.Root.Shape = d2graph.Scalar{Value: d2target.ShapeSequenceDiagram} a := g.Root.EnsureChild([]string{"a"}) a.Box = geo.NewBox(nil, 100, 100) - a.Attributes = &d2graph.Attributes{ + a.Attributes = d2graph.Attributes{ Shape: d2graph.Scalar{Value: shape.PERSON_TYPE}, } a_t1 := a.EnsureChild([]string{"t1"}) @@ -425,15 +425,13 @@ func TestSequenceToDescendant(t *testing.T) { g.Edges = []*d2graph.Edge{ { - Src: a, - Dst: a_t1, - Index: 0, - Attributes: &d2graph.Attributes{}, + Src: a, + Dst: a_t1, + Index: 0, }, { - Src: a_t1, - Dst: a, - Index: 0, - Attributes: &d2graph.Attributes{}, + Src: a_t1, + Dst: a, + Index: 0, }, } diff --git a/d2layouts/d2sequence/sequence_diagram.go b/d2layouts/d2sequence/sequence_diagram.go index c5b736507..ac2e8d2e2 100644 --- a/d2layouts/d2sequence/sequence_diagram.go +++ b/d2layouts/d2sequence/sequence_diagram.go @@ -110,7 +110,7 @@ func newSequenceDiagram(objects []*d2graph.Object, messages []*d2graph.Edge) (*s sd.objectRank[actor] = rank if actor.Width < MIN_ACTOR_WIDTH { - dslShape := strings.ToLower(actor.Attributes.Shape.Value) + dslShape := strings.ToLower(actor.Shape.Value) switch dslShape { case d2target.ShapePerson, d2target.ShapeOval, d2target.ShapeSquare, d2target.ShapeCircle: // scale shape up to min width uniformly @@ -131,7 +131,7 @@ func newSequenceDiagram(objects []*d2graph.Object, messages []*d2graph.Edge) (*s // edge groups are children of actors with no edges and children edges if child.IsSequenceDiagramNote() { sd.verticalIndices[child.AbsID()] = getObjEarliestLineNum(child) - child.Attributes.Shape = d2graph.Scalar{Value: shape.PAGE_TYPE} + child.Shape = d2graph.Scalar{Value: shape.PAGE_TYPE} sd.notes = append(sd.notes, child) sd.objectRank[child] = rank child.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) @@ -139,8 +139,8 @@ func newSequenceDiagram(objects []*d2graph.Object, messages []*d2graph.Edge) (*s } else { // spans have no labels // TODO why not? Spans should be able to - child.Attributes.Label = d2graph.Scalar{Value: ""} - child.Attributes.Shape = d2graph.Scalar{Value: shape.SQUARE_TYPE} + child.Label = d2graph.Scalar{Value: ""} + child.Shape = d2graph.Scalar{Value: shape.SQUARE_TYPE} sd.spans = append(sd.spans, child) sd.objectRank[child] = rank } @@ -390,15 +390,15 @@ func (sd *sequenceDiagram) addLifelineEdges() { StrokeDash: &d2graph.Scalar{Value: fmt.Sprintf("%d", LIFELINE_STROKE_DASH)}, StrokeWidth: &d2graph.Scalar{Value: fmt.Sprintf("%d", LIFELINE_STROKE_WIDTH)}, } - if actor.Attributes.Style.StrokeDash != nil { - style.StrokeDash = &d2graph.Scalar{Value: actor.Attributes.Style.StrokeDash.Value} + if actor.Style.StrokeDash != nil { + style.StrokeDash = &d2graph.Scalar{Value: actor.Style.StrokeDash.Value} } - if actor.Attributes.Style.Stroke != nil { - style.Stroke = &d2graph.Scalar{Value: actor.Attributes.Style.Stroke.Value} + if actor.Style.Stroke != nil { + style.Stroke = &d2graph.Scalar{Value: actor.Style.Stroke.Value} } sd.lifelines = append(sd.lifelines, &d2graph.Edge{ - Attributes: &d2graph.Attributes{Style: style}, + Attributes: d2graph.Attributes{Style: style}, Src: actor, SrcArrow: false, Dst: &d2graph.Object{ @@ -581,7 +581,7 @@ func (sd *sequenceDiagram) routeMessages() error { } messageOffset += sd.yStep - if message.Attributes.Label.Value != "" { + if message.Label.Value != "" { message.LabelPosition = go2.Pointer(string(label.InsideMiddleCenter)) } } diff --git a/d2oracle/edit.go b/d2oracle/edit.go index 2e3408114..f5bc34f70 100644 --- a/d2oracle/edit.go +++ b/d2oracle/edit.go @@ -159,12 +159,12 @@ func _set(g *d2graph.Graph, key string, tag, value *string) error { } } - if obj.Attributes.Label.MapKey != nil && obj.Map == nil && (!found || reserved || len(mk.Edges) > 0) { + if obj.Label.MapKey != nil && obj.Map == nil && (!found || reserved || len(mk.Edges) > 0) { obj.Map = &d2ast.Map{ Range: d2ast.MakeRange(",1:0:0-1:0:0"), } - obj.Attributes.Label.MapKey.Primary = obj.Attributes.Label.MapKey.Value.ScalarBox() - obj.Attributes.Label.MapKey.Value = d2ast.MakeValueBox(obj.Map) + obj.Label.MapKey.Primary = obj.Label.MapKey.Value.ScalarBox() + obj.Label.MapKey.Value = d2ast.MakeValueBox(obj.Map) scope = obj.Map mk.Key.Path = mk.Key.Path[toSkip-1:] @@ -247,10 +247,10 @@ func _set(g *d2graph.Graph, key string, tag, value *string) error { if n.MapKey.Key.Path[0].Unbox().ScalarString() == mk.Key.Path[toSkip-1].Unbox().ScalarString() { scope = n.MapKey.Value.Map if mk.Key.Path[0].Unbox().ScalarString() == "source-arrowhead" && edge.SrcArrowhead != nil { - attrs = edge.SrcArrowhead + attrs = *edge.SrcArrowhead } if mk.Key.Path[0].Unbox().ScalarString() == "target-arrowhead" && edge.DstArrowhead != nil { - attrs = edge.DstArrowhead + attrs = *edge.DstArrowhead } reservedKey = mk.Key.Path[0].Unbox().ScalarString() mk.Key.Path = mk.Key.Path[1:] @@ -295,13 +295,13 @@ func _set(g *d2graph.Graph, key string, tag, value *string) error { return nil } case "width": - if attrs.Width != nil && attrs.Width.MapKey != nil { - attrs.Width.MapKey.SetScalar(mk.Value.ScalarBox()) + if attrs.WidthAttr != nil && attrs.WidthAttr.MapKey != nil { + attrs.WidthAttr.MapKey.SetScalar(mk.Value.ScalarBox()) return nil } case "height": - if attrs.Height != nil && attrs.Height.MapKey != nil { - attrs.Height.MapKey.SetScalar(mk.Value.ScalarBox()) + if attrs.HeightAttr != nil && attrs.HeightAttr.MapKey != nil { + attrs.HeightAttr.MapKey.SetScalar(mk.Value.ScalarBox()) return nil } case "top": @@ -340,12 +340,13 @@ func _set(g *d2graph.Graph, key string, tag, value *string) error { return nil } case "source-arrowhead", "target-arrowhead": + var arrowhead *d2graph.Attributes if reservedKey == "source-arrowhead" { - attrs = edge.SrcArrowhead + arrowhead = edge.SrcArrowhead } else { - attrs = edge.DstArrowhead + arrowhead = edge.DstArrowhead } - if attrs != nil { + if arrowhead != nil { if reservedTargetKey == "" { if len(mk.Key.Path[reservedIndex:]) != 2 { return errors.New("malformed style setting, expected 2 part path") @@ -354,13 +355,13 @@ func _set(g *d2graph.Graph, key string, tag, value *string) error { } switch reservedTargetKey { case "shape": - if attrs.Shape.MapKey != nil { - attrs.Shape.MapKey.SetScalar(mk.Value.ScalarBox()) + if arrowhead.Shape.MapKey != nil { + arrowhead.Shape.MapKey.SetScalar(mk.Value.ScalarBox()) return nil } case "label": - if attrs.Label.MapKey != nil { - attrs.Label.MapKey.SetScalar(mk.Value.ScalarBox()) + if arrowhead.Label.MapKey != nil { + arrowhead.Label.MapKey.SetScalar(mk.Value.ScalarBox()) return nil } } @@ -664,7 +665,7 @@ func renameConflictsToParent(g *d2graph.Graph, key *d2ast.KeyPath) (*d2graph.Gra if !ok { return g, nil } - if obj.Attributes.Shape.Value == d2target.ShapeSQLTable || obj.Attributes.Shape.Value == d2target.ShapeClass { + if obj.Shape.Value == d2target.ShapeSQLTable || obj.Shape.Value == d2target.ShapeClass { return g, nil } @@ -961,7 +962,7 @@ func deleteObject(g *d2graph.Graph, key *d2ast.KeyPath, obj *d2graph.Object) (*d isSpecial := isReserved || x.Unbox().ScalarString() == "_" return !isSpecial }) - if obj.Attributes.Shape.Value == d2target.ShapeSQLTable || obj.Attributes.Shape.Value == d2target.ShapeClass { + if obj.Shape.Value == d2target.ShapeSQLTable || obj.Shape.Value == d2target.ShapeClass { deleteFromMap(ref.Scope, ref.MapKey) } else if len(withoutSpecial) == 0 { hoistRefChildren(g, key, ref) @@ -990,7 +991,7 @@ func deleteObject(g *d2graph.Graph, key *d2ast.KeyPath, obj *d2graph.Object) (*d } else if ref.InEdge() { edge := ref.MapKey.Edges[ref.MapKeyEdgeIndex] - if obj.Attributes.Shape.Value == d2target.ShapeSQLTable || obj.Attributes.Shape.Value == d2target.ShapeClass { + if obj.Shape.Value == d2target.ShapeSQLTable || obj.Shape.Value == d2target.ShapeClass { if ref.MapKeyEdgeDest() { ensureNode(g, refEdges, ref.ScopeObj, ref.Scope, ref.MapKey, edge.Src, true) } else { diff --git a/d2oracle/edit_test.go b/d2oracle/edit_test.go index 736fbcf69..9ee197769 100644 --- a/d2oracle/edit_test.go +++ b/d2oracle/edit_test.go @@ -50,11 +50,11 @@ func TestCreate(t *testing.T) { if g.Objects[0].ID != "square" { t.Fatalf("expected g.Objects[0].ID to be square: %#v", g.Objects[0]) } - if g.Objects[0].Attributes.Label.MapKey.Value.Unbox() != nil { - t.Fatalf("expected g.Objects[0].Attributes.Label.Node.Value.Unbox() == nil: %#v", g.Objects[0].Attributes.Label.MapKey.Value) + if g.Objects[0].Label.MapKey.Value.Unbox() != nil { + t.Fatalf("expected g.Objects[0].Label.Node.Value.Unbox() == nil: %#v", g.Objects[0].Label.MapKey.Value) } - if d2format.Format(g.Objects[0].Attributes.Label.MapKey.Key) != "square" { - t.Fatalf("expected g.Objects[0].Attributes.Label.Node.Key to be square: %#v", g.Objects[0].Attributes.Label.MapKey.Key) + if d2format.Format(g.Objects[0].Label.MapKey.Key) != "square" { + t.Fatalf("expected g.Objects[0].Label.Node.Key to be square: %#v", g.Objects[0].Label.MapKey.Key) } }, }, @@ -92,11 +92,11 @@ x 2 if g.Objects[2].AbsID() != "b.c.square" { t.Fatalf("bad absolute ID: %#v", g.Objects[2].AbsID()) } - if d2format.Format(g.Objects[2].Attributes.Label.MapKey.Key) != "b.c.square" { - t.Fatalf("bad mapkey: %#v", g.Objects[2].Attributes.Label.MapKey.Key) + if d2format.Format(g.Objects[2].Label.MapKey.Key) != "b.c.square" { + t.Fatalf("bad mapkey: %#v", g.Objects[2].Label.MapKey.Key) } - if g.Objects[2].Attributes.Label.MapKey.Value.Unbox() != nil { - t.Fatalf("expected nil mapkey value: %#v", g.Objects[2].Attributes.Label.MapKey.Value) + if g.Objects[2].Label.MapKey.Value.Unbox() != nil { + t.Fatalf("expected nil mapkey value: %#v", g.Objects[2].Label.MapKey.Value) } }, }, @@ -116,11 +116,11 @@ square 2 if g.Objects[1].ID != "square 2" { t.Fatalf("expected g.Objects[1].ID to be square 2: %#v", g.Objects[1]) } - if g.Objects[1].Attributes.Label.MapKey.Value.Unbox() != nil { - t.Fatalf("expected g.Objects[1].Attributes.Label.Node.Value.Unbox() == nil: %#v", g.Objects[1].Attributes.Label.MapKey.Value) + if g.Objects[1].Label.MapKey.Value.Unbox() != nil { + t.Fatalf("expected g.Objects[1].Label.Node.Value.Unbox() == nil: %#v", g.Objects[1].Label.MapKey.Value) } - if d2format.Format(g.Objects[1].Attributes.Label.MapKey.Key) != "square 2" { - t.Fatalf("expected g.Objects[1].Attributes.Label.Node.Key to be square 2: %#v", g.Objects[1].Attributes.Label.MapKey.Key) + if d2format.Format(g.Objects[1].Label.MapKey.Key) != "square 2" { + t.Fatalf("expected g.Objects[1].Label.Node.Key to be square 2: %#v", g.Objects[1].Label.MapKey.Key) } }, }, @@ -160,11 +160,11 @@ x.y.z.square 2 if g.Objects[3].ID != "square" { t.Fatalf("expected g.Objects[3].ID to be square: %#v", g.Objects[3]) } - if g.Objects[3].Attributes.Label.MapKey.Value.Unbox() != nil { - t.Fatalf("expected g.Objects[3].Attributes.Label.Node.Value.Unbox() == nil: %#v", g.Objects[3].Attributes.Label.MapKey.Value) + if g.Objects[3].Label.MapKey.Value.Unbox() != nil { + t.Fatalf("expected g.Objects[3].Label.Node.Value.Unbox() == nil: %#v", g.Objects[3].Label.MapKey.Value) } - if d2format.Format(g.Objects[3].Attributes.Label.MapKey.Key) != "square" { - t.Fatalf("expected g.Objects[3].Attributes.Label.Node.Key to be square: %#v", g.Objects[3].Attributes.Label.MapKey.Key) + if d2format.Format(g.Objects[3].Label.MapKey.Key) != "square" { + t.Fatalf("expected g.Objects[3].Label.Node.Key to be square: %#v", g.Objects[3].Label.MapKey.Key) } }, }, @@ -188,11 +188,11 @@ x.y.z.square 2 if g.Objects[4].ID != "square 2" { t.Fatalf("expected g.Objects[4].ID to be square 2: %#v", g.Objects[4]) } - if g.Objects[4].Attributes.Label.MapKey.Value.Unbox() != nil { - t.Fatalf("expected g.Objects[4].Attributes.Label.Node.Value.Unbox() == nil: %#v", g.Objects[4].Attributes.Label.MapKey.Value) + if g.Objects[4].Label.MapKey.Value.Unbox() != nil { + t.Fatalf("expected g.Objects[4].Label.Node.Value.Unbox() == nil: %#v", g.Objects[4].Label.MapKey.Value) } - if d2format.Format(g.Objects[4].Attributes.Label.MapKey.Key) != "square 2" { - t.Fatalf("expected g.Objects[4].Attributes.Label.Node.Key to be square 2: %#v", g.Objects[4].Attributes.Label.MapKey.Key) + if d2format.Format(g.Objects[4].Label.MapKey.Key) != "square 2" { + t.Fatalf("expected g.Objects[4].Label.Node.Key to be square 2: %#v", g.Objects[4].Label.MapKey.Key) } }, }, @@ -234,8 +234,8 @@ x.y.z.square 2 if g.Objects[13].ID != "square 11" { t.Fatalf("expected g.Objects[13].ID to be square 11: %#v", g.Objects[13]) } - if d2format.Format(g.Objects[13].Attributes.Label.MapKey.Key) != "square 11" { - t.Fatalf("expected g.Objects[13].Attributes.Label.Node.Key to be square 11: %#v", g.Objects[13].Attributes.Label.MapKey.Key) + if d2format.Format(g.Objects[13].Label.MapKey.Key) != "square 11" { + t.Fatalf("expected g.Objects[13].Label.Node.Key to be square 11: %#v", g.Objects[13].Label.MapKey.Key) } }, }, @@ -517,11 +517,11 @@ func TestSet(t *testing.T) { if g.Objects[0].ID != "square" { t.Fatalf("expected g.Objects[0].ID to be square: %#v", g.Objects[0]) } - if g.Objects[0].Attributes.Label.MapKey.Value.Unbox() != nil { - t.Fatalf("expected g.Objects[0].Attributes.Label.Node.Value.Unbox() == nil: %#v", g.Objects[0].Attributes.Label.MapKey.Value) + if g.Objects[0].Label.MapKey.Value.Unbox() != nil { + t.Fatalf("expected g.Objects[0].Label.Node.Value.Unbox() == nil: %#v", g.Objects[0].Label.MapKey.Value) } - if d2format.Format(g.Objects[0].Attributes.Label.MapKey.Key) != "square" { - t.Fatalf("expected g.Objects[0].Attributes.Label.Node.Key to be square: %#v", g.Objects[0].Attributes.Label.MapKey.Key) + if d2format.Format(g.Objects[0].Label.MapKey.Key) != "square" { + t.Fatalf("expected g.Objects[0].Label.Node.Key to be square: %#v", g.Objects[0].Label.MapKey.Key) } }, }, @@ -546,8 +546,8 @@ func TestSet(t *testing.T) { if g.Edges[0].Dst.ID != "y" { t.Fatalf("expected g.Edges[0].Dst.ID == y: %#v", g.Edges[0].Dst.ID) } - if g.Edges[0].Attributes.Label.Value != "two" { - t.Fatalf("expected g.Edges[0].Attributes.Label.Value == two: %#v", g.Edges[0].Attributes.Label.Value) + if g.Edges[0].Label.Value != "two" { + t.Fatalf("expected g.Edges[0].Label.Value == two: %#v", g.Edges[0].Label.Value) } }, }, @@ -566,8 +566,8 @@ func TestSet(t *testing.T) { if g.Objects[0].ID != "square" { t.Fatalf("expected g.Objects[0].ID to be square: %#v", g.Objects[0]) } - if g.Objects[0].Attributes.Shape.Value != d2target.ShapeSquare { - t.Fatalf("expected g.Objects[0].Attributes.Shape.Value == square: %#v", g.Objects[0].Attributes.Shape.Value) + if g.Objects[0].Shape.Value != d2target.ShapeSquare { + t.Fatalf("expected g.Objects[0].Shape.Value == square: %#v", g.Objects[0].Shape.Value) } }, }, @@ -586,8 +586,8 @@ func TestSet(t *testing.T) { if g.Objects[0].ID != "square" { t.Fatalf("expected g.Objects[0].ID to be square: %#v", g.Objects[0]) } - if g.Objects[0].Attributes.Shape.Value != d2target.ShapeCircle { - t.Fatalf("expected g.Objects[0].Attributes.Shape.Value == circle: %#v", g.Objects[0].Attributes.Shape.Value) + if g.Objects[0].Shape.Value != d2target.ShapeCircle { + t.Fatalf("expected g.Objects[0].Shape.Value == circle: %#v", g.Objects[0].Shape.Value) } }, }, @@ -606,7 +606,7 @@ func TestSet(t *testing.T) { if len(g.Objects) != 1 { t.Fatalf("expected 1 object but got %#v", len(g.Objects)) } - f, err := strconv.ParseFloat(g.Objects[0].Attributes.Style.Opacity.Value, 64) + f, err := strconv.ParseFloat(g.Objects[0].Style.Opacity.Value, 64) if err != nil || f != 0.2 { t.Fatalf("expected g.Objects[0].Map.Nodes[0].MapKey.Value.Number.Value.Float64() == 0.2: %#v", f) } @@ -652,7 +652,7 @@ func TestSet(t *testing.T) { if len(g.AST.Nodes[0].MapKey.Value.Map.Nodes) != 1 { t.Fatalf("expected 1 node within square but got %v", len(g.AST.Nodes[0].MapKey.Value.Map.Nodes)) } - f, err := strconv.ParseFloat(g.Objects[0].Attributes.Style.Opacity.Value, 64) + f, err := strconv.ParseFloat(g.Objects[0].Style.Opacity.Value, 64) if err != nil || f != 0.2 { t.Fatal(err, f) } @@ -670,7 +670,7 @@ func TestSet(t *testing.T) { if len(g.AST.Nodes) != 1 { t.Fatal(g.AST) } - f, err := strconv.ParseFloat(g.Objects[0].Attributes.Style.Opacity.Value, 64) + f, err := strconv.ParseFloat(g.Objects[0].Style.Opacity.Value, 64) if err != nil || f != 0.2 { t.Fatal(err, f) } @@ -689,7 +689,7 @@ square.style.opacity: 0.2 if len(g.AST.Nodes) != 2 { t.Fatal(g.AST) } - f, err := strconv.ParseFloat(g.Objects[0].Attributes.Style.Opacity.Value, 64) + f, err := strconv.ParseFloat(g.Objects[0].Style.Opacity.Value, 64) if err != nil || f != 0.2 { t.Fatal(err, f) } @@ -877,8 +877,8 @@ square.style.opacity: 0.2 if g.Objects[0].ID != "square" { t.Fatalf("expected g.Objects[0].ID to be square: %#v", g.Objects[0]) } - if g.Objects[0].Attributes.Shape.Value == d2target.ShapeSquare { - t.Fatalf("expected g.Objects[0].Attributes.Shape.Value == square: %#v", g.Objects[0].Attributes.Shape.Value) + if g.Objects[0].Shape.Value == d2target.ShapeSquare { + t.Fatalf("expected g.Objects[0].Shape.Value == square: %#v", g.Objects[0].Shape.Value) } }, }, @@ -897,8 +897,8 @@ square.style.opacity: 0.2 if g.Objects[0].ID != "square" { t.Fatalf("expected g.Objects[0].ID to be square: %#v", g.Objects[0]) } - if g.Objects[0].Attributes.Shape.Value == d2target.ShapeSquare { - t.Fatalf("expected g.Objects[0].Attributes.Shape.Value == square: %#v", g.Objects[0].Attributes.Shape.Value) + if g.Objects[0].Shape.Value == d2target.ShapeSquare { + t.Fatalf("expected g.Objects[0].Shape.Value == square: %#v", g.Objects[0].Shape.Value) } }, }, @@ -920,8 +920,8 @@ square.style.opacity: 0.2 if g.Objects[0].ID != "square" { t.Fatal(g.Objects[0]) } - if g.Objects[0].Attributes.Label.Value == "I am deeply CONCERNED and I want something GOOD for BREAKFAST!" { - t.Fatal(g.Objects[0].Attributes.Label.Value) + if g.Objects[0].Label.Value == "I am deeply CONCERNED and I want something GOOD for BREAKFAST!" { + t.Fatal(g.Objects[0].Label.Value) } }, }, @@ -1036,8 +1036,8 @@ z: { if len(g.Edges) != 2 { t.Fatalf("expected 2 edges: %#v", g.Edges) } - if g.Edges[0].Attributes.Label.Value != "two" { - t.Fatalf("expected g.Edges[0].Attributes.Label.Value == two: %#v", g.Edges[0].Attributes.Label.Value) + if g.Edges[0].Label.Value != "two" { + t.Fatalf("expected g.Edges[0].Label.Value == two: %#v", g.Edges[0].Label.Value) } }, }, @@ -1054,8 +1054,8 @@ z: { if len(g.Objects) != 1 { t.Fatal(g.Objects) } - if g.Objects[0].Attributes.Icon.String() != "https://icons.terrastruct.com/essentials/087-menu.svg" { - t.Fatal(g.Objects[0].Attributes.Icon.String()) + if g.Objects[0].Icon.String() != "https://icons.terrastruct.com/essentials/087-menu.svg" { + t.Fatal(g.Objects[0].Icon.String()) } }, }, @@ -1133,7 +1133,7 @@ z: { assert.JSON(t, 3, len(g.Objects)) assert.JSON(t, 1, len(g.Edges)) assert.JSON(t, "q", g.Edges[0].Src.ID) - assert.JSON(t, "0.4", g.Edges[0].Attributes.Style.Opacity.Value) + assert.JSON(t, "0.4", g.Edges[0].Style.Opacity.Value) }, }, { @@ -1309,8 +1309,8 @@ a.b -> a.c: {style.animated: true} if g.Edges[0].Src.ID != "q" { t.Fatal(g.Edges[0].Src.ID) } - if g.Edges[0].Attributes.Style.Opacity.Value != "0.4" { - t.Fatal(g.Edges[0].Attributes.Style.Opacity.Value) + if g.Edges[0].Style.Opacity.Value != "0.4" { + t.Fatal(g.Edges[0].Style.Opacity.Value) } }, }, diff --git a/d2plugin/plugin_features.go b/d2plugin/plugin_features.go index 76e1825b4..5f241de48 100644 --- a/d2plugin/plugin_features.go +++ b/d2plugin/plugin_features.go @@ -33,19 +33,19 @@ func FeatureSupportCheck(info *PluginInfo, g *d2graph.Graph) error { } for _, obj := range g.Objects { - if obj.Attributes.Top != nil || obj.Attributes.Left != nil { + if obj.Top != nil || obj.Left != nil { if _, ok := featureMap[TOP_LEFT]; !ok { return fmt.Errorf(`Object "%s" has attribute "top" and/or "left" set, but layout engine "%s" does not support locked positions.`, obj.AbsID(), info.Name) } } - if (obj.Attributes.Width != nil || obj.Attributes.Height != nil) && len(obj.ChildrenArray) > 0 { + if (obj.WidthAttr != nil || obj.HeightAttr != nil) && len(obj.ChildrenArray) > 0 { if _, ok := featureMap[CONTAINER_DIMENSIONS]; !ok { return fmt.Errorf(`Object "%s" has attribute "width" and/or "height" set, but layout engine "%s" does not support dimensions set on containers.`, obj.AbsID(), info.Name) } } - if obj.Attributes.NearKey != nil { - _, isKey := g.Root.HasChild(d2graph.Key(obj.Attributes.NearKey)) + if obj.NearKey != nil { + _, isKey := g.Root.HasChild(d2graph.Key(obj.NearKey)) if isKey { if _, ok := featureMap[NEAR_OBJECT]; !ok { return fmt.Errorf(`Object "%s" has "near" set to another object, but layout engine "%s" only supports constant values for "near".`, obj.AbsID(), info.Name)