package email import ( "fmt" "github.com/stonith404/pocket-id/backend/resources" htemplate "html/template" "io/fs" "path" ttemplate "text/template" ) type Template[V any] struct { Path string Title func(data *TemplateData[V]) string } type TemplateData[V any] struct { AppName string LogoURL string Data *V } type TemplateMap[V any] map[string]*V func GetTemplate[U any, V any](templateMap TemplateMap[U], template Template[V]) *U { return templateMap[template.Path] } type clonable[V pareseable[V]] interface { Clone() (V, error) } type pareseable[V any] interface { ParseFS(fs.FS, ...string) (V, error) } func prepareTemplate[V pareseable[V]](templateFS fs.FS, template string, rootTemplate clonable[V], suffix string) (V, error) { tmpl, err := rootTemplate.Clone() if err != nil { return *new(V), fmt.Errorf("clone root template: %w", err) } filename := fmt.Sprintf("%s%s", template, suffix) templatePath := path.Join("email-templates", filename) _, err = tmpl.ParseFS(templateFS, templatePath) if err != nil { return *new(V), fmt.Errorf("parsing template '%s': %w", template, err) } return tmpl, nil } func PrepareTextTemplates(templates []string) (map[string]*ttemplate.Template, error) { components := path.Join("email-templates", "components", "*_text.tmpl") rootTmpl, err := ttemplate.ParseFS(resources.FS, components) if err != nil { return nil, fmt.Errorf("unable to parse templates '%s': %w", components, err) } textTemplates := make(map[string]*ttemplate.Template, len(templates)) for _, tmpl := range templates { rootTmplClone, err := rootTmpl.Clone() if err != nil { return nil, fmt.Errorf("clone root template: %w", err) } textTemplates[tmpl], err = prepareTemplate[*ttemplate.Template](resources.FS, tmpl, rootTmplClone, "_text.tmpl") if err != nil { return nil, fmt.Errorf("parse '%s': %w", tmpl, err) } } return textTemplates, nil } func PrepareHTMLTemplates(templates []string) (map[string]*htemplate.Template, error) { components := path.Join("email-templates", "components", "*_html.tmpl") rootTmpl, err := htemplate.ParseFS(resources.FS, components) if err != nil { return nil, fmt.Errorf("unable to parse templates '%s': %w", components, err) } htmlTemplates := make(map[string]*htemplate.Template, len(templates)) for _, tmpl := range templates { rootTmplClone, err := rootTmpl.Clone() if err != nil { return nil, fmt.Errorf("clone root template: %w", err) } htmlTemplates[tmpl], err = prepareTemplate[*htemplate.Template](resources.FS, tmpl, rootTmplClone, "_html.tmpl") if err != nil { return nil, fmt.Errorf("parse '%s': %w", tmpl, err) } } return htmlTemplates, nil }