// Package viewutil provides utilities and common templates for views across all packages. package viewutil import ( "embed" "fmt" "github.com/bouncepaw/mycorrhiza/cfg" "github.com/bouncepaw/mycorrhiza/util" "io/fs" "log" "strings" "text/template" // TODO: save the world ) var ( //go:embed *.html fsys embed.FS BaseEn *template.Template BaseRu *template.Template m = template.Must ) const ruText = ` {{define "search by title"}}Поиск по названию{{end}} {{define "close this dialog"}}Закрыть этот диалог{{end}} {{define "login"}}Войти{{end}} {{define "register"}}Регистрация{{end}} ` func Init() { dataText := fmt.Sprintf(` {{define "wiki name"}}%s{{end}} {{define "user hypha"}}%s{{end}} `, cfg.WikiName, cfg.UserHypha) BaseEn = m(m(template.New(""). Funcs(template.FuncMap{ "beautifulName": util.BeautifulName, "inc": func(i int) int { return i + 1 }, }).ParseFS(fsys, "base.html")). Parse(dataText)) if cfg.UseAuth { BaseEn = m(BaseEn.Parse(` {{define "auth"}} {{end}} `)) } if cfg.AllowRegistration { m(BaseEn.Parse(`{{define "registration"}} {{if .Meta.U.Group | eq "anon"}} {{end}} {{end}}`)) } BaseRu = m(m(BaseEn.Clone()).Parse(ruText)) } func localizedBaseWithWeirdBody(meta Meta) *template.Template { t := func() *template.Template { if meta.Locale() == "ru" { return BaseRu } return BaseEn }() return m(m(t.Clone()).Parse(` {{define "body"}}{{.Body}}{{end}} {{define "title"}}{{.Title}}{{end}} `)) } type BaseData struct { Meta Meta HeadElements []string HeaderLinks []cfg.HeaderLink CommonScripts []string Addr string Title string // TODO: remove Body string // TODO: remove } func (bd *BaseData) withBaseValues(meta Meta, headerLinks []cfg.HeaderLink, commonScripts []string) { bd.Meta = meta bd.HeaderLinks = headerLinks bd.CommonScripts = commonScripts } // Base is a temporary wrapper around BaseEn and BaseRu, meant to facilitate the migration from qtpl. // TODO: get rid of this func Base(meta Meta, title, body string, headElements ...string) string { var w strings.Builder meta.W = &w t := localizedBaseWithWeirdBody(meta) err := t.ExecuteTemplate(&w, "page", BaseData{ Meta: meta, Title: title, HeadElements: headElements, HeaderLinks: cfg.HeaderLinks, CommonScripts: cfg.CommonScripts, Body: body, }) if err != nil { log.Println(err) } return w.String() } func CopyEnRuWith(fsys fs.FS, filename, ruTranslation string) Chain { return en(copyEnWith(fsys, filename)). ru(template.Must(copyRuWith(fsys, filename).Parse(ruTranslation))) } func copyEnWith(fsys fs.FS, f string) *template.Template { return m(m(BaseEn.Clone()).ParseFS(fsys, f)) } func copyRuWith(fsys fs.FS, f string) *template.Template { return m(m(BaseRu.Clone()).ParseFS(fsys, f)) } // ExecutePage executes template page in the given chain with the given data that has BaseData nested. It also sets some common BaseData fields func ExecutePage(meta Meta, chain Chain, data interface { withBaseValues(meta Meta, headerLinks []cfg.HeaderLink, commonScripts []string) }) { data.withBaseValues(meta, cfg.HeaderLinks, cfg.CommonScripts) if err := chain.Get(meta).ExecuteTemplate(meta.W, "page", data); err != nil { log.Println(err) } }