D0 Part 1: vendored fonts + Lucide sprite + setup CSS fix
- Vendor Plus Jakarta Sans + JetBrains Mono as variable woff2 (latin + latin-ext) under internal/web/static/fonts/, embedded via go:embed and served at /static/fonts/ (font/woff2, immutable cache). Google Fonts @import replaced with @font-face rules preserving unicode-range — removes the CDN dependency that silently broke on offline nodes. - Add templates/icons.html: vendored Lucide sprite (30 icons, symbol ids i-<name>), included at the top of <body> in layout.html. - Fix setup wizard handleCSS: serve the embedded web.StyleCSS() instead of a dataDir-derived filesystem path that never exists in the container (production setup silently served minimalCSS). Fallback to minimalCSS only if the embedded read errors, with a WARN log. - Tests: font route + StyleCSS accessor (web), Scenario E embedded-CSS test (setup; red-proven against the pre-fix handler).
This commit is contained in:
@@ -322,6 +322,8 @@ func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
s.serveCSSHandler(w, r)
|
||||
case path == "/static/chart.min.js":
|
||||
s.serveChartJSHandler(w, r)
|
||||
case strings.HasPrefix(path, "/static/fonts/"):
|
||||
s.serveFontHandler(w, r, strings.TrimPrefix(path, "/static/fonts/"))
|
||||
case path == "/static/felhom-logo.svg":
|
||||
s.serveLogoHandler(w, r)
|
||||
case path == "/static/favicon.svg":
|
||||
@@ -489,6 +491,20 @@ func (s *Server) serveChartJSHandler(w http.ResponseWriter, r *http.Request) {
|
||||
w.Write(chartJS)
|
||||
}
|
||||
|
||||
// serveFontHandler serves the vendored woff2 files embedded in the binary
|
||||
// (self-hosted fonts — no Google Fonts CDN dependency on offline nodes).
|
||||
func (s *Server) serveFontHandler(w http.ResponseWriter, r *http.Request, filename string) {
|
||||
filename = filepath.Base(filename)
|
||||
data, err := fontFS.ReadFile("static/fonts/" + filename)
|
||||
if err != nil {
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "font/woff2")
|
||||
w.Header().Set("Cache-Control", "public, max-age=31536000, immutable")
|
||||
w.Write(data)
|
||||
}
|
||||
|
||||
func (s *Server) serveLogoHandler(w http.ResponseWriter, r *http.Request) {
|
||||
// Try synced asset first (allows logo updates via Hub without rebuild)
|
||||
if s.assetsSyncer != nil {
|
||||
|
||||
Reference in New Issue
Block a user