update_server/internal/http/render.go
2026-06-10 20:51:17 +03:00

78 lines
1.9 KiB
Go

package httpserver
import (
"bytes"
"fmt"
"html/template"
"net/http"
"path/filepath"
"strings"
)
type Renderer struct {
templates map[string]*template.Template
}
func NewRenderer(templatesDir string) (*Renderer, error) {
layouts, err := filepath.Glob(filepath.Join(templatesDir, "layouts", "*.gohtml"))
if err != nil {
return nil, fmt.Errorf("find layouts: %w", err)
}
if len(layouts) == 0 {
return nil, fmt.Errorf("no layout templates found in %s", filepath.Join(templatesDir, "layouts"))
}
partials, err := filepath.Glob(filepath.Join(templatesDir, "partials", "*.gohtml"))
if err != nil {
return nil, fmt.Errorf("find partials: %w", err)
}
pages, err := filepath.Glob(filepath.Join(templatesDir, "pages", "*.gohtml"))
if err != nil {
return nil, fmt.Errorf("find pages: %w", err)
}
if len(pages) == 0 {
return nil, fmt.Errorf("no page templates found in %s", filepath.Join(templatesDir, "pages"))
}
renderer := &Renderer{templates: make(map[string]*template.Template, len(pages))}
for _, page := range pages {
files := append([]string{}, layouts...)
files = append(files, partials...)
files = append(files, page)
tmpl, err := template.ParseFiles(files...)
if err != nil {
return nil, fmt.Errorf("parse template set for %s: %w", page, err)
}
name := strings.TrimSuffix(filepath.Base(page), filepath.Ext(page))
renderer.templates[name] = tmpl
}
return renderer, nil
}
func (r *Renderer) Render(w http.ResponseWriter, name string, status int, data any) error {
tmpl, ok := r.templates[name]
if !ok {
return fmt.Errorf("unknown template %q", name)
}
var output bytes.Buffer
if err := tmpl.ExecuteTemplate(&output, "base", data); err != nil {
return err
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
if status <= 0 {
status = http.StatusOK
}
w.WriteHeader(status)
_, err := output.WriteTo(w)
return err
}