| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- // 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"
- "embed"
- "html/template"
- "time"
- "miniflux.app/v2/internal/locale"
- "github.com/gorilla/mux"
- )
- //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
- }
- // 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))
- }
- e.templates[name] = template.Must(tpl.ParseFS(viewTemplateFiles, "templates/views/"+name))
- }
- // 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()
- }
|