package main import ( "embed" "html/template" "io/fs" "net/http" "time" ) //go:embed templates/*.html var templateFS embed.FS //go:embed static var staticFS embed.FS // staticHandler serves the embedded static/ directory at /static/. func staticHandler() http.Handler { sub, err := fs.Sub(staticFS, "static") if err != nil { panic(err) } return http.StripPrefix("/static/", http.FileServer(http.FS(sub))) } var tmpl *template.Template var funcMap = template.FuncMap{ "money": func(v float64) string { return fmtNum(v) }, "hours": func(minutes float64) string { return fmtNum(minutes / 60.0) }, "datef": func(t time.Time) string { return t.Format("02 Jan") }, "hm": func(t time.Time) string { return t.Format("15:04") }, "hmp": func(t *time.Time) string { if t == nil { return "" } return t.Format("15:04") }, "timef": func(t *time.Time) string { if t == nil { return "running…" } return t.Format("15:04") }, "dateInput": func(t time.Time) string { return t.Format("02-01-2006") }, "today": func() string { return time.Now().Format("02-01-2006") }, "rfc3339": func(t time.Time) string { return t.Format(time.RFC3339) }, } func parseTemplates() error { t, err := template.New("").Funcs(funcMap).ParseFS(templateFS, "templates/*.html") if err != nil { return err } tmpl = t return nil } // render executes a named template and writes any error to the log/response. func (s *Server) render(w http.ResponseWriter, name string, data any) { w.Header().Set("Content-Type", "text/html; charset=utf-8") if err := tmpl.ExecuteTemplate(w, name, data); err != nil { s.errl.Printf("render %s: %v", name, err) http.Error(w, "template error", http.StatusInternalServerError) } }