99 lines
2.3 KiB
Go
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
|
|
}
|