package render import ( "bytes" "context" "embed" "html/template" "io" "io/fs" ) type Render struct { fs embed.FS t *template.Template FileExtension string } type Data map[string]interface{} func NewRender(efs embed.FS, t *template.Template) Render { tr := Render{ fs: efs, t: t, } return tr } func NewRenderWithoutTemplate(ets embed.FS) (Render, error) { tmpl, err := template.ParseFS(ets, "templates/*") if err != nil { return Render{}, err } r := NewRender(ets, tmpl) return r, nil } func (r Render) Render(ctx context.Context, w io.Writer, name string, data interface{}) error { tmpl := template.Must(r.t.Clone()) _, err := fs.Stat(r.fs, "templates/"+name+".txt") if err == nil { tmpl = template.Must(tmpl.ParseFS(r.fs, "templates/"+name+".txt")) } _, err = fs.Stat(r.fs, "templates/"+name+".html") if err == nil { tmpl = template.Must(tmpl.ParseFS(r.fs, "templates/"+name+".html")) } _, err = fs.Stat(r.fs, "templates/"+name) if err == nil { tmpl = template.Must(tmpl.ParseFS(r.fs, "templates/"+name)) } return tmpl.ExecuteTemplate(w, name, data) } func (r Render) RenderToString(ctx context.Context, name string, data interface{}) (string, error) { var output bytes.Buffer err := r.Render(ctx, &output, name, data) if err != nil { return "", err } return output.String(), nil }