feat: validate gradient color stops

This commit is contained in:
melsonic 2025-04-16 00:22:55 +05:30
parent 9fe52cf8b2
commit 8bbdac7c18
No known key found for this signature in database
GPG key ID: DFA426742F621CD7
2 changed files with 38 additions and 16 deletions

View file

@ -1069,9 +1069,10 @@ func renderDoubleOval(tl *geo.Point, width, height float64, fill, fillStroke, st
return renderOval(tl, width, height, fill, fillStroke, stroke, style, inlineTheme) + renderOval(innerTL, width-10, height-10, fill, "", stroke, style, inlineTheme)
}
func defineGradients(writer io.Writer, cssGradient string) {
gradient, _ := color.ParseGradient(cssGradient)
func defineGradients(writer io.Writer, cssGradient string) error {
gradient, err := color.ParseGradient(cssGradient)
fmt.Fprint(writer, fmt.Sprintf(`<defs>%s</defs>`, color.GradientToSVG(gradient)))
return err
}
func defineShadowFilter(writer io.Writer) {
@ -2278,28 +2279,42 @@ func Render(diagram *d2target.Diagram, opts *RenderOpts) ([]byte, error) {
}
if color.IsGradient(diagram.Root.Fill) {
defineGradients(buf, diagram.Root.Fill)
if err := defineGradients(buf, diagram.Root.Fill); err != nil {
return nil, err
}
}
if color.IsGradient(diagram.Root.Stroke) {
defineGradients(buf, diagram.Root.Stroke)
if err := defineGradients(buf, diagram.Root.Stroke); err != nil {
return nil, err
}
}
for _, s := range diagram.Shapes {
if color.IsGradient(s.Fill) {
defineGradients(buf, s.Fill)
if err := defineGradients(buf, s.Fill); err != nil {
return nil, err
}
}
if color.IsGradient(s.Stroke) {
defineGradients(buf, s.Stroke)
if err := defineGradients(buf, s.Stroke); err != nil {
return nil, err
}
}
if color.IsGradient(s.Color) {
defineGradients(buf, s.Color)
if err := defineGradients(buf, s.Color); err != nil {
return nil, err
}
}
}
for _, c := range diagram.Connections {
if color.IsGradient(c.Stroke) {
defineGradients(buf, c.Stroke)
if err := defineGradients(buf, c.Stroke); err != nil {
return nil, err
}
}
if color.IsGradient(c.Fill) {
defineGradients(buf, c.Fill)
if err := defineGradients(buf, c.Fill); err != nil {
return nil, err
}
}
}

View file

@ -9,6 +9,8 @@ import (
"regexp"
"strconv"
"strings"
"github.com/mazznoer/csscolorparser"
)
type Gradient struct {
@ -46,23 +48,26 @@ func ParseGradient(cssGradient string) (Gradient, error) {
}
firstParam := strings.TrimSpace(paramList[0])
var err error
if gradient.Type == "linear" && (strings.HasSuffix(firstParam, "deg") || strings.HasPrefix(firstParam, "to ")) {
gradient.Direction = firstParam
colorStops := paramList[1:]
if len(colorStops) == 0 {
return Gradient{}, errors.New("no color stops in gradient")
}
gradient.ColorStops = parseColorStops(colorStops)
gradient.ColorStops, err = parseColorStops(colorStops)
} else if gradient.Type == "radial" && (firstParam == "circle" || firstParam == "ellipse") {
gradient.Direction = firstParam
colorStops := paramList[1:]
if len(colorStops) == 0 {
return Gradient{}, errors.New("no color stops in gradient")
}
gradient.ColorStops = parseColorStops(colorStops)
gradient.ColorStops, err = parseColorStops(colorStops)
} else {
gradient.ColorStops = parseColorStops(paramList)
gradient.ColorStops, err = parseColorStops(paramList)
}
if err != nil {
return Gradient{}, err
}
gradient.ID = UniqueGradientID(cssGradient)
@ -97,12 +102,14 @@ func splitParams(params string) []string {
return parts
}
func parseColorStops(params []string) []ColorStop {
func parseColorStops(params []string) ([]ColorStop, error) {
var colorStops []ColorStop
for _, p := range params {
p = strings.TrimSpace(p)
parts := strings.Fields(p)
if _, err := csscolorparser.Parse(parts[0]); err != nil {
return nil, fmt.Errorf("%s is not a valid color format", parts[0])
}
switch len(parts) {
case 1:
colorStops = append(colorStops, ColorStop{Color: parts[0]})
@ -112,7 +119,7 @@ func parseColorStops(params []string) []ColorStop {
continue
}
}
return colorStops
return colorStops, nil
}
func GradientToSVG(gradient Gradient) string {