-
Notifications
You must be signed in to change notification settings - Fork 0
/
templates.go
160 lines (147 loc) · 3.73 KB
/
templates.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package golatt
import (
"html/template"
"log/slog"
"net/http"
)
// SeoData contains seo data used by opengraph and twitter
type SeoData struct {
// Title of the page (always replaced by TemplateData's title)
Title string
// URL of the page
URL string
// Image used in embeds
Image string
// Description of the page
Description string
// Domain of the website (always replaced by Golatt's DefaultSeoData)
Domain string
}
// TemplateData is passed to the template during the render
type TemplateData struct {
// Title of the page
Title string
// SEO data
SEO *SeoData
// Data is custom data passed to the template
Data interface{}
}
func (g *Golatt) setupTemplates() *template.Template {
var t *template.Template
if g.Templates == nil || len(g.Templates) == 0 {
panic("templates are not initialized")
}
for _, p := range g.Templates {
if t == nil {
t = template.New(p)
} else {
t = t.New(p)
}
}
return template.Must(t.Funcs(template.FuncMap{
"getStaticPath": func(path string) string {
return GetStaticPath(path)
},
"getAssetPath": func(path string) string {
return GetAssetPath(path)
},
}).ParseFS(g.Files, g.Templates...))
}
func (g *Golatt) mergeData(d *TemplateData) {
d.Title = g.FormatTitle(d.Title)
if g.DefaultSeoData == nil {
return
}
s := d.SEO
s.Domain = g.DefaultSeoData.Domain
s.Title = d.Title
if s.Image == "" {
s.Image = g.DefaultSeoData.Image
}
if s.Description == "" {
s.Description = g.DefaultSeoData.Description
}
}
// Render the template available at templates/page/name.gohtml with the data provided
func (g *Golatt) Render(w http.ResponseWriter, name string, data *TemplateData) {
g.mergeData(data)
t := g.setupTemplates()
template.Must(t.ParseFS(g.Files, g.getFile(name)))
err := t.ExecuteTemplate(w, g.InitialSection, data)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
slog.Error("error while rendering template", "err", err.Error())
}
}
func (g *Golatt) getFile(path string) string {
return g.FsDirectory + "/" + g.PageDirectory + "/" + path + "." + g.TemplateExtension
}
// GetStaticPath returns the path of a static file (image, font)
func GetStaticPath(path string) string {
return "/static/" + path
}
// GetAssetPath returns the path of an asset (js, css)
func GetAssetPath(path string) string {
return "/assets/" + path
}
// Template represents a generic template
type Template struct {
// Golatt used
Golatt *Golatt
// Name of the template (check Golatt.Render)
Name string
// Title of the template
Title string
// Data to pass
Data interface{}
// Image to use in the SEO
Image string
// Description to use in the SEO
Description string
// URL of the template
URL string
}
// NewTemplate creates a new template.
// You can directly handle it with Template.Handle
func (g *Golatt) NewTemplate(name string, url string, title string, image string, description string, data interface{}) *Template {
return &Template{
Golatt: g,
Name: name,
Title: title,
Data: data,
Image: image,
Description: description,
URL: url,
}
}
// Handle a http request
func (t *Template) Handle() {
url := t.URL
if url == "" {
url = "/" + t.Name
}
t.Golatt.HandleFunc(url, func(w http.ResponseWriter, r *http.Request) {
seo := &SeoData{
URL: url,
Description: t.Description,
}
if t.Image != "" {
seo.Image = GetStaticPath(t.Image)
}
t.Golatt.Render(w, t.Name, &TemplateData{
Title: t.Title,
SEO: seo,
Data: t.Data,
})
})
}
// HandleSimpleTemplate handles a http request for a simple Template (only name and title are present)
func (g *Golatt) HandleSimpleTemplate(name string, title string) {
t := Template{
Golatt: g,
Name: name,
Title: title,
Data: nil,
}
t.Handle()
}