-
Notifications
You must be signed in to change notification settings - Fork 0
/
builder.go
93 lines (74 loc) · 2.33 KB
/
builder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
package emailtemplates
import (
"embed"
"fmt"
"io/fs"
"path/filepath"
"strings"
"text/template"
"github.com/rs/zerolog/log"
"github.com/stoewer/go-strcase"
)
const (
// Email templates must be provided in this directory and are loaded at compile time
templatesDir = "templates"
// Partials are included when rendering templates for composability and reuse - includes footer, header, etc.
partialsDir = "partials"
)
var (
//go:embed templates/*.html templates/*.txt templates/partials/*html
files embed.FS
templates map[string]*template.Template
)
// Load templates when the package is imported
func init() {
templates = make(map[string]*template.Template)
templateFiles, err := fs.ReadDir(files, templatesDir)
if err != nil {
log.Panic().Err(err).Msg("could not read template files")
}
// Each template needs to be parsed independently to ensure that define directives
// are not overwritten if they have the same name; e.g. to use the base template
for _, file := range templateFiles {
if file.IsDir() {
continue
}
// Each template will be accessible by its base name in the global map
patterns := make([]string, 0, 2) //nolint:mnd
patterns = append(patterns, filepath.Join(templatesDir, file.Name()))
if filepath.Ext(file.Name()) == ".html" {
patterns = append(patterns, filepath.Join(templatesDir, partialsDir, "*.html"))
}
// function map for template
fm := template.FuncMap{
"ToUpper": strcase.UpperCamelCase,
}
var err error
templates[file.Name()], err = template.New(file.Name()).Funcs(fm).ParseFS(files, patterns...)
if err != nil {
log.Panic().Err(err).Str("template", file.Name()).Msg("could not parse template")
}
}
}
// Render returns the text and html executed templates for the specified name and data
func Render(name string, data interface{}) (text, html string, err error) {
if text, err = render(name+".txt", data); err != nil {
return
}
if html, err = render(name+".html", data); err != nil {
return
}
return
}
// render the provided template with the data
func render(name string, data interface{}) (_ string, err error) {
t, ok := templates[name]
if !ok {
return "", fmt.Errorf("%w: %q not found in templates", ErrMissingTemplate, name)
}
buf := &strings.Builder{}
if err = t.Execute(buf, data); err != nil {
return "", err
}
return buf.String(), nil
}