Add go generate setup for SVG icon embedding

- gen_icons.go: reads SVG files, generates icons.go with go:embed
- icons.go: generated file with embedded SVG strings
- Supports cut, copy, paste icons (search, conflict, wrapOn/Off to be added)
This commit is contained in:
Greg Pomerantz 2026-05-09 23:08:10 -04:00
parent 9b745bf66f
commit 92d22cf0cd
3 changed files with 150 additions and 6 deletions

View File

@ -1,7 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="8" cy="18" r="3" fill="none" stroke="currentColor" stroke-width="1.5"/> <circle cx="6" cy="6" r="3"/>
<circle cx="16" cy="18" r="3" fill="none" stroke="currentColor" stroke-width="1.5"/> <circle cx="6" cy="18" r="3"/>
<path d="M8 15.5L12 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/> <path d="M20 4 8.12 15.12"/>
<path d="M16 15.5L12 6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/> <path d="M14.8 14.8 20 20"/>
<circle cx="12" cy="6" r="1" fill="currentColor"/> <path d="M8.12 8.12 12 12"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 500 B

After

Width:  |  Height:  |  Size: 347 B

104
icons/gen_icons.go Normal file
View File

@ -0,0 +1,104 @@
//go:build ignore
//go:generate go run gen_icons.go
// gen_icons reads SVG files and generates icons/embedded.go with go:embed directives.
// Run: go generate ./icons
// To regenerate: cd icons && go run gen_icons.go
package main
import (
"bytes"
"fmt"
"go/format"
"io/fs"
"os"
"path/filepath"
"sort"
"strings"
"text/template"
)
const output = "icons.go"
var iconTemplate = template.Must(template.New("").Parse(`// Code generated by gen_icons.go; DO NOT EDIT.
package icons
import (
_ "embed"
)
//go:embed {{.Embeds}}
var svgFS embed.FS
{{range $name, $files := .Icons}}
// {{$name}}SVG contains the {{$name}} icon SVG source.
var {{$name}}SVG = ` + "`" + `{{.}}` + "`" + `
{{end}}
`))
type iconData struct {
Embeds string
Icons map[string]string
}
func main() {
icons := make(map[string]string)
var embeds []string
err := filepath.WalkDir(".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
if d.IsDir() {
return nil
}
if !strings.HasSuffix(path, ".svg") {
return nil
}
data, err := os.ReadFile(path)
if err != nil {
return err
}
name := strings.TrimSuffix(filepath.Base(path), ".svg")
icons[name] = string(data)
embeds = append(embeds, filepath.Base(path))
return nil
})
if err != nil {
fmt.Fprintf(os.Stderr, "error: %v\n", err)
os.Exit(1)
}
// Sort embeds for deterministic output
sort.Strings(embeds)
data := iconData{
Embeds: strings.Join(embeds, " "),
Icons: icons,
}
var buf bytes.Buffer
if err := iconTemplate.Execute(&buf, data); err != nil {
fmt.Fprintf(os.Stderr, "template error: %v\n", err)
os.Exit(1)
}
src, err := format.Source(buf.Bytes())
if err != nil {
fmt.Fprintf(os.Stderr, "format error: %v\n", err)
os.Exit(1)
}
if err := os.WriteFile(output, src, 0644); err != nil {
fmt.Fprintf(os.Stderr, "write error: %v\n", err)
os.Exit(1)
}
fmt.Println("generated icons.go")
}

40
icons/icons.go Normal file
View File

@ -0,0 +1,40 @@
// Code generated by gen_icons.go; DO NOT EDIT.
package icons
import (
_ "embed"
)
//go:embed copy.svg cut.svg paste.svg
var svgFS embed.FS
// copySVG contains the copy icon SVG source.
var copySVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<rect x="7" y="7" width="12" height="14" rx="1" fill="none" stroke="currentColor" stroke-width="1.5"/>
<rect x="4" y="4" width="12" height="14" rx="1" fill="none" stroke="currentColor" stroke-width="1.5"/>
</svg>
`
// cutSVG contains the cut icon SVG source.
var cutSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<!-- Left blade -->
<circle cx="7" cy="7" r="4" />
<line x1="9.5" y1="9.5" x2="14" y2="14" />
<!-- Right blade -->
<circle cx="17" cy="7" r="4" />
<line x1="14.5" y1="9.5" x2="10" y2="14" />
<!-- Handles -->
<line x1="7" y1="3" x2="7" y2="11" />
<line x1="17" y1="3" x2="17" y2="11" />
</svg>
`
// pasteSVG contains the paste icon SVG source.
var pasteSVG = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
<rect x="5" y="6" width="14" height="15" rx="1" fill="none" stroke="currentColor" stroke-width="1.5"/>
<path d="M8 6V4.5C8 3.67 8.67 3 9.5 3h5C15.33 3 16 3.67 16 4.5V6" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
<line x1="8" y1="10" x2="16" y2="10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
<line x1="8" y1="14" x2="16" y2="14" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
</svg>
`