mirror of
https://github.com/osmarks/mycorrhiza.git
synced 2024-10-30 11:46:16 +00:00
c1946d8849
BodyAttributes is now a map of attribute name -> attribute value. This was done because attribute names have a restricted set of characters, but attribute values are much less restrictive
164 lines
4.7 KiB
Go
164 lines
4.7 KiB
Go
// 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}}
|
|
{{define "confirm"}}Подтвердить{{end}}
|
|
{{define "cancel"}}Отмена{{end}}
|
|
{{define "save"}}Сохранить{{end}}
|
|
{{define "error"}}Ошибка{{end}}
|
|
{{define "delete"}}Удалить{{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"}}
|
|
<ul class="top-bar__auth auth-links">
|
|
<li class="auth-links__box auth-links__user-box">
|
|
{{if .Meta.U.Group | eq "anon" }}
|
|
<a href="/login" class="auth-links__link auth-links__login-link">
|
|
{{block "login" .}}Login{{end}}
|
|
</a>
|
|
{{else}}
|
|
<a href="/hypha/{{block "user hypha" .}}{{end}}/{{.Meta.U.Name}}" class="auth-links__link auth-links__user-link">
|
|
{{beautifulName .Meta.U.Name}}
|
|
</a>
|
|
{{end}}
|
|
</li>
|
|
{{block "registration" .}}{{end}}
|
|
</ul>
|
|
{{end}}
|
|
`))
|
|
}
|
|
if cfg.AllowRegistration {
|
|
m(BaseEn.Parse(`{{define "registration"}}
|
|
{{if .Meta.U.Group | eq "anon"}}
|
|
<li class="auth-links__box auth-links__register-box">
|
|
<a href="/register" class="auth-links__link auth-links__register-link">
|
|
{{block "register" .}}Register{{end}}
|
|
</a>
|
|
</li>
|
|
{{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 []HeaderLink
|
|
CommonScripts []string
|
|
Addr string
|
|
Title string // TODO: remove
|
|
Body string // TODO: remove
|
|
BodyAttributes map[string]string
|
|
}
|
|
|
|
func (bd *BaseData) withBaseValues(meta Meta, headerLinks []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, bodyAttributes map[string]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: HeaderLinks,
|
|
CommonScripts: cfg.CommonScripts,
|
|
Body: body,
|
|
BodyAttributes: bodyAttributes,
|
|
})
|
|
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 []HeaderLink, commonScripts []string)
|
|
}) {
|
|
data.withBaseValues(meta, HeaderLinks, cfg.CommonScripts)
|
|
if err := chain.Get(meta).ExecuteTemplate(meta.W, "page", data); err != nil {
|
|
log.Println(err)
|
|
}
|
|
}
|
|
|
|
// HeaderLinks is a list off current header links. Feel free to iterate it directly but do not modify it by yourself. Call ParseHeaderLinks if you need to set new header links.
|
|
var HeaderLinks []HeaderLink
|
|
|
|
// HeaderLink represents a header link. Header links are the links shown in the top gray bar.
|
|
type HeaderLink struct {
|
|
// Href is the URL of the link. It goes <a href="here">...</a>.
|
|
Href string
|
|
// Display is what is shown when the link is rendered. It goes <a href="...">here</a>.
|
|
Display string
|
|
}
|