axiom/views/views.go
2025-07-01 11:32:37 -06:00

99 lines
2.3 KiB
Go

package views
import (
"bytes"
"compress/gzip"
"embed"
"fmt"
"html/template"
"io"
"net/http"
"path/filepath"
"strings"
)
var (
TemplateCache map[string]*template.Template
)
func Init(viewFS embed.FS, viewMap map[string][]string, funcMap map[string]any) error {
var err error
TemplateCache, err = initTemplates(viewFS, viewMap, funcMap)
if err != nil {
return fmt.Errorf("failed to initialize templates: %v", err)
}
return nil
}
func initTemplates(viewFS embed.FS, viewMap map[string][]string, funcMap map[string]any) (map[string]*template.Template, error) {
cache := make(map[string]*template.Template)
tmplFuncMap := template.FuncMap(funcMap)
for name, paths := range viewMap {
if len(paths) == 0 {
continue
}
rootName := strings.TrimSuffix(filepath.Base(paths[0]), filepath.Ext(paths[0]))
tmpl := template.New(rootName).Funcs(tmplFuncMap)
var combined []byte
for _, path := range paths {
content, err := viewFS.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("reading %s: %w", path, err)
}
combined = append(combined, content...)
combined = append(combined, '\n')
}
parsed, err := tmpl.Parse(string(combined))
if err != nil {
return nil, fmt.Errorf("parsing template %s: %w", name, err)
}
cache[name] = parsed
}
return cache, nil
}
func RenderHTML(w http.ResponseWriter, r *http.Request, name string, data any) error {
tmpl, ok := TemplateCache[name]
if !ok {
return fmt.Errorf("template %q not found", name)
}
var buf bytes.Buffer
if err := tmpl.ExecuteTemplate(&buf, tmpl.Name(), data); err != nil {
return fmt.Errorf("failed to execute template %q: %w", name, err)
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Header().Set("Vary", "Accept-Encoding")
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
w.Header().Set("Content-Encoding", "gzip")
gz := gzip.NewWriter(w)
defer gz.Close()
_, err := io.Copy(gz, &buf)
return err
}
_, err := io.Copy(w, &buf)
return err
}
func RenderHTMLToString(name string, data any) (string, error) {
tmpl, ok := TemplateCache[name]
if !ok {
return "", fmt.Errorf("template %q not found", name)
}
var buf bytes.Buffer
if err := tmpl.ExecuteTemplate(&buf, tmpl.Name(), data); err != nil {
return "", fmt.Errorf("failed to execute template %q: %w", name, err)
}
return buf.String(), nil
}