11
"xelbot.com/reprogl/container"
12
"xelbot.com/reprogl/security"
13
"xelbot.com/reprogl/session"
16
const defaultPageSize = 64 * 1024
19
//go:embed templates markdown
22
templates map[string]*template.Template
26
templates = make(map[string]*template.Template)
29
func LoadViewSet() error {
30
templatesMap := map[string][]string{
32
"templates/about.gohtml",
33
"templates/partials/menu.gohtml",
34
"templates/partials/sticky-header.gohtml",
35
"templates/partials/big-header.gohtml",
36
"templates/partials/footer.gohtml",
37
"templates/partials/social-icons.gohtml",
38
"templates/layout/svg-sprites.gohtml",
39
"templates/layout/base.gohtml",
42
"templates/article.gohtml",
43
"templates/partials/author-info.gohtml",
44
"templates/partials/comment-form.gohtml",
45
"templates/partials/menu.gohtml",
46
"templates/partials/sidebar.gohtml",
47
"templates/partials/social-icons.gohtml",
48
"templates/partials/powered-by.gohtml",
49
"templates/layout/svg-auth.gohtml",
50
"templates/layout/svg-sprites.gohtml",
51
"templates/layout/base.gohtml",
53
"statistics.gohtml": {
54
"templates/statistics.gohtml",
55
"templates/partials/author-info.gohtml",
56
"templates/partials/menu.gohtml",
57
"templates/partials/sidebar.gohtml",
58
"templates/partials/social-icons.gohtml",
59
"templates/partials/powered-by.gohtml",
60
"templates/layout/svg-sprites.gohtml",
61
"templates/layout/base.gohtml",
64
"templates/profile.gohtml",
65
"templates/partials/profile-form.gohtml",
66
"templates/partials/menu.gohtml",
67
"templates/partials/sidebar.gohtml",
68
"templates/partials/social-icons.gohtml",
69
"templates/layout/svg-sprites.gohtml",
70
"templates/layout/base.gohtml",
73
"templates/index.gohtml",
74
"templates/partials/menu.gohtml",
75
"templates/partials/sticky-header.gohtml",
76
"templates/partials/big-header.gohtml",
77
"templates/partials/footer.gohtml",
78
"templates/partials/social-icons.gohtml",
79
"templates/layout/svg-sprites.gohtml",
80
"templates/layout/base.gohtml",
82
"categories.gohtml": {
83
"templates/fragments/categories.gohtml",
86
"templates/fragments/comments.gohtml",
88
"recent-posts.gohtml": {
89
"templates/fragments/recent-posts.gohtml",
92
"templates/auth/login.gohtml",
94
"auth-navigation.gohtml": {
95
"templates/fragments/auth-navigation.gohtml",
98
"templates/fragments/menu-auth.gohtml",
100
"unsubscribe.gohtml": {
101
"templates/unsubscribe.gohtml",
103
"oauth-pending.gohtml": {
104
"templates/oauth/oauth-pending.gohtml",
108
customFunctions := template.FuncMap{
110
"is_dev": func() bool { return container.IsDevMode() },
111
"path": urlGenerator,
112
"abs_path": absUrlGenerator,
113
"render_esi": renderESI,
117
"author_bio": authorBio,
118
"author_data": authorDataPart,
119
"author_adr": authorLocation,
120
"author_job": authorJob,
121
"author_avatar": authorAvatar,
125
"go_version": func() string { return container.GoVersionNumbers },
126
"commit_hash": func() string { return container.GitRevision },
127
"cnt_comments": commentsCountString,
128
"cnt_times": timesCountString,
129
"flag_cnt": flagCounterImage(true),
130
"flag_cnt_mini": flagCounterImage(false),
131
"emojiFlag": emojiFlag,
133
"articleStyles": articleStyles,
134
"statisticsStyles": statisticsStyles,
135
"indexStyles": indexStyles,
136
"infoStyles": infoStyles,
137
"profileStyles": profileStyles,
140
for key, files := range templatesMap {
141
tmpl, err := template.New(key).Funcs(customFunctions).ParseFS(sources, files...)
146
templates[key] = tmpl
152
func RenderTemplate(name string, data interface{}) (string, error) {
153
tmpl, ok := templates[name]
155
return "", fmt.Errorf("the template %s does not exist", name)
158
var buf strings.Builder
159
buf.Grow(defaultPageSize)
161
err := tmpl.Execute(&buf, data)
166
return buf.String(), nil
169
func WriteTemplate(w http.ResponseWriter, name string, data any) error {
170
content, err := RenderTemplate(name, data)
175
w.Header().Set("Content-Type", "text/html; charset=utf-8")
176
w.Header().Set("Surrogate-Control", "content=\"ESI/1.0\"")
177
_, err = w.Write([]byte(content))
185
func WriteTemplateWithContext(ctx context.Context, w http.ResponseWriter, name string, data any) error {
186
if flashObjectPart, ok := data.(DataWithFlashMessage); ok {
187
if flashSuccessMessage, found := session.Pop[string](ctx, session.FlashSuccessKey); found {
188
flashObjectPart.SetSuccessFlash(flashSuccessMessage)
192
if identityPart, ok := data.(security.IdentityAware); ok {
193
identity, _ := session.GetIdentity(ctx)
194
identityPart.SetIdentity(identity)
197
return WriteTemplate(w, name, data)