Monorepo for Tangled
Something went wrong. Try again.
Go
at sl/rbac2test
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196package main
import ( "bytes" _ "embed" "flag" "fmt" "image" "image/color" "image/png" "os" "path/filepath" "strconv" "strings" "text/template"
"github.com/srwiley/oksvg" "github.com/srwiley/rasterx" "golang.org/x/image/draw" "tangled.org/core/ico")
func main() { var ( size string fillColor string output string templatePath string )
flag.StringVar(&templatePath, "template", "", "Path to dolly go-html template") flag.StringVar(&size, "size", "512x512", "Output size in format WIDTHxHEIGHT (e.g., 512x512)") flag.StringVar(&fillColor, "color", "#000000", "Fill color in hex format (e.g., #FF5733)") flag.StringVar(&output, "output", "dolly.svg", "Output file path (format detected from extension: .svg, .png, or .ico)") flag.Parse()
if templatePath == "" { fmt.Fprintf(os.Stderr, "Empty template path") os.Exit(1) }
width, height, err := parseSize(size) if err != nil { fmt.Fprintf(os.Stderr, "Error parsing size: %v\n", err) os.Exit(1) }
// Detect format from file extension ext := strings.ToLower(filepath.Ext(output)) format := strings.TrimPrefix(ext, ".")
if format != "svg" && format != "png" && format != "ico" { fmt.Fprintf(os.Stderr, "Invalid file extension: %s. Must be .svg, .png, or .ico\n", ext) os.Exit(1) }
if fillColor != "currentColor" && !isValidHexColor(fillColor) { fmt.Fprintf(os.Stderr, "Invalid color format: %s. Use hex format like #FF5733\n", fillColor) os.Exit(1) }
tpl, err := os.ReadFile(templatePath) if err != nil { fmt.Fprintf(os.Stderr, "Failed to read template from path %s: %v\n", templatePath, err) os.Exit(1) }
svgData, err := dolly(string(tpl), fillColor) if err != nil { fmt.Fprintf(os.Stderr, "Error generating SVG: %v\n", err) os.Exit(1) }
// Create output directory if it doesn't exist dir := filepath.Dir(output) if dir != "" && dir != "." { if err := os.MkdirAll(dir, 0755); err != nil { fmt.Fprintf(os.Stderr, "Error creating output directory: %v\n", err) os.Exit(1) } }
switch format { case "svg": err = saveSVG(svgData, output, width, height) case "png": err = savePNG(svgData, output, width, height) case "ico": err = saveICO(svgData, output, width, height) }
if err != nil { fmt.Fprintf(os.Stderr, "Error saving file: %v\n", err) os.Exit(1) }
fmt.Printf("Successfully generated %s (%dx%d)\n", output, width, height)}
func dolly(tplString, hexColor string) ([]byte, error) { tpl, err := template.New("dolly").Parse(tplString) if err != nil { return nil, err }
var svgData bytes.Buffer if err := tpl.ExecuteTemplate(&svgData, "fragments/dolly/logo", map[string]any{ "FillColor": hexColor, "Classes": "", }); err != nil { return nil, err }
return svgData.Bytes(), nil}
func svgToImage(svgData []byte, w, h int) (image.Image, error) { icon, err := oksvg.ReadIconStream(bytes.NewReader(svgData)) if err != nil { return nil, fmt.Errorf("error parsing SVG: %v", err) }
icon.SetTarget(0, 0, float64(w), float64(h)) rgba := image.NewRGBA(image.Rect(0, 0, w, h)) draw.Draw(rgba, rgba.Bounds(), &image.Uniform{color.Transparent}, image.Point{}, draw.Src) scanner := rasterx.NewScannerGV(w, h, rgba, rgba.Bounds()) raster := rasterx.NewDasher(w, h, scanner) icon.Draw(raster, 1.0)
return rgba, nil}
func parseSize(size string) (int, int, error) { parts := strings.Split(size, "x") if len(parts) != 2 { return 0, 0, fmt.Errorf("invalid size format, use WIDTHxHEIGHT") }
width, err := strconv.Atoi(parts[0]) if err != nil { return 0, 0, fmt.Errorf("invalid width: %v", err) }
height, err := strconv.Atoi(parts[1]) if err != nil { return 0, 0, fmt.Errorf("invalid height: %v", err) }
if width <= 0 || height <= 0 { return 0, 0, fmt.Errorf("width and height must be positive") }
return width, height, nil}
func isValidHexColor(hex string) bool { if len(hex) != 7 || hex[0] != '#' { return false } _, err := strconv.ParseUint(hex[1:], 16, 32) return err == nil}
func saveSVG(svgData []byte, filepath string, _, _ int) error { return os.WriteFile(filepath, svgData, 0644)}
func savePNG(svgData []byte, filepath string, width, height int) error { img, err := svgToImage(svgData, width, height) if err != nil { return err }
f, err := os.Create(filepath) if err != nil { return err } defer f.Close()
return png.Encode(f, img)}
func saveICO(svgData []byte, filepath string, width, height int) error { img, err := svgToImage(svgData, width, height) if err != nil { return err }
icoData, err := ico.ImageToIco(img) if err != nil { return err }
return os.WriteFile(filepath, icoData, 0644)}