feat: ability to add border-radius to d2 icons
This commit is contained in:
parent
32c14d586c
commit
9603f1ae3b
6 changed files with 67 additions and 14 deletions
|
|
@ -383,7 +383,9 @@ func (c *compiler) compileField(obj *d2graph.Object, f *d2ir.Field) {
|
|||
|
||||
} else if isReserved {
|
||||
c.compileReserved(&obj.Attributes, f)
|
||||
return
|
||||
if keyword != "icon" {
|
||||
return
|
||||
}
|
||||
} else if f.Name.ScalarString() == "style" && f.Name.IsUnquoted() {
|
||||
if f.Map() == nil || len(f.Map().Fields) == 0 {
|
||||
c.errorf(f.LastRef().AST(), `"style" expected to be set to a map of key-values, or contain an additional keyword like "style.opacity: 0.4"`)
|
||||
|
|
@ -473,7 +475,10 @@ func (c *compiler) compileLabel(attrs *d2graph.Attributes, f d2ir.Node) {
|
|||
}
|
||||
attrs.Label.Value = scalar.ScalarString()
|
||||
default:
|
||||
attrs.Label.Value = scalar.ScalarString()
|
||||
name := f.LastPrimaryKey().Key.Path[0].UnquotedString.Value[0].String
|
||||
if *name != "icon" {
|
||||
attrs.Label.Value = scalar.ScalarString()
|
||||
}
|
||||
}
|
||||
attrs.Label.MapKey = f.LastPrimaryKey()
|
||||
}
|
||||
|
|
@ -757,7 +762,15 @@ func (c *compiler) compileStyleField(attrs *d2graph.Attributes, f *d2ir.Field) {
|
|||
}
|
||||
compileStyleFieldInit(attrs, f)
|
||||
scalar := f.Primary().Value
|
||||
err := attrs.Style.Apply(f.Name.ScalarString(), scalar.ScalarString())
|
||||
|
||||
parentKeyword := f.LastPrimaryKey().Key.Path[0].ScalarString()
|
||||
|
||||
var err error
|
||||
if parentKeyword == "icon" {
|
||||
err = attrs.IconStyle.Apply(f.Name.ScalarString(), scalar.ScalarString())
|
||||
} else {
|
||||
err = attrs.Style.Apply(f.Name.ScalarString(), scalar.ScalarString())
|
||||
}
|
||||
if err != nil {
|
||||
c.errorf(scalar, err.Error())
|
||||
return
|
||||
|
|
@ -779,7 +792,12 @@ func compileStyleFieldInit(attrs *d2graph.Attributes, f *d2ir.Field) {
|
|||
case "stroke-dash":
|
||||
attrs.Style.StrokeDash = &d2graph.Scalar{MapKey: f.LastPrimaryKey()}
|
||||
case "border-radius":
|
||||
attrs.Style.BorderRadius = &d2graph.Scalar{MapKey: f.LastPrimaryKey()}
|
||||
if attrs.Style.BorderRadius == nil {
|
||||
attrs.Style.BorderRadius = &d2graph.Scalar{MapKey: f.LastPrimaryKey()}
|
||||
}
|
||||
if attrs.IconStyle.BorderRadius == nil {
|
||||
attrs.IconStyle.BorderRadius = &d2graph.Scalar{MapKey: f.LastPrimaryKey()}
|
||||
}
|
||||
case "shadow":
|
||||
attrs.Style.Shadow = &d2graph.Scalar{MapKey: f.LastPrimaryKey()}
|
||||
case "3d":
|
||||
|
|
|
|||
|
|
@ -194,6 +194,9 @@ func applyStyles(shape *d2target.Shape, obj *d2graph.Object) {
|
|||
if obj.Style.DoubleBorder != nil {
|
||||
shape.DoubleBorder, _ = strconv.ParseBool(obj.Style.DoubleBorder.Value)
|
||||
}
|
||||
if obj.IconStyle.BorderRadius != nil {
|
||||
shape.IconBorderRadius, _ = strconv.Atoi(obj.IconStyle.BorderRadius.Value)
|
||||
}
|
||||
}
|
||||
|
||||
func toShape(obj *d2graph.Object, g *d2graph.Graph) d2target.Shape {
|
||||
|
|
|
|||
|
|
@ -196,10 +196,11 @@ type Attributes struct {
|
|||
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"`
|
||||
Style Style `json:"style"`
|
||||
Icon *url.URL `json:"icon,omitempty"`
|
||||
IconStyle Style `json:"iconStyle"`
|
||||
Tooltip *Scalar `json:"tooltip,omitempty"`
|
||||
Link *Scalar `json:"link,omitempty"`
|
||||
|
||||
WidthAttr *Scalar `json:"width,omitempty"`
|
||||
HeightAttr *Scalar `json:"height,omitempty"`
|
||||
|
|
|
|||
|
|
@ -1163,6 +1163,7 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape
|
|||
}
|
||||
|
||||
case d2target.ShapeImage:
|
||||
fmt.Fprint(writer, clipPathForIconBorderRadius(diagramHash, targetShape))
|
||||
el := d2themes.NewThemableElement("image", inlineTheme)
|
||||
el.X = float64(targetShape.Pos.X)
|
||||
el.Y = float64(targetShape.Pos.Y)
|
||||
|
|
@ -1172,6 +1173,7 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape
|
|||
el.Fill = fill
|
||||
el.Stroke = stroke
|
||||
el.Style = style
|
||||
el.ClipPath = fmt.Sprintf("%v-%v-icon", diagramHash, targetShape.ID)
|
||||
fmt.Fprint(writer, el.Render())
|
||||
|
||||
// TODO should standardize "" to rectangle
|
||||
|
|
@ -1364,12 +1366,13 @@ func drawShape(writer, appendixWriter io.Writer, diagramHash string, targetShape
|
|||
|
||||
tl := iconPosition.GetPointOnBox(box, label.PADDING, float64(iconSize), float64(iconSize))
|
||||
|
||||
fmt.Fprintf(writer, `<image href="%s" x="%f" y="%f" width="%d" height="%d" />`,
|
||||
fmt.Fprintf(writer, `<image href="%s" x="%f" y="%f" width="%d" height="%d" clip-path="inset(0 round %dpx)" />`,
|
||||
html.EscapeString(targetShape.Icon.String()),
|
||||
tl.X,
|
||||
tl.Y,
|
||||
iconSize,
|
||||
iconSize,
|
||||
targetShape.IconBorderRadius,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,33 @@ func clipPathForBorderRadius(diagramHash string, shape d2target.Shape) string {
|
|||
return out + `fill="none" /> </clipPath>`
|
||||
}
|
||||
|
||||
func clipPathForIconBorderRadius(diagramHash string, shape d2target.Shape) string {
|
||||
box := geo.NewBox(
|
||||
geo.NewPoint(float64(shape.Pos.X), float64(shape.Pos.Y)),
|
||||
float64(shape.Width),
|
||||
float64(shape.Height),
|
||||
)
|
||||
topX, topY := box.TopLeft.X+box.Width, box.TopLeft.Y
|
||||
|
||||
out := fmt.Sprintf(`<clipPath id="%v-%v-icon">`, diagramHash, shape.ID)
|
||||
out += fmt.Sprintf(`<path d="M %f %f L %f %f S %f %f %f %f `, box.TopLeft.X, box.TopLeft.Y+float64(shape.IconBorderRadius), box.TopLeft.X, box.TopLeft.Y+float64(shape.IconBorderRadius), box.TopLeft.X, box.TopLeft.Y, box.TopLeft.X+float64(shape.IconBorderRadius), box.TopLeft.Y)
|
||||
out += fmt.Sprintf(`L %f %f L %f %f `, box.TopLeft.X+box.Width-float64(shape.IconBorderRadius), box.TopLeft.Y, topX-float64(shape.IconBorderRadius), topY)
|
||||
|
||||
out += fmt.Sprintf(`S %f %f %f %f `, topX, topY, topX, topY+float64(shape.IconBorderRadius))
|
||||
out += fmt.Sprintf(`L %f %f `, topX, topY+box.Height-float64(shape.IconBorderRadius))
|
||||
|
||||
if len(shape.Columns) != 0 {
|
||||
out += fmt.Sprintf(`L %f %f L %f %f`, topX, topY+box.Height, box.TopLeft.X, box.TopLeft.Y+box.Height)
|
||||
} else {
|
||||
out += fmt.Sprintf(`S %f % f %f %f `, topX, topY+box.Height, topX-float64(shape.IconBorderRadius), topY+box.Height)
|
||||
out += fmt.Sprintf(`L %f %f `, box.TopLeft.X+float64(shape.IconBorderRadius), box.TopLeft.Y+box.Height)
|
||||
out += fmt.Sprintf(`S %f %f %f %f`, box.TopLeft.X, box.TopLeft.Y+box.Height, box.TopLeft.X, box.TopLeft.Y+box.Height-float64(shape.IconBorderRadius))
|
||||
out += fmt.Sprintf(`L %f %f`, box.TopLeft.X, box.TopLeft.Y+float64(shape.IconBorderRadius))
|
||||
}
|
||||
out += fmt.Sprintf(`Z %f %f" `, box.TopLeft.X, box.TopLeft.Y)
|
||||
return out + `fill="none" /> </clipPath>`
|
||||
}
|
||||
|
||||
func tableHeader(diagramHash string, shape d2target.Shape, box *geo.Box, text string, textWidth, textHeight, fontSize float64, inlineTheme *d2themes.Theme) string {
|
||||
rectEl := d2themes.NewThemableElement("rect", inlineTheme)
|
||||
rectEl.X, rectEl.Y = box.TopLeft.X, box.TopLeft.Y
|
||||
|
|
|
|||
|
|
@ -493,11 +493,12 @@ type Shape struct {
|
|||
Multiple bool `json:"multiple"`
|
||||
DoubleBorder bool `json:"double-border"`
|
||||
|
||||
Tooltip string `json:"tooltip"`
|
||||
Link string `json:"link"`
|
||||
PrettyLink string `json:"prettyLink,omitempty"`
|
||||
Icon *url.URL `json:"icon"`
|
||||
IconPosition string `json:"iconPosition"`
|
||||
Tooltip string `json:"tooltip"`
|
||||
Link string `json:"link"`
|
||||
PrettyLink string `json:"prettyLink,omitempty"`
|
||||
Icon *url.URL `json:"icon"`
|
||||
IconBorderRadius int `json:"iconBorderRadius"`
|
||||
IconPosition string `json:"iconPosition"`
|
||||
|
||||
// Whether the shape should allow shapes behind it to bleed through
|
||||
// Currently just used for sequence diagram groups
|
||||
|
|
|
|||
Loading…
Reference in a new issue