// Package templates provides HTML template handling. package templates import ( "embed" "fmt" "html/template" "io" "sync" ) //go:embed *.html var templatesRaw embed.FS // Template cache variables are global to enable efficient template reuse // across requests without re-parsing on each call. var ( //nolint:gochecknoglobals // singleton pattern for template cache baseTemplate *template.Template //nolint:gochecknoglobals // singleton pattern for template cache pageTemplates map[string]*template.Template //nolint:gochecknoglobals // protects template cache access templatesMutex sync.RWMutex ) // initTemplates parses base template and creates cloned templates for each page. func initTemplates() { templatesMutex.Lock() defer templatesMutex.Unlock() if pageTemplates != nil { return } // Parse base template with shared components baseTemplate = template.Must(template.ParseFS(templatesRaw, "base.html")) // Pages that extend base pages := []string{ "setup.html", "login.html", "dashboard.html", "app_new.html", "app_detail.html", "app_edit.html", "deployments.html", } pageTemplates = make(map[string]*template.Template) for _, page := range pages { // Clone base template and parse page-specific template into it clone := template.Must(baseTemplate.Clone()) pageTemplates[page] = template.Must(clone.ParseFS(templatesRaw, page)) } } // GetParsed returns a template executor that routes to the correct page template. func GetParsed() *TemplateExecutor { initTemplates() return &TemplateExecutor{} } // TemplateExecutor executes templates using the correct cloned template set. type TemplateExecutor struct{} // ExecuteTemplate executes the named template with the given data. func (t *TemplateExecutor) ExecuteTemplate( writer io.Writer, name string, data any, ) error { templatesMutex.RLock() tmpl, ok := pageTemplates[name] templatesMutex.RUnlock() if !ok { // Fallback for non-page templates err := baseTemplate.ExecuteTemplate(writer, name, data) if err != nil { return fmt.Errorf("execute base template %s: %w", name, err) } return nil } // Execute the "base" template from the cloned set // (which has page-specific overrides) err := tmpl.ExecuteTemplate(writer, "base", data) if err != nil { return fmt.Errorf("execute page template %s: %w", name, err) } return nil }