mirror of
https://github.com/miniflux/v2.git
synced 2025-08-26 18:21:01 +00:00
Replaces usage of the word "bookmark" with "star"/"starred" in order to be more consistent with the UI and database models, and to reduce confusion with "bookmarklet" and integration features. This is in preparation of future work on read-it-later features. Which are also not called "bookmarks" to prevent any further confusion. https://github.com/orgs/miniflux/discussions/3719 Related-to: https://github.com/miniflux/v2/pull/2219
116 lines
4.2 KiB
Go
116 lines
4.2 KiB
Go
// 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()
|
|
}
|