1
0
Fork 0
mirror of https://github.com/miniflux/v2.git synced 2025-08-26 18:21:01 +00:00
miniflux-v2/internal/template/engine.go

117 lines
4.2 KiB
Go
Raw Normal View History

// SPDX-FileCopyrightText: Copyright The Miniflux Authors. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
package template // import "miniflux.app/v2/internal/template"
import (
"bytes"
2021-02-18 21:33:29 -08:00
"embed"
"html/template"
"time"
"miniflux.app/v2/internal/locale"
"github.com/gorilla/mux"
)
2021-02-18 21:33:29 -08:00
//go:embed templates/common/*.html
var commonTemplateFiles embed.FS
//go:embed templates/views/*.html
var viewTemplateFiles embed.FS
// Engine handles the templating system.
type Engine struct {
templates map[string]*template.Template
funcMap *funcMap
}
2021-02-18 21:33:29 -08:00
// NewEngine returns a new template engine.
func NewEngine(router *mux.Router) *Engine {
return &Engine{
templates: make(map[string]*template.Template),
funcMap: &funcMap{router},
}
}
func (e *Engine) ParseTemplates() {
funcMap := e.funcMap.Map()
templates := map[string][]string{ // this isn't a global variable so that it can be garbage-collected.
"about.html": {"layout.html", "settings_menu.html"},
"add_subscription.html": {"feed_menu.html", "layout.html", "settings_menu.html"},
"api_keys.html": {"layout.html", "settings_menu.html"},
"starred_entries.html": {"item_meta.html", "layout.html", "pagination.html"},
"categories.html": {"layout.html"},
"category_entries.html": {"item_meta.html", "layout.html", "pagination.html"},
"category_feeds.html": {"feed_list.html", "layout.html"},
"choose_subscription.html": {"feed_menu.html", "layout.html"},
"create_api_key.html": {"layout.html", "settings_menu.html"},
"create_category.html": {"layout.html"},
"create_user.html": {"layout.html", "settings_menu.html"},
"edit_category.html": {"layout.html", "settings_menu.html"},
"edit_feed.html": {"layout.html"},
"edit_user.html": {"layout.html", "settings_menu.html"},
"entry.html": {"layout.html"},
"feed_entries.html": {"item_meta.html", "layout.html", "pagination.html"},
"feeds.html": {"feed_list.html", "feed_menu.html", "item_meta.html", "layout.html", "pagination.html"},
"history_entries.html": {"item_meta.html", "layout.html", "pagination.html"},
"import.html": {"feed_menu.html", "layout.html"},
"integrations.html": {"layout.html", "settings_menu.html"},
"login.html": {"layout.html"},
"offline.html": {},
"search.html": {"item_meta.html", "layout.html", "pagination.html"},
"sessions.html": {"layout.html", "settings_menu.html"},
"settings.html": {"layout.html", "settings_menu.html"},
"shared_entries.html": {"layout.html", "pagination.html"},
"tag_entries.html": {"item_meta.html", "layout.html", "pagination.html"},
"unread_entries.html": {"item_meta.html", "layout.html", "pagination.html"},
"users.html": {"layout.html", "settings_menu.html"},
"webauthn_rename.html": {"layout.html"},
}
for name, dependencies := range templates {
tpl := template.New("").Funcs(funcMap)
for _, dependency := range dependencies {
template.Must(tpl.ParseFS(commonTemplateFiles, "templates/common/"+dependency))
2021-02-18 21:33:29 -08:00
}
e.templates[name] = template.Must(tpl.ParseFS(viewTemplateFiles, "templates/views/"+name))
2021-02-18 21:33:29 -08:00
}
// Sanity check to ensure that all templates are correctly declared in `templates`.
if entries, err := viewTemplateFiles.ReadDir("templates/views"); err == nil {
for _, entry := range entries {
if _, ok := e.templates[entry.Name()]; !ok {
panic("Template " + entry.Name() + " isn't declared in ParseTemplates")
}
}
} else {
panic("Unable to read all embedded views templates")
}
}
// Render process a template.
func (e *Engine) Render(name string, data map[string]any) []byte {
tpl, ok := e.templates[name]
if !ok {
panic("The template " + name + " does not exists.")
}
printer := locale.NewPrinter(data["language"].(string))
// Functions that need to be declared at runtime.
tpl.Funcs(template.FuncMap{
"elapsed": func(timezone string, t time.Time) string {
return elapsedTime(printer, timezone, t)
},
"t": printer.Printf,
"plural": printer.Plural,
})
var b bytes.Buffer
if err := tpl.ExecuteTemplate(&b, "base", data); err != nil {
panic(err)
}
return b.Bytes()
}