From 8bbdac7c18f64f00e48b5c7d00bd7bc81f1d1da8 Mon Sep 17 00:00:00 2001 From: melsonic Date: Wed, 16 Apr 2025 00:22:55 +0530 Subject: [PATCH] feat: validate gradient color stops --- d2renderers/d2svg/d2svg.go | 33 ++++++++++++++++++++++++--------- lib/color/gradient.go | 21 ++++++++++++++------- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/d2renderers/d2svg/d2svg.go b/d2renderers/d2svg/d2svg.go index 089eaae4b..07faa9464 100644 --- a/d2renderers/d2svg/d2svg.go +++ b/d2renderers/d2svg/d2svg.go @@ -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(`%s`, 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 + } } } diff --git a/lib/color/gradient.go b/lib/color/gradient.go index 29f29acc3..5abda25e5 100644 --- a/lib/color/gradient.go +++ b/lib/color/gradient.go @@ -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 {