// Package brand serves the suite's app icons from Go, so a page can link // any sibling app's icon (the app switcher) without vendoring the file. // The artwork itself is brand/svg/, generated by generate.mjs; see README.md. package brand import ( "embed" "net/http" "strings" ) //go:embed svg/*.svg var svgFS embed.FS // Prefix is the URL path Handler serves under. const Prefix = "/static/estilo/brand/" // files maps a public slug to its master. "meet" is Calls' name before // the rename, kept so a page still linking it gets the right icon. var files = map[string]string{ "oficina": "oficina.svg", "docs": "docs.svg", "sheets": "sheets.svg", "slides": "slides.svg", "calendar": "calendar.svg", "calls": "calls.svg", "meet": "calls.svg", "memoria": "memoria.svg", "fichas": "fichas.svg", "mail": "mail.svg", "files": "files.svg", } // SVG returns the icon for slug, or nil for an unknown slug. func SVG(slug string) []byte { name, ok := files[slug] if !ok { return nil } body, err := svgFS.ReadFile("svg/" + name) if err != nil { return nil } return body } // Path is the URL Handler serves slug's icon at. func Path(slug string) string { return Prefix + slug + ".svg" } // Handler serves GET and HEAD for Prefix + ".svg". Mount it at // Prefix. Anything else is 404; the icons are public artwork and need no // session. func Handler() http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { slug, ok := strings.CutSuffix(strings.TrimPrefix(r.URL.Path, Prefix), ".svg") body := SVG(slug) if !ok || body == nil || !strings.HasPrefix(r.URL.Path, Prefix) { http.NotFound(w, r) return } if r.Method != http.MethodGet && r.Method != http.MethodHead { w.Header().Set("Allow", "GET, HEAD") http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) return } w.Header().Set("Content-Type", "image/svg+xml") w.Header().Set("Cache-Control", "public, max-age=86400") w.Header().Set("X-Content-Type-Options", "nosniff") if r.Method == http.MethodHead { return } _, _ = w.Write(body) }) }