From a8b3e3d43ae120e2dbc2d038e76e1bfa8b53f6b6 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Tue, 29 Mar 2022 23:59:36 +0300 Subject: [PATCH 01/23] Implement viewutil.Base --- main.go | 2 + views/admin.go | 5 +- views/base.go | 21 -- views/categories.go | 11 +- views/nav.qtpl | 3 +- views/nav.qtpl.go | 217 ++++++++++---------- views/readers.qtpl | 3 +- views/readers.qtpl.go | 453 +++++++++++++++++++++--------------------- viewutil/base.html | 83 ++++++++ viewutil/meta.go | 28 +++ viewutil/viewutil.go | 85 ++++++++ web/admin.go | 3 +- web/categories.go | 5 +- web/readers.go | 5 +- 14 files changed, 557 insertions(+), 367 deletions(-) create mode 100644 viewutil/base.html create mode 100644 viewutil/meta.go create mode 100644 viewutil/viewutil.go diff --git a/main.go b/main.go index bfa549c..40a1f9e 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ package main import ( "github.com/bouncepaw/mycorrhiza/hyphae/categories" "github.com/bouncepaw/mycorrhiza/migration" + "github.com/bouncepaw/mycorrhiza/viewutil" "log" "os" @@ -41,6 +42,7 @@ func main() { log.Println("Using Git storage at", files.HyphaeDir()) // Init the subsystems: + viewutil.Init() hyphae.Index(files.HyphaeDir()) backlinks.IndexBacklinks() go backlinks.RunBacklinksConveyor() diff --git a/views/admin.go b/views/admin.go index dd89e2b..3a383d2 100644 --- a/views/admin.go +++ b/views/admin.go @@ -2,6 +2,7 @@ package views import ( "github.com/bouncepaw/mycorrhiza/util" + "github.com/bouncepaw/mycorrhiza/viewutil" "html/template" "io" "log" @@ -25,7 +26,7 @@ var ( adminTemplatesRu *template.Template ) -func localizedAdminTemplates(meta Meta) *template.Template { +func localizedAdminTemplates(meta viewutil.Meta) *template.Template { if meta.Lc.Locale == "ru" { return adminTemplatesRu } @@ -59,7 +60,7 @@ func init() { template.Must(adminTemplatesEn.Clone()).Parse(adminTranslationRu)) } -func AdminPanel(meta Meta) { +func AdminPanel(meta viewutil.Meta) { var buf strings.Builder err := localizedAdminTemplates(meta).ExecuteTemplate(&buf, "panel", nil) if err != nil { diff --git a/views/base.go b/views/base.go index df5464c..1fc4ccd 100644 --- a/views/base.go +++ b/views/base.go @@ -2,28 +2,7 @@ package views import ( "embed" - "github.com/bouncepaw/mycorrhiza/l18n" - "github.com/bouncepaw/mycorrhiza/user" - "io" - "net/http" ) -// Meta is a bundle of common stuffs used by views, templates. -type Meta struct { - Lc *l18n.Localizer - U *user.User - W io.Writer - PageTitle string -} - -// MetaFrom makes a Meta from the given data. You are meant to further modify it. -func MetaFrom(w http.ResponseWriter, rq *http.Request) Meta { - return Meta{ - Lc: l18n.FromRequest(rq), - U: user.FromRequest(rq), - W: w, - } -} - //go:embed *.html var fs embed.FS diff --git a/views/categories.go b/views/categories.go index f377a73..665ac0f 100644 --- a/views/categories.go +++ b/views/categories.go @@ -3,6 +3,7 @@ package views import ( "github.com/bouncepaw/mycorrhiza/hyphae/categories" "github.com/bouncepaw/mycorrhiza/util" + "github.com/bouncepaw/mycorrhiza/viewutil" "html/template" "io" "log" @@ -39,14 +40,14 @@ func init() { categoryTemplatesRu = template.Must(template.Must(categoryTemplatesEn.Clone()).Parse(categoriesRu)) } -func localizedCatTemplates(meta Meta) *template.Template { +func localizedCatTemplates(meta viewutil.Meta) *template.Template { if meta.Lc.Locale == "ru" { return categoryTemplatesRu } return categoryTemplatesEn } -func localizedCatTemplateAsString(meta Meta, name string, datum ...interface{}) string { +func localizedCatTemplateAsString(meta viewutil.Meta, name string, datum ...interface{}) string { var buf strings.Builder var err error if len(datum) == 1 { @@ -61,7 +62,7 @@ func localizedCatTemplateAsString(meta Meta, name string, datum ...interface{}) return buf.String() } -func categoryCard(meta Meta, hyphaName string) string { +func categoryCard(meta viewutil.Meta, hyphaName string) string { var buf strings.Builder err := localizedCatTemplates(meta).ExecuteTemplate(&buf, "category card", struct { HyphaName string @@ -78,7 +79,7 @@ func categoryCard(meta Meta, hyphaName string) string { return buf.String() } -func CategoryPage(meta Meta, catName string) { +func CategoryPage(meta viewutil.Meta, catName string) { var buf strings.Builder err := localizedCatTemplates(meta).ExecuteTemplate(&buf, "category page", struct { CatName string @@ -103,7 +104,7 @@ func CategoryPage(meta Meta, catName string) { } } -func CategoryList(meta Meta) { +func CategoryList(meta viewutil.Meta) { var buf strings.Builder err := localizedCatTemplates(meta).ExecuteTemplate(&buf, "category list", struct { Categories []string diff --git a/views/nav.qtpl b/views/nav.qtpl index 097c7f1..132beb3 100644 --- a/views/nav.qtpl +++ b/views/nav.qtpl @@ -4,6 +4,7 @@ {% import "github.com/bouncepaw/mycorrhiza/l18n" %} {% import "github.com/bouncepaw/mycorrhiza/user" %} {% import "github.com/bouncepaw/mycorrhiza/hyphae" %} +{% import "github.com/bouncepaw/mycorrhiza/viewutil" %} {% func hyphaInfoEntry(h hyphae.Hypha, u *user.User, action, displayText string) %} {% if u.CanProceed(action) %} @@ -13,7 +14,7 @@ {% endif %} {% endfunc %} -{% func hyphaInfo(meta Meta, h hyphae.Hypha) %} +{% func hyphaInfo(meta viewutil.Meta, h hyphae.Hypha) %} {% code u := meta.U lc := meta.Lc diff --git a/views/nav.qtpl.go b/views/nav.qtpl.go index ee546a7..3965210 100644 --- a/views/nav.qtpl.go +++ b/views/nav.qtpl.go @@ -22,270 +22,273 @@ import "github.com/bouncepaw/mycorrhiza/user" //line views/nav.qtpl:6 import "github.com/bouncepaw/mycorrhiza/hyphae" -//line views/nav.qtpl:8 +//line views/nav.qtpl:7 +import "github.com/bouncepaw/mycorrhiza/viewutil" + +//line views/nav.qtpl:9 import ( qtio422016 "io" qt422016 "github.com/valyala/quicktemplate" ) -//line views/nav.qtpl:8 +//line views/nav.qtpl:9 var ( _ = qtio422016.Copy _ = qt422016.AcquireByteBuffer ) -//line views/nav.qtpl:8 +//line views/nav.qtpl:9 func streamhyphaInfoEntry(qw422016 *qt422016.Writer, h hyphae.Hypha, u *user.User, action, displayText string) { -//line views/nav.qtpl:8 +//line views/nav.qtpl:9 qw422016.N().S(` `) -//line views/nav.qtpl:9 +//line views/nav.qtpl:10 if u.CanProceed(action) { -//line views/nav.qtpl:9 +//line views/nav.qtpl:10 qw422016.N().S(`
  • `) -//line views/nav.qtpl:11 +//line views/nav.qtpl:12 qw422016.E().S(displayText) -//line views/nav.qtpl:11 +//line views/nav.qtpl:12 qw422016.N().S(`
  • `) -//line views/nav.qtpl:13 +//line views/nav.qtpl:14 } -//line views/nav.qtpl:13 +//line views/nav.qtpl:14 qw422016.N().S(` `) -//line views/nav.qtpl:14 +//line views/nav.qtpl:15 } -//line views/nav.qtpl:14 +//line views/nav.qtpl:15 func writehyphaInfoEntry(qq422016 qtio422016.Writer, h hyphae.Hypha, u *user.User, action, displayText string) { -//line views/nav.qtpl:14 +//line views/nav.qtpl:15 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/nav.qtpl:14 +//line views/nav.qtpl:15 streamhyphaInfoEntry(qw422016, h, u, action, displayText) -//line views/nav.qtpl:14 +//line views/nav.qtpl:15 qt422016.ReleaseWriter(qw422016) -//line views/nav.qtpl:14 +//line views/nav.qtpl:15 } -//line views/nav.qtpl:14 +//line views/nav.qtpl:15 func hyphaInfoEntry(h hyphae.Hypha, u *user.User, action, displayText string) string { -//line views/nav.qtpl:14 +//line views/nav.qtpl:15 qb422016 := qt422016.AcquireByteBuffer() -//line views/nav.qtpl:14 +//line views/nav.qtpl:15 writehyphaInfoEntry(qb422016, h, u, action, displayText) -//line views/nav.qtpl:14 +//line views/nav.qtpl:15 qs422016 := string(qb422016.B) -//line views/nav.qtpl:14 +//line views/nav.qtpl:15 qt422016.ReleaseByteBuffer(qb422016) -//line views/nav.qtpl:14 +//line views/nav.qtpl:15 return qs422016 -//line views/nav.qtpl:14 +//line views/nav.qtpl:15 } -//line views/nav.qtpl:16 -func streamhyphaInfo(qw422016 *qt422016.Writer, meta Meta, h hyphae.Hypha) { -//line views/nav.qtpl:16 +//line views/nav.qtpl:17 +func streamhyphaInfo(qw422016 *qt422016.Writer, meta viewutil.Meta, h hyphae.Hypha) { +//line views/nav.qtpl:17 qw422016.N().S(` `) -//line views/nav.qtpl:18 +//line views/nav.qtpl:19 u := meta.U lc := meta.Lc backs := backlinks.BacklinksCount(h) -//line views/nav.qtpl:21 +//line views/nav.qtpl:22 qw422016.N().S(` `) -//line views/nav.qtpl:32 +//line views/nav.qtpl:33 } -//line views/nav.qtpl:32 -func writehyphaInfo(qq422016 qtio422016.Writer, meta Meta, h hyphae.Hypha) { -//line views/nav.qtpl:32 +//line views/nav.qtpl:33 +func writehyphaInfo(qq422016 qtio422016.Writer, meta viewutil.Meta, h hyphae.Hypha) { +//line views/nav.qtpl:33 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/nav.qtpl:32 +//line views/nav.qtpl:33 streamhyphaInfo(qw422016, meta, h) -//line views/nav.qtpl:32 +//line views/nav.qtpl:33 qt422016.ReleaseWriter(qw422016) -//line views/nav.qtpl:32 +//line views/nav.qtpl:33 } -//line views/nav.qtpl:32 -func hyphaInfo(meta Meta, h hyphae.Hypha) string { -//line views/nav.qtpl:32 +//line views/nav.qtpl:33 +func hyphaInfo(meta viewutil.Meta, h hyphae.Hypha) string { +//line views/nav.qtpl:33 qb422016 := qt422016.AcquireByteBuffer() -//line views/nav.qtpl:32 +//line views/nav.qtpl:33 writehyphaInfo(qb422016, meta, h) -//line views/nav.qtpl:32 +//line views/nav.qtpl:33 qs422016 := string(qb422016.B) -//line views/nav.qtpl:32 +//line views/nav.qtpl:33 qt422016.ReleaseByteBuffer(qb422016) -//line views/nav.qtpl:32 +//line views/nav.qtpl:33 return qs422016 -//line views/nav.qtpl:32 +//line views/nav.qtpl:33 } -//line views/nav.qtpl:34 +//line views/nav.qtpl:35 func streamsiblingHyphae(qw422016 *qt422016.Writer, siblings string, lc *l18n.Localizer) { -//line views/nav.qtpl:34 +//line views/nav.qtpl:35 qw422016.N().S(` `) -//line views/nav.qtpl:35 +//line views/nav.qtpl:36 if cfg.UseSiblingHyphaeSidebar { -//line views/nav.qtpl:35 +//line views/nav.qtpl:36 qw422016.N().S(` `) -//line views/nav.qtpl:40 +//line views/nav.qtpl:41 } -//line views/nav.qtpl:40 +//line views/nav.qtpl:41 qw422016.N().S(` `) -//line views/nav.qtpl:41 +//line views/nav.qtpl:42 } -//line views/nav.qtpl:41 +//line views/nav.qtpl:42 func writesiblingHyphae(qq422016 qtio422016.Writer, siblings string, lc *l18n.Localizer) { -//line views/nav.qtpl:41 +//line views/nav.qtpl:42 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/nav.qtpl:41 +//line views/nav.qtpl:42 streamsiblingHyphae(qw422016, siblings, lc) -//line views/nav.qtpl:41 +//line views/nav.qtpl:42 qt422016.ReleaseWriter(qw422016) -//line views/nav.qtpl:41 +//line views/nav.qtpl:42 } -//line views/nav.qtpl:41 +//line views/nav.qtpl:42 func siblingHyphae(siblings string, lc *l18n.Localizer) string { -//line views/nav.qtpl:41 +//line views/nav.qtpl:42 qb422016 := qt422016.AcquireByteBuffer() -//line views/nav.qtpl:41 +//line views/nav.qtpl:42 writesiblingHyphae(qb422016, siblings, lc) -//line views/nav.qtpl:41 +//line views/nav.qtpl:42 qs422016 := string(qb422016.B) -//line views/nav.qtpl:41 +//line views/nav.qtpl:42 qt422016.ReleaseByteBuffer(qb422016) -//line views/nav.qtpl:41 +//line views/nav.qtpl:42 return qs422016 -//line views/nav.qtpl:41 +//line views/nav.qtpl:42 } -//line views/nav.qtpl:43 +//line views/nav.qtpl:44 func StreamSubhyphae(qw422016 *qt422016.Writer, subhyphae string, lc *l18n.Localizer) { -//line views/nav.qtpl:43 +//line views/nav.qtpl:44 qw422016.N().S(` `) -//line views/nav.qtpl:44 +//line views/nav.qtpl:45 if strings.TrimSpace(subhyphae) != "" { -//line views/nav.qtpl:44 +//line views/nav.qtpl:45 qw422016.N().S(`

    `) -//line views/nav.qtpl:46 +//line views/nav.qtpl:47 qw422016.E().S(lc.Get("ui.subhyphae")) -//line views/nav.qtpl:46 +//line views/nav.qtpl:47 qw422016.N().S(`

    `) -//line views/nav.qtpl:53 +//line views/nav.qtpl:54 } -//line views/nav.qtpl:53 +//line views/nav.qtpl:54 qw422016.N().S(` `) -//line views/nav.qtpl:54 +//line views/nav.qtpl:55 } -//line views/nav.qtpl:54 +//line views/nav.qtpl:55 func WriteSubhyphae(qq422016 qtio422016.Writer, subhyphae string, lc *l18n.Localizer) { -//line views/nav.qtpl:54 +//line views/nav.qtpl:55 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/nav.qtpl:54 +//line views/nav.qtpl:55 StreamSubhyphae(qw422016, subhyphae, lc) -//line views/nav.qtpl:54 +//line views/nav.qtpl:55 qt422016.ReleaseWriter(qw422016) -//line views/nav.qtpl:54 +//line views/nav.qtpl:55 } -//line views/nav.qtpl:54 +//line views/nav.qtpl:55 func Subhyphae(subhyphae string, lc *l18n.Localizer) string { -//line views/nav.qtpl:54 +//line views/nav.qtpl:55 qb422016 := qt422016.AcquireByteBuffer() -//line views/nav.qtpl:54 +//line views/nav.qtpl:55 WriteSubhyphae(qb422016, subhyphae, lc) -//line views/nav.qtpl:54 +//line views/nav.qtpl:55 qs422016 := string(qb422016.B) -//line views/nav.qtpl:54 +//line views/nav.qtpl:55 qt422016.ReleaseByteBuffer(qb422016) -//line views/nav.qtpl:54 +//line views/nav.qtpl:55 return qs422016 -//line views/nav.qtpl:54 +//line views/nav.qtpl:55 } diff --git a/views/readers.qtpl b/views/readers.qtpl index 116f0e9..4eb397d 100644 --- a/views/readers.qtpl +++ b/views/readers.qtpl @@ -10,6 +10,7 @@ {% import "github.com/bouncepaw/mycorrhiza/tree" %} {% import "github.com/bouncepaw/mycorrhiza/user" %} {% import "github.com/bouncepaw/mycorrhiza/util" %} +{% import "github.com/bouncepaw/mycorrhiza/viewutil" %} {% func MediaMenu(rq *http.Request, h hyphae.Hypha, u *user.User) %} {% code @@ -85,7 +86,7 @@ If `contents` == "", a helpful message is shown instead. If you rename .prevnext, change the docs too. -{% func Hypha(meta Meta, h hyphae.Hypha, contents string) %} +{% func Hypha(meta viewutil.Meta, h hyphae.Hypha, contents string) %} {% code siblings, subhyphae, prevHyphaName, nextHyphaName := tree.Tree(h.CanonicalName()) lc := meta.Lc diff --git a/views/readers.qtpl.go b/views/readers.qtpl.go index 06ffd59..90e6540 100644 --- a/views/readers.qtpl.go +++ b/views/readers.qtpl.go @@ -37,599 +37,602 @@ import "github.com/bouncepaw/mycorrhiza/user" //line views/readers.qtpl:12 import "github.com/bouncepaw/mycorrhiza/util" -//line views/readers.qtpl:14 +//line views/readers.qtpl:13 +import "github.com/bouncepaw/mycorrhiza/viewutil" + +//line views/readers.qtpl:15 import ( qtio422016 "io" qt422016 "github.com/valyala/quicktemplate" ) -//line views/readers.qtpl:14 +//line views/readers.qtpl:15 var ( _ = qtio422016.Copy _ = qt422016.AcquireByteBuffer ) -//line views/readers.qtpl:14 +//line views/readers.qtpl:15 func StreamMediaMenu(qw422016 *qt422016.Writer, rq *http.Request, h hyphae.Hypha, u *user.User) { -//line views/readers.qtpl:14 +//line views/readers.qtpl:15 qw422016.N().S(` `) -//line views/readers.qtpl:16 +//line views/readers.qtpl:17 lc := l18n.FromRequest(rq) -//line views/readers.qtpl:17 +//line views/readers.qtpl:18 qw422016.N().S(`

    `) -//line views/readers.qtpl:20 +//line views/readers.qtpl:21 qw422016.N().S(lc.Get("ui.media_title", &l18n.Replacements{"name": beautifulLink(h.CanonicalName())})) -//line views/readers.qtpl:20 +//line views/readers.qtpl:21 qw422016.N().S(`

    `) -//line views/readers.qtpl:21 +//line views/readers.qtpl:22 switch h.(type) { -//line views/readers.qtpl:22 +//line views/readers.qtpl:23 case *hyphae.MediaHypha: -//line views/readers.qtpl:22 +//line views/readers.qtpl:23 qw422016.N().S(`

    `) -//line views/readers.qtpl:23 +//line views/readers.qtpl:24 qw422016.E().S(lc.Get("ui.media_tip")) -//line views/readers.qtpl:23 +//line views/readers.qtpl:24 qw422016.N().S(` `) -//line views/readers.qtpl:23 +//line views/readers.qtpl:24 qw422016.E().S(lc.Get("ui.media_what_is")) -//line views/readers.qtpl:23 +//line views/readers.qtpl:24 qw422016.N().S(`

    `) -//line views/readers.qtpl:24 +//line views/readers.qtpl:25 default: -//line views/readers.qtpl:24 +//line views/readers.qtpl:25 qw422016.N().S(`

    `) -//line views/readers.qtpl:25 +//line views/readers.qtpl:26 qw422016.E().S(lc.Get("ui.media_empty")) -//line views/readers.qtpl:25 +//line views/readers.qtpl:26 qw422016.N().S(` `) -//line views/readers.qtpl:25 +//line views/readers.qtpl:26 qw422016.E().S(lc.Get("ui.media_what_is")) -//line views/readers.qtpl:25 +//line views/readers.qtpl:26 qw422016.N().S(`

    `) -//line views/readers.qtpl:26 +//line views/readers.qtpl:27 } -//line views/readers.qtpl:26 +//line views/readers.qtpl:27 qw422016.N().S(`
    `) -//line views/readers.qtpl:29 +//line views/readers.qtpl:30 switch h := h.(type) { -//line views/readers.qtpl:30 +//line views/readers.qtpl:31 case *hyphae.MediaHypha: -//line views/readers.qtpl:30 +//line views/readers.qtpl:31 qw422016.N().S(` `) -//line views/readers.qtpl:32 +//line views/readers.qtpl:33 mime := mimetype.FromExtension(path.Ext(h.MediaFilePath())) fileinfo, err := os.Stat(h.MediaFilePath()) -//line views/readers.qtpl:33 +//line views/readers.qtpl:34 qw422016.N().S(` `) -//line views/readers.qtpl:34 +//line views/readers.qtpl:35 if err == nil { -//line views/readers.qtpl:34 +//line views/readers.qtpl:35 qw422016.N().S(`
    `) -//line views/readers.qtpl:36 +//line views/readers.qtpl:37 qw422016.E().S(lc.Get("ui.media_stat")) -//line views/readers.qtpl:36 +//line views/readers.qtpl:37 qw422016.N().S(`

    `) -//line views/readers.qtpl:38 +//line views/readers.qtpl:39 qw422016.E().S(lc.Get("ui.media_stat_mime")) -//line views/readers.qtpl:38 +//line views/readers.qtpl:39 qw422016.N().S(` `) -//line views/readers.qtpl:38 +//line views/readers.qtpl:39 qw422016.E().S(mime) -//line views/readers.qtpl:38 +//line views/readers.qtpl:39 qw422016.N().S(`

    `) -//line views/readers.qtpl:40 +//line views/readers.qtpl:41 } -//line views/readers.qtpl:40 +//line views/readers.qtpl:41 qw422016.N().S(` `) -//line views/readers.qtpl:42 +//line views/readers.qtpl:43 if strings.HasPrefix(mime, "image/") { -//line views/readers.qtpl:42 +//line views/readers.qtpl:43 qw422016.N().S(`
    `) -//line views/readers.qtpl:44 +//line views/readers.qtpl:45 qw422016.E().S(lc.Get("ui.media_include")) -//line views/readers.qtpl:44 +//line views/readers.qtpl:45 qw422016.N().S(`
    img { `)
    -//line views/readers.qtpl:46
    +//line views/readers.qtpl:47
     			qw422016.E().S(h.CanonicalName())
    -//line views/readers.qtpl:46
    +//line views/readers.qtpl:47
     			qw422016.N().S(` }
    `) -//line views/readers.qtpl:48 +//line views/readers.qtpl:49 } -//line views/readers.qtpl:48 +//line views/readers.qtpl:49 qw422016.N().S(` `) -//line views/readers.qtpl:49 +//line views/readers.qtpl:50 } -//line views/readers.qtpl:49 +//line views/readers.qtpl:50 qw422016.N().S(` `) -//line views/readers.qtpl:51 +//line views/readers.qtpl:52 if u.CanProceed("upload-binary") { -//line views/readers.qtpl:51 +//line views/readers.qtpl:52 qw422016.N().S(` `) -//line views/readers.qtpl:64 +//line views/readers.qtpl:65 } -//line views/readers.qtpl:64 +//line views/readers.qtpl:65 qw422016.N().S(` `) -//line views/readers.qtpl:67 +//line views/readers.qtpl:68 switch h := h.(type) { -//line views/readers.qtpl:68 +//line views/readers.qtpl:69 case *hyphae.MediaHypha: -//line views/readers.qtpl:68 +//line views/readers.qtpl:69 qw422016.N().S(` `) -//line views/readers.qtpl:69 +//line views/readers.qtpl:70 if u.CanProceed("remove-media") { -//line views/readers.qtpl:69 +//line views/readers.qtpl:70 qw422016.N().S(` `) -//line views/readers.qtpl:77 +//line views/readers.qtpl:78 } -//line views/readers.qtpl:77 +//line views/readers.qtpl:78 qw422016.N().S(` `) -//line views/readers.qtpl:78 +//line views/readers.qtpl:79 } -//line views/readers.qtpl:78 +//line views/readers.qtpl:79 qw422016.N().S(`
    `) -//line views/readers.qtpl:83 +//line views/readers.qtpl:84 } -//line views/readers.qtpl:83 +//line views/readers.qtpl:84 func WriteMediaMenu(qq422016 qtio422016.Writer, rq *http.Request, h hyphae.Hypha, u *user.User) { -//line views/readers.qtpl:83 +//line views/readers.qtpl:84 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/readers.qtpl:83 +//line views/readers.qtpl:84 StreamMediaMenu(qw422016, rq, h, u) -//line views/readers.qtpl:83 +//line views/readers.qtpl:84 qt422016.ReleaseWriter(qw422016) -//line views/readers.qtpl:83 +//line views/readers.qtpl:84 } -//line views/readers.qtpl:83 +//line views/readers.qtpl:84 func MediaMenu(rq *http.Request, h hyphae.Hypha, u *user.User) string { -//line views/readers.qtpl:83 +//line views/readers.qtpl:84 qb422016 := qt422016.AcquireByteBuffer() -//line views/readers.qtpl:83 +//line views/readers.qtpl:84 WriteMediaMenu(qb422016, rq, h, u) -//line views/readers.qtpl:83 +//line views/readers.qtpl:84 qs422016 := string(qb422016.B) -//line views/readers.qtpl:83 +//line views/readers.qtpl:84 qt422016.ReleaseByteBuffer(qb422016) -//line views/readers.qtpl:83 +//line views/readers.qtpl:84 return qs422016 -//line views/readers.qtpl:83 +//line views/readers.qtpl:84 } // If `contents` == "", a helpful message is shown instead. // // If you rename .prevnext, change the docs too. -//line views/readers.qtpl:88 -func StreamHypha(qw422016 *qt422016.Writer, meta Meta, h hyphae.Hypha, contents string) { -//line views/readers.qtpl:88 +//line views/readers.qtpl:89 +func StreamHypha(qw422016 *qt422016.Writer, meta viewutil.Meta, h hyphae.Hypha, contents string) { +//line views/readers.qtpl:89 qw422016.N().S(` `) -//line views/readers.qtpl:90 +//line views/readers.qtpl:91 siblings, subhyphae, prevHyphaName, nextHyphaName := tree.Tree(h.CanonicalName()) lc := meta.Lc -//line views/readers.qtpl:92 +//line views/readers.qtpl:93 qw422016.N().S(`
    `) -//line views/readers.qtpl:96 +//line views/readers.qtpl:97 if meta.U.CanProceed("edit") { -//line views/readers.qtpl:96 +//line views/readers.qtpl:97 qw422016.N().S(` `) -//line views/readers.qtpl:100 +//line views/readers.qtpl:101 } -//line views/readers.qtpl:100 +//line views/readers.qtpl:101 qw422016.N().S(` `) -//line views/readers.qtpl:102 +//line views/readers.qtpl:103 if cfg.UseAuth && util.IsProfileName(h.CanonicalName()) && meta.U.Name == strings.TrimPrefix(h.CanonicalName(), cfg.UserHypha+"/") { -//line views/readers.qtpl:102 +//line views/readers.qtpl:103 qw422016.N().S(` `) -//line views/readers.qtpl:106 +//line views/readers.qtpl:107 if meta.U.Group == "admin" { -//line views/readers.qtpl:106 +//line views/readers.qtpl:107 qw422016.N().S(` `) -//line views/readers.qtpl:110 +//line views/readers.qtpl:111 } -//line views/readers.qtpl:110 +//line views/readers.qtpl:111 qw422016.N().S(` `) -//line views/readers.qtpl:111 +//line views/readers.qtpl:112 } -//line views/readers.qtpl:111 +//line views/readers.qtpl:112 qw422016.N().S(` `) -//line views/readers.qtpl:113 +//line views/readers.qtpl:114 qw422016.N().S(NaviTitle(h)) -//line views/readers.qtpl:113 +//line views/readers.qtpl:114 qw422016.N().S(` `) -//line views/readers.qtpl:114 +//line views/readers.qtpl:115 switch h.(type) { -//line views/readers.qtpl:115 +//line views/readers.qtpl:116 case *hyphae.EmptyHypha: -//line views/readers.qtpl:115 +//line views/readers.qtpl:116 qw422016.N().S(` `) -//line views/readers.qtpl:116 +//line views/readers.qtpl:117 streamnonExistentHyphaNotice(qw422016, h, meta.U, meta.Lc) -//line views/readers.qtpl:116 +//line views/readers.qtpl:117 qw422016.N().S(` `) -//line views/readers.qtpl:117 +//line views/readers.qtpl:118 default: -//line views/readers.qtpl:117 +//line views/readers.qtpl:118 qw422016.N().S(` `) -//line views/readers.qtpl:118 +//line views/readers.qtpl:119 qw422016.N().S(contents) -//line views/readers.qtpl:118 +//line views/readers.qtpl:119 qw422016.N().S(` `) -//line views/readers.qtpl:119 +//line views/readers.qtpl:120 } -//line views/readers.qtpl:119 +//line views/readers.qtpl:120 qw422016.N().S(`
    `) -//line views/readers.qtpl:122 +//line views/readers.qtpl:123 if prevHyphaName != "" { -//line views/readers.qtpl:122 +//line views/readers.qtpl:123 qw422016.N().S(` `) -//line views/readers.qtpl:124 +//line views/readers.qtpl:125 } -//line views/readers.qtpl:124 +//line views/readers.qtpl:125 qw422016.N().S(` `) -//line views/readers.qtpl:125 +//line views/readers.qtpl:126 if nextHyphaName != "" { -//line views/readers.qtpl:125 +//line views/readers.qtpl:126 qw422016.N().S(` `) -//line views/readers.qtpl:127 +//line views/readers.qtpl:128 } -//line views/readers.qtpl:127 +//line views/readers.qtpl:128 qw422016.N().S(`
    `) -//line views/readers.qtpl:129 +//line views/readers.qtpl:130 StreamSubhyphae(qw422016, subhyphae, meta.Lc) -//line views/readers.qtpl:129 +//line views/readers.qtpl:130 qw422016.N().S(`
    `) -//line views/readers.qtpl:131 +//line views/readers.qtpl:132 streamhyphaInfo(qw422016, meta, h) -//line views/readers.qtpl:131 +//line views/readers.qtpl:132 qw422016.N().S(`
    `) -//line views/readers.qtpl:134 +//line views/readers.qtpl:135 qw422016.N().S(categoryCard(meta, h.CanonicalName())) -//line views/readers.qtpl:134 +//line views/readers.qtpl:135 qw422016.N().S(` `) -//line views/readers.qtpl:135 +//line views/readers.qtpl:136 streamsiblingHyphae(qw422016, siblings, meta.Lc) -//line views/readers.qtpl:135 +//line views/readers.qtpl:136 qw422016.N().S(`
    `) -//line views/readers.qtpl:137 +//line views/readers.qtpl:138 streamviewScripts(qw422016) -//line views/readers.qtpl:137 +//line views/readers.qtpl:138 qw422016.N().S(` `) -//line views/readers.qtpl:138 +//line views/readers.qtpl:139 } -//line views/readers.qtpl:138 -func WriteHypha(qq422016 qtio422016.Writer, meta Meta, h hyphae.Hypha, contents string) { -//line views/readers.qtpl:138 +//line views/readers.qtpl:139 +func WriteHypha(qq422016 qtio422016.Writer, meta viewutil.Meta, h hyphae.Hypha, contents string) { +//line views/readers.qtpl:139 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/readers.qtpl:138 +//line views/readers.qtpl:139 StreamHypha(qw422016, meta, h, contents) -//line views/readers.qtpl:138 +//line views/readers.qtpl:139 qt422016.ReleaseWriter(qw422016) -//line views/readers.qtpl:138 +//line views/readers.qtpl:139 } -//line views/readers.qtpl:138 -func Hypha(meta Meta, h hyphae.Hypha, contents string) string { -//line views/readers.qtpl:138 +//line views/readers.qtpl:139 +func Hypha(meta viewutil.Meta, h hyphae.Hypha, contents string) string { +//line views/readers.qtpl:139 qb422016 := qt422016.AcquireByteBuffer() -//line views/readers.qtpl:138 +//line views/readers.qtpl:139 WriteHypha(qb422016, meta, h, contents) -//line views/readers.qtpl:138 +//line views/readers.qtpl:139 qs422016 := string(qb422016.B) -//line views/readers.qtpl:138 +//line views/readers.qtpl:139 qt422016.ReleaseByteBuffer(qb422016) -//line views/readers.qtpl:138 +//line views/readers.qtpl:139 return qs422016 -//line views/readers.qtpl:138 +//line views/readers.qtpl:139 } -//line views/readers.qtpl:140 +//line views/readers.qtpl:141 func StreamRevision(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents, revHash string) { -//line views/readers.qtpl:140 +//line views/readers.qtpl:141 qw422016.N().S(`

    `) -//line views/readers.qtpl:144 +//line views/readers.qtpl:145 qw422016.E().S(lc.Get("ui.revision_warning")) -//line views/readers.qtpl:144 +//line views/readers.qtpl:145 qw422016.N().S(` `) -//line views/readers.qtpl:144 +//line views/readers.qtpl:145 qw422016.E().S(lc.Get("ui.revision_link")) -//line views/readers.qtpl:144 +//line views/readers.qtpl:145 qw422016.N().S(`

    `) -//line views/readers.qtpl:145 +//line views/readers.qtpl:146 qw422016.N().S(NaviTitle(h)) -//line views/readers.qtpl:145 +//line views/readers.qtpl:146 qw422016.N().S(` `) -//line views/readers.qtpl:146 +//line views/readers.qtpl:147 qw422016.N().S(contents) -//line views/readers.qtpl:146 +//line views/readers.qtpl:147 qw422016.N().S(`
    `) -//line views/readers.qtpl:150 +//line views/readers.qtpl:151 streamviewScripts(qw422016) -//line views/readers.qtpl:150 +//line views/readers.qtpl:151 qw422016.N().S(` `) -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 } -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 func WriteRevision(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents, revHash string) { -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 StreamRevision(qw422016, rq, lc, h, contents, revHash) -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 qt422016.ReleaseWriter(qw422016) -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 } -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 func Revision(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents, revHash string) string { -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 qb422016 := qt422016.AcquireByteBuffer() -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 WriteRevision(qb422016, rq, lc, h, contents, revHash) -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 qs422016 := string(qb422016.B) -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 qt422016.ReleaseByteBuffer(qb422016) -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 return qs422016 -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 } -//line views/readers.qtpl:153 +//line views/readers.qtpl:154 func streamviewScripts(qw422016 *qt422016.Writer) { -//line views/readers.qtpl:153 +//line views/readers.qtpl:154 qw422016.N().S(` `) -//line views/readers.qtpl:154 +//line views/readers.qtpl:155 for _, scriptPath := range cfg.ViewScripts { -//line views/readers.qtpl:154 +//line views/readers.qtpl:155 qw422016.N().S(` `) -//line views/readers.qtpl:156 +//line views/readers.qtpl:157 } -//line views/readers.qtpl:156 +//line views/readers.qtpl:157 qw422016.N().S(` `) -//line views/readers.qtpl:157 +//line views/readers.qtpl:158 } -//line views/readers.qtpl:157 +//line views/readers.qtpl:158 func writeviewScripts(qq422016 qtio422016.Writer) { -//line views/readers.qtpl:157 +//line views/readers.qtpl:158 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/readers.qtpl:157 +//line views/readers.qtpl:158 streamviewScripts(qw422016) -//line views/readers.qtpl:157 +//line views/readers.qtpl:158 qt422016.ReleaseWriter(qw422016) -//line views/readers.qtpl:157 +//line views/readers.qtpl:158 } -//line views/readers.qtpl:157 +//line views/readers.qtpl:158 func viewScripts() string { -//line views/readers.qtpl:157 +//line views/readers.qtpl:158 qb422016 := qt422016.AcquireByteBuffer() -//line views/readers.qtpl:157 +//line views/readers.qtpl:158 writeviewScripts(qb422016) -//line views/readers.qtpl:157 +//line views/readers.qtpl:158 qs422016 := string(qb422016.B) -//line views/readers.qtpl:157 +//line views/readers.qtpl:158 qt422016.ReleaseByteBuffer(qb422016) -//line views/readers.qtpl:157 +//line views/readers.qtpl:158 return qs422016 -//line views/readers.qtpl:157 +//line views/readers.qtpl:158 } diff --git a/viewutil/base.html b/viewutil/base.html new file mode 100644 index 0000000..8bbdf7c --- /dev/null +++ b/viewutil/base.html @@ -0,0 +1,83 @@ +{{define "base"}} + + + + + + {{.Title}} + + + + {{range .HeadElements}}{{.}}{{end}} + + +
    + +
    +{{block "body" .}}{{end}} + +{{range .CommonScripts}}{{.}}{{end}} + + + + +{{end}} \ No newline at end of file diff --git a/viewutil/meta.go b/viewutil/meta.go new file mode 100644 index 0000000..c51db6e --- /dev/null +++ b/viewutil/meta.go @@ -0,0 +1,28 @@ +package viewutil + +import ( + "github.com/bouncepaw/mycorrhiza/l18n" + "github.com/bouncepaw/mycorrhiza/user" + "io" + "net/http" +) + +// Meta is a bundle of common stuffs used by views, templates. +type Meta struct { + Lc *l18n.Localizer + U *user.User + W io.Writer +} + +// MetaFrom makes a Meta from the given data. You are meant to further modify it. +func MetaFrom(w http.ResponseWriter, rq *http.Request) Meta { + return Meta{ + Lc: l18n.FromRequest(rq), + U: user.FromRequest(rq), + W: w, + } +} + +func (m *Meta) Locale() string { + return m.Lc.Locale +} diff --git a/viewutil/viewutil.go b/viewutil/viewutil.go new file mode 100644 index 0000000..f023101 --- /dev/null +++ b/viewutil/viewutil.go @@ -0,0 +1,85 @@ +// 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/l18n" + "github.com/bouncepaw/mycorrhiza/user" + "html/template" + "log" + "strings" +) + +var ( + //go:embed viewutil.go + fs 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}} +`, cfg.WikiName) + BaseEn = m(m(template.ParseFS(fs, "viewutil.go")).Parse(dataText)) + if !cfg.UseAuth { + m(BaseEn.Parse(`{{define "auth"}}{{end}}`)) + } + if !cfg.AllowRegistration { + m(BaseEn.Parse(`{{define "registration"}}{{end}}`)) + } + BaseRu = m(m(BaseEn.Clone()).Parse(ruText)) +} + +// TODO: get rid of this +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}}`)) +} + +type baseData struct { + Meta Meta + Title string + HeadElements []string + HeaderLinks []cfg.HeaderLink + CommonScripts []string + Body string // TODO: remove +} + +// Base is a temporary wrapper around BaseEn and BaseRu, meant to facilitate the migration from qtpl. +func Base(title, body string, lc *l18n.Localizer, u *user.User, headElements ...string) string { + var w strings.Builder + meta := Meta{ + Lc: lc, + U: u, + W: &w, + } + t := localizedBaseWithWeirdBody(meta) + err := t.Execute(&w, baseData{ + Meta: meta, + Title: title, + HeadElements: headElements, + HeaderLinks: cfg.HeaderLinks, + CommonScripts: cfg.CommonScripts, + Body: body, + }) + if err != nil { + log.Println(err) + } + return w.String() +} diff --git a/web/admin.go b/web/admin.go index a463f9a..2302d85 100644 --- a/web/admin.go +++ b/web/admin.go @@ -2,6 +2,7 @@ package web import ( "fmt" + "github.com/bouncepaw/mycorrhiza/viewutil" "io" "log" "mime" @@ -35,7 +36,7 @@ func initAdmin(r *mux.Router) { func handlerAdmin(w http.ResponseWriter, rq *http.Request) { w.Header().Set("Content-Type", "text/html;charset=utf-8") w.WriteHeader(http.StatusOK) - views.AdminPanel(views.MetaFrom(w, rq)) + views.AdminPanel(viewutil.MetaFrom(w, rq)) } // handlerAdminShutdown kills the wiki. diff --git a/web/categories.go b/web/categories.go index fc42444..aa38545 100644 --- a/web/categories.go +++ b/web/categories.go @@ -5,6 +5,7 @@ import ( "github.com/bouncepaw/mycorrhiza/user" "github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/views" + "github.com/bouncepaw/mycorrhiza/viewutil" "github.com/gorilla/mux" "io" "log" @@ -21,7 +22,7 @@ func initCategories(r *mux.Router) { func handlerListCategory(w http.ResponseWriter, rq *http.Request) { log.Println("Viewing list of categories") - views.CategoryList(views.MetaFrom(w, rq)) + views.CategoryList(viewutil.MetaFrom(w, rq)) } func handlerCategory(w http.ResponseWriter, rq *http.Request) { @@ -32,7 +33,7 @@ func handlerCategory(w http.ResponseWriter, rq *http.Request) { return } log.Println("Viewing category", catName) - views.CategoryPage(views.MetaFrom(w, rq), catName) + views.CategoryPage(viewutil.MetaFrom(w, rq), catName) } func handlerRemoveFromCategory(w http.ResponseWriter, rq *http.Request) { diff --git a/web/readers.go b/web/readers.go index 051279d..de44839 100644 --- a/web/readers.go +++ b/web/readers.go @@ -3,6 +3,7 @@ package web import ( "encoding/hex" "fmt" + "github.com/bouncepaw/mycorrhiza/viewutil" "io" "log" "net/http" @@ -209,7 +210,7 @@ func handlerHypha(w http.ResponseWriter, rq *http.Request) { util.HTTP404Page(w, views.Base( util.BeautifulName(hyphaName), - views.Hypha(views.MetaFrom(w, rq), h, contents), + views.Hypha(viewutil.MetaFrom(w, rq), h, contents), lc, u, openGraph)) @@ -231,7 +232,7 @@ func handlerHypha(w http.ResponseWriter, rq *http.Request) { util.HTTP200Page(w, views.Base( util.BeautifulName(hyphaName), - views.Hypha(views.MetaFrom(w, rq), h, contents), + views.Hypha(viewutil.MetaFrom(w, rq), h, contents), lc, u, openGraph)) From 2769a096e53ecf2eb4bc2ee012e2513ada75df01 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Wed, 30 Mar 2022 00:11:34 +0300 Subject: [PATCH 02/23] Alias views.Base to a wrapper to viewutil.Base --- views/base.go | 8 +- views/stuff.qtpl | 77 ------- views/stuff.qtpl.go | 536 +++++++++++++------------------------------ viewutil/meta.go | 2 +- viewutil/viewutil.go | 13 +- 5 files changed, 176 insertions(+), 460 deletions(-) diff --git a/views/base.go b/views/base.go index 1fc4ccd..4b7e50b 100644 --- a/views/base.go +++ b/views/base.go @@ -2,7 +2,11 @@ package views import ( "embed" + "github.com/bouncepaw/mycorrhiza/viewutil" ) -//go:embed *.html -var fs embed.FS +var ( + //go:embed *.html + fs embed.FS + Base = viewutil.Base +) diff --git a/views/stuff.qtpl b/views/stuff.qtpl index 3c164d5..9536c04 100644 --- a/views/stuff.qtpl +++ b/views/stuff.qtpl @@ -3,86 +3,9 @@ {% import "github.com/bouncepaw/mycorrhiza/cfg" %} {% import "github.com/bouncepaw/mycorrhiza/hyphae" %} -{% import "github.com/bouncepaw/mycorrhiza/user" %} {% import "github.com/bouncepaw/mycorrhiza/util" %} {% import "github.com/bouncepaw/mycorrhiza/l18n" %} -{% func Base(title, body string, lc *l18n.Localizer, u *user.User, headElements ...string) %} - - - - - - {%s title %} - - - - {% for _, el := range headElements %}{%s= el %}{% endfor %} - - -
    - -
    - {%s= body %} - - {%= commonScripts() %} - - - -{% endfunc %} - {% func TitleSearch(query string, generator func(string) <-chan string, lc *l18n.Localizer) %}
    diff --git a/views/stuff.qtpl.go b/views/stuff.qtpl.go index ee439b0..043876f 100644 --- a/views/stuff.qtpl.go +++ b/views/stuff.qtpl.go @@ -17,318 +17,102 @@ import "github.com/bouncepaw/mycorrhiza/cfg" import "github.com/bouncepaw/mycorrhiza/hyphae" //line views/stuff.qtpl:6 -import "github.com/bouncepaw/mycorrhiza/user" - -//line views/stuff.qtpl:7 import "github.com/bouncepaw/mycorrhiza/util" -//line views/stuff.qtpl:8 +//line views/stuff.qtpl:7 import "github.com/bouncepaw/mycorrhiza/l18n" -//line views/stuff.qtpl:10 +//line views/stuff.qtpl:9 import ( qtio422016 "io" qt422016 "github.com/valyala/quicktemplate" ) -//line views/stuff.qtpl:10 +//line views/stuff.qtpl:9 var ( _ = qtio422016.Copy _ = qt422016.AcquireByteBuffer ) -//line views/stuff.qtpl:10 -func StreamBase(qw422016 *qt422016.Writer, title, body string, lc *l18n.Localizer, u *user.User, headElements ...string) { -//line views/stuff.qtpl:10 - qw422016.N().S(` - - - - - - `) -//line views/stuff.qtpl:16 - qw422016.E().S(title) -//line views/stuff.qtpl:16 - qw422016.N().S(` - - - - `) -//line views/stuff.qtpl:20 - for _, el := range headElements { -//line views/stuff.qtpl:20 - qw422016.N().S(el) -//line views/stuff.qtpl:20 - } -//line views/stuff.qtpl:20 - qw422016.N().S(` - - -
    - -
    - `) -//line views/stuff.qtpl:68 - qw422016.N().S(body) -//line views/stuff.qtpl:68 - qw422016.N().S(` - - `) -//line views/stuff.qtpl:80 - streamcommonScripts(qw422016) -//line views/stuff.qtpl:80 - qw422016.N().S(` - - - -`) -//line views/stuff.qtpl:84 -} - -//line views/stuff.qtpl:84 -func WriteBase(qq422016 qtio422016.Writer, title, body string, lc *l18n.Localizer, u *user.User, headElements ...string) { -//line views/stuff.qtpl:84 - qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:84 - StreamBase(qw422016, title, body, lc, u, headElements...) -//line views/stuff.qtpl:84 - qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:84 -} - -//line views/stuff.qtpl:84 -func Base(title, body string, lc *l18n.Localizer, u *user.User, headElements ...string) string { -//line views/stuff.qtpl:84 - qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:84 - WriteBase(qb422016, title, body, lc, u, headElements...) -//line views/stuff.qtpl:84 - qs422016 := string(qb422016.B) -//line views/stuff.qtpl:84 - qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:84 - return qs422016 -//line views/stuff.qtpl:84 -} - -//line views/stuff.qtpl:86 +//line views/stuff.qtpl:9 func StreamTitleSearch(qw422016 *qt422016.Writer, query string, generator func(string) <-chan string, lc *l18n.Localizer) { -//line views/stuff.qtpl:86 +//line views/stuff.qtpl:9 qw422016.N().S(`

    `) -//line views/stuff.qtpl:89 +//line views/stuff.qtpl:12 qw422016.E().S(lc.Get("ui.search_results_query", &l18n.Replacements{"query": query})) -//line views/stuff.qtpl:89 +//line views/stuff.qtpl:12 qw422016.N().S(`

    `) -//line views/stuff.qtpl:90 +//line views/stuff.qtpl:13 qw422016.E().S(lc.Get("ui.search_results_desc")) -//line views/stuff.qtpl:90 +//line views/stuff.qtpl:13 qw422016.N().S(`

    `) -//line views/stuff.qtpl:99 +//line views/stuff.qtpl:22 } -//line views/stuff.qtpl:99 +//line views/stuff.qtpl:22 func WriteTitleSearch(qq422016 qtio422016.Writer, query string, generator func(string) <-chan string, lc *l18n.Localizer) { -//line views/stuff.qtpl:99 +//line views/stuff.qtpl:22 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:99 +//line views/stuff.qtpl:22 StreamTitleSearch(qw422016, query, generator, lc) -//line views/stuff.qtpl:99 +//line views/stuff.qtpl:22 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:99 +//line views/stuff.qtpl:22 } -//line views/stuff.qtpl:99 +//line views/stuff.qtpl:22 func TitleSearch(query string, generator func(string) <-chan string, lc *l18n.Localizer) string { -//line views/stuff.qtpl:99 +//line views/stuff.qtpl:22 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:99 +//line views/stuff.qtpl:22 WriteTitleSearch(qb422016, query, generator, lc) -//line views/stuff.qtpl:99 +//line views/stuff.qtpl:22 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:99 +//line views/stuff.qtpl:22 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:99 +//line views/stuff.qtpl:22 return qs422016 -//line views/stuff.qtpl:99 +//line views/stuff.qtpl:22 } -//line views/stuff.qtpl:101 +//line views/stuff.qtpl:24 func StreamBacklinks(qw422016 *qt422016.Writer, hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) { -//line views/stuff.qtpl:101 +//line views/stuff.qtpl:24 qw422016.N().S(`

    `) -//line views/stuff.qtpl:104 +//line views/stuff.qtpl:27 qw422016.N().S(lc.Get( "ui.backlinks_heading", &l18n.Replacements{ @@ -339,194 +123,194 @@ func StreamBacklinks(qw422016 *qt422016.Writer, hyphaName string, generator func ), }, )) -//line views/stuff.qtpl:113 +//line views/stuff.qtpl:36 qw422016.N().S(`

    `) -//line views/stuff.qtpl:114 +//line views/stuff.qtpl:37 qw422016.E().S(lc.Get("ui.backlinks_desc")) -//line views/stuff.qtpl:114 +//line views/stuff.qtpl:37 qw422016.N().S(`

    `) -//line views/stuff.qtpl:124 +//line views/stuff.qtpl:47 } -//line views/stuff.qtpl:124 +//line views/stuff.qtpl:47 func WriteBacklinks(qq422016 qtio422016.Writer, hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) { -//line views/stuff.qtpl:124 +//line views/stuff.qtpl:47 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:124 +//line views/stuff.qtpl:47 StreamBacklinks(qw422016, hyphaName, generator, lc) -//line views/stuff.qtpl:124 +//line views/stuff.qtpl:47 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:124 +//line views/stuff.qtpl:47 } -//line views/stuff.qtpl:124 +//line views/stuff.qtpl:47 func Backlinks(hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) string { -//line views/stuff.qtpl:124 +//line views/stuff.qtpl:47 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:124 +//line views/stuff.qtpl:47 WriteBacklinks(qb422016, hyphaName, generator, lc) -//line views/stuff.qtpl:124 +//line views/stuff.qtpl:47 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:124 +//line views/stuff.qtpl:47 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:124 +//line views/stuff.qtpl:47 return qs422016 -//line views/stuff.qtpl:124 +//line views/stuff.qtpl:47 } -//line views/stuff.qtpl:126 +//line views/stuff.qtpl:49 func StreamHelp(qw422016 *qt422016.Writer, content, lang string, lc *l18n.Localizer) { -//line views/stuff.qtpl:126 +//line views/stuff.qtpl:49 qw422016.N().S(`
    `) -//line views/stuff.qtpl:130 +//line views/stuff.qtpl:53 qw422016.N().S(content) -//line views/stuff.qtpl:130 +//line views/stuff.qtpl:53 qw422016.N().S(`
    `) -//line views/stuff.qtpl:133 +//line views/stuff.qtpl:56 qw422016.N().S(helpTopics(lang, lc)) -//line views/stuff.qtpl:133 +//line views/stuff.qtpl:56 qw422016.N().S(`
    `) -//line views/stuff.qtpl:135 +//line views/stuff.qtpl:58 } -//line views/stuff.qtpl:135 +//line views/stuff.qtpl:58 func WriteHelp(qq422016 qtio422016.Writer, content, lang string, lc *l18n.Localizer) { -//line views/stuff.qtpl:135 +//line views/stuff.qtpl:58 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:135 +//line views/stuff.qtpl:58 StreamHelp(qw422016, content, lang, lc) -//line views/stuff.qtpl:135 +//line views/stuff.qtpl:58 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:135 +//line views/stuff.qtpl:58 } -//line views/stuff.qtpl:135 +//line views/stuff.qtpl:58 func Help(content, lang string, lc *l18n.Localizer) string { -//line views/stuff.qtpl:135 +//line views/stuff.qtpl:58 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:135 +//line views/stuff.qtpl:58 WriteHelp(qb422016, content, lang, lc) -//line views/stuff.qtpl:135 +//line views/stuff.qtpl:58 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:135 +//line views/stuff.qtpl:58 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:135 +//line views/stuff.qtpl:58 return qs422016 -//line views/stuff.qtpl:135 +//line views/stuff.qtpl:58 } -//line views/stuff.qtpl:137 +//line views/stuff.qtpl:60 func StreamHelpEmptyError(qw422016 *qt422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:137 +//line views/stuff.qtpl:60 qw422016.N().S(`

    `) -//line views/stuff.qtpl:138 +//line views/stuff.qtpl:61 qw422016.E().S(lc.Get("help.empty_error_title")) -//line views/stuff.qtpl:138 +//line views/stuff.qtpl:61 qw422016.N().S(`

    `) -//line views/stuff.qtpl:139 +//line views/stuff.qtpl:62 qw422016.E().S(lc.Get("help.empty_error_line_1")) -//line views/stuff.qtpl:139 +//line views/stuff.qtpl:62 qw422016.N().S(`

    `) -//line views/stuff.qtpl:140 +//line views/stuff.qtpl:63 qw422016.E().S(lc.Get("help.empty_error_line_2a")) -//line views/stuff.qtpl:140 +//line views/stuff.qtpl:63 qw422016.N().S(` `) -//line views/stuff.qtpl:140 +//line views/stuff.qtpl:63 qw422016.E().S(lc.Get("help.empty_error_link")) -//line views/stuff.qtpl:140 +//line views/stuff.qtpl:63 qw422016.N().S(` `) -//line views/stuff.qtpl:140 +//line views/stuff.qtpl:63 qw422016.E().S(lc.Get("help.empty_error_line_2b")) -//line views/stuff.qtpl:140 +//line views/stuff.qtpl:63 qw422016.N().S(`

    `) -//line views/stuff.qtpl:141 +//line views/stuff.qtpl:64 } -//line views/stuff.qtpl:141 +//line views/stuff.qtpl:64 func WriteHelpEmptyError(qq422016 qtio422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:141 +//line views/stuff.qtpl:64 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:141 +//line views/stuff.qtpl:64 StreamHelpEmptyError(qw422016, lc) -//line views/stuff.qtpl:141 +//line views/stuff.qtpl:64 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:141 +//line views/stuff.qtpl:64 } -//line views/stuff.qtpl:141 +//line views/stuff.qtpl:64 func HelpEmptyError(lc *l18n.Localizer) string { -//line views/stuff.qtpl:141 +//line views/stuff.qtpl:64 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:141 +//line views/stuff.qtpl:64 WriteHelpEmptyError(qb422016, lc) -//line views/stuff.qtpl:141 +//line views/stuff.qtpl:64 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:141 +//line views/stuff.qtpl:64 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:141 +//line views/stuff.qtpl:64 return qs422016 -//line views/stuff.qtpl:141 +//line views/stuff.qtpl:64 } -//line views/stuff.qtpl:143 +//line views/stuff.qtpl:66 func StreamHyphaList(qw422016 *qt422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:143 +//line views/stuff.qtpl:66 qw422016.N().S(`

    `) -//line views/stuff.qtpl:146 +//line views/stuff.qtpl:69 qw422016.E().S(lc.Get("ui.list_heading")) -//line views/stuff.qtpl:146 +//line views/stuff.qtpl:69 qw422016.N().S(`

    `) -//line views/stuff.qtpl:147 +//line views/stuff.qtpl:70 qw422016.E().S(lc.GetPlural("ui.list_desc", hyphae.Count())) -//line views/stuff.qtpl:147 +//line views/stuff.qtpl:70 qw422016.N().S(`

      `) -//line views/stuff.qtpl:150 +//line views/stuff.qtpl:73 hyphaNames := make(chan string) sortedHypha := hyphae.PathographicSort(hyphaNames) for hypha := range hyphae.YieldExistingHyphae() { @@ -534,134 +318,134 @@ func StreamHyphaList(qw422016 *qt422016.Writer, lc *l18n.Localizer) { } close(hyphaNames) -//line views/stuff.qtpl:156 +//line views/stuff.qtpl:79 qw422016.N().S(` `) -//line views/stuff.qtpl:157 +//line views/stuff.qtpl:80 for hyphaName := range sortedHypha { -//line views/stuff.qtpl:157 +//line views/stuff.qtpl:80 qw422016.N().S(` `) -//line views/stuff.qtpl:158 +//line views/stuff.qtpl:81 h := hyphae.ByName(hyphaName) -//line views/stuff.qtpl:158 +//line views/stuff.qtpl:81 qw422016.N().S(`
    • `) -//line views/stuff.qtpl:161 +//line views/stuff.qtpl:84 qw422016.E().S(util.BeautifulName(h.CanonicalName())) -//line views/stuff.qtpl:161 +//line views/stuff.qtpl:84 qw422016.N().S(` `) -//line views/stuff.qtpl:163 +//line views/stuff.qtpl:86 switch h := h.(type) { -//line views/stuff.qtpl:164 +//line views/stuff.qtpl:87 case *hyphae.MediaHypha: -//line views/stuff.qtpl:164 +//line views/stuff.qtpl:87 qw422016.N().S(` `) -//line views/stuff.qtpl:166 +//line views/stuff.qtpl:89 qw422016.E().S(filepath.Ext(h.MediaFilePath())[1:]) -//line views/stuff.qtpl:166 +//line views/stuff.qtpl:89 qw422016.N().S(` `) -//line views/stuff.qtpl:168 +//line views/stuff.qtpl:91 } -//line views/stuff.qtpl:168 +//line views/stuff.qtpl:91 qw422016.N().S(`
    • `) -//line views/stuff.qtpl:170 +//line views/stuff.qtpl:93 } -//line views/stuff.qtpl:170 +//line views/stuff.qtpl:93 qw422016.N().S(`
    `) -//line views/stuff.qtpl:174 +//line views/stuff.qtpl:97 } -//line views/stuff.qtpl:174 +//line views/stuff.qtpl:97 func WriteHyphaList(qq422016 qtio422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:174 +//line views/stuff.qtpl:97 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:174 +//line views/stuff.qtpl:97 StreamHyphaList(qw422016, lc) -//line views/stuff.qtpl:174 +//line views/stuff.qtpl:97 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:174 +//line views/stuff.qtpl:97 } -//line views/stuff.qtpl:174 +//line views/stuff.qtpl:97 func HyphaList(lc *l18n.Localizer) string { -//line views/stuff.qtpl:174 +//line views/stuff.qtpl:97 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:174 +//line views/stuff.qtpl:97 WriteHyphaList(qb422016, lc) -//line views/stuff.qtpl:174 +//line views/stuff.qtpl:97 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:174 +//line views/stuff.qtpl:97 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:174 +//line views/stuff.qtpl:97 return qs422016 -//line views/stuff.qtpl:174 +//line views/stuff.qtpl:97 } -//line views/stuff.qtpl:176 +//line views/stuff.qtpl:99 func streamcommonScripts(qw422016 *qt422016.Writer) { -//line views/stuff.qtpl:176 +//line views/stuff.qtpl:99 qw422016.N().S(` `) -//line views/stuff.qtpl:177 +//line views/stuff.qtpl:100 for _, scriptPath := range cfg.CommonScripts { -//line views/stuff.qtpl:177 +//line views/stuff.qtpl:100 qw422016.N().S(` `) -//line views/stuff.qtpl:179 +//line views/stuff.qtpl:102 } -//line views/stuff.qtpl:179 +//line views/stuff.qtpl:102 qw422016.N().S(` `) -//line views/stuff.qtpl:180 +//line views/stuff.qtpl:103 } -//line views/stuff.qtpl:180 +//line views/stuff.qtpl:103 func writecommonScripts(qq422016 qtio422016.Writer) { -//line views/stuff.qtpl:180 +//line views/stuff.qtpl:103 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:180 +//line views/stuff.qtpl:103 streamcommonScripts(qw422016) -//line views/stuff.qtpl:180 +//line views/stuff.qtpl:103 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:180 +//line views/stuff.qtpl:103 } -//line views/stuff.qtpl:180 +//line views/stuff.qtpl:103 func commonScripts() string { -//line views/stuff.qtpl:180 +//line views/stuff.qtpl:103 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:180 +//line views/stuff.qtpl:103 writecommonScripts(qb422016) -//line views/stuff.qtpl:180 +//line views/stuff.qtpl:103 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:180 +//line views/stuff.qtpl:103 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:180 +//line views/stuff.qtpl:103 return qs422016 -//line views/stuff.qtpl:180 +//line views/stuff.qtpl:103 } diff --git a/viewutil/meta.go b/viewutil/meta.go index c51db6e..36a4e90 100644 --- a/viewutil/meta.go +++ b/viewutil/meta.go @@ -23,6 +23,6 @@ func MetaFrom(w http.ResponseWriter, rq *http.Request) Meta { } } -func (m *Meta) Locale() string { +func (m Meta) Locale() string { return m.Lc.Locale } diff --git a/viewutil/viewutil.go b/viewutil/viewutil.go index f023101..82b67a0 100644 --- a/viewutil/viewutil.go +++ b/viewutil/viewutil.go @@ -7,13 +7,14 @@ import ( "github.com/bouncepaw/mycorrhiza/cfg" "github.com/bouncepaw/mycorrhiza/l18n" "github.com/bouncepaw/mycorrhiza/user" - "html/template" + "github.com/bouncepaw/mycorrhiza/util" "log" "strings" + "text/template" // TODO: save the world ) var ( - //go:embed viewutil.go + //go:embed *.html fs embed.FS BaseEn *template.Template BaseRu *template.Template @@ -31,7 +32,11 @@ func Init() { dataText := fmt.Sprintf(` {{define "wiki name"}}%s{{end}} `, cfg.WikiName) - BaseEn = m(m(template.ParseFS(fs, "viewutil.go")).Parse(dataText)) + BaseEn = m(m(template.New(""). + Funcs(template.FuncMap{ + "beautifulName": util.BeautifulName, + }).ParseFS(fs, "base.html")). + Parse(dataText)) if !cfg.UseAuth { m(BaseEn.Parse(`{{define "auth"}}{{end}}`)) } @@ -70,7 +75,7 @@ func Base(title, body string, lc *l18n.Localizer, u *user.User, headElements ... W: &w, } t := localizedBaseWithWeirdBody(meta) - err := t.Execute(&w, baseData{ + err := t.ExecuteTemplate(&w, "base", baseData{ Meta: meta, Title: title, HeadElements: headElements, From 78bae127b32a4cbb86164b3d2d35442be44f8167 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Fri, 1 Apr 2022 22:51:15 +0300 Subject: [PATCH 03/23] Use viewutil.Meta in many places --- views/admin.go | 3 +- views/categories.go | 6 ++-- viewutil/viewutil.go | 12 ++----- web/admin.go | 10 +++--- web/auth.go | 20 +++++------ web/backlinks.go | 6 ++-- web/history.go | 10 +++--- web/mutators.go | 80 +++++++++++++++++++++++--------------------- web/readers.go | 23 +++++-------- web/search.go | 6 ++-- web/stuff.go | 41 ++++++++++++++--------- web/web.go | 15 +++++---- 12 files changed, 113 insertions(+), 119 deletions(-) diff --git a/views/admin.go b/views/admin.go index 3a383d2..e9d8351 100644 --- a/views/admin.go +++ b/views/admin.go @@ -67,9 +67,8 @@ func AdminPanel(meta viewutil.Meta) { log.Println(err) } _, err = io.WriteString(meta.W, Base( + meta, templateAsString(localizedAdminTemplates(meta), "panel title"), buf.String(), - meta.Lc, - meta.U, )) } diff --git a/views/categories.go b/views/categories.go index 665ac0f..6cfccd6 100644 --- a/views/categories.go +++ b/views/categories.go @@ -94,10 +94,9 @@ func CategoryPage(meta viewutil.Meta, catName string) { log.Println(err) } _, err = io.WriteString(meta.W, Base( + meta, localizedCatTemplateAsString(meta, "category x", catName), buf.String(), - meta.Lc, - meta.U, )) if err != nil { log.Println(err) @@ -115,10 +114,9 @@ func CategoryList(meta viewutil.Meta) { log.Println(err) } _, err = io.WriteString(meta.W, Base( + meta, localizedCatTemplateAsString(meta, "category list heading"), buf.String(), - meta.Lc, - meta.U, )) if err != nil { log.Println(err) diff --git a/viewutil/viewutil.go b/viewutil/viewutil.go index 82b67a0..b7bfd5f 100644 --- a/viewutil/viewutil.go +++ b/viewutil/viewutil.go @@ -5,8 +5,6 @@ import ( "embed" "fmt" "github.com/bouncepaw/mycorrhiza/cfg" - "github.com/bouncepaw/mycorrhiza/l18n" - "github.com/bouncepaw/mycorrhiza/user" "github.com/bouncepaw/mycorrhiza/util" "log" "strings" @@ -54,7 +52,7 @@ func localizedBaseWithWeirdBody(meta Meta) *template.Template { } return BaseEn }() - return m(m(t.Clone()).Parse(`{{define "body"}}.Body{{end}}`)) + return m(m(t.Clone()).Parse(`{{define "body"}}{{.Body}}{{end}}`)) } type baseData struct { @@ -67,13 +65,9 @@ type baseData struct { } // Base is a temporary wrapper around BaseEn and BaseRu, meant to facilitate the migration from qtpl. -func Base(title, body string, lc *l18n.Localizer, u *user.User, headElements ...string) string { +func Base(meta Meta, title, body string, headElements ...string) string { var w strings.Builder - meta := Meta{ - Lc: lc, - U: u, - W: &w, - } + meta.W = &w t := localizedBaseWithWeirdBody(meta) err := t.ExecuteTemplate(&w, "base", baseData{ Meta: meta, diff --git a/web/admin.go b/web/admin.go index 2302d85..5a87bf7 100644 --- a/web/admin.go +++ b/web/admin.go @@ -71,7 +71,7 @@ func handlerAdminUsers(w http.ResponseWriter, rq *http.Request) { var lc = l18n.FromRequest(rq) html := views.AdminUsersPanel(userList, lc) - html = views.Base(lc.Get("admin.users_title"), html, lc, user.FromRequest(rq)) + html = views.Base(viewutil.MetaFrom(w, rq), lc.Get("admin.users_title"), html) w.Header().Set("Content-Type", mime.TypeByExtension(".html")) io.WriteString(w, html) @@ -110,7 +110,7 @@ func handlerAdminUserEdit(w http.ResponseWriter, rq *http.Request) { var lc = l18n.FromRequest(rq) html := views.AdminUserEdit(u, f, lc) - html = views.Base(fmt.Sprintf(lc.Get("admin.user_title"), u.Name), html, lc, user.FromRequest(rq)) + html = views.Base(viewutil.MetaFrom(w, rq), fmt.Sprintf(lc.Get("admin.user_title"), u.Name), html) if f.HasError() { w.WriteHeader(http.StatusBadRequest) @@ -140,7 +140,7 @@ func handlerAdminUserDelete(w http.ResponseWriter, rq *http.Request) { var lc = l18n.FromRequest(rq) html := views.AdminUserDelete(u, util.NewFormData(), lc) - html = views.Base(fmt.Sprintf(lc.Get("admin.user_title"), u.Name), html, l18n.FromRequest(rq), user.FromRequest(rq)) + html = views.Base(viewutil.MetaFrom(w, rq), fmt.Sprintf(lc.Get("admin.user_title"), u.Name), html) if f.HasError() { w.WriteHeader(http.StatusBadRequest) @@ -154,7 +154,7 @@ func handlerAdminUserNew(w http.ResponseWriter, rq *http.Request) { if rq.Method == http.MethodGet { // New user form html := views.AdminUserNew(util.NewFormData(), lc) - html = views.Base(lc.Get("admin.newuser_title"), html, lc, user.FromRequest(rq)) + html = views.Base(viewutil.MetaFrom(w, rq), lc.Get("admin.newuser_title"), html) w.Header().Set("Content-Type", mime.TypeByExtension(".html")) io.WriteString(w, html) @@ -166,7 +166,7 @@ func handlerAdminUserNew(w http.ResponseWriter, rq *http.Request) { if err != nil { html := views.AdminUserNew(f.WithError(err), lc) - html = views.Base(lc.Get("admin.newuser_title"), html, lc, user.FromRequest(rq)) + html = views.Base(viewutil.MetaFrom(w, rq), lc.Get("admin.newuser_title"), html) w.WriteHeader(http.StatusBadRequest) w.Header().Set("Content-Type", mime.TypeByExtension(".html")) diff --git a/web/auth.go b/web/auth.go index fc47510..0734c2f 100644 --- a/web/auth.go +++ b/web/auth.go @@ -3,6 +3,7 @@ package web import ( "errors" "fmt" + "github.com/bouncepaw/mycorrhiza/viewutil" "io" "log" "mime" @@ -46,10 +47,9 @@ func handlerRegister(w http.ResponseWriter, rq *http.Request) { _, _ = io.WriteString( w, views.Base( + viewutil.MetaFrom(w, rq), lc.Get("auth.register_title"), views.Register(rq), - lc, - user.FromRequest(rq), ), ) } else if rq.Method == http.MethodPost { @@ -65,14 +65,13 @@ func handlerRegister(w http.ResponseWriter, rq *http.Request) { _, _ = io.WriteString( w, views.Base( + viewutil.MetaFrom(w, rq), lc.Get("auth.register_title"), fmt.Sprintf( `

    %s

    %s

    `, err.Error(), lc.Get("auth.try_again"), ), - lc, - user.FromRequest(rq), ), ) } else { @@ -101,7 +100,7 @@ func handlerLogout(w http.ResponseWriter, rq *http.Request) { } _, _ = io.WriteString( w, - views.Base(lc.Get("auth.logout_title"), views.Logout(can, lc), lc, u), + views.Base(viewutil.MetaFrom(w, rq), lc.Get("auth.logout_title"), views.Logout(can, lc)), ) } else if rq.Method == http.MethodPost { user.LogoutFromRequest(w, rq) @@ -118,10 +117,9 @@ func handlerLogin(w http.ResponseWriter, rq *http.Request) { _, _ = io.WriteString( w, views.Base( + viewutil.MetaFrom(w, rq), lc.Get("auth.login_title"), views.Login(lc), - lc, - user.EmptyUser(), ), ) } else if rq.Method == http.MethodPost { @@ -133,7 +131,7 @@ func handlerLogin(w http.ResponseWriter, rq *http.Request) { if err != "" { w.Header().Set("Content-Type", "text/html;charset=utf-8") w.WriteHeader(http.StatusInternalServerError) - _, _ = io.WriteString(w, views.Base(err, views.LoginError(err, lc), lc, user.EmptyUser())) + _, _ = io.WriteString(w, views.Base(viewutil.MetaFrom(w, rq), err, views.LoginError(err, lc))) return } http.Redirect(w, rq, "/", http.StatusSeeOther) @@ -172,6 +170,7 @@ func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) { _, _ = io.WriteString( w, views.Base( + viewutil.MetaFrom(w, rq), lc.Get("ui.error"), fmt.Sprintf( `

    %s

    %s

    %s

    `, @@ -179,8 +178,6 @@ func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) { err.Error(), lc.Get("auth.go_login"), ), - lc, - user.FromRequest(rq), ), ) return @@ -193,6 +190,7 @@ func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) { _, _ = io.WriteString( w, views.Base( + viewutil.MetaFrom(w, rq), "Error", fmt.Sprintf( `

    %s

    %s

    %s

    `, @@ -200,8 +198,6 @@ func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) { err.Error(), lc.Get("auth.go_login"), ), - lc, - user.FromRequest(rq), ), ) return diff --git a/web/backlinks.go b/web/backlinks.go index f7747ae..1bb10d7 100644 --- a/web/backlinks.go +++ b/web/backlinks.go @@ -2,12 +2,12 @@ package web import ( "github.com/bouncepaw/mycorrhiza/hyphae/backlinks" + "github.com/bouncepaw/mycorrhiza/viewutil" "net/http" "github.com/gorilla/mux" "github.com/bouncepaw/mycorrhiza/l18n" - "github.com/bouncepaw/mycorrhiza/user" "github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/views" ) @@ -23,8 +23,8 @@ func handlerBacklinks(w http.ResponseWriter, rq *http.Request) { lc = l18n.FromRequest(rq) ) util.HTTP200Page(w, views.Base( + viewutil.MetaFrom(w, rq), lc.Get("ui.backlinks_title", &l18n.Replacements{"query": util.BeautifulName(hyphaName)}), views.Backlinks(hyphaName, backlinks.YieldHyphaBacklinks, lc), - lc, - user.FromRequest(rq))) + )) } diff --git a/web/history.go b/web/history.go index 8b3a245..bcac81b 100644 --- a/web/history.go +++ b/web/history.go @@ -2,6 +2,7 @@ package web import ( "fmt" + "github.com/bouncepaw/mycorrhiza/viewutil" "log" "net/http" "strconv" @@ -10,7 +11,6 @@ import ( "github.com/bouncepaw/mycorrhiza/history" "github.com/bouncepaw/mycorrhiza/l18n" - "github.com/bouncepaw/mycorrhiza/user" "github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/views" ) @@ -42,10 +42,10 @@ func handlerHistory(w http.ResponseWriter, rq *http.Request) { var lc = l18n.FromRequest(rq) util.HTTP200Page(w, views.Base( + viewutil.MetaFrom(w, rq), fmt.Sprintf(lc.Get("ui.history_title"), util.BeautifulName(hyphaName)), views.History(rq, hyphaName, list, lc), - lc, - user.FromRequest(rq))) + )) } // handlerRecentChanges displays the /recent-changes/ page. @@ -57,10 +57,10 @@ func handlerRecentChanges(w http.ResponseWriter, rq *http.Request) { } var lc = l18n.FromRequest(rq) util.HTTP200Page(w, views.Base( + viewutil.MetaFrom(w, rq), lc.GetPlural("ui.recent_title", n), views.RecentChanges(n, lc), - lc, - user.FromRequest(rq))) + )) } // genericHandlerOfFeeds is a helper function for the web feed handlers. diff --git a/web/mutators.go b/web/mutators.go index 2d97c24..d14cb4c 100644 --- a/web/mutators.go +++ b/web/mutators.go @@ -2,6 +2,7 @@ package web import ( "fmt" + "github.com/bouncepaw/mycorrhiza/viewutil" "log" "net/http" @@ -32,31 +33,31 @@ func initMutators(r *mux.Router) { func handlerRemoveMedia(w http.ResponseWriter, rq *http.Request) { util.PrepareRq(rq) var ( - u = user.FromRequest(rq) - lc = l18n.FromRequest(rq) - h = hyphae.ByName(util.HyphaNameFromRq(rq, "delete")) + u = user.FromRequest(rq) + lc = l18n.FromRequest(rq) + h = hyphae.ByName(util.HyphaNameFromRq(rq, "delete")) + meta = viewutil.MetaFrom(w, rq) ) if !u.CanProceed("remove-media") { - httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "no rights") + httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "no rights") return } if rq.Method == "GET" { util.HTTP200Page( w, views.Base( + meta, fmt.Sprintf(lc.Get("ui.ask_remove_media"), util.BeautifulName(h.CanonicalName())), - views.RemoveMediaAsk(rq, h.CanonicalName()), - lc, - u)) + views.RemoveMediaAsk(rq, h.CanonicalName()))) return } switch h := h.(type) { case *hyphae.EmptyHypha, *hyphae.TextualHypha: - httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "no media to remove") + httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "no media to remove") return case *hyphae.MediaHypha: if err := shroom.RemoveMedia(u, h); err != nil { - httpErr(w, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error()) + httpErr(meta, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error()) return } } @@ -65,14 +66,15 @@ func handlerRemoveMedia(w http.ResponseWriter, rq *http.Request) { func handlerDelete(w http.ResponseWriter, rq *http.Request) { util.PrepareRq(rq) var ( - u = user.FromRequest(rq) - lc = l18n.FromRequest(rq) - h = hyphae.ByName(util.HyphaNameFromRq(rq, "delete")) + u = user.FromRequest(rq) + lc = l18n.FromRequest(rq) + h = hyphae.ByName(util.HyphaNameFromRq(rq, "delete")) + meta = viewutil.MetaFrom(w, rq) ) if !u.CanProceed("delete") { log.Printf("%s has no rights to delete ‘%s’\n", u.Name, h.CanonicalName()) - httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "No rights") + httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "No rights") return } @@ -80,7 +82,7 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) { case *hyphae.EmptyHypha: log.Printf("%s tries to delete empty hypha ‘%s’\n", u.Name, h.CanonicalName()) // TODO: localize - httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "Cannot delete an empty hypha") + httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "Cannot delete an empty hypha") return } @@ -88,16 +90,15 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) { util.HTTP200Page( w, views.Base( + meta, fmt.Sprintf(lc.Get("ui.ask_delete"), util.BeautifulName(h.CanonicalName())), - views.DeleteAsk(rq, h.CanonicalName()), - lc, - u)) + views.DeleteAsk(rq, h.CanonicalName()))) return } if err := shroom.Delete(u, h.(hyphae.ExistingHypha)); err != nil { log.Println(err) - httpErr(w, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error()) + httpErr(meta, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error()) return } http.Redirect(w, rq, "/hypha/"+h.CanonicalName(), http.StatusSeeOther) @@ -106,21 +107,22 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) { func handlerRename(w http.ResponseWriter, rq *http.Request) { util.PrepareRq(rq) var ( - u = user.FromRequest(rq) - lc = l18n.FromRequest(rq) - h = hyphae.ByName(util.HyphaNameFromRq(rq, "rename")) + u = user.FromRequest(rq) + lc = l18n.FromRequest(rq) + h = hyphae.ByName(util.HyphaNameFromRq(rq, "rename")) + meta = viewutil.MetaFrom(w, rq) ) switch h.(type) { case *hyphae.EmptyHypha: log.Printf("%s tries to rename empty hypha ‘%s’", u.Name, h.CanonicalName()) - httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "Cannot rename an empty hypha") // TODO: localize + httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "Cannot rename an empty hypha") // TODO: localize return } if !u.CanProceed("rename") { log.Printf("%s has no rights to rename ‘%s’\n", u.Name, h.CanonicalName()) - httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "No rights") + httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "No rights") return } @@ -134,16 +136,15 @@ func handlerRename(w http.ResponseWriter, rq *http.Request) { util.HTTP200Page( w, views.Base( + meta, fmt.Sprintf(lc.Get("ui.ask_rename"), util.BeautifulName(oldHypha.CanonicalName())), - views.RenameAsk(rq, oldHypha.CanonicalName()), - lc, - u)) + views.RenameAsk(rq, oldHypha.CanonicalName()))) return } if err := shroom.Rename(oldHypha, newName, recursive, u); err != nil { log.Printf("%s tries to rename ‘%s’: %s", u.Name, oldHypha.CanonicalName(), err.Error()) - httpErr(w, lc, http.StatusForbidden, oldHypha.CanonicalName(), lc.Get(err.Error())) // TODO: localize + httpErr(meta, lc, http.StatusForbidden, oldHypha.CanonicalName(), lc.Get(err.Error())) // TODO: localize return } http.Redirect(w, rq, "/hypha/"+newName, http.StatusSeeOther) @@ -160,9 +161,10 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) { err error u = user.FromRequest(rq) lc = l18n.FromRequest(rq) + meta = viewutil.MetaFrom(w, rq) ) if err := shroom.CanEdit(u, h, lc); err != nil { - httpErr(w, lc, http.StatusInternalServerError, hyphaName, + httpErr(meta, lc, http.StatusInternalServerError, hyphaName, err.Error()) return } @@ -173,7 +175,7 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) { textAreaFill, err = shroom.FetchTextFile(h) if err != nil { log.Println(err) - httpErr(w, lc, http.StatusInternalServerError, hyphaName, + httpErr(meta, lc, http.StatusInternalServerError, hyphaName, lc.Get("ui.error_text_fetch")) return } @@ -181,10 +183,9 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) { util.HTTP200Page( w, views.Base( + meta, fmt.Sprintf(lc.Get("edit.title"), util.BeautifulName(hyphaName)), - views.Editor(rq, hyphaName, textAreaFill, warning), - lc, - u)) + views.Editor(rq, hyphaName, textAreaFill, warning))) } // handlerUploadText uploads a new text part for the hypha. @@ -198,11 +199,12 @@ func handlerUploadText(w http.ResponseWriter, rq *http.Request) { message = rq.PostFormValue("message") u = user.FromRequest(rq) lc = l18n.FromRequest(rq) + meta = viewutil.MetaFrom(w, rq) ) if action != "Preview" { if err := shroom.UploadText(h, []byte(textData), message, u); err != nil { - httpErr(w, lc, http.StatusForbidden, hyphaName, err.Error()) + httpErr(meta, lc, http.StatusForbidden, hyphaName, err.Error()) return } } @@ -213,6 +215,7 @@ func handlerUploadText(w http.ResponseWriter, rq *http.Request) { util.HTTP200Page( w, views.Base( + meta, fmt.Sprintf(lc.Get("edit.preview_title"), util.BeautifulName(hyphaName)), views.Preview( rq, @@ -220,9 +223,7 @@ func handlerUploadText(w http.ResponseWriter, rq *http.Request) { textData, message, "", - mycomarkup.BlocksToHTML(ctx, mycomarkup.BlockTree(ctx))), - lc, - u)) + mycomarkup.BlocksToHTML(ctx, mycomarkup.BlockTree(ctx))))) } else { http.Redirect(w, rq, "/hypha/"+hyphaName, http.StatusSeeOther) } @@ -238,13 +239,14 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) { u = user.FromRequest(rq) lc = l18n.FromRequest(rq) file, handler, err = rq.FormFile("binary") + meta = viewutil.MetaFrom(w, rq) ) if err != nil { - httpErr(w, lc, http.StatusInternalServerError, hyphaName, + httpErr(meta, lc, http.StatusInternalServerError, hyphaName, err.Error()) } if err := shroom.CanAttach(u, h, lc); err != nil { - httpErr(w, lc, http.StatusInternalServerError, hyphaName, + httpErr(meta, lc, http.StatusInternalServerError, hyphaName, err.Error()) } @@ -263,7 +265,7 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) { ) if err := shroom.UploadBinary(h, mime, file, u); err != nil { - httpErr(w, lc, http.StatusInternalServerError, hyphaName, err.Error()) + httpErr(meta, lc, http.StatusInternalServerError, hyphaName, err.Error()) return } http.Redirect(w, rq, "/hypha/"+hyphaName, http.StatusSeeOther) diff --git a/web/readers.go b/web/readers.go index de44839..c5e1ba6 100644 --- a/web/readers.go +++ b/web/readers.go @@ -48,10 +48,9 @@ func handlerMedia(w http.ResponseWriter, rq *http.Request) { ) util.HTTP200Page(w, views.Base( + viewutil.MetaFrom(w, rq), lc.Get("ui.media_title", &l18n.Replacements{"name": util.BeautifulName(hyphaName)}), - views.MediaMenu(rq, h, u), - lc, - u)) + views.MediaMenu(rq, h, u))) } func handlerPrimitiveDiff(w http.ResponseWriter, rq *http.Request) { @@ -74,7 +73,7 @@ func handlerPrimitiveDiff(w http.ResponseWriter, rq *http.Request) { hyphaName = util.CanonicalName(slug) h = hyphae.ByName(hyphaName) user = user.FromRequest(rq) - locale = l18n.FromRequest(rq) + lc = l18n.FromRequest(rq) ) switch h := h.(type) { case *hyphae.EmptyHypha: @@ -82,8 +81,9 @@ func handlerPrimitiveDiff(w http.ResponseWriter, rq *http.Request) { io.WriteString(w, "404 not found") case hyphae.ExistingHypha: util.HTTP200Page(w, views.Base( - locale.Get("ui.diff_title", &l18n.Replacements{"name": util.BeautifulName(hyphaName), "rev": revHash}), - views.PrimitiveDiff(rq, h, user, revHash), locale, user)) + viewutil.MetaFrom(w, rq), + lc.Get("ui.diff_title", &l18n.Replacements{"name": util.BeautifulName(hyphaName), "rev": revHash}), + views.PrimitiveDiff(rq, h, user, revHash))) } } @@ -134,7 +134,6 @@ func handlerRevision(w http.ResponseWriter, rq *http.Request) { hyphaName = util.CanonicalName(shorterURL[firstSlashIndex+1:]) h = hyphae.ByName(hyphaName) contents = fmt.Sprintf(`

    %s

    `, lc.Get("ui.revision_no_text")) - u = user.FromRequest(rq) ) switch h := h.(type) { case hyphae.ExistingHypha: @@ -157,10 +156,9 @@ func handlerRevision(w http.ResponseWriter, rq *http.Request) { _, _ = fmt.Fprint( w, views.Base( + viewutil.MetaFrom(w, rq), lc.Get("ui.revision_title", &l18n.Replacements{"name": util.BeautifulName(hyphaName), "rev": revHash}), page, - lc, - u, ), ) } @@ -201,7 +199,6 @@ func handlerHypha(w http.ResponseWriter, rq *http.Request) { h = hyphae.ByName(hyphaName) contents string openGraph string - u = user.FromRequest(rq) lc = l18n.FromRequest(rq) ) @@ -209,10 +206,9 @@ func handlerHypha(w http.ResponseWriter, rq *http.Request) { case *hyphae.EmptyHypha: util.HTTP404Page(w, views.Base( + viewutil.MetaFrom(w, rq), util.BeautifulName(hyphaName), views.Hypha(viewutil.MetaFrom(w, rq), h, contents), - lc, - u, openGraph)) case hyphae.ExistingHypha: fileContentsT, errT := os.ReadFile(h.TextFilePath()) @@ -231,10 +227,9 @@ func handlerHypha(w http.ResponseWriter, rq *http.Request) { util.HTTP200Page(w, views.Base( + viewutil.MetaFrom(w, rq), util.BeautifulName(hyphaName), views.Hypha(viewutil.MetaFrom(w, rq), h, contents), - lc, - u, openGraph)) } } diff --git a/web/search.go b/web/search.go index 06453a1..0a9b7d4 100644 --- a/web/search.go +++ b/web/search.go @@ -1,6 +1,7 @@ package web import ( + "github.com/bouncepaw/mycorrhiza/viewutil" "io" "net/http" @@ -8,7 +9,6 @@ import ( "github.com/bouncepaw/mycorrhiza/l18n" "github.com/bouncepaw/mycorrhiza/shroom" - "github.com/bouncepaw/mycorrhiza/user" "github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/views" ) @@ -22,17 +22,15 @@ func handlerTitleSearch(w http.ResponseWriter, rq *http.Request) { _ = rq.ParseForm() var ( query = rq.FormValue("q") - u = user.FromRequest(rq) lc = l18n.FromRequest(rq) ) w.WriteHeader(http.StatusOK) _, _ = io.WriteString( w, views.Base( + viewutil.MetaFrom(w, rq), lc.Get("ui.title_search_title", &l18n.Replacements{"query": query}), views.TitleSearch(query, shroom.YieldHyphaNamesContainingString, lc), - lc, - u, ), ) } diff --git a/web/stuff.go b/web/stuff.go index ad5866f..f43c387 100644 --- a/web/stuff.go +++ b/web/stuff.go @@ -3,6 +3,7 @@ package web // stuff.go is used for meta stuff about the wiki or all hyphae at once. import ( "github.com/bouncepaw/mycorrhiza/hyphae/backlinks" + "github.com/bouncepaw/mycorrhiza/viewutil" "io" "log" "math/rand" @@ -58,10 +59,11 @@ func handlerHelp(w http.ResponseWriter, rq *http.Request) { w.WriteHeader(http.StatusNotFound) _, _ = io.WriteString( w, - views.Base(lc.Get("help.entry_not_found"), + views.Base( + viewutil.MetaFrom(w, rq), + lc.Get("help.entry_not_found"), views.Help(views.HelpEmptyError(lc), lang, lc), - lc, - user.FromRequest(rq)), + ), ) return } @@ -69,10 +71,11 @@ func handlerHelp(w http.ResponseWriter, rq *http.Request) { w.WriteHeader(http.StatusInternalServerError) _, _ = io.WriteString( w, - views.Base(err.Error(), + views.Base( + viewutil.MetaFrom(w, rq), + err.Error(), views.Help(err.Error(), lang, lc), - lc, - user.FromRequest(rq)), + ), ) return } @@ -84,19 +87,23 @@ func handlerHelp(w http.ResponseWriter, rq *http.Request) { w.WriteHeader(http.StatusOK) _, _ = io.WriteString( w, - views.Base(lc.Get("help.title"), + views.Base( + viewutil.MetaFrom(w, rq), + lc.Get("help.title"), views.Help(result, lang, lc), - lc, - user.FromRequest(rq)), + ), ) } // handlerList shows a list of all hyphae in the wiki in random order. func handlerList(w http.ResponseWriter, rq *http.Request) { - u := user.FromRequest(rq) var lc = l18n.FromRequest(rq) util.PrepareRq(rq) - util.HTTP200Page(w, views.Base(lc.Get("ui.list_title"), views.HyphaList(lc), lc, u)) + util.HTTP200Page(w, views.Base( + viewutil.MetaFrom(w, rq), + lc.Get("ui.list_title"), + views.HyphaList(lc), + )) } // handlerReindex reindexes all hyphae by checking the wiki storage directory anew. @@ -104,7 +111,7 @@ func handlerReindex(w http.ResponseWriter, rq *http.Request) { util.PrepareRq(rq) if ok := user.CanProceed(rq, "reindex"); !ok { var lc = l18n.FromRequest(rq) - httpErr(w, lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.reindex_no_rights")) + httpErr(viewutil.MetaFrom(w, rq), lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.reindex_no_rights")) log.Println("Rejected", rq.URL) return } @@ -122,7 +129,7 @@ func handlerUpdateHeaderLinks(w http.ResponseWriter, rq *http.Request) { util.PrepareRq(rq) if ok := user.CanProceed(rq, "update-header-links"); !ok { var lc = l18n.FromRequest(rq) - httpErr(w, lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.header_no_rights")) + httpErr(viewutil.MetaFrom(w, rq), lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.header_no_rights")) log.Println("Rejected", rq.URL) return } @@ -139,7 +146,7 @@ func handlerRandom(w http.ResponseWriter, rq *http.Request) { ) if amountOfHyphae == 0 { var lc = l18n.FromRequest(rq) - httpErr(w, lc, http.StatusNotFound, cfg.HomeHypha, lc.Get("ui.random_no_hyphae_tip")) + httpErr(viewutil.MetaFrom(w, rq), lc, http.StatusNotFound, cfg.HomeHypha, lc.Get("ui.random_no_hyphae_tip")) return } i := rand.Intn(amountOfHyphae) @@ -160,7 +167,11 @@ func handlerAbout(w http.ResponseWriter, rq *http.Request) { lc = l18n.FromRequest(rq) title = lc.Get("ui.about_title", &l18n.Replacements{"name": cfg.WikiName}) ) - _, err := io.WriteString(w, views.Base(title, views.AboutHTML(lc), lc, user.FromRequest(rq))) + _, err := io.WriteString(w, views.Base( + viewutil.MetaFrom(w, rq), + title, + views.AboutHTML(lc), + )) if err != nil { log.Println(err) } diff --git a/web/web.go b/web/web.go index c255b5d..d1167ee 100644 --- a/web/web.go +++ b/web/web.go @@ -3,6 +3,7 @@ package web import ( "fmt" + "github.com/bouncepaw/mycorrhiza/viewutil" "io" "mime" "net/http" @@ -21,12 +22,14 @@ import ( var stylesheets = []string{"default.css", "custom.css"} // httpErr is used by many handlers to signal errors in a compact way. -func httpErr(w http.ResponseWriter, lc *l18n.Localizer, status int, name, errMsg string) { - w.Header().Set("Content-Type", mime.TypeByExtension(".html")) - w.WriteHeader(status) +// TODO: get rid of this abomination +func httpErr(meta viewutil.Meta, lc *l18n.Localizer, status int, name, errMsg string) { + meta.W.(http.ResponseWriter).Header().Set("Content-Type", mime.TypeByExtension(".html")) + meta.W.(http.ResponseWriter).WriteHeader(status) fmt.Fprint( - w, + meta.W, views.Base( + meta, "Error", fmt.Sprintf( `

    %s. %s

    `, @@ -34,8 +37,6 @@ func httpErr(w http.ResponseWriter, lc *l18n.Localizer, status int, name, errMsg name, lc.Get("ui.error_go_back"), ), - lc, - user.EmptyUser(), ), ) } @@ -56,7 +57,7 @@ func handlerUserList(w http.ResponseWriter, rq *http.Request) { lc := l18n.FromRequest(rq) w.Header().Set("Content-Type", mime.TypeByExtension(".html")) w.WriteHeader(http.StatusOK) - w.Write([]byte(views.Base(lc.Get("ui.users_title"), views.UserList(lc), lc, user.FromRequest(rq)))) + w.Write([]byte(views.Base(viewutil.MetaFrom(w, rq), lc.Get("ui.users_title"), views.UserList(lc)))) } func handlerRobotsTxt(w http.ResponseWriter, rq *http.Request) { From 3dad3a3a4fff10a5c75aa635101fbf96ac7972b4 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Fri, 1 Apr 2022 22:52:38 +0300 Subject: [PATCH 04/23] Move package categories to the root level --- {hyphae/categories => categories}/categories.go | 0 {hyphae/categories => categories}/files.go | 0 main.go | 2 +- views/categories.go | 2 +- web/categories.go | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) rename {hyphae/categories => categories}/categories.go (100%) rename {hyphae/categories => categories}/files.go (100%) diff --git a/hyphae/categories/categories.go b/categories/categories.go similarity index 100% rename from hyphae/categories/categories.go rename to categories/categories.go diff --git a/hyphae/categories/files.go b/categories/files.go similarity index 100% rename from hyphae/categories/files.go rename to categories/files.go diff --git a/main.go b/main.go index 40a1f9e..a7fb228 100644 --- a/main.go +++ b/main.go @@ -5,7 +5,7 @@ package main import ( - "github.com/bouncepaw/mycorrhiza/hyphae/categories" + "github.com/bouncepaw/mycorrhiza/categories" "github.com/bouncepaw/mycorrhiza/migration" "github.com/bouncepaw/mycorrhiza/viewutil" "log" diff --git a/views/categories.go b/views/categories.go index 6cfccd6..5da998e 100644 --- a/views/categories.go +++ b/views/categories.go @@ -1,7 +1,7 @@ package views import ( - "github.com/bouncepaw/mycorrhiza/hyphae/categories" + "github.com/bouncepaw/mycorrhiza/categories" "github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/viewutil" "html/template" diff --git a/web/categories.go b/web/categories.go index aa38545..8723ca8 100644 --- a/web/categories.go +++ b/web/categories.go @@ -1,7 +1,7 @@ package web import ( - "github.com/bouncepaw/mycorrhiza/hyphae/categories" + "github.com/bouncepaw/mycorrhiza/categories" "github.com/bouncepaw/mycorrhiza/user" "github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/views" From c3fafb735f34c579851e9b5bdcaadfb91d8f0119 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Fri, 1 Apr 2022 23:52:56 +0300 Subject: [PATCH 05/23] Categories, views: Refactor the list view --- {views => categories}/categories.html | 18 +- web/categories.go => categories/handlers.go | 15 +- categories/view_list.html | 16 + views/categories.go => categories/views.go | 71 +-- views/readers.qtpl | 3 +- views/readers.qtpl.go | 459 ++++++++++---------- viewutil/base.html | 3 +- viewutil/viewutil.go | 4 +- web/web.go | 3 +- 9 files changed, 307 insertions(+), 285 deletions(-) rename {views => categories}/categories.html (85%) rename web/categories.go => categories/handlers.go (85%) create mode 100644 categories/view_list.html rename views/categories.go => categories/views.go (63%) diff --git a/views/categories.html b/categories/categories.html similarity index 85% rename from views/categories.html rename to categories/categories.html index 41b2594..bfae50e 100644 --- a/views/categories.html +++ b/categories/categories.html @@ -1,4 +1,5 @@ {{define "category x"}}Category {{. | beautifulName}}{{end}} +{{define "category list heading"}}Category list{{end}} {{define "category card"}} {{$hyphaName := .HyphaName}} @@ -62,21 +63,4 @@ {{end}}
    -{{end}} - -{{define "category list"}} -
    -

    {{block `category list heading` .}}Category list{{end}}

    - {{if len .Categories}} -
    - {{else}} -

    {{block `no categories` .}}This wiki has no categories.{{end}}

    - {{end}} -
    {{end}} \ No newline at end of file diff --git a/web/categories.go b/categories/handlers.go similarity index 85% rename from web/categories.go rename to categories/handlers.go index 8723ca8..5bb4179 100644 --- a/web/categories.go +++ b/categories/handlers.go @@ -1,10 +1,8 @@ -package web +package categories import ( - "github.com/bouncepaw/mycorrhiza/categories" "github.com/bouncepaw/mycorrhiza/user" "github.com/bouncepaw/mycorrhiza/util" - "github.com/bouncepaw/mycorrhiza/views" "github.com/bouncepaw/mycorrhiza/viewutil" "github.com/gorilla/mux" "io" @@ -13,16 +11,17 @@ import ( "strings" ) -func initCategories(r *mux.Router) { +func InitCategoriesHandlers(r *mux.Router) { r.PathPrefix("/add-to-category").HandlerFunc(handlerAddToCategory).Methods("POST") r.PathPrefix("/remove-from-category").HandlerFunc(handlerRemoveFromCategory).Methods("POST") r.PathPrefix("/category/").HandlerFunc(handlerCategory).Methods("GET") r.PathPrefix("/category").HandlerFunc(handlerListCategory).Methods("GET") + prepareViews() } func handlerListCategory(w http.ResponseWriter, rq *http.Request) { log.Println("Viewing list of categories") - views.CategoryList(viewutil.MetaFrom(w, rq)) + categoryList(viewutil.MetaFrom(w, rq)) } func handlerCategory(w http.ResponseWriter, rq *http.Request) { @@ -33,7 +32,7 @@ func handlerCategory(w http.ResponseWriter, rq *http.Request) { return } log.Println("Viewing category", catName) - views.CategoryPage(viewutil.MetaFrom(w, rq), catName) + categoryPage(viewutil.MetaFrom(w, rq), catName) } func handlerRemoveFromCategory(w http.ResponseWriter, rq *http.Request) { @@ -52,7 +51,7 @@ func handlerRemoveFromCategory(w http.ResponseWriter, rq *http.Request) { http.Redirect(w, rq, redirectTo, http.StatusSeeOther) return } - categories.RemoveHyphaFromCategory(hyphaName, catName) + RemoveHyphaFromCategory(hyphaName, catName) http.Redirect(w, rq, redirectTo, http.StatusSeeOther) } @@ -72,6 +71,6 @@ func handlerAddToCategory(w http.ResponseWriter, rq *http.Request) { http.Redirect(w, rq, redirectTo, http.StatusSeeOther) return } - categories.AddHyphaToCategory(hyphaName, catName) + AddHyphaToCategory(hyphaName, catName) http.Redirect(w, rq, redirectTo, http.StatusSeeOther) } diff --git a/categories/view_list.html b/categories/view_list.html new file mode 100644 index 0000000..8cd79da --- /dev/null +++ b/categories/view_list.html @@ -0,0 +1,16 @@ +{{define "body"}} +
    +

    {{block `category list heading` .}}Category list{{end}}

    + {{if len .Categories}} + + {{else}} +

    {{block `no categories` .}}This wiki has no categories.{{end}}

    + {{end}} +
    +{{end}} \ No newline at end of file diff --git a/views/categories.go b/categories/views.go similarity index 63% rename from views/categories.go rename to categories/views.go index 5da998e..fd75e6b 100644 --- a/views/categories.go +++ b/categories/views.go @@ -1,13 +1,14 @@ -package views +package categories import ( - "github.com/bouncepaw/mycorrhiza/categories" + "embed" + "github.com/bouncepaw/mycorrhiza/cfg" "github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/viewutil" - "html/template" "io" "log" "strings" + "text/template" // TODO: Fight ) const categoriesRu = ` @@ -25,11 +26,15 @@ const categoriesRu = ` ` var ( - categoryTemplatesEn *template.Template - categoryTemplatesRu *template.Template + //go:embed *.html + fs embed.FS + m = template.Must + baseEn, baseRu, listEn, listRu *template.Template + categoryTemplatesEn *template.Template + categoryTemplatesRu *template.Template ) -func init() { +func prepareViews() { categoryTemplatesEn = template.Must(template. New("category"). Funcs( @@ -38,6 +43,11 @@ func init() { }). ParseFS(fs, "categories.html")) categoryTemplatesRu = template.Must(template.Must(categoryTemplatesEn.Clone()).Parse(categoriesRu)) + + baseEn = m(viewutil.BaseEn.Clone()) + baseRu = m(viewutil.BaseEn.Clone()) + listEn = m(m(baseEn.Clone()).ParseFS(fs, "view_list.html")) + listRu = m(m(m(baseRu.Clone()).ParseFS(fs, "view_list.html")).Parse(categoriesRu)) } func localizedCatTemplates(meta viewutil.Meta) *template.Template { @@ -62,7 +72,7 @@ func localizedCatTemplateAsString(meta viewutil.Meta, name string, datum ...inte return buf.String() } -func categoryCard(meta viewutil.Meta, hyphaName string) string { +func CategoryCard(meta viewutil.Meta, hyphaName string) string { var buf strings.Builder err := localizedCatTemplates(meta).ExecuteTemplate(&buf, "category card", struct { HyphaName string @@ -70,7 +80,7 @@ func categoryCard(meta viewutil.Meta, hyphaName string) string { GivenPermissionToModify bool }{ hyphaName, - categories.WithHypha(hyphaName), + WithHypha(hyphaName), meta.U.CanProceed("add-to-category"), }) if err != nil { @@ -79,7 +89,7 @@ func categoryCard(meta viewutil.Meta, hyphaName string) string { return buf.String() } -func CategoryPage(meta viewutil.Meta, catName string) { +func categoryPage(meta viewutil.Meta, catName string) { var buf strings.Builder err := localizedCatTemplates(meta).ExecuteTemplate(&buf, "category page", struct { CatName string @@ -87,13 +97,13 @@ func CategoryPage(meta viewutil.Meta, catName string) { GivenPermissionToModify bool }{ catName, - categories.Contents(catName), + Contents(catName), meta.U.CanProceed("add-to-category"), }) if err != nil { log.Println(err) } - _, err = io.WriteString(meta.W, Base( + _, err = io.WriteString(meta.W, viewutil.Base( meta, localizedCatTemplateAsString(meta, "category x", catName), buf.String(), @@ -103,22 +113,31 @@ func CategoryPage(meta viewutil.Meta, catName string) { } } -func CategoryList(meta viewutil.Meta) { - var buf strings.Builder - err := localizedCatTemplates(meta).ExecuteTemplate(&buf, "category list", struct { - Categories []string - }{ - categories.List(), - }) - if err != nil { - log.Println(err) +func loctmp(meta viewutil.Meta, en *template.Template, ru *template.Template) *template.Template { + switch meta.Locale() { + case "en": + return en + case "ru": + return ru } - _, err = io.WriteString(meta.W, Base( - meta, - localizedCatTemplateAsString(meta, "category list heading"), - buf.String(), - )) - if err != nil { + panic("aaa") +} + +type listData struct { + viewutil.BaseData + Categories []string +} + +func categoryList(meta viewutil.Meta) { + if err := loctmp(meta, listEn, listRu).ExecuteTemplate(meta.W, "page", listData{ + BaseData: viewutil.BaseData{ + Meta: meta, + Title: localizedCatTemplateAsString(meta, "category list heading"), + HeaderLinks: cfg.HeaderLinks, + CommonScripts: cfg.CommonScripts, + }, + Categories: List(), + }); err != nil { log.Println(err) } } diff --git a/views/readers.qtpl b/views/readers.qtpl index 4eb397d..76de41e 100644 --- a/views/readers.qtpl +++ b/views/readers.qtpl @@ -5,6 +5,7 @@ {% import "github.com/bouncepaw/mycorrhiza/cfg" %} {% import "github.com/bouncepaw/mycorrhiza/hyphae" %} +{% import "github.com/bouncepaw/mycorrhiza/categories" %} {% import "github.com/bouncepaw/mycorrhiza/l18n" %} {% import "github.com/bouncepaw/mycorrhiza/mimetype" %} {% import "github.com/bouncepaw/mycorrhiza/tree" %} @@ -132,7 +133,7 @@ If you rename .prevnext, change the docs too. {%= hyphaInfo(meta, h) %} -{%s= categoryCard(meta, h.CanonicalName()) %} +{%s= categories.CategoryCard(meta, h.CanonicalName()) %} {%= siblingHyphae(siblings, meta.Lc) %}
    {%= viewScripts() %} diff --git a/views/readers.qtpl.go b/views/readers.qtpl.go index 90e6540..fac57cb 100644 --- a/views/readers.qtpl.go +++ b/views/readers.qtpl.go @@ -23,616 +23,619 @@ import "github.com/bouncepaw/mycorrhiza/cfg" import "github.com/bouncepaw/mycorrhiza/hyphae" //line views/readers.qtpl:8 -import "github.com/bouncepaw/mycorrhiza/l18n" +import "github.com/bouncepaw/mycorrhiza/categories" //line views/readers.qtpl:9 -import "github.com/bouncepaw/mycorrhiza/mimetype" +import "github.com/bouncepaw/mycorrhiza/l18n" //line views/readers.qtpl:10 -import "github.com/bouncepaw/mycorrhiza/tree" +import "github.com/bouncepaw/mycorrhiza/mimetype" //line views/readers.qtpl:11 -import "github.com/bouncepaw/mycorrhiza/user" +import "github.com/bouncepaw/mycorrhiza/tree" //line views/readers.qtpl:12 -import "github.com/bouncepaw/mycorrhiza/util" +import "github.com/bouncepaw/mycorrhiza/user" //line views/readers.qtpl:13 +import "github.com/bouncepaw/mycorrhiza/util" + +//line views/readers.qtpl:14 import "github.com/bouncepaw/mycorrhiza/viewutil" -//line views/readers.qtpl:15 +//line views/readers.qtpl:16 import ( qtio422016 "io" qt422016 "github.com/valyala/quicktemplate" ) -//line views/readers.qtpl:15 +//line views/readers.qtpl:16 var ( _ = qtio422016.Copy _ = qt422016.AcquireByteBuffer ) -//line views/readers.qtpl:15 +//line views/readers.qtpl:16 func StreamMediaMenu(qw422016 *qt422016.Writer, rq *http.Request, h hyphae.Hypha, u *user.User) { -//line views/readers.qtpl:15 +//line views/readers.qtpl:16 qw422016.N().S(` `) -//line views/readers.qtpl:17 +//line views/readers.qtpl:18 lc := l18n.FromRequest(rq) -//line views/readers.qtpl:18 +//line views/readers.qtpl:19 qw422016.N().S(`

    `) -//line views/readers.qtpl:21 +//line views/readers.qtpl:22 qw422016.N().S(lc.Get("ui.media_title", &l18n.Replacements{"name": beautifulLink(h.CanonicalName())})) -//line views/readers.qtpl:21 +//line views/readers.qtpl:22 qw422016.N().S(`

    `) -//line views/readers.qtpl:22 +//line views/readers.qtpl:23 switch h.(type) { -//line views/readers.qtpl:23 +//line views/readers.qtpl:24 case *hyphae.MediaHypha: -//line views/readers.qtpl:23 +//line views/readers.qtpl:24 qw422016.N().S(`

    `) -//line views/readers.qtpl:24 +//line views/readers.qtpl:25 qw422016.E().S(lc.Get("ui.media_tip")) -//line views/readers.qtpl:24 +//line views/readers.qtpl:25 qw422016.N().S(` `) -//line views/readers.qtpl:24 +//line views/readers.qtpl:25 qw422016.E().S(lc.Get("ui.media_what_is")) -//line views/readers.qtpl:24 +//line views/readers.qtpl:25 qw422016.N().S(`

    `) -//line views/readers.qtpl:25 +//line views/readers.qtpl:26 default: -//line views/readers.qtpl:25 +//line views/readers.qtpl:26 qw422016.N().S(`

    `) -//line views/readers.qtpl:26 +//line views/readers.qtpl:27 qw422016.E().S(lc.Get("ui.media_empty")) -//line views/readers.qtpl:26 +//line views/readers.qtpl:27 qw422016.N().S(` `) -//line views/readers.qtpl:26 +//line views/readers.qtpl:27 qw422016.E().S(lc.Get("ui.media_what_is")) -//line views/readers.qtpl:26 +//line views/readers.qtpl:27 qw422016.N().S(`

    `) -//line views/readers.qtpl:27 +//line views/readers.qtpl:28 } -//line views/readers.qtpl:27 +//line views/readers.qtpl:28 qw422016.N().S(`
    `) -//line views/readers.qtpl:30 +//line views/readers.qtpl:31 switch h := h.(type) { -//line views/readers.qtpl:31 +//line views/readers.qtpl:32 case *hyphae.MediaHypha: -//line views/readers.qtpl:31 +//line views/readers.qtpl:32 qw422016.N().S(` `) -//line views/readers.qtpl:33 +//line views/readers.qtpl:34 mime := mimetype.FromExtension(path.Ext(h.MediaFilePath())) fileinfo, err := os.Stat(h.MediaFilePath()) -//line views/readers.qtpl:34 +//line views/readers.qtpl:35 qw422016.N().S(` `) -//line views/readers.qtpl:35 +//line views/readers.qtpl:36 if err == nil { -//line views/readers.qtpl:35 +//line views/readers.qtpl:36 qw422016.N().S(`
    `) -//line views/readers.qtpl:37 +//line views/readers.qtpl:38 qw422016.E().S(lc.Get("ui.media_stat")) -//line views/readers.qtpl:37 +//line views/readers.qtpl:38 qw422016.N().S(`

    `) -//line views/readers.qtpl:39 +//line views/readers.qtpl:40 qw422016.E().S(lc.Get("ui.media_stat_mime")) -//line views/readers.qtpl:39 +//line views/readers.qtpl:40 qw422016.N().S(` `) -//line views/readers.qtpl:39 +//line views/readers.qtpl:40 qw422016.E().S(mime) -//line views/readers.qtpl:39 +//line views/readers.qtpl:40 qw422016.N().S(`

    `) -//line views/readers.qtpl:41 +//line views/readers.qtpl:42 } -//line views/readers.qtpl:41 +//line views/readers.qtpl:42 qw422016.N().S(` `) -//line views/readers.qtpl:43 +//line views/readers.qtpl:44 if strings.HasPrefix(mime, "image/") { -//line views/readers.qtpl:43 +//line views/readers.qtpl:44 qw422016.N().S(`
    `) -//line views/readers.qtpl:45 +//line views/readers.qtpl:46 qw422016.E().S(lc.Get("ui.media_include")) -//line views/readers.qtpl:45 +//line views/readers.qtpl:46 qw422016.N().S(`
    img { `)
    -//line views/readers.qtpl:47
    +//line views/readers.qtpl:48
     			qw422016.E().S(h.CanonicalName())
    -//line views/readers.qtpl:47
    +//line views/readers.qtpl:48
     			qw422016.N().S(` }
    `) -//line views/readers.qtpl:49 +//line views/readers.qtpl:50 } -//line views/readers.qtpl:49 +//line views/readers.qtpl:50 qw422016.N().S(` `) -//line views/readers.qtpl:50 +//line views/readers.qtpl:51 } -//line views/readers.qtpl:50 +//line views/readers.qtpl:51 qw422016.N().S(` `) -//line views/readers.qtpl:52 +//line views/readers.qtpl:53 if u.CanProceed("upload-binary") { -//line views/readers.qtpl:52 +//line views/readers.qtpl:53 qw422016.N().S(` `) -//line views/readers.qtpl:65 +//line views/readers.qtpl:66 } -//line views/readers.qtpl:65 +//line views/readers.qtpl:66 qw422016.N().S(` `) -//line views/readers.qtpl:68 +//line views/readers.qtpl:69 switch h := h.(type) { -//line views/readers.qtpl:69 +//line views/readers.qtpl:70 case *hyphae.MediaHypha: -//line views/readers.qtpl:69 +//line views/readers.qtpl:70 qw422016.N().S(` `) -//line views/readers.qtpl:70 +//line views/readers.qtpl:71 if u.CanProceed("remove-media") { -//line views/readers.qtpl:70 +//line views/readers.qtpl:71 qw422016.N().S(` `) -//line views/readers.qtpl:78 +//line views/readers.qtpl:79 } -//line views/readers.qtpl:78 +//line views/readers.qtpl:79 qw422016.N().S(` `) -//line views/readers.qtpl:79 +//line views/readers.qtpl:80 } -//line views/readers.qtpl:79 +//line views/readers.qtpl:80 qw422016.N().S(`
    `) -//line views/readers.qtpl:84 +//line views/readers.qtpl:85 } -//line views/readers.qtpl:84 +//line views/readers.qtpl:85 func WriteMediaMenu(qq422016 qtio422016.Writer, rq *http.Request, h hyphae.Hypha, u *user.User) { -//line views/readers.qtpl:84 +//line views/readers.qtpl:85 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/readers.qtpl:84 +//line views/readers.qtpl:85 StreamMediaMenu(qw422016, rq, h, u) -//line views/readers.qtpl:84 +//line views/readers.qtpl:85 qt422016.ReleaseWriter(qw422016) -//line views/readers.qtpl:84 +//line views/readers.qtpl:85 } -//line views/readers.qtpl:84 +//line views/readers.qtpl:85 func MediaMenu(rq *http.Request, h hyphae.Hypha, u *user.User) string { -//line views/readers.qtpl:84 +//line views/readers.qtpl:85 qb422016 := qt422016.AcquireByteBuffer() -//line views/readers.qtpl:84 +//line views/readers.qtpl:85 WriteMediaMenu(qb422016, rq, h, u) -//line views/readers.qtpl:84 +//line views/readers.qtpl:85 qs422016 := string(qb422016.B) -//line views/readers.qtpl:84 +//line views/readers.qtpl:85 qt422016.ReleaseByteBuffer(qb422016) -//line views/readers.qtpl:84 +//line views/readers.qtpl:85 return qs422016 -//line views/readers.qtpl:84 +//line views/readers.qtpl:85 } // If `contents` == "", a helpful message is shown instead. // // If you rename .prevnext, change the docs too. -//line views/readers.qtpl:89 +//line views/readers.qtpl:90 func StreamHypha(qw422016 *qt422016.Writer, meta viewutil.Meta, h hyphae.Hypha, contents string) { -//line views/readers.qtpl:89 +//line views/readers.qtpl:90 qw422016.N().S(` `) -//line views/readers.qtpl:91 +//line views/readers.qtpl:92 siblings, subhyphae, prevHyphaName, nextHyphaName := tree.Tree(h.CanonicalName()) lc := meta.Lc -//line views/readers.qtpl:93 +//line views/readers.qtpl:94 qw422016.N().S(`
    `) -//line views/readers.qtpl:97 +//line views/readers.qtpl:98 if meta.U.CanProceed("edit") { -//line views/readers.qtpl:97 +//line views/readers.qtpl:98 qw422016.N().S(` `) -//line views/readers.qtpl:101 +//line views/readers.qtpl:102 } -//line views/readers.qtpl:101 +//line views/readers.qtpl:102 qw422016.N().S(` `) -//line views/readers.qtpl:103 +//line views/readers.qtpl:104 if cfg.UseAuth && util.IsProfileName(h.CanonicalName()) && meta.U.Name == strings.TrimPrefix(h.CanonicalName(), cfg.UserHypha+"/") { -//line views/readers.qtpl:103 +//line views/readers.qtpl:104 qw422016.N().S(` `) -//line views/readers.qtpl:107 +//line views/readers.qtpl:108 if meta.U.Group == "admin" { -//line views/readers.qtpl:107 +//line views/readers.qtpl:108 qw422016.N().S(` `) -//line views/readers.qtpl:111 +//line views/readers.qtpl:112 } -//line views/readers.qtpl:111 +//line views/readers.qtpl:112 qw422016.N().S(` `) -//line views/readers.qtpl:112 +//line views/readers.qtpl:113 } -//line views/readers.qtpl:112 +//line views/readers.qtpl:113 qw422016.N().S(` `) -//line views/readers.qtpl:114 +//line views/readers.qtpl:115 qw422016.N().S(NaviTitle(h)) -//line views/readers.qtpl:114 +//line views/readers.qtpl:115 qw422016.N().S(` `) -//line views/readers.qtpl:115 +//line views/readers.qtpl:116 switch h.(type) { -//line views/readers.qtpl:116 +//line views/readers.qtpl:117 case *hyphae.EmptyHypha: -//line views/readers.qtpl:116 +//line views/readers.qtpl:117 qw422016.N().S(` `) -//line views/readers.qtpl:117 +//line views/readers.qtpl:118 streamnonExistentHyphaNotice(qw422016, h, meta.U, meta.Lc) -//line views/readers.qtpl:117 +//line views/readers.qtpl:118 qw422016.N().S(` `) -//line views/readers.qtpl:118 +//line views/readers.qtpl:119 default: -//line views/readers.qtpl:118 +//line views/readers.qtpl:119 qw422016.N().S(` `) -//line views/readers.qtpl:119 +//line views/readers.qtpl:120 qw422016.N().S(contents) -//line views/readers.qtpl:119 +//line views/readers.qtpl:120 qw422016.N().S(` `) -//line views/readers.qtpl:120 +//line views/readers.qtpl:121 } -//line views/readers.qtpl:120 +//line views/readers.qtpl:121 qw422016.N().S(`
    `) -//line views/readers.qtpl:123 +//line views/readers.qtpl:124 if prevHyphaName != "" { -//line views/readers.qtpl:123 +//line views/readers.qtpl:124 qw422016.N().S(` `) -//line views/readers.qtpl:125 +//line views/readers.qtpl:126 } -//line views/readers.qtpl:125 +//line views/readers.qtpl:126 qw422016.N().S(` `) -//line views/readers.qtpl:126 +//line views/readers.qtpl:127 if nextHyphaName != "" { -//line views/readers.qtpl:126 +//line views/readers.qtpl:127 qw422016.N().S(` `) -//line views/readers.qtpl:128 +//line views/readers.qtpl:129 } -//line views/readers.qtpl:128 +//line views/readers.qtpl:129 qw422016.N().S(`
    `) -//line views/readers.qtpl:130 +//line views/readers.qtpl:131 StreamSubhyphae(qw422016, subhyphae, meta.Lc) -//line views/readers.qtpl:130 +//line views/readers.qtpl:131 qw422016.N().S(`
    `) -//line views/readers.qtpl:132 +//line views/readers.qtpl:133 streamhyphaInfo(qw422016, meta, h) -//line views/readers.qtpl:132 +//line views/readers.qtpl:133 qw422016.N().S(`
    `) -//line views/readers.qtpl:135 - qw422016.N().S(categoryCard(meta, h.CanonicalName())) -//line views/readers.qtpl:135 +//line views/readers.qtpl:136 + qw422016.N().S(categories.CategoryCard(meta, h.CanonicalName())) +//line views/readers.qtpl:136 qw422016.N().S(` `) -//line views/readers.qtpl:136 +//line views/readers.qtpl:137 streamsiblingHyphae(qw422016, siblings, meta.Lc) -//line views/readers.qtpl:136 +//line views/readers.qtpl:137 qw422016.N().S(`
    `) -//line views/readers.qtpl:138 +//line views/readers.qtpl:139 streamviewScripts(qw422016) -//line views/readers.qtpl:138 +//line views/readers.qtpl:139 qw422016.N().S(` `) -//line views/readers.qtpl:139 +//line views/readers.qtpl:140 } -//line views/readers.qtpl:139 +//line views/readers.qtpl:140 func WriteHypha(qq422016 qtio422016.Writer, meta viewutil.Meta, h hyphae.Hypha, contents string) { -//line views/readers.qtpl:139 +//line views/readers.qtpl:140 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/readers.qtpl:139 +//line views/readers.qtpl:140 StreamHypha(qw422016, meta, h, contents) -//line views/readers.qtpl:139 +//line views/readers.qtpl:140 qt422016.ReleaseWriter(qw422016) -//line views/readers.qtpl:139 +//line views/readers.qtpl:140 } -//line views/readers.qtpl:139 +//line views/readers.qtpl:140 func Hypha(meta viewutil.Meta, h hyphae.Hypha, contents string) string { -//line views/readers.qtpl:139 +//line views/readers.qtpl:140 qb422016 := qt422016.AcquireByteBuffer() -//line views/readers.qtpl:139 +//line views/readers.qtpl:140 WriteHypha(qb422016, meta, h, contents) -//line views/readers.qtpl:139 +//line views/readers.qtpl:140 qs422016 := string(qb422016.B) -//line views/readers.qtpl:139 +//line views/readers.qtpl:140 qt422016.ReleaseByteBuffer(qb422016) -//line views/readers.qtpl:139 +//line views/readers.qtpl:140 return qs422016 -//line views/readers.qtpl:139 +//line views/readers.qtpl:140 } -//line views/readers.qtpl:141 +//line views/readers.qtpl:142 func StreamRevision(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents, revHash string) { -//line views/readers.qtpl:141 +//line views/readers.qtpl:142 qw422016.N().S(`

    `) -//line views/readers.qtpl:145 +//line views/readers.qtpl:146 qw422016.E().S(lc.Get("ui.revision_warning")) -//line views/readers.qtpl:145 +//line views/readers.qtpl:146 qw422016.N().S(` `) -//line views/readers.qtpl:145 +//line views/readers.qtpl:146 qw422016.E().S(lc.Get("ui.revision_link")) -//line views/readers.qtpl:145 +//line views/readers.qtpl:146 qw422016.N().S(`

    `) -//line views/readers.qtpl:146 +//line views/readers.qtpl:147 qw422016.N().S(NaviTitle(h)) -//line views/readers.qtpl:146 +//line views/readers.qtpl:147 qw422016.N().S(` `) -//line views/readers.qtpl:147 +//line views/readers.qtpl:148 qw422016.N().S(contents) -//line views/readers.qtpl:147 +//line views/readers.qtpl:148 qw422016.N().S(`
    `) -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 streamviewScripts(qw422016) -//line views/readers.qtpl:151 +//line views/readers.qtpl:152 qw422016.N().S(` `) -//line views/readers.qtpl:152 +//line views/readers.qtpl:153 } -//line views/readers.qtpl:152 +//line views/readers.qtpl:153 func WriteRevision(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents, revHash string) { -//line views/readers.qtpl:152 +//line views/readers.qtpl:153 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/readers.qtpl:152 +//line views/readers.qtpl:153 StreamRevision(qw422016, rq, lc, h, contents, revHash) -//line views/readers.qtpl:152 +//line views/readers.qtpl:153 qt422016.ReleaseWriter(qw422016) -//line views/readers.qtpl:152 +//line views/readers.qtpl:153 } -//line views/readers.qtpl:152 +//line views/readers.qtpl:153 func Revision(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents, revHash string) string { -//line views/readers.qtpl:152 +//line views/readers.qtpl:153 qb422016 := qt422016.AcquireByteBuffer() -//line views/readers.qtpl:152 +//line views/readers.qtpl:153 WriteRevision(qb422016, rq, lc, h, contents, revHash) -//line views/readers.qtpl:152 +//line views/readers.qtpl:153 qs422016 := string(qb422016.B) -//line views/readers.qtpl:152 +//line views/readers.qtpl:153 qt422016.ReleaseByteBuffer(qb422016) -//line views/readers.qtpl:152 +//line views/readers.qtpl:153 return qs422016 -//line views/readers.qtpl:152 +//line views/readers.qtpl:153 } -//line views/readers.qtpl:154 +//line views/readers.qtpl:155 func streamviewScripts(qw422016 *qt422016.Writer) { -//line views/readers.qtpl:154 +//line views/readers.qtpl:155 qw422016.N().S(` `) -//line views/readers.qtpl:155 +//line views/readers.qtpl:156 for _, scriptPath := range cfg.ViewScripts { -//line views/readers.qtpl:155 +//line views/readers.qtpl:156 qw422016.N().S(` `) -//line views/readers.qtpl:157 +//line views/readers.qtpl:158 } -//line views/readers.qtpl:157 +//line views/readers.qtpl:158 qw422016.N().S(` `) -//line views/readers.qtpl:158 +//line views/readers.qtpl:159 } -//line views/readers.qtpl:158 +//line views/readers.qtpl:159 func writeviewScripts(qq422016 qtio422016.Writer) { -//line views/readers.qtpl:158 +//line views/readers.qtpl:159 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/readers.qtpl:158 +//line views/readers.qtpl:159 streamviewScripts(qw422016) -//line views/readers.qtpl:158 +//line views/readers.qtpl:159 qt422016.ReleaseWriter(qw422016) -//line views/readers.qtpl:158 +//line views/readers.qtpl:159 } -//line views/readers.qtpl:158 +//line views/readers.qtpl:159 func viewScripts() string { -//line views/readers.qtpl:158 +//line views/readers.qtpl:159 qb422016 := qt422016.AcquireByteBuffer() -//line views/readers.qtpl:158 +//line views/readers.qtpl:159 writeviewScripts(qb422016) -//line views/readers.qtpl:158 +//line views/readers.qtpl:159 qs422016 := string(qb422016.B) -//line views/readers.qtpl:158 +//line views/readers.qtpl:159 qt422016.ReleaseByteBuffer(qb422016) -//line views/readers.qtpl:158 +//line views/readers.qtpl:159 return qs422016 -//line views/readers.qtpl:158 +//line views/readers.qtpl:159 } diff --git a/viewutil/base.html b/viewutil/base.html index 8bbdf7c..d6fcbc7 100644 --- a/viewutil/base.html +++ b/viewutil/base.html @@ -1,4 +1,4 @@ -{{define "base"}} +{{define "page"}} @@ -79,5 +79,4 @@ - {{end}} \ No newline at end of file diff --git a/viewutil/viewutil.go b/viewutil/viewutil.go index b7bfd5f..fc0963c 100644 --- a/viewutil/viewutil.go +++ b/viewutil/viewutil.go @@ -55,7 +55,7 @@ func localizedBaseWithWeirdBody(meta Meta) *template.Template { return m(m(t.Clone()).Parse(`{{define "body"}}{{.Body}}{{end}}`)) } -type baseData struct { +type BaseData struct { Meta Meta Title string HeadElements []string @@ -69,7 +69,7 @@ func Base(meta Meta, title, body string, headElements ...string) string { var w strings.Builder meta.W = &w t := localizedBaseWithWeirdBody(meta) - err := t.ExecuteTemplate(&w, "base", baseData{ + err := t.ExecuteTemplate(&w, "page", BaseData{ Meta: meta, Title: title, HeadElements: headElements, diff --git a/web/web.go b/web/web.go index d1167ee..fa66170 100644 --- a/web/web.go +++ b/web/web.go @@ -3,6 +3,7 @@ package web import ( "fmt" + "github.com/bouncepaw/mycorrhiza/categories" "github.com/bouncepaw/mycorrhiza/viewutil" "io" "mime" @@ -109,7 +110,7 @@ func Handler() http.Handler { initStuff(wikiRouter) initSearch(wikiRouter) initBacklinks(wikiRouter) - initCategories(wikiRouter) + categories.InitCategoriesHandlers(wikiRouter) // Admin routes. if cfg.UseAuth { From ca3da43e53b05bc1265654b338702d4f62e3a600 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 2 Apr 2022 00:07:28 +0300 Subject: [PATCH 06/23] Categories, views: Refactor the cat page view --- categories/categories.html | 28 --------------- categories/view_page.html | 27 ++++++++++++++ categories/views.go | 72 +++++++++++++++++++------------------- 3 files changed, 63 insertions(+), 64 deletions(-) create mode 100644 categories/view_page.html diff --git a/categories/categories.html b/categories/categories.html index bfae50e..ea099c9 100644 --- a/categories/categories.html +++ b/categories/categories.html @@ -35,32 +35,4 @@ {{end}} -{{end}} - -{{define "category page"}} -{{$catName := .CatName}} -
    -

    {{block "cat" .}}Category{{end}} {{beautifulName $catName}}

    - {{if len .Hyphae | not}} -

    {{block "empty cat" .}}This category is empty{{end}}

    - {{end}} -
      - {{range .Hyphae}} -
    • - {{beautifulName .}} -
    • - {{end}} - {{if .GivenPermissionToModify}} -
    • -
      - - - - -
      -
    • - {{end}} -
    -
    {{end}} \ No newline at end of file diff --git a/categories/view_page.html b/categories/view_page.html new file mode 100644 index 0000000..6d45d51 --- /dev/null +++ b/categories/view_page.html @@ -0,0 +1,27 @@ +{{define "body"}} + {{$catName := .CatName}} +
    +

    {{block "cat" .}}Category{{end}} {{beautifulName $catName}}

    + {{if len .Hyphae | not}} +

    {{block "empty cat" .}}This category is empty{{end}}

    + {{end}} +
      + {{range .Hyphae}} +
    • + {{beautifulName .}} +
    • + {{end}} + {{if .GivenPermissionToModify}} +
    • +
      + + + + +
      +
    • + {{end}} +
    +
    +{{end}} \ No newline at end of file diff --git a/categories/views.go b/categories/views.go index fd75e6b..5258c8d 100644 --- a/categories/views.go +++ b/categories/views.go @@ -5,7 +5,6 @@ import ( "github.com/bouncepaw/mycorrhiza/cfg" "github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/viewutil" - "io" "log" "strings" "text/template" // TODO: Fight @@ -27,13 +26,23 @@ const categoriesRu = ` var ( //go:embed *.html - fs embed.FS - m = template.Must - baseEn, baseRu, listEn, listRu *template.Template - categoryTemplatesEn *template.Template - categoryTemplatesRu *template.Template + fs embed.FS + m = template.Must + baseEn, baseRu, listEn, listRu, pageEn, pageRu *template.Template + categoryTemplatesEn *template.Template + categoryTemplatesRu *template.Template ) +func loctmp(meta viewutil.Meta, en *template.Template, ru *template.Template) *template.Template { + switch meta.Locale() { + case "en": + return en + case "ru": + return ru + } + panic("aaa") +} + func prepareViews() { categoryTemplatesEn = template.Must(template. New("category"). @@ -45,9 +54,11 @@ func prepareViews() { categoryTemplatesRu = template.Must(template.Must(categoryTemplatesEn.Clone()).Parse(categoriesRu)) baseEn = m(viewutil.BaseEn.Clone()) - baseRu = m(viewutil.BaseEn.Clone()) + baseRu = m(viewutil.BaseRu.Clone()) listEn = m(m(baseEn.Clone()).ParseFS(fs, "view_list.html")) listRu = m(m(m(baseRu.Clone()).ParseFS(fs, "view_list.html")).Parse(categoriesRu)) + pageEn = m(m(baseEn.Clone()).ParseFS(fs, "view_page.html")) + pageRu = m(m(m(baseRu.Clone()).ParseFS(fs, "view_page.html")).Parse(categoriesRu)) } func localizedCatTemplates(meta viewutil.Meta) *template.Template { @@ -89,38 +100,27 @@ func CategoryCard(meta viewutil.Meta, hyphaName string) string { return buf.String() } -func categoryPage(meta viewutil.Meta, catName string) { - var buf strings.Builder - err := localizedCatTemplates(meta).ExecuteTemplate(&buf, "category page", struct { - CatName string - Hyphae []string - GivenPermissionToModify bool - }{ - catName, - Contents(catName), - meta.U.CanProceed("add-to-category"), - }) - if err != nil { - log.Println(err) - } - _, err = io.WriteString(meta.W, viewutil.Base( - meta, - localizedCatTemplateAsString(meta, "category x", catName), - buf.String(), - )) - if err != nil { - log.Println(err) - } +type pageData struct { + viewutil.BaseData + CatName string + Hyphae []string + GivenPermissionToModify bool } -func loctmp(meta viewutil.Meta, en *template.Template, ru *template.Template) *template.Template { - switch meta.Locale() { - case "en": - return en - case "ru": - return ru +func categoryPage(meta viewutil.Meta, catName string) { + if err := loctmp(meta, pageEn, pageRu).ExecuteTemplate(meta.W, "page", pageData{ + BaseData: viewutil.BaseData{ + Meta: meta, + Title: localizedCatTemplateAsString(meta, "category x", catName), + HeaderLinks: cfg.HeaderLinks, + CommonScripts: cfg.CommonScripts, + }, + CatName: catName, + Hyphae: Contents(catName), + GivenPermissionToModify: meta.U.CanProceed("add-to-category"), + }); err != nil { + log.Println(err) } - panic("aaa") } type listData struct { From cbf416d7bb46a1eb2e976c647a3c95e8d929e5db Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 2 Apr 2022 00:18:37 +0300 Subject: [PATCH 07/23] Categories, views: Implement viewutil.Chain --- categories/views.go | 40 +++++++++++++++++++--------------------- viewutil/chain.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 21 deletions(-) create mode 100644 viewutil/chain.go diff --git a/categories/views.go b/categories/views.go index 5258c8d..370edf5 100644 --- a/categories/views.go +++ b/categories/views.go @@ -26,23 +26,14 @@ const categoriesRu = ` var ( //go:embed *.html - fs embed.FS - m = template.Must - baseEn, baseRu, listEn, listRu, pageEn, pageRu *template.Template - categoryTemplatesEn *template.Template - categoryTemplatesRu *template.Template + fs embed.FS + m = template.Must + baseEn, baseRu *template.Template + viewListChain, viewPageChain viewutil.Chain + categoryTemplatesEn *template.Template + categoryTemplatesRu *template.Template ) -func loctmp(meta viewutil.Meta, en *template.Template, ru *template.Template) *template.Template { - switch meta.Locale() { - case "en": - return en - case "ru": - return ru - } - panic("aaa") -} - func prepareViews() { categoryTemplatesEn = template.Must(template. New("category"). @@ -55,10 +46,17 @@ func prepareViews() { baseEn = m(viewutil.BaseEn.Clone()) baseRu = m(viewutil.BaseRu.Clone()) - listEn = m(m(baseEn.Clone()).ParseFS(fs, "view_list.html")) - listRu = m(m(m(baseRu.Clone()).ParseFS(fs, "view_list.html")).Parse(categoriesRu)) - pageEn = m(m(baseEn.Clone()).ParseFS(fs, "view_page.html")) - pageRu = m(m(m(baseRu.Clone()).ParseFS(fs, "view_page.html")).Parse(categoriesRu)) + + viewListChain = viewutil. + En( + m(m(baseEn.Clone()).ParseFS(fs, "view_list.html"))). + Ru( + m(m(m(baseRu.Clone()).ParseFS(fs, "view_list.html")).Parse(categoriesRu))) + viewPageChain = viewutil. + En( + m(m(baseEn.Clone()).ParseFS(fs, "view_page.html"))). + Ru( + m(m(m(baseRu.Clone()).ParseFS(fs, "view_page.html")).Parse(categoriesRu))) } func localizedCatTemplates(meta viewutil.Meta) *template.Template { @@ -108,7 +106,7 @@ type pageData struct { } func categoryPage(meta viewutil.Meta, catName string) { - if err := loctmp(meta, pageEn, pageRu).ExecuteTemplate(meta.W, "page", pageData{ + if err := viewPageChain.Get(meta).ExecuteTemplate(meta.W, "page", pageData{ BaseData: viewutil.BaseData{ Meta: meta, Title: localizedCatTemplateAsString(meta, "category x", catName), @@ -129,7 +127,7 @@ type listData struct { } func categoryList(meta viewutil.Meta) { - if err := loctmp(meta, listEn, listRu).ExecuteTemplate(meta.W, "page", listData{ + if err := viewListChain.Get(meta).ExecuteTemplate(meta.W, "page", listData{ BaseData: viewutil.BaseData{ Meta: meta, Title: localizedCatTemplateAsString(meta, "category list heading"), diff --git a/viewutil/chain.go b/viewutil/chain.go new file mode 100644 index 0000000..783be46 --- /dev/null +++ b/viewutil/chain.go @@ -0,0 +1,33 @@ +package viewutil + +import "text/template" + +// Chain represents a chain of different language versions of the same template. +type Chain struct { + en *template.Template + ru *template.Template +} + +// En returns a new Chain. This is the only constructor of the type, so every view is forced to have an English representation. +func En(en *template.Template) Chain { + return Chain{ + en: en, + } +} + +// Ru adds a Russian translation to the Chain. +func (c Chain) Ru(ru *template.Template) Chain { + c.ru = ru + return c +} + +// Get returns an appropriate language representation for the given locale in meta. +func (c Chain) Get(meta Meta) *template.Template { + switch meta.Locale() { + case "en": + return c.en + case "ru": + return c.ru + } + panic("unknown language " + meta.Locale()) +} From 686c329615d1d1f68db79038c96e45cb80f098bb Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 2 Apr 2022 00:35:40 +0300 Subject: [PATCH 08/23] Categories, views: Give the card view its own file, make title a block --- categories/categories.html | 38 -------------------------- categories/view_card.html | 35 ++++++++++++++++++++++++ categories/view_list.html | 3 +- categories/view_page.html | 1 + categories/views.go | 56 ++++++++++---------------------------- viewutil/base.html | 2 +- viewutil/viewutil.go | 7 +++-- 7 files changed, 58 insertions(+), 84 deletions(-) delete mode 100644 categories/categories.html create mode 100644 categories/view_card.html diff --git a/categories/categories.html b/categories/categories.html deleted file mode 100644 index ea099c9..0000000 --- a/categories/categories.html +++ /dev/null @@ -1,38 +0,0 @@ -{{define "category x"}}Category {{. | beautifulName}}{{end}} -{{define "category list heading"}}Category list{{end}} - -{{define "category card"}} -{{$hyphaName := .HyphaName}} -{{$givenPermission := .GivenPermissionToModify}} - -{{end}} \ No newline at end of file diff --git a/categories/view_card.html b/categories/view_card.html new file mode 100644 index 0000000..1f145c2 --- /dev/null +++ b/categories/view_card.html @@ -0,0 +1,35 @@ +{{define "category card"}} + {{$hyphaName := .HyphaName}} + {{$givenPermission := .GivenPermissionToModify}} + +{{end}} \ No newline at end of file diff --git a/categories/view_list.html b/categories/view_list.html index 8cd79da..fdd21db 100644 --- a/categories/view_list.html +++ b/categories/view_list.html @@ -1,6 +1,7 @@ +{{define "title"}}Category list{{end}} {{define "body"}}
    -

    {{block `category list heading` .}}Category list{{end}}

    +

    {{template "title"}}

    {{if len .Categories}}
      {{range .Categories}} diff --git a/categories/view_page.html b/categories/view_page.html index 6d45d51..569df58 100644 --- a/categories/view_page.html +++ b/categories/view_page.html @@ -1,3 +1,4 @@ +{{define "title"}}Category {{.CatName | beautifulName}}{{end}} {{define "body"}} {{$catName := .CatName}}
      diff --git a/categories/views.go b/categories/views.go index 370edf5..d44dd71 100644 --- a/categories/views.go +++ b/categories/views.go @@ -3,7 +3,6 @@ package categories import ( "embed" "github.com/bouncepaw/mycorrhiza/cfg" - "github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/viewutil" "log" "strings" @@ -26,27 +25,22 @@ const categoriesRu = ` var ( //go:embed *.html - fs embed.FS - m = template.Must - baseEn, baseRu *template.Template - viewListChain, viewPageChain viewutil.Chain - categoryTemplatesEn *template.Template - categoryTemplatesRu *template.Template + fs embed.FS + m = template.Must + baseEn, baseRu *template.Template + viewListChain, viewPageChain, viewCardChain viewutil.Chain ) func prepareViews() { - categoryTemplatesEn = template.Must(template. - New("category"). - Funcs( - template.FuncMap{ - "beautifulName": util.BeautifulName, - }). - ParseFS(fs, "categories.html")) - categoryTemplatesRu = template.Must(template.Must(categoryTemplatesEn.Clone()).Parse(categoriesRu)) baseEn = m(viewutil.BaseEn.Clone()) baseRu = m(viewutil.BaseRu.Clone()) + viewCardChain = viewutil. + En( + m(m(baseEn.Clone()).ParseFS(fs, "view_card.html"))). + Ru( + m(m(m(baseRu.Clone()).ParseFS(fs, "view_card.html")).Parse(categoriesRu))) viewListChain = viewutil. En( m(m(baseEn.Clone()).ParseFS(fs, "view_list.html"))). @@ -59,35 +53,15 @@ func prepareViews() { m(m(m(baseRu.Clone()).ParseFS(fs, "view_page.html")).Parse(categoriesRu))) } -func localizedCatTemplates(meta viewutil.Meta) *template.Template { - if meta.Lc.Locale == "ru" { - return categoryTemplatesRu - } - return categoryTemplatesEn -} - -func localizedCatTemplateAsString(meta viewutil.Meta, name string, datum ...interface{}) string { - var buf strings.Builder - var err error - if len(datum) == 1 { - err = localizedCatTemplates(meta).ExecuteTemplate(&buf, name, datum[0]) - } else { - err = localizedCatTemplates(meta).ExecuteTemplate(&buf, name, nil) - } - if err != nil { - log.Println(err) - return "" - } - return buf.String() +type cardData struct { + HyphaName string + Categories []string + GivenPermissionToModify bool } func CategoryCard(meta viewutil.Meta, hyphaName string) string { var buf strings.Builder - err := localizedCatTemplates(meta).ExecuteTemplate(&buf, "category card", struct { - HyphaName string - Categories []string - GivenPermissionToModify bool - }{ + err := viewCardChain.Get(meta).ExecuteTemplate(&buf, "category card", cardData{ hyphaName, WithHypha(hyphaName), meta.U.CanProceed("add-to-category"), @@ -109,7 +83,6 @@ func categoryPage(meta viewutil.Meta, catName string) { if err := viewPageChain.Get(meta).ExecuteTemplate(meta.W, "page", pageData{ BaseData: viewutil.BaseData{ Meta: meta, - Title: localizedCatTemplateAsString(meta, "category x", catName), HeaderLinks: cfg.HeaderLinks, CommonScripts: cfg.CommonScripts, }, @@ -130,7 +103,6 @@ func categoryList(meta viewutil.Meta) { if err := viewListChain.Get(meta).ExecuteTemplate(meta.W, "page", listData{ BaseData: viewutil.BaseData{ Meta: meta, - Title: localizedCatTemplateAsString(meta, "category list heading"), HeaderLinks: cfg.HeaderLinks, CommonScripts: cfg.CommonScripts, }, diff --git a/viewutil/base.html b/viewutil/base.html index d6fcbc7..c604709 100644 --- a/viewutil/base.html +++ b/viewutil/base.html @@ -4,7 +4,7 @@ - {{.Title}} + {{block "title" .}}{{end}} diff --git a/viewutil/viewutil.go b/viewutil/viewutil.go index fc0963c..af37550 100644 --- a/viewutil/viewutil.go +++ b/viewutil/viewutil.go @@ -52,15 +52,18 @@ func localizedBaseWithWeirdBody(meta Meta) *template.Template { } return BaseEn }() - return m(m(t.Clone()).Parse(`{{define "body"}}{{.Body}}{{end}}`)) + return m(m(t.Clone()).Parse(` +{{define "body"}}{{.Body}}{{end}} +{{define "title"}}{{.Title}}{{end}} +`)) } type BaseData struct { Meta Meta - Title string HeadElements []string HeaderLinks []cfg.HeaderLink CommonScripts []string + Title string // TODO: remove Body string // TODO: remove } From e69c1dc2f9ed20e6df5e03e14e2e5b5c385f08eb Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 2 Apr 2022 00:43:11 +0300 Subject: [PATCH 09/23] Categories, views: Unexport stuff --- categories/categories.go | 29 ++++++++++++++++++----------- categories/handlers.go | 5 +++-- categories/views.go | 6 +++--- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/categories/categories.go b/categories/categories.go index 4e26fa5..50ab12b 100644 --- a/categories/categories.go +++ b/categories/categories.go @@ -1,4 +1,4 @@ -// Package categories provides category management. All operations in this package are mutexed. +// Package categories provides category management. // // As per the long pondering, this is how categories (cats for short) // work in Mycorrhiza: @@ -12,12 +12,19 @@ // cat operations are not mentioned on the recent changes page. // - For cat A, if there are 0 hyphae in the cat, cat A does not // exist. If there are 1 or more hyphae in the cat, cat A exists. +// +// List of things to do with categories later: +// +// - Forbid / in cat names. +// - Rename categories. +// - Delete categories. +// - Bind hyphae. package categories import "sync" -// List returns names of all categories. -func List() (categoryList []string) { +// listOfCategories returns names of all categories. +func listOfCategories() (categoryList []string) { mutex.RLock() for cat, _ := range categoryToHyphae { categoryList = append(categoryList, cat) @@ -26,8 +33,8 @@ func List() (categoryList []string) { return categoryList } -// WithHypha returns what categories have the given hypha. The hypha name must be canonical. -func WithHypha(hyphaName string) (categoryList []string) { +// categoriesWithHypha returns what categories have the given hypha. The hypha name must be canonical. +func categoriesWithHypha(hyphaName string) (categoryList []string) { mutex.RLock() defer mutex.RUnlock() if node, ok := hyphaToCategories[hyphaName]; ok { @@ -37,8 +44,8 @@ func WithHypha(hyphaName string) (categoryList []string) { } } -// Contents returns what hyphae are in the category. If the returned slice is empty, the category does not exist, and vice versa. The category name must be canonical. -func Contents(catName string) (hyphaList []string) { +// hyphaeInCategory returns what hyphae are in the category. If the returned slice is empty, the category does not exist, and vice versa. The category name must be canonical. +func hyphaeInCategory(catName string) (hyphaList []string) { mutex.RLock() defer mutex.RUnlock() if node, ok := categoryToHyphae[catName]; ok { @@ -50,8 +57,8 @@ func Contents(catName string) (hyphaList []string) { var mutex sync.RWMutex -// AddHyphaToCategory adds the hypha to the category and updates the records on the disk. If the hypha is already in the category, nothing happens. Pass canonical names. -func AddHyphaToCategory(hyphaName, catName string) { +// addHyphaToCategory adds the hypha to the category and updates the records on the disk. If the hypha is already in the category, nothing happens. Pass canonical names. +func addHyphaToCategory(hyphaName, catName string) { mutex.Lock() if node, ok := hyphaToCategories[hyphaName]; ok { node.storeCategory(catName) @@ -68,8 +75,8 @@ func AddHyphaToCategory(hyphaName, catName string) { go saveToDisk() } -// RemoveHyphaFromCategory removes the hypha from the category and updates the records on the disk. If the hypha is not in the category, nothing happens. Pass canonical names. -func RemoveHyphaFromCategory(hyphaName, catName string) { +// removeHyphaFromCategory removes the hypha from the category and updates the records on the disk. If the hypha is not in the category, nothing happens. Pass canonical names. +func removeHyphaFromCategory(hyphaName, catName string) { mutex.Lock() if node, ok := hyphaToCategories[hyphaName]; ok { node.removeCategory(catName) diff --git a/categories/handlers.go b/categories/handlers.go index 5bb4179..5417efc 100644 --- a/categories/handlers.go +++ b/categories/handlers.go @@ -11,6 +11,7 @@ import ( "strings" ) +// InitCategoriesHandlers initializes HTTP handlers for the given router. Call somewhere in package web. func InitCategoriesHandlers(r *mux.Router) { r.PathPrefix("/add-to-category").HandlerFunc(handlerAddToCategory).Methods("POST") r.PathPrefix("/remove-from-category").HandlerFunc(handlerRemoveFromCategory).Methods("POST") @@ -51,7 +52,7 @@ func handlerRemoveFromCategory(w http.ResponseWriter, rq *http.Request) { http.Redirect(w, rq, redirectTo, http.StatusSeeOther) return } - RemoveHyphaFromCategory(hyphaName, catName) + removeHyphaFromCategory(hyphaName, catName) http.Redirect(w, rq, redirectTo, http.StatusSeeOther) } @@ -71,6 +72,6 @@ func handlerAddToCategory(w http.ResponseWriter, rq *http.Request) { http.Redirect(w, rq, redirectTo, http.StatusSeeOther) return } - AddHyphaToCategory(hyphaName, catName) + addHyphaToCategory(hyphaName, catName) http.Redirect(w, rq, redirectTo, http.StatusSeeOther) } diff --git a/categories/views.go b/categories/views.go index d44dd71..dcb4609 100644 --- a/categories/views.go +++ b/categories/views.go @@ -63,7 +63,7 @@ func CategoryCard(meta viewutil.Meta, hyphaName string) string { var buf strings.Builder err := viewCardChain.Get(meta).ExecuteTemplate(&buf, "category card", cardData{ hyphaName, - WithHypha(hyphaName), + categoriesWithHypha(hyphaName), meta.U.CanProceed("add-to-category"), }) if err != nil { @@ -87,7 +87,7 @@ func categoryPage(meta viewutil.Meta, catName string) { CommonScripts: cfg.CommonScripts, }, CatName: catName, - Hyphae: Contents(catName), + Hyphae: hyphaeInCategory(catName), GivenPermissionToModify: meta.U.CanProceed("add-to-category"), }); err != nil { log.Println(err) @@ -106,7 +106,7 @@ func categoryList(meta viewutil.Meta) { HeaderLinks: cfg.HeaderLinks, CommonScripts: cfg.CommonScripts, }, - Categories: List(), + Categories: listOfCategories(), }); err != nil { log.Println(err) } From 9d971871eb407a881b0dcb95d01a65f656750b78 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 2 Apr 2022 00:45:58 +0300 Subject: [PATCH 10/23] Categories: Log category mutations --- categories/handlers.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/categories/handlers.go b/categories/handlers.go index 5417efc..0ed1a74 100644 --- a/categories/handlers.go +++ b/categories/handlers.go @@ -52,6 +52,7 @@ func handlerRemoveFromCategory(w http.ResponseWriter, rq *http.Request) { http.Redirect(w, rq, redirectTo, http.StatusSeeOther) return } + log.Println(user.FromRequest(rq).Name, "removed", hyphaName, "from", catName) removeHyphaFromCategory(hyphaName, catName) http.Redirect(w, rq, redirectTo, http.StatusSeeOther) } @@ -72,6 +73,7 @@ func handlerAddToCategory(w http.ResponseWriter, rq *http.Request) { http.Redirect(w, rq, redirectTo, http.StatusSeeOther) return } + log.Println(user.FromRequest(rq).Name, "added", hyphaName, "to", catName) addHyphaToCategory(hyphaName, catName) http.Redirect(w, rq, redirectTo, http.StatusSeeOther) } From 0ab4bb5846dab3ac82f82cdf413cfb7ff7f31b60 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 2 Apr 2022 00:59:47 +0300 Subject: [PATCH 11/23] Categories: Localized titles --- categories/view_list.html | 3 ++- categories/view_page.html | 3 ++- categories/views.go | 37 ++++++++++++++++++------------------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/categories/view_list.html b/categories/view_list.html index fdd21db..53754b3 100644 --- a/categories/view_list.html +++ b/categories/view_list.html @@ -1,4 +1,5 @@ -{{define "title"}}Category list{{end}} +{{define "category list"}}Category list{{end}} +{{define "title"}}{{template "category list"}}{{end}} {{define "body"}}

      {{template "title"}}

      diff --git a/categories/view_page.html b/categories/view_page.html index 569df58..a250d38 100644 --- a/categories/view_page.html +++ b/categories/view_page.html @@ -1,4 +1,5 @@ -{{define "title"}}Category {{.CatName | beautifulName}}{{end}} +{{define "category x"}}Category {{. | beautifulName}}{{end}} +{{define "title"}}{{template "category x" .CatName}}{{end}} {{define "body"}} {{$catName := .CatName}}
      diff --git a/categories/views.go b/categories/views.go index dcb4609..87c6111 100644 --- a/categories/views.go +++ b/categories/views.go @@ -9,7 +9,7 @@ import ( "text/template" // TODO: Fight ) -const categoriesRu = ` +const ruTranslation = ` {{define "empty cat"}}Эта категория пуста.{{end}} {{define "add hypha"}}Добавить в категорию{{end}} {{define "cat"}}Категория{{end}} @@ -18,7 +18,7 @@ const categoriesRu = ` {{define "placeholder"}}Имя категории...{{end}} {{define "remove from category title"}}Убрать гифу из этой категории{{end}} {{define "add to category title"}}Добавить гифу в эту категорию{{end}} -{{define "category list heading"}}Список категорий{{end}} +{{define "category list"}}Список категорий{{end}} {{define "no categories"}}В этой вики нет категорий.{{end}} {{define "category x"}}Категория {{. | beautifulName}}{{end}} ` @@ -26,31 +26,29 @@ const categoriesRu = ` var ( //go:embed *.html fs embed.FS - m = template.Must - baseEn, baseRu *template.Template viewListChain, viewPageChain, viewCardChain viewutil.Chain ) func prepareViews() { - - baseEn = m(viewutil.BaseEn.Clone()) - baseRu = m(viewutil.BaseRu.Clone()) + var ( + m = template.Must + copyEnWith = func(f string) *template.Template { + return m(m(viewutil.BaseEn.Clone()).ParseFS(fs, f)) + } + copyRuWith = func(f string) *template.Template { + return m(m(viewutil.BaseRu.Clone()).ParseFS(fs, f)) + } + ) viewCardChain = viewutil. - En( - m(m(baseEn.Clone()).ParseFS(fs, "view_card.html"))). - Ru( - m(m(m(baseRu.Clone()).ParseFS(fs, "view_card.html")).Parse(categoriesRu))) + En(copyEnWith("view_card.html")). + Ru(m(copyRuWith("view_card.html").Parse(ruTranslation))) viewListChain = viewutil. - En( - m(m(baseEn.Clone()).ParseFS(fs, "view_list.html"))). - Ru( - m(m(m(baseRu.Clone()).ParseFS(fs, "view_list.html")).Parse(categoriesRu))) + En(copyEnWith("view_list.html")). + Ru(m(copyRuWith("view_list.html").Parse(ruTranslation))) viewPageChain = viewutil. - En( - m(m(baseEn.Clone()).ParseFS(fs, "view_page.html"))). - Ru( - m(m(m(baseRu.Clone()).ParseFS(fs, "view_page.html")).Parse(categoriesRu))) + En(copyEnWith("view_page.html")). + Ru(m(copyRuWith("view_page.html").Parse(ruTranslation))) } type cardData struct { @@ -59,6 +57,7 @@ type cardData struct { GivenPermissionToModify bool } +// CategoryCard is the little sidebar that is shown nearby the hypha view. func CategoryCard(meta viewutil.Meta, hyphaName string) string { var buf strings.Builder err := viewCardChain.Get(meta).ExecuteTemplate(&buf, "category card", cardData{ From f9857768b72361eaa64f9bc07cad407e54266c82 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 2 Apr 2022 01:01:54 +0300 Subject: [PATCH 12/23] Categories: Rename exported functions --- categories/files.go | 4 ++-- categories/handlers.go | 4 ++-- main.go | 2 +- web/web.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/categories/files.go b/categories/files.go index fd5c3df..7c51322 100644 --- a/categories/files.go +++ b/categories/files.go @@ -12,8 +12,8 @@ import ( var categoryToHyphae = map[string]*categoryNode{} var hyphaToCategories = map[string]*hyphaNode{} -// InitCategories initializes the category system. Call it after the Structure is initialized. This function might terminate the program in case of a bad mood or filesystem faults. -func InitCategories() { +// Init initializes the category system. Call it after the Structure is initialized. This function might terminate the program in case of a bad mood or filesystem faults. +func Init() { var ( record, err = readCategoriesFromDisk() ) diff --git a/categories/handlers.go b/categories/handlers.go index 0ed1a74..3c30319 100644 --- a/categories/handlers.go +++ b/categories/handlers.go @@ -11,8 +11,8 @@ import ( "strings" ) -// InitCategoriesHandlers initializes HTTP handlers for the given router. Call somewhere in package web. -func InitCategoriesHandlers(r *mux.Router) { +// InitHandlers initializes HTTP handlers for the given router. Call somewhere in package web. +func InitHandlers(r *mux.Router) { r.PathPrefix("/add-to-category").HandlerFunc(handlerAddToCategory).Methods("POST") r.PathPrefix("/remove-from-category").HandlerFunc(handlerRemoveFromCategory).Methods("POST") r.PathPrefix("/category/").HandlerFunc(handlerCategory).Methods("GET") diff --git a/main.go b/main.go index a7fb228..3fec678 100644 --- a/main.go +++ b/main.go @@ -51,7 +51,7 @@ func main() { history.InitGitRepo() migration.MigrateRocketsMaybe() shroom.SetHeaderLinks() - categories.InitCategories() + categories.Init() // Static files: static.InitFS(files.StaticFiles()) diff --git a/web/web.go b/web/web.go index fa66170..04a1cbd 100644 --- a/web/web.go +++ b/web/web.go @@ -110,7 +110,7 @@ func Handler() http.Handler { initStuff(wikiRouter) initSearch(wikiRouter) initBacklinks(wikiRouter) - categories.InitCategoriesHandlers(wikiRouter) + categories.InitHandlers(wikiRouter) // Admin routes. if cfg.UseAuth { From f8fbc23202bd7a543f70cbe24be943b9b7b4c494 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 2 Apr 2022 09:38:16 +0300 Subject: [PATCH 13/23] Misc: Make the new package It contains things like hypha list or about wiki pages --- misc/misc.go | 111 ++++++++++++++++++++++++++++++++++++++++++++++++ viewutil/err.go | 28 ++++++++++++ web/mutators.go | 30 ++++++------- web/stuff.go | 99 ------------------------------------------ web/web.go | 23 +--------- 5 files changed, 156 insertions(+), 135 deletions(-) create mode 100644 misc/misc.go create mode 100644 viewutil/err.go diff --git a/misc/misc.go b/misc/misc.go new file mode 100644 index 0000000..2f9b44e --- /dev/null +++ b/misc/misc.go @@ -0,0 +1,111 @@ +// Package misc provides miscellaneous informative views. +package misc + +import ( + "github.com/bouncepaw/mycorrhiza/cfg" + "github.com/bouncepaw/mycorrhiza/files" + "github.com/bouncepaw/mycorrhiza/hyphae" + "github.com/bouncepaw/mycorrhiza/hyphae/backlinks" + "github.com/bouncepaw/mycorrhiza/l18n" + "github.com/bouncepaw/mycorrhiza/shroom" + "github.com/bouncepaw/mycorrhiza/user" + "github.com/bouncepaw/mycorrhiza/util" + "github.com/bouncepaw/mycorrhiza/views" + "github.com/bouncepaw/mycorrhiza/viewutil" + "github.com/gorilla/mux" + "io" + "log" + "math/rand" + "net/http" +) + +func InitHandlers(rtr *mux.Router) { + rtr.HandleFunc("/list", handlerList) + rtr.HandleFunc("/reindex", handlerReindex) + rtr.HandleFunc("/update-header-links", handlerUpdateHeaderLinks) + rtr.HandleFunc("/random", handlerRandom) + rtr.HandleFunc("/about", handlerAbout) + rtr.HandleFunc("/favicon.ico", func(w http.ResponseWriter, rq *http.Request) { + http.Redirect(w, rq, "/static/favicon.ico", http.StatusSeeOther) + }) +} + +// handlerList shows a list of all hyphae in the wiki in random order. +func handlerList(w http.ResponseWriter, rq *http.Request) { + var lc = l18n.FromRequest(rq) + util.PrepareRq(rq) + util.HTTP200Page(w, views.Base( + viewutil.MetaFrom(w, rq), + lc.Get("ui.list_title"), + views.HyphaList(lc), + )) +} + +// handlerReindex reindexes all hyphae by checking the wiki storage directory anew. +func handlerReindex(w http.ResponseWriter, rq *http.Request) { + util.PrepareRq(rq) + if ok := user.CanProceed(rq, "reindex"); !ok { + var lc = l18n.FromRequest(rq) + viewutil.HttpErr(viewutil.MetaFrom(w, rq), lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.reindex_no_rights")) + log.Println("Rejected", rq.URL) + return + } + hyphae.ResetCount() + log.Println("Reindexing hyphae in", files.HyphaeDir()) + hyphae.Index(files.HyphaeDir()) + backlinks.IndexBacklinks() + http.Redirect(w, rq, "/", http.StatusSeeOther) +} + +// handlerUpdateHeaderLinks updates header links by reading the configured hypha, if there is any, or resorting to default values. +func handlerUpdateHeaderLinks(w http.ResponseWriter, rq *http.Request) { + util.PrepareRq(rq) + if ok := user.CanProceed(rq, "update-header-links"); !ok { + var lc = l18n.FromRequest(rq) + viewutil.HttpErr(viewutil.MetaFrom(w, rq), lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.header_no_rights")) + log.Println("Rejected", rq.URL) + return + } + shroom.SetHeaderLinks() + http.Redirect(w, rq, "/", http.StatusSeeOther) +} + +// handlerRandom redirects to a random hypha. +func handlerRandom(w http.ResponseWriter, rq *http.Request) { + util.PrepareRq(rq) + var ( + randomHyphaName string + amountOfHyphae = hyphae.Count() + ) + if amountOfHyphae == 0 { + var lc = l18n.FromRequest(rq) + viewutil.HttpErr(viewutil.MetaFrom(w, rq), lc, http.StatusNotFound, cfg.HomeHypha, lc.Get("ui.random_no_hyphae_tip")) + return + } + i := rand.Intn(amountOfHyphae) + for h := range hyphae.YieldExistingHyphae() { + if i == 0 { + randomHyphaName = h.CanonicalName() + } + i-- + } + http.Redirect(w, rq, "/hypha/"+randomHyphaName, http.StatusSeeOther) +} + +// handlerAbout shows a summary of wiki's software. +func handlerAbout(w http.ResponseWriter, rq *http.Request) { + w.Header().Set("Content-Type", "text/html;charset=utf-8") + w.WriteHeader(http.StatusOK) + var ( + lc = l18n.FromRequest(rq) + title = lc.Get("ui.about_title", &l18n.Replacements{"name": cfg.WikiName}) + ) + _, err := io.WriteString(w, views.Base( + viewutil.MetaFrom(w, rq), + title, + views.AboutHTML(lc), + )) + if err != nil { + log.Println(err) + } +} diff --git a/viewutil/err.go b/viewutil/err.go new file mode 100644 index 0000000..200233e --- /dev/null +++ b/viewutil/err.go @@ -0,0 +1,28 @@ +package viewutil + +import ( + "fmt" + "github.com/bouncepaw/mycorrhiza/l18n" + "mime" + "net/http" +) + +// HttpErr is used by many handlers to signal errors in a compact way. +// TODO: get rid of this abomination +func HttpErr(meta Meta, lc *l18n.Localizer, status int, name, errMsg string) { + meta.W.(http.ResponseWriter).Header().Set("Content-Type", mime.TypeByExtension(".html")) + meta.W.(http.ResponseWriter).WriteHeader(status) + fmt.Fprint( + meta.W, + Base( + meta, + "Error", + fmt.Sprintf( + `

      %s. %s

      `, + errMsg, + name, + lc.Get("ui.error_go_back"), + ), + ), + ) +} diff --git a/web/mutators.go b/web/mutators.go index d14cb4c..0737e69 100644 --- a/web/mutators.go +++ b/web/mutators.go @@ -39,7 +39,7 @@ func handlerRemoveMedia(w http.ResponseWriter, rq *http.Request) { meta = viewutil.MetaFrom(w, rq) ) if !u.CanProceed("remove-media") { - httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "no rights") + viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "no rights") return } if rq.Method == "GET" { @@ -53,11 +53,11 @@ func handlerRemoveMedia(w http.ResponseWriter, rq *http.Request) { } switch h := h.(type) { case *hyphae.EmptyHypha, *hyphae.TextualHypha: - httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "no media to remove") + viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "no media to remove") return case *hyphae.MediaHypha: if err := shroom.RemoveMedia(u, h); err != nil { - httpErr(meta, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error()) + viewutil.HttpErr(meta, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error()) return } } @@ -74,7 +74,7 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) { if !u.CanProceed("delete") { log.Printf("%s has no rights to delete ‘%s’\n", u.Name, h.CanonicalName()) - httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "No rights") + viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "No rights") return } @@ -82,7 +82,7 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) { case *hyphae.EmptyHypha: log.Printf("%s tries to delete empty hypha ‘%s’\n", u.Name, h.CanonicalName()) // TODO: localize - httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "Cannot delete an empty hypha") + viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "Cannot delete an empty hypha") return } @@ -98,7 +98,7 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) { if err := shroom.Delete(u, h.(hyphae.ExistingHypha)); err != nil { log.Println(err) - httpErr(meta, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error()) + viewutil.HttpErr(meta, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error()) return } http.Redirect(w, rq, "/hypha/"+h.CanonicalName(), http.StatusSeeOther) @@ -116,13 +116,13 @@ func handlerRename(w http.ResponseWriter, rq *http.Request) { switch h.(type) { case *hyphae.EmptyHypha: log.Printf("%s tries to rename empty hypha ‘%s’", u.Name, h.CanonicalName()) - httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "Cannot rename an empty hypha") // TODO: localize + viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "Cannot rename an empty hypha") // TODO: localize return } if !u.CanProceed("rename") { log.Printf("%s has no rights to rename ‘%s’\n", u.Name, h.CanonicalName()) - httpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "No rights") + viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "No rights") return } @@ -144,7 +144,7 @@ func handlerRename(w http.ResponseWriter, rq *http.Request) { if err := shroom.Rename(oldHypha, newName, recursive, u); err != nil { log.Printf("%s tries to rename ‘%s’: %s", u.Name, oldHypha.CanonicalName(), err.Error()) - httpErr(meta, lc, http.StatusForbidden, oldHypha.CanonicalName(), lc.Get(err.Error())) // TODO: localize + viewutil.HttpErr(meta, lc, http.StatusForbidden, oldHypha.CanonicalName(), lc.Get(err.Error())) // TODO: localize return } http.Redirect(w, rq, "/hypha/"+newName, http.StatusSeeOther) @@ -164,7 +164,7 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) { meta = viewutil.MetaFrom(w, rq) ) if err := shroom.CanEdit(u, h, lc); err != nil { - httpErr(meta, lc, http.StatusInternalServerError, hyphaName, + viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName, err.Error()) return } @@ -175,7 +175,7 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) { textAreaFill, err = shroom.FetchTextFile(h) if err != nil { log.Println(err) - httpErr(meta, lc, http.StatusInternalServerError, hyphaName, + viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName, lc.Get("ui.error_text_fetch")) return } @@ -204,7 +204,7 @@ func handlerUploadText(w http.ResponseWriter, rq *http.Request) { if action != "Preview" { if err := shroom.UploadText(h, []byte(textData), message, u); err != nil { - httpErr(meta, lc, http.StatusForbidden, hyphaName, err.Error()) + viewutil.HttpErr(meta, lc, http.StatusForbidden, hyphaName, err.Error()) return } } @@ -242,11 +242,11 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) { meta = viewutil.MetaFrom(w, rq) ) if err != nil { - httpErr(meta, lc, http.StatusInternalServerError, hyphaName, + viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName, err.Error()) } if err := shroom.CanAttach(u, h, lc); err != nil { - httpErr(meta, lc, http.StatusInternalServerError, hyphaName, + viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName, err.Error()) } @@ -265,7 +265,7 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) { ) if err := shroom.UploadBinary(h, mime, file, u); err != nil { - httpErr(meta, lc, http.StatusInternalServerError, hyphaName, err.Error()) + viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName, err.Error()) return } http.Redirect(w, rq, "/hypha/"+hyphaName, http.StatusSeeOther) diff --git a/web/stuff.go b/web/stuff.go index f43c387..71eb1f7 100644 --- a/web/stuff.go +++ b/web/stuff.go @@ -2,24 +2,15 @@ package web // stuff.go is used for meta stuff about the wiki or all hyphae at once. import ( - "github.com/bouncepaw/mycorrhiza/hyphae/backlinks" "github.com/bouncepaw/mycorrhiza/viewutil" "io" - "log" - "math/rand" "net/http" "strings" "github.com/gorilla/mux" - "github.com/bouncepaw/mycorrhiza/cfg" - "github.com/bouncepaw/mycorrhiza/files" "github.com/bouncepaw/mycorrhiza/help" - "github.com/bouncepaw/mycorrhiza/hyphae" "github.com/bouncepaw/mycorrhiza/l18n" - "github.com/bouncepaw/mycorrhiza/shroom" - "github.com/bouncepaw/mycorrhiza/user" - "github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/views" "github.com/bouncepaw/mycomarkup/v3" @@ -28,14 +19,6 @@ import ( func initStuff(r *mux.Router) { r.PathPrefix("/help").HandlerFunc(handlerHelp) - r.HandleFunc("/list", handlerList) - r.HandleFunc("/reindex", handlerReindex) - r.HandleFunc("/update-header-links", handlerUpdateHeaderLinks) - r.HandleFunc("/random", handlerRandom) - r.HandleFunc("/about", handlerAbout) - r.HandleFunc("/favicon.ico", func(w http.ResponseWriter, rq *http.Request) { - http.Redirect(w, rq, "/static/favicon.ico", http.StatusSeeOther) - }) } // handlerHelp gets the appropriate documentation or tells you where you (personally) have failed. @@ -94,85 +77,3 @@ func handlerHelp(w http.ResponseWriter, rq *http.Request) { ), ) } - -// handlerList shows a list of all hyphae in the wiki in random order. -func handlerList(w http.ResponseWriter, rq *http.Request) { - var lc = l18n.FromRequest(rq) - util.PrepareRq(rq) - util.HTTP200Page(w, views.Base( - viewutil.MetaFrom(w, rq), - lc.Get("ui.list_title"), - views.HyphaList(lc), - )) -} - -// handlerReindex reindexes all hyphae by checking the wiki storage directory anew. -func handlerReindex(w http.ResponseWriter, rq *http.Request) { - util.PrepareRq(rq) - if ok := user.CanProceed(rq, "reindex"); !ok { - var lc = l18n.FromRequest(rq) - httpErr(viewutil.MetaFrom(w, rq), lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.reindex_no_rights")) - log.Println("Rejected", rq.URL) - return - } - hyphae.ResetCount() - log.Println("Reindexing hyphae in", files.HyphaeDir()) - hyphae.Index(files.HyphaeDir()) - backlinks.IndexBacklinks() - http.Redirect(w, rq, "/", http.StatusSeeOther) -} - -// handlerUpdateHeaderLinks updates header links by reading the configured hypha, if there is any, or resorting to default values. -// -// See https://mycorrhiza.wiki/hypha/configuration/header -func handlerUpdateHeaderLinks(w http.ResponseWriter, rq *http.Request) { - util.PrepareRq(rq) - if ok := user.CanProceed(rq, "update-header-links"); !ok { - var lc = l18n.FromRequest(rq) - httpErr(viewutil.MetaFrom(w, rq), lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.header_no_rights")) - log.Println("Rejected", rq.URL) - return - } - shroom.SetHeaderLinks() - http.Redirect(w, rq, "/", http.StatusSeeOther) -} - -// handlerRandom redirects to a random hypha. -func handlerRandom(w http.ResponseWriter, rq *http.Request) { - util.PrepareRq(rq) - var ( - randomHyphaName string - amountOfHyphae = hyphae.Count() - ) - if amountOfHyphae == 0 { - var lc = l18n.FromRequest(rq) - httpErr(viewutil.MetaFrom(w, rq), lc, http.StatusNotFound, cfg.HomeHypha, lc.Get("ui.random_no_hyphae_tip")) - return - } - i := rand.Intn(amountOfHyphae) - for h := range hyphae.YieldExistingHyphae() { - if i == 0 { - randomHyphaName = h.CanonicalName() - } - i-- - } - http.Redirect(w, rq, "/hypha/"+randomHyphaName, http.StatusSeeOther) -} - -// handlerAbout shows a summary of wiki's software. -func handlerAbout(w http.ResponseWriter, rq *http.Request) { - w.Header().Set("Content-Type", "text/html;charset=utf-8") - w.WriteHeader(http.StatusOK) - var ( - lc = l18n.FromRequest(rq) - title = lc.Get("ui.about_title", &l18n.Replacements{"name": cfg.WikiName}) - ) - _, err := io.WriteString(w, views.Base( - viewutil.MetaFrom(w, rq), - title, - views.AboutHTML(lc), - )) - if err != nil { - log.Println(err) - } -} diff --git a/web/web.go b/web/web.go index 04a1cbd..0686cb2 100644 --- a/web/web.go +++ b/web/web.go @@ -2,8 +2,8 @@ package web import ( - "fmt" "github.com/bouncepaw/mycorrhiza/categories" + "github.com/bouncepaw/mycorrhiza/misc" "github.com/bouncepaw/mycorrhiza/viewutil" "io" "mime" @@ -22,26 +22,6 @@ import ( var stylesheets = []string{"default.css", "custom.css"} -// httpErr is used by many handlers to signal errors in a compact way. -// TODO: get rid of this abomination -func httpErr(meta viewutil.Meta, lc *l18n.Localizer, status int, name, errMsg string) { - meta.W.(http.ResponseWriter).Header().Set("Content-Type", mime.TypeByExtension(".html")) - meta.W.(http.ResponseWriter).WriteHeader(status) - fmt.Fprint( - meta.W, - views.Base( - meta, - "Error", - fmt.Sprintf( - `

      %s. %s

      `, - errMsg, - name, - lc.Get("ui.error_go_back"), - ), - ), - ) -} - func handlerStyle(w http.ResponseWriter, rq *http.Request) { w.Header().Set("Content-Type", mime.TypeByExtension(".css")) for _, name := range stylesheets { @@ -111,6 +91,7 @@ func Handler() http.Handler { initSearch(wikiRouter) initBacklinks(wikiRouter) categories.InitHandlers(wikiRouter) + misc.InitHandlers(wikiRouter) // Admin routes. if cfg.UseAuth { From 9eb92cfa6e86861d586ba846c42e1fb81eacf8c4 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 2 Apr 2022 10:10:32 +0300 Subject: [PATCH 14/23] Misc: Port /list to the new approach --- categories/views.go | 22 +- misc/{misc.go => handlers.go} | 8 +- misc/view_list.html | 21 ++ misc/views.go | 69 +++++++ views/stuff.qtpl | 35 ---- views/stuff.qtpl.go | 365 ++++++++++++---------------------- viewutil/viewutil.go | 13 +- 7 files changed, 235 insertions(+), 298 deletions(-) rename misc/{misc.go => handlers.go} (95%) create mode 100644 misc/view_list.html create mode 100644 misc/views.go diff --git a/categories/views.go b/categories/views.go index 87c6111..3401f2d 100644 --- a/categories/views.go +++ b/categories/views.go @@ -30,25 +30,17 @@ var ( ) func prepareViews() { - var ( - m = template.Must - copyEnWith = func(f string) *template.Template { - return m(m(viewutil.BaseEn.Clone()).ParseFS(fs, f)) - } - copyRuWith = func(f string) *template.Template { - return m(m(viewutil.BaseRu.Clone()).ParseFS(fs, f)) - } - ) + m := template.Must viewCardChain = viewutil. - En(copyEnWith("view_card.html")). - Ru(m(copyRuWith("view_card.html").Parse(ruTranslation))) + En(viewutil.CopyEnWith(fs, "view_card.html")). + Ru(m(viewutil.CopyRuWith(fs, "view_card.html").Parse(ruTranslation))) viewListChain = viewutil. - En(copyEnWith("view_list.html")). - Ru(m(copyRuWith("view_list.html").Parse(ruTranslation))) + En(viewutil.CopyEnWith(fs, "view_list.html")). + Ru(m(viewutil.CopyRuWith(fs, "view_list.html").Parse(ruTranslation))) viewPageChain = viewutil. - En(copyEnWith("view_page.html")). - Ru(m(copyRuWith("view_page.html").Parse(ruTranslation))) + En(viewutil.CopyEnWith(fs, "view_page.html")). + Ru(m(viewutil.CopyRuWith(fs, "view_page.html").Parse(ruTranslation))) } type cardData struct { diff --git a/misc/misc.go b/misc/handlers.go similarity index 95% rename from misc/misc.go rename to misc/handlers.go index 2f9b44e..ea96760 100644 --- a/misc/misc.go +++ b/misc/handlers.go @@ -28,17 +28,13 @@ func InitHandlers(rtr *mux.Router) { rtr.HandleFunc("/favicon.ico", func(w http.ResponseWriter, rq *http.Request) { http.Redirect(w, rq, "/static/favicon.ico", http.StatusSeeOther) }) + initViews() } // handlerList shows a list of all hyphae in the wiki in random order. func handlerList(w http.ResponseWriter, rq *http.Request) { - var lc = l18n.FromRequest(rq) util.PrepareRq(rq) - util.HTTP200Page(w, views.Base( - viewutil.MetaFrom(w, rq), - lc.Get("ui.list_title"), - views.HyphaList(lc), - )) + viewList(viewutil.MetaFrom(w, rq)) } // handlerReindex reindexes all hyphae by checking the wiki storage directory anew. diff --git a/misc/view_list.html b/misc/view_list.html new file mode 100644 index 0000000..0b99b5b --- /dev/null +++ b/misc/view_list.html @@ -0,0 +1,21 @@ +{{define "list of hyphae"}}List of hyphae{{end}} +{{define "title"}}{{template "list of hyphae"}}{{end}} +{{define "body"}} + +{{end}} \ No newline at end of file diff --git a/misc/views.go b/misc/views.go new file mode 100644 index 0000000..79f5242 --- /dev/null +++ b/misc/views.go @@ -0,0 +1,69 @@ +package misc + +import ( + "embed" + "github.com/bouncepaw/mycorrhiza/cfg" + "github.com/bouncepaw/mycorrhiza/hyphae" + "github.com/bouncepaw/mycorrhiza/viewutil" + "log" + "path/filepath" + "text/template" +) + +var ( + //go:embed *html + fs embed.FS + chainList viewutil.Chain + ruTranslation = ` +{{define "list of hyphae"}}Список гиф{{end}} +` +) + +func initViews() { + m := template.Must + chainList = viewutil. + En(viewutil.CopyEnWith(fs, "view_list.html")). + Ru(m(viewutil.CopyRuWith(fs, "view_list.html").Parse(ruTranslation))) +} + +type listDatum struct { + Name string + Ext string +} + +type listData struct { + viewutil.BaseData + Entries []listDatum +} + +func viewList(meta viewutil.Meta) { + // TODO: make this better, there are too many loops and vars + var ( + hyphaNames = make(chan string) + sortedHypha = hyphae.PathographicSort(hyphaNames) + data []listDatum + ) + for hypha := range hyphae.YieldExistingHyphae() { + hyphaNames <- hypha.CanonicalName() + } + close(hyphaNames) + for hyphaName := range sortedHypha { + switch h := hyphae.ByName(hyphaName).(type) { + case *hyphae.TextualHypha: + data = append(data, listDatum{h.CanonicalName(), ""}) + case *hyphae.MediaHypha: + data = append(data, listDatum{h.CanonicalName(), filepath.Ext(h.MediaFilePath())[1:]}) + } + } + + if err := chainList.Get(meta).ExecuteTemplate(meta.W, "page", listData{ + BaseData: viewutil.BaseData{ + Meta: meta, + HeaderLinks: cfg.HeaderLinks, + CommonScripts: cfg.CommonScripts, + }, + Entries: data, + }); err != nil { + log.Println(err) + } +} diff --git a/views/stuff.qtpl b/views/stuff.qtpl index 9536c04..37151c4 100644 --- a/views/stuff.qtpl +++ b/views/stuff.qtpl @@ -1,8 +1,6 @@ {% import "fmt" %} -{% import "path/filepath" %} {% import "github.com/bouncepaw/mycorrhiza/cfg" %} -{% import "github.com/bouncepaw/mycorrhiza/hyphae" %} {% import "github.com/bouncepaw/mycorrhiza/util" %} {% import "github.com/bouncepaw/mycorrhiza/l18n" %} @@ -63,39 +61,6 @@

      {%s lc.Get("help.empty_error_line_2a") %} {%s lc.Get("help.empty_error_link") %} {%s lc.Get("help.empty_error_line_2b") %}

      {% endfunc %} -{% func HyphaList(lc *l18n.Localizer) %} -
      -
      -

      {%s lc.Get("ui.list_heading") %}

      -

      {%s lc.GetPlural("ui.list_desc", hyphae.Count()) %}

      -
        - {% code - hyphaNames := make(chan string) - sortedHypha := hyphae.PathographicSort(hyphaNames) - for hypha := range hyphae.YieldExistingHyphae() { - hyphaNames <- hypha.CanonicalName() - } - close(hyphaNames) - %} - {% for hyphaName := range sortedHypha %} - {% code h := hyphae.ByName(hyphaName) %} -
      • - - {%s util.BeautifulName(h.CanonicalName()) %} - - {% switch h := h.(type) %} - {% case *hyphae.MediaHypha %} - - {%s filepath.Ext(h.MediaFilePath())[1:] %} - - {% endswitch %} -
      • - {% endfor %} -
      -
      -
      -{% endfunc %} - {% func commonScripts() %} {% for _, scriptPath := range cfg.CommonScripts %} diff --git a/views/stuff.qtpl.go b/views/stuff.qtpl.go index 043876f..31ae9ff 100644 --- a/views/stuff.qtpl.go +++ b/views/stuff.qtpl.go @@ -7,112 +7,106 @@ package views //line views/stuff.qtpl:1 import "fmt" -//line views/stuff.qtpl:2 -import "path/filepath" - -//line views/stuff.qtpl:4 +//line views/stuff.qtpl:3 import "github.com/bouncepaw/mycorrhiza/cfg" -//line views/stuff.qtpl:5 -import "github.com/bouncepaw/mycorrhiza/hyphae" - -//line views/stuff.qtpl:6 +//line views/stuff.qtpl:4 import "github.com/bouncepaw/mycorrhiza/util" -//line views/stuff.qtpl:7 +//line views/stuff.qtpl:5 import "github.com/bouncepaw/mycorrhiza/l18n" -//line views/stuff.qtpl:9 +//line views/stuff.qtpl:7 import ( qtio422016 "io" qt422016 "github.com/valyala/quicktemplate" ) -//line views/stuff.qtpl:9 +//line views/stuff.qtpl:7 var ( _ = qtio422016.Copy _ = qt422016.AcquireByteBuffer ) -//line views/stuff.qtpl:9 +//line views/stuff.qtpl:7 func StreamTitleSearch(qw422016 *qt422016.Writer, query string, generator func(string) <-chan string, lc *l18n.Localizer) { -//line views/stuff.qtpl:9 +//line views/stuff.qtpl:7 qw422016.N().S(`

      `) -//line views/stuff.qtpl:12 +//line views/stuff.qtpl:10 qw422016.E().S(lc.Get("ui.search_results_query", &l18n.Replacements{"query": query})) -//line views/stuff.qtpl:12 +//line views/stuff.qtpl:10 qw422016.N().S(`

      `) -//line views/stuff.qtpl:13 +//line views/stuff.qtpl:11 qw422016.E().S(lc.Get("ui.search_results_desc")) -//line views/stuff.qtpl:13 +//line views/stuff.qtpl:11 qw422016.N().S(`

      `) -//line views/stuff.qtpl:22 +//line views/stuff.qtpl:20 } -//line views/stuff.qtpl:22 +//line views/stuff.qtpl:20 func WriteTitleSearch(qq422016 qtio422016.Writer, query string, generator func(string) <-chan string, lc *l18n.Localizer) { -//line views/stuff.qtpl:22 +//line views/stuff.qtpl:20 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:22 +//line views/stuff.qtpl:20 StreamTitleSearch(qw422016, query, generator, lc) -//line views/stuff.qtpl:22 +//line views/stuff.qtpl:20 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:22 +//line views/stuff.qtpl:20 } -//line views/stuff.qtpl:22 +//line views/stuff.qtpl:20 func TitleSearch(query string, generator func(string) <-chan string, lc *l18n.Localizer) string { -//line views/stuff.qtpl:22 +//line views/stuff.qtpl:20 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:22 +//line views/stuff.qtpl:20 WriteTitleSearch(qb422016, query, generator, lc) -//line views/stuff.qtpl:22 +//line views/stuff.qtpl:20 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:22 +//line views/stuff.qtpl:20 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:22 +//line views/stuff.qtpl:20 return qs422016 -//line views/stuff.qtpl:22 +//line views/stuff.qtpl:20 } -//line views/stuff.qtpl:24 +//line views/stuff.qtpl:22 func StreamBacklinks(qw422016 *qt422016.Writer, hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) { -//line views/stuff.qtpl:24 +//line views/stuff.qtpl:22 qw422016.N().S(`

      `) -//line views/stuff.qtpl:27 +//line views/stuff.qtpl:25 qw422016.N().S(lc.Get( "ui.backlinks_heading", &l18n.Replacements{ @@ -123,329 +117,220 @@ func StreamBacklinks(qw422016 *qt422016.Writer, hyphaName string, generator func ), }, )) -//line views/stuff.qtpl:36 +//line views/stuff.qtpl:34 qw422016.N().S(`

      `) -//line views/stuff.qtpl:37 +//line views/stuff.qtpl:35 qw422016.E().S(lc.Get("ui.backlinks_desc")) -//line views/stuff.qtpl:37 +//line views/stuff.qtpl:35 qw422016.N().S(`

      `) -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:45 } -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:45 func WriteBacklinks(qq422016 qtio422016.Writer, hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) { -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:45 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:45 StreamBacklinks(qw422016, hyphaName, generator, lc) -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:45 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:45 } -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:45 func Backlinks(hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) string { -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:45 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:45 WriteBacklinks(qb422016, hyphaName, generator, lc) -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:45 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:45 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:45 return qs422016 -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:45 } -//line views/stuff.qtpl:49 +//line views/stuff.qtpl:47 func StreamHelp(qw422016 *qt422016.Writer, content, lang string, lc *l18n.Localizer) { -//line views/stuff.qtpl:49 +//line views/stuff.qtpl:47 qw422016.N().S(`
      `) -//line views/stuff.qtpl:53 +//line views/stuff.qtpl:51 qw422016.N().S(content) -//line views/stuff.qtpl:53 +//line views/stuff.qtpl:51 qw422016.N().S(`
      `) -//line views/stuff.qtpl:56 +//line views/stuff.qtpl:54 qw422016.N().S(helpTopics(lang, lc)) -//line views/stuff.qtpl:56 +//line views/stuff.qtpl:54 qw422016.N().S(`
      `) -//line views/stuff.qtpl:58 +//line views/stuff.qtpl:56 } -//line views/stuff.qtpl:58 +//line views/stuff.qtpl:56 func WriteHelp(qq422016 qtio422016.Writer, content, lang string, lc *l18n.Localizer) { -//line views/stuff.qtpl:58 +//line views/stuff.qtpl:56 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:58 +//line views/stuff.qtpl:56 StreamHelp(qw422016, content, lang, lc) -//line views/stuff.qtpl:58 +//line views/stuff.qtpl:56 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:58 +//line views/stuff.qtpl:56 } -//line views/stuff.qtpl:58 +//line views/stuff.qtpl:56 func Help(content, lang string, lc *l18n.Localizer) string { -//line views/stuff.qtpl:58 +//line views/stuff.qtpl:56 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:58 +//line views/stuff.qtpl:56 WriteHelp(qb422016, content, lang, lc) -//line views/stuff.qtpl:58 +//line views/stuff.qtpl:56 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:58 +//line views/stuff.qtpl:56 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:58 +//line views/stuff.qtpl:56 return qs422016 -//line views/stuff.qtpl:58 +//line views/stuff.qtpl:56 } -//line views/stuff.qtpl:60 +//line views/stuff.qtpl:58 func StreamHelpEmptyError(qw422016 *qt422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:60 +//line views/stuff.qtpl:58 qw422016.N().S(`

      `) -//line views/stuff.qtpl:61 +//line views/stuff.qtpl:59 qw422016.E().S(lc.Get("help.empty_error_title")) -//line views/stuff.qtpl:61 +//line views/stuff.qtpl:59 qw422016.N().S(`

      `) -//line views/stuff.qtpl:62 +//line views/stuff.qtpl:60 qw422016.E().S(lc.Get("help.empty_error_line_1")) -//line views/stuff.qtpl:62 +//line views/stuff.qtpl:60 qw422016.N().S(`

      `) -//line views/stuff.qtpl:63 +//line views/stuff.qtpl:61 qw422016.E().S(lc.Get("help.empty_error_line_2a")) -//line views/stuff.qtpl:63 +//line views/stuff.qtpl:61 qw422016.N().S(` `) -//line views/stuff.qtpl:63 +//line views/stuff.qtpl:61 qw422016.E().S(lc.Get("help.empty_error_link")) -//line views/stuff.qtpl:63 +//line views/stuff.qtpl:61 qw422016.N().S(` `) -//line views/stuff.qtpl:63 +//line views/stuff.qtpl:61 qw422016.E().S(lc.Get("help.empty_error_line_2b")) -//line views/stuff.qtpl:63 +//line views/stuff.qtpl:61 qw422016.N().S(`

      `) -//line views/stuff.qtpl:64 +//line views/stuff.qtpl:62 } -//line views/stuff.qtpl:64 +//line views/stuff.qtpl:62 func WriteHelpEmptyError(qq422016 qtio422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:64 +//line views/stuff.qtpl:62 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:64 +//line views/stuff.qtpl:62 StreamHelpEmptyError(qw422016, lc) -//line views/stuff.qtpl:64 +//line views/stuff.qtpl:62 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:64 +//line views/stuff.qtpl:62 } -//line views/stuff.qtpl:64 +//line views/stuff.qtpl:62 func HelpEmptyError(lc *l18n.Localizer) string { -//line views/stuff.qtpl:64 +//line views/stuff.qtpl:62 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:64 +//line views/stuff.qtpl:62 WriteHelpEmptyError(qb422016, lc) -//line views/stuff.qtpl:64 +//line views/stuff.qtpl:62 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:64 +//line views/stuff.qtpl:62 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:64 +//line views/stuff.qtpl:62 return qs422016 +//line views/stuff.qtpl:62 +} + //line views/stuff.qtpl:64 -} - -//line views/stuff.qtpl:66 -func StreamHyphaList(qw422016 *qt422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:66 - qw422016.N().S(` -
      -
      -

      `) -//line views/stuff.qtpl:69 - qw422016.E().S(lc.Get("ui.list_heading")) -//line views/stuff.qtpl:69 - qw422016.N().S(`

      -

      `) -//line views/stuff.qtpl:70 - qw422016.E().S(lc.GetPlural("ui.list_desc", hyphae.Count())) -//line views/stuff.qtpl:70 - qw422016.N().S(`

      -
        - `) -//line views/stuff.qtpl:73 - hyphaNames := make(chan string) - sortedHypha := hyphae.PathographicSort(hyphaNames) - for hypha := range hyphae.YieldExistingHyphae() { - hyphaNames <- hypha.CanonicalName() - } - close(hyphaNames) - -//line views/stuff.qtpl:79 - qw422016.N().S(` - `) -//line views/stuff.qtpl:80 - for hyphaName := range sortedHypha { -//line views/stuff.qtpl:80 - qw422016.N().S(` - `) -//line views/stuff.qtpl:81 - h := hyphae.ByName(hyphaName) - -//line views/stuff.qtpl:81 - qw422016.N().S(` -
      • - - `) -//line views/stuff.qtpl:84 - qw422016.E().S(util.BeautifulName(h.CanonicalName())) -//line views/stuff.qtpl:84 - qw422016.N().S(` - - `) -//line views/stuff.qtpl:86 - switch h := h.(type) { -//line views/stuff.qtpl:87 - case *hyphae.MediaHypha: -//line views/stuff.qtpl:87 - qw422016.N().S(` - - `) -//line views/stuff.qtpl:89 - qw422016.E().S(filepath.Ext(h.MediaFilePath())[1:]) -//line views/stuff.qtpl:89 - qw422016.N().S(` - - `) -//line views/stuff.qtpl:91 - } -//line views/stuff.qtpl:91 - qw422016.N().S(` -
      • - `) -//line views/stuff.qtpl:93 - } -//line views/stuff.qtpl:93 - qw422016.N().S(` -
      -
      -
      -`) -//line views/stuff.qtpl:97 -} - -//line views/stuff.qtpl:97 -func WriteHyphaList(qq422016 qtio422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:97 - qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:97 - StreamHyphaList(qw422016, lc) -//line views/stuff.qtpl:97 - qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:97 -} - -//line views/stuff.qtpl:97 -func HyphaList(lc *l18n.Localizer) string { -//line views/stuff.qtpl:97 - qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:97 - WriteHyphaList(qb422016, lc) -//line views/stuff.qtpl:97 - qs422016 := string(qb422016.B) -//line views/stuff.qtpl:97 - qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:97 - return qs422016 -//line views/stuff.qtpl:97 -} - -//line views/stuff.qtpl:99 func streamcommonScripts(qw422016 *qt422016.Writer) { -//line views/stuff.qtpl:99 +//line views/stuff.qtpl:64 qw422016.N().S(` `) -//line views/stuff.qtpl:100 +//line views/stuff.qtpl:65 for _, scriptPath := range cfg.CommonScripts { -//line views/stuff.qtpl:100 +//line views/stuff.qtpl:65 qw422016.N().S(` `) -//line views/stuff.qtpl:102 +//line views/stuff.qtpl:67 } -//line views/stuff.qtpl:102 +//line views/stuff.qtpl:67 qw422016.N().S(` `) -//line views/stuff.qtpl:103 +//line views/stuff.qtpl:68 } -//line views/stuff.qtpl:103 +//line views/stuff.qtpl:68 func writecommonScripts(qq422016 qtio422016.Writer) { -//line views/stuff.qtpl:103 +//line views/stuff.qtpl:68 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:103 +//line views/stuff.qtpl:68 streamcommonScripts(qw422016) -//line views/stuff.qtpl:103 +//line views/stuff.qtpl:68 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:103 +//line views/stuff.qtpl:68 } -//line views/stuff.qtpl:103 +//line views/stuff.qtpl:68 func commonScripts() string { -//line views/stuff.qtpl:103 +//line views/stuff.qtpl:68 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:103 +//line views/stuff.qtpl:68 writecommonScripts(qb422016) -//line views/stuff.qtpl:103 +//line views/stuff.qtpl:68 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:103 +//line views/stuff.qtpl:68 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:103 +//line views/stuff.qtpl:68 return qs422016 -//line views/stuff.qtpl:103 +//line views/stuff.qtpl:68 } diff --git a/viewutil/viewutil.go b/viewutil/viewutil.go index af37550..6fd71e6 100644 --- a/viewutil/viewutil.go +++ b/viewutil/viewutil.go @@ -6,6 +6,7 @@ import ( "fmt" "github.com/bouncepaw/mycorrhiza/cfg" "github.com/bouncepaw/mycorrhiza/util" + "io/fs" "log" "strings" "text/template" // TODO: save the world @@ -13,7 +14,7 @@ import ( var ( //go:embed *.html - fs embed.FS + fsys embed.FS BaseEn *template.Template BaseRu *template.Template m = template.Must @@ -33,7 +34,7 @@ func Init() { BaseEn = m(m(template.New(""). Funcs(template.FuncMap{ "beautifulName": util.BeautifulName, - }).ParseFS(fs, "base.html")). + }).ParseFS(fsys, "base.html")). Parse(dataText)) if !cfg.UseAuth { m(BaseEn.Parse(`{{define "auth"}}{{end}}`)) @@ -85,3 +86,11 @@ func Base(meta Meta, title, body string, headElements ...string) string { } return w.String() } + +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)) +} From 5bf3808039ebcd61cdd5ca2f357d70148b563cdc Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 2 Apr 2022 10:22:26 +0300 Subject: [PATCH 15/23] Misc: Move more stuff here --- misc/handlers.go | 43 +++++++++++++++++++++++++++++++++--- misc/views.go | 2 +- viewutil/err.go | 5 ++--- web/auth.go | 8 +++++++ web/{stuff.go => help.go} | 2 +- web/mutators.go | 34 +++++++++++++---------------- web/web.go | 46 +-------------------------------------- 7 files changed, 68 insertions(+), 72 deletions(-) rename web/{stuff.go => help.go} (98%) diff --git a/misc/handlers.go b/misc/handlers.go index ea96760..629ce07 100644 --- a/misc/handlers.go +++ b/misc/handlers.go @@ -8,6 +8,7 @@ import ( "github.com/bouncepaw/mycorrhiza/hyphae/backlinks" "github.com/bouncepaw/mycorrhiza/l18n" "github.com/bouncepaw/mycorrhiza/shroom" + "github.com/bouncepaw/mycorrhiza/static" "github.com/bouncepaw/mycorrhiza/user" "github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/views" @@ -16,10 +17,15 @@ import ( "io" "log" "math/rand" + "mime" "net/http" ) func InitHandlers(rtr *mux.Router) { + rtr.HandleFunc("/robots.txt", handlerRobotsTxt) + rtr.HandleFunc("/static/style.css", handlerStyle) + rtr.PathPrefix("/static/"). + Handler(http.StripPrefix("/static/", http.FileServer(http.FS(static.FS)))) rtr.HandleFunc("/list", handlerList) rtr.HandleFunc("/reindex", handlerReindex) rtr.HandleFunc("/update-header-links", handlerUpdateHeaderLinks) @@ -42,7 +48,7 @@ func handlerReindex(w http.ResponseWriter, rq *http.Request) { util.PrepareRq(rq) if ok := user.CanProceed(rq, "reindex"); !ok { var lc = l18n.FromRequest(rq) - viewutil.HttpErr(viewutil.MetaFrom(w, rq), lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.reindex_no_rights")) + viewutil.HttpErr(viewutil.MetaFrom(w, rq), http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.reindex_no_rights")) log.Println("Rejected", rq.URL) return } @@ -58,7 +64,7 @@ func handlerUpdateHeaderLinks(w http.ResponseWriter, rq *http.Request) { util.PrepareRq(rq) if ok := user.CanProceed(rq, "update-header-links"); !ok { var lc = l18n.FromRequest(rq) - viewutil.HttpErr(viewutil.MetaFrom(w, rq), lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.header_no_rights")) + viewutil.HttpErr(viewutil.MetaFrom(w, rq), http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.header_no_rights")) log.Println("Rejected", rq.URL) return } @@ -75,7 +81,7 @@ func handlerRandom(w http.ResponseWriter, rq *http.Request) { ) if amountOfHyphae == 0 { var lc = l18n.FromRequest(rq) - viewutil.HttpErr(viewutil.MetaFrom(w, rq), lc, http.StatusNotFound, cfg.HomeHypha, lc.Get("ui.random_no_hyphae_tip")) + viewutil.HttpErr(viewutil.MetaFrom(w, rq), http.StatusNotFound, cfg.HomeHypha, lc.Get("ui.random_no_hyphae_tip")) return } i := rand.Intn(amountOfHyphae) @@ -105,3 +111,34 @@ func handlerAbout(w http.ResponseWriter, rq *http.Request) { log.Println(err) } } + +var stylesheets = []string{"default.css", "custom.css"} + +func handlerStyle(w http.ResponseWriter, rq *http.Request) { + w.Header().Set("Content-Type", mime.TypeByExtension(".css")) + for _, name := range stylesheets { + file, err := static.FS.Open(name) + if err != nil { + continue + } + _, err = io.Copy(w, file) + if err != nil { + log.Println(err) + } + _ = file.Close() + } +} + +func handlerRobotsTxt(w http.ResponseWriter, rq *http.Request) { + w.Header().Set("Content-Type", "text/plain; charset=utf-8") + + file, err := static.FS.Open("robots.txt") + if err != nil { + return + } + _, err = io.Copy(w, file) + if err != nil { + log.Println() + } + _ = file.Close() +} diff --git a/misc/views.go b/misc/views.go index 79f5242..870d8e3 100644 --- a/misc/views.go +++ b/misc/views.go @@ -37,7 +37,7 @@ type listData struct { } func viewList(meta viewutil.Meta) { - // TODO: make this better, there are too many loops and vars + // TODO: make this more effective, there are too many loops and vars var ( hyphaNames = make(chan string) sortedHypha = hyphae.PathographicSort(hyphaNames) diff --git a/viewutil/err.go b/viewutil/err.go index 200233e..c375842 100644 --- a/viewutil/err.go +++ b/viewutil/err.go @@ -2,14 +2,13 @@ package viewutil import ( "fmt" - "github.com/bouncepaw/mycorrhiza/l18n" "mime" "net/http" ) // HttpErr is used by many handlers to signal errors in a compact way. // TODO: get rid of this abomination -func HttpErr(meta Meta, lc *l18n.Localizer, status int, name, errMsg string) { +func HttpErr(meta Meta, status int, name, errMsg string) { meta.W.(http.ResponseWriter).Header().Set("Content-Type", mime.TypeByExtension(".html")) meta.W.(http.ResponseWriter).WriteHeader(status) fmt.Fprint( @@ -21,7 +20,7 @@ func HttpErr(meta Meta, lc *l18n.Localizer, status int, name, errMsg string) { `

      %s. %s

      `, errMsg, name, - lc.Get("ui.error_go_back"), + meta.Lc.Get("ui.error_go_back"), ), ), ) diff --git a/web/auth.go b/web/auth.go index 0734c2f..f4ea069 100644 --- a/web/auth.go +++ b/web/auth.go @@ -20,6 +20,7 @@ import ( ) func initAuth(r *mux.Router) { + r.HandleFunc("/user-list", handlerUserList) r.HandleFunc("/lock", handlerLock) // The check below saves a lot of extra checks and lines of codes in other places in this file. if !cfg.UseAuth { @@ -35,6 +36,13 @@ func initAuth(r *mux.Router) { r.HandleFunc("/logout", handlerLogout) } +func handlerUserList(w http.ResponseWriter, rq *http.Request) { + lc := l18n.FromRequest(rq) + w.Header().Set("Content-Type", mime.TypeByExtension(".html")) + w.WriteHeader(http.StatusOK) + w.Write([]byte(views.Base(viewutil.MetaFrom(w, rq), lc.Get("ui.users_title"), views.UserList(lc)))) +} + func handlerLock(w http.ResponseWriter, rq *http.Request) { _, _ = io.WriteString(w, views.Lock(l18n.FromRequest(rq))) } diff --git a/web/stuff.go b/web/help.go similarity index 98% rename from web/stuff.go rename to web/help.go index 71eb1f7..8227b5b 100644 --- a/web/stuff.go +++ b/web/help.go @@ -17,7 +17,7 @@ import ( "github.com/bouncepaw/mycomarkup/v3/mycocontext" ) -func initStuff(r *mux.Router) { +func initHelp(r *mux.Router) { r.PathPrefix("/help").HandlerFunc(handlerHelp) } diff --git a/web/mutators.go b/web/mutators.go index 0737e69..331464d 100644 --- a/web/mutators.go +++ b/web/mutators.go @@ -39,7 +39,7 @@ func handlerRemoveMedia(w http.ResponseWriter, rq *http.Request) { meta = viewutil.MetaFrom(w, rq) ) if !u.CanProceed("remove-media") { - viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "no rights") + viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "no rights") return } if rq.Method == "GET" { @@ -53,11 +53,11 @@ func handlerRemoveMedia(w http.ResponseWriter, rq *http.Request) { } switch h := h.(type) { case *hyphae.EmptyHypha, *hyphae.TextualHypha: - viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "no media to remove") + viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "no media to remove") return case *hyphae.MediaHypha: if err := shroom.RemoveMedia(u, h); err != nil { - viewutil.HttpErr(meta, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error()) + viewutil.HttpErr(meta, http.StatusInternalServerError, h.CanonicalName(), err.Error()) return } } @@ -74,7 +74,7 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) { if !u.CanProceed("delete") { log.Printf("%s has no rights to delete ‘%s’\n", u.Name, h.CanonicalName()) - viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "No rights") + viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "No rights") return } @@ -82,7 +82,7 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) { case *hyphae.EmptyHypha: log.Printf("%s tries to delete empty hypha ‘%s’\n", u.Name, h.CanonicalName()) // TODO: localize - viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "Cannot delete an empty hypha") + viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "Cannot delete an empty hypha") return } @@ -98,7 +98,7 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) { if err := shroom.Delete(u, h.(hyphae.ExistingHypha)); err != nil { log.Println(err) - viewutil.HttpErr(meta, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error()) + viewutil.HttpErr(meta, http.StatusInternalServerError, h.CanonicalName(), err.Error()) return } http.Redirect(w, rq, "/hypha/"+h.CanonicalName(), http.StatusSeeOther) @@ -116,13 +116,13 @@ func handlerRename(w http.ResponseWriter, rq *http.Request) { switch h.(type) { case *hyphae.EmptyHypha: log.Printf("%s tries to rename empty hypha ‘%s’", u.Name, h.CanonicalName()) - viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "Cannot rename an empty hypha") // TODO: localize + viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "Cannot rename an empty hypha") // TODO: localize return } if !u.CanProceed("rename") { log.Printf("%s has no rights to rename ‘%s’\n", u.Name, h.CanonicalName()) - viewutil.HttpErr(meta, lc, http.StatusForbidden, h.CanonicalName(), "No rights") + viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "No rights") return } @@ -144,7 +144,7 @@ func handlerRename(w http.ResponseWriter, rq *http.Request) { if err := shroom.Rename(oldHypha, newName, recursive, u); err != nil { log.Printf("%s tries to rename ‘%s’: %s", u.Name, oldHypha.CanonicalName(), err.Error()) - viewutil.HttpErr(meta, lc, http.StatusForbidden, oldHypha.CanonicalName(), lc.Get(err.Error())) // TODO: localize + viewutil.HttpErr(meta, http.StatusForbidden, oldHypha.CanonicalName(), lc.Get(err.Error())) // TODO: localize return } http.Redirect(w, rq, "/hypha/"+newName, http.StatusSeeOther) @@ -164,8 +164,7 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) { meta = viewutil.MetaFrom(w, rq) ) if err := shroom.CanEdit(u, h, lc); err != nil { - viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName, - err.Error()) + viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, err.Error()) return } switch h.(type) { @@ -175,8 +174,7 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) { textAreaFill, err = shroom.FetchTextFile(h) if err != nil { log.Println(err) - viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName, - lc.Get("ui.error_text_fetch")) + viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, lc.Get("ui.error_text_fetch")) return } } @@ -204,7 +202,7 @@ func handlerUploadText(w http.ResponseWriter, rq *http.Request) { if action != "Preview" { if err := shroom.UploadText(h, []byte(textData), message, u); err != nil { - viewutil.HttpErr(meta, lc, http.StatusForbidden, hyphaName, err.Error()) + viewutil.HttpErr(meta, http.StatusForbidden, hyphaName, err.Error()) return } } @@ -242,12 +240,10 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) { meta = viewutil.MetaFrom(w, rq) ) if err != nil { - viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName, - err.Error()) + viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, err.Error()) } if err := shroom.CanAttach(u, h, lc); err != nil { - viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName, - err.Error()) + viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, err.Error()) } // If file is not passed: @@ -265,7 +261,7 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) { ) if err := shroom.UploadBinary(h, mime, file, u); err != nil { - viewutil.HttpErr(meta, lc, http.StatusInternalServerError, hyphaName, err.Error()) + viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, err.Error()) return } http.Redirect(w, rq, "/hypha/"+hyphaName, http.StatusSeeOther) diff --git a/web/web.go b/web/web.go index 0686cb2..304aeb0 100644 --- a/web/web.go +++ b/web/web.go @@ -4,54 +4,17 @@ package web import ( "github.com/bouncepaw/mycorrhiza/categories" "github.com/bouncepaw/mycorrhiza/misc" - "github.com/bouncepaw/mycorrhiza/viewutil" "io" - "mime" "net/http" "net/url" "github.com/gorilla/mux" "github.com/bouncepaw/mycorrhiza/cfg" - "github.com/bouncepaw/mycorrhiza/l18n" - "github.com/bouncepaw/mycorrhiza/static" "github.com/bouncepaw/mycorrhiza/user" "github.com/bouncepaw/mycorrhiza/util" - "github.com/bouncepaw/mycorrhiza/views" ) -var stylesheets = []string{"default.css", "custom.css"} - -func handlerStyle(w http.ResponseWriter, rq *http.Request) { - w.Header().Set("Content-Type", mime.TypeByExtension(".css")) - for _, name := range stylesheets { - file, err := static.FS.Open(name) - if err != nil { - continue - } - io.Copy(w, file) - file.Close() - } -} - -func handlerUserList(w http.ResponseWriter, rq *http.Request) { - lc := l18n.FromRequest(rq) - w.Header().Set("Content-Type", mime.TypeByExtension(".html")) - w.WriteHeader(http.StatusOK) - w.Write([]byte(views.Base(viewutil.MetaFrom(w, rq), lc.Get("ui.users_title"), views.UserList(lc)))) -} - -func handlerRobotsTxt(w http.ResponseWriter, rq *http.Request) { - w.Header().Set("Content-Type", "text/plain; charset=utf-8") - - file, err := static.FS.Open("robots.txt") - if err != nil { - return - } - io.Copy(w, file) - file.Close() -} - // Handler initializes and returns the HTTP router based on the configuration. func Handler() http.Handler { router := mux.NewRouter() @@ -68,10 +31,6 @@ func Handler() http.Handler { // Public routes. They're always accessible regardless of the user status. initAuth(router) - router.HandleFunc("/robots.txt", handlerRobotsTxt) - router.HandleFunc("/static/style.css", handlerStyle) - router.PathPrefix("/static/"). - Handler(http.StripPrefix("/static/", http.FileServer(http.FS(static.FS)))) // Wiki routes. They may be locked or restricted. wikiRouter := router.PathPrefix("").Subrouter() @@ -87,7 +46,7 @@ func Handler() http.Handler { initReaders(wikiRouter) initMutators(wikiRouter) initHistory(wikiRouter) - initStuff(wikiRouter) + initHelp(wikiRouter) initSearch(wikiRouter) initBacklinks(wikiRouter) categories.InitHandlers(wikiRouter) @@ -100,9 +59,6 @@ func Handler() http.Handler { initAdmin(adminRouter) } - // Miscellaneous - wikiRouter.HandleFunc("/user-list", handlerUserList) - // Index page wikiRouter.HandleFunc("/", func(w http.ResponseWriter, rq *http.Request) { // Let's pray it never fails From cc01a3551d724bd826007b6440854c938526d4b7 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 2 Apr 2022 11:00:10 +0300 Subject: [PATCH 16/23] Misc: Move more stuff here, including title search --- misc/handlers.go | 15 + misc/view_title_search.html | 16 + misc/views.go | 32 +- shroom/search.go | 2 +- views/auth.qtpl | 62 ++++ views/auth.qtpl.go | 605 +++++++++++++++++++++++------------- views/stuff.qtpl | 15 - views/stuff.qtpl.go | 252 ++++++--------- views/user_list.qtpl | 64 ---- views/user_list.qtpl.go | 199 ------------ web/search.go | 36 --- web/web.go | 1 - 12 files changed, 604 insertions(+), 695 deletions(-) create mode 100644 misc/view_title_search.html delete mode 100644 views/user_list.qtpl delete mode 100644 views/user_list.qtpl.go delete mode 100644 web/search.go diff --git a/misc/handlers.go b/misc/handlers.go index 629ce07..cdf81c1 100644 --- a/misc/handlers.go +++ b/misc/handlers.go @@ -34,6 +34,7 @@ func InitHandlers(rtr *mux.Router) { rtr.HandleFunc("/favicon.ico", func(w http.ResponseWriter, rq *http.Request) { http.Redirect(w, rq, "/static/favicon.ico", http.StatusSeeOther) }) + rtr.HandleFunc("/title-search/", handlerTitleSearch) initViews() } @@ -142,3 +143,17 @@ func handlerRobotsTxt(w http.ResponseWriter, rq *http.Request) { } _ = file.Close() } + +func handlerTitleSearch(w http.ResponseWriter, rq *http.Request) { + util.PrepareRq(rq) + _ = rq.ParseForm() + var ( + query = rq.FormValue("q") + results []string + ) + for hyphaName := range shroom.YieldHyphaNamesContainingString(query) { + results = append(results, hyphaName) + } + w.WriteHeader(http.StatusOK) + viewTitleSearch(viewutil.MetaFrom(w, rq), query, results) +} diff --git a/misc/view_title_search.html b/misc/view_title_search.html new file mode 100644 index 0000000..0ce4872 --- /dev/null +++ b/misc/view_title_search.html @@ -0,0 +1,16 @@ +{{define "search:"}}Search: {{.}}{{end}} +{{define "title"}}{{template "search:" .Query}}{{end}} +{{define "body"}} + +{{end}} \ No newline at end of file diff --git a/misc/views.go b/misc/views.go index 870d8e3..e288067 100644 --- a/misc/views.go +++ b/misc/views.go @@ -12,10 +12,13 @@ import ( var ( //go:embed *html - fs embed.FS - chainList viewutil.Chain - ruTranslation = ` + fs embed.FS + chainList, chainTitleSearch viewutil.Chain + ruTranslation = ` {{define "list of hyphae"}}Список гиф{{end}} +{{define "search:"}}Поиск:{{end}} +{{define "search results for"}}Результаты поиска для «{{.}}»{{end}} +{{define "search desc"}}Название каждой из существующих гиф сопоставлено с запросом. Подходящие гифы приведены ниже.{{end}} ` ) @@ -24,6 +27,9 @@ func initViews() { chainList = viewutil. En(viewutil.CopyEnWith(fs, "view_list.html")). Ru(m(viewutil.CopyRuWith(fs, "view_list.html").Parse(ruTranslation))) + chainTitleSearch = viewutil. + En(viewutil.CopyEnWith(fs, "view_title_search.html")). + Ru(m(viewutil.CopyRuWith(fs, "view_title_search.html").Parse(ruTranslation))) } type listDatum struct { @@ -67,3 +73,23 @@ func viewList(meta viewutil.Meta) { log.Println(err) } } + +type titleSearchData struct { + viewutil.BaseData + Query string + Results []string +} + +func viewTitleSearch(meta viewutil.Meta, query string, results []string) { + if err := chainTitleSearch.Get(meta).ExecuteTemplate(meta.W, "page", titleSearchData{ + BaseData: viewutil.BaseData{ + Meta: meta, + HeaderLinks: cfg.HeaderLinks, + CommonScripts: cfg.CommonScripts, + }, + Query: query, + Results: results, + }); err != nil { + log.Println(err) + } +} diff --git a/shroom/search.go b/shroom/search.go index 6f6e902..4387abf 100644 --- a/shroom/search.go +++ b/shroom/search.go @@ -7,7 +7,7 @@ import ( "github.com/bouncepaw/mycorrhiza/util" ) -// YieldHyphaNamesContainingString picks hyphae with have a string in their title, sorts and iterates over them. +// YieldHyphaNamesContainingString picks hyphae with have a string in their title, sorts and iterates over them in alphabetical order. func YieldHyphaNamesContainingString(query string) <-chan string { query = util.CanonicalName(strings.TrimSpace(query)) out := make(chan string) diff --git a/views/auth.qtpl b/views/auth.qtpl index 619d2fd..fc94ec5 100644 --- a/views/auth.qtpl +++ b/views/auth.qtpl @@ -1,6 +1,8 @@ {% import "net/http" %} +{% import "sort" %} {% import "github.com/bouncepaw/mycorrhiza/cfg" %} {% import "github.com/bouncepaw/mycorrhiza/l18n" %} +{% import "github.com/bouncepaw/mycorrhiza/user" %} {% func Register(rq *http.Request) %} {% code @@ -148,3 +150,63 @@ Telegram auth widget was requested by Yogurt. As you can see, we don't offer use {% endfunc %} + +{% code +var userListL10n = map[string]l10nEntry{ + "heading": en("List of users").ru("Список пользователей"), + "administrators": en("Administrators").ru("Администраторы"), + "moderators": en("Moderators").ru("Модераторы"), + "editors": en("Editors").ru("Редакторы"), +} +%} + +{% func UserList(lc *l18n.Localizer) %} +
      +
      +{% code +var get = func(key string) string { + return userListL10n[key].get(lc.Locale) +} + +var ( + admins = make([]string, 0) + moderators = make([]string, 0) + editors = make([]string, 0) +) +for u := range user.YieldUsers() { + switch u.Group { + // What if we place the users into sorted slices? + case "admin": + admins = append(admins, u.Name) + case "moderator": + moderators = append(moderators, u.Name) + case "editor", "trusted": + editors = append(editors, u.Name) + } +} +sort.Strings(admins) +sort.Strings(moderators) +sort.Strings(editors) +%} +

      {%s get("heading") %}

      +
      +

      {%s get("administrators") %}

      +
        {% for _, name := range admins %} +
      1. {%s name %}
      2. + {% endfor %}
      +
      +
      +

      {%s get("moderators") %}

      +
        {% for _, name := range moderators %} +
      1. {%s name %}
      2. + {% endfor %}
      +
      +
      +

      {%s get("editors") %}

      +
        {% for _, name := range editors %} +
      1. {%s name %}
      2. + {% endfor %}
      +
      +
      +
      +{% endfunc %} \ No newline at end of file diff --git a/views/auth.qtpl.go b/views/auth.qtpl.go index 8018252..8f54d26 100644 --- a/views/auth.qtpl.go +++ b/views/auth.qtpl.go @@ -8,517 +8,523 @@ package views import "net/http" //line views/auth.qtpl:2 -import "github.com/bouncepaw/mycorrhiza/cfg" +import "sort" //line views/auth.qtpl:3 +import "github.com/bouncepaw/mycorrhiza/cfg" + +//line views/auth.qtpl:4 import "github.com/bouncepaw/mycorrhiza/l18n" //line views/auth.qtpl:5 +import "github.com/bouncepaw/mycorrhiza/user" + +//line views/auth.qtpl:7 import ( qtio422016 "io" qt422016 "github.com/valyala/quicktemplate" ) -//line views/auth.qtpl:5 +//line views/auth.qtpl:7 var ( _ = qtio422016.Copy _ = qt422016.AcquireByteBuffer ) -//line views/auth.qtpl:5 +//line views/auth.qtpl:7 func StreamRegister(qw422016 *qt422016.Writer, rq *http.Request) { -//line views/auth.qtpl:5 +//line views/auth.qtpl:7 qw422016.N().S(` `) -//line views/auth.qtpl:7 +//line views/auth.qtpl:9 lc := l18n.FromRequest(rq) -//line views/auth.qtpl:8 +//line views/auth.qtpl:10 qw422016.N().S(`
      `) -//line views/auth.qtpl:12 +//line views/auth.qtpl:14 if cfg.AllowRegistration { -//line views/auth.qtpl:12 +//line views/auth.qtpl:14 qw422016.N().S(` `) -//line views/auth.qtpl:30 +//line views/auth.qtpl:32 streamtelegramWidget(qw422016, lc) -//line views/auth.qtpl:30 +//line views/auth.qtpl:32 qw422016.N().S(` `) -//line views/auth.qtpl:31 +//line views/auth.qtpl:33 } else if cfg.UseAuth { -//line views/auth.qtpl:31 +//line views/auth.qtpl:33 qw422016.N().S(`

      `) -//line views/auth.qtpl:32 +//line views/auth.qtpl:34 qw422016.E().S(lc.Get("auth.noregister")) -//line views/auth.qtpl:32 +//line views/auth.qtpl:34 qw422016.N().S(`

      ← `) -//line views/auth.qtpl:33 +//line views/auth.qtpl:35 qw422016.E().S(lc.Get("auth.go_back")) -//line views/auth.qtpl:33 +//line views/auth.qtpl:35 qw422016.N().S(`

      `) -//line views/auth.qtpl:34 +//line views/auth.qtpl:36 } else { -//line views/auth.qtpl:34 +//line views/auth.qtpl:36 qw422016.N().S(`

      `) -//line views/auth.qtpl:35 +//line views/auth.qtpl:37 qw422016.E().S(lc.Get("auth.noauth")) -//line views/auth.qtpl:35 +//line views/auth.qtpl:37 qw422016.N().S(`

      ← `) -//line views/auth.qtpl:36 +//line views/auth.qtpl:38 qw422016.E().S(lc.Get("auth.go_back")) -//line views/auth.qtpl:36 +//line views/auth.qtpl:38 qw422016.N().S(`

      `) -//line views/auth.qtpl:37 +//line views/auth.qtpl:39 } -//line views/auth.qtpl:37 +//line views/auth.qtpl:39 qw422016.N().S(`
      `) -//line views/auth.qtpl:41 +//line views/auth.qtpl:43 } -//line views/auth.qtpl:41 +//line views/auth.qtpl:43 func WriteRegister(qq422016 qtio422016.Writer, rq *http.Request) { -//line views/auth.qtpl:41 +//line views/auth.qtpl:43 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/auth.qtpl:41 +//line views/auth.qtpl:43 StreamRegister(qw422016, rq) -//line views/auth.qtpl:41 +//line views/auth.qtpl:43 qt422016.ReleaseWriter(qw422016) -//line views/auth.qtpl:41 +//line views/auth.qtpl:43 } -//line views/auth.qtpl:41 +//line views/auth.qtpl:43 func Register(rq *http.Request) string { -//line views/auth.qtpl:41 +//line views/auth.qtpl:43 qb422016 := qt422016.AcquireByteBuffer() -//line views/auth.qtpl:41 +//line views/auth.qtpl:43 WriteRegister(qb422016, rq) -//line views/auth.qtpl:41 +//line views/auth.qtpl:43 qs422016 := string(qb422016.B) -//line views/auth.qtpl:41 +//line views/auth.qtpl:43 qt422016.ReleaseByteBuffer(qb422016) -//line views/auth.qtpl:41 +//line views/auth.qtpl:43 return qs422016 -//line views/auth.qtpl:41 +//line views/auth.qtpl:43 } -//line views/auth.qtpl:43 +//line views/auth.qtpl:45 func StreamLogin(qw422016 *qt422016.Writer, lc *l18n.Localizer) { -//line views/auth.qtpl:43 +//line views/auth.qtpl:45 qw422016.N().S(`
      `) -//line views/auth.qtpl:47 +//line views/auth.qtpl:49 if cfg.UseAuth { -//line views/auth.qtpl:47 +//line views/auth.qtpl:49 qw422016.N().S(` `) -//line views/auth.qtpl:63 +//line views/auth.qtpl:65 streamtelegramWidget(qw422016, lc) -//line views/auth.qtpl:63 +//line views/auth.qtpl:65 qw422016.N().S(` `) -//line views/auth.qtpl:64 +//line views/auth.qtpl:66 } else { -//line views/auth.qtpl:64 +//line views/auth.qtpl:66 qw422016.N().S(`

      `) -//line views/auth.qtpl:65 +//line views/auth.qtpl:67 qw422016.E().S(lc.Get("auth.noauth")) -//line views/auth.qtpl:65 +//line views/auth.qtpl:67 qw422016.N().S(`

      ← `) -//line views/auth.qtpl:66 +//line views/auth.qtpl:68 qw422016.E().S(lc.Get("auth.go_home")) -//line views/auth.qtpl:66 +//line views/auth.qtpl:68 qw422016.N().S(`

      `) -//line views/auth.qtpl:67 +//line views/auth.qtpl:69 } -//line views/auth.qtpl:67 +//line views/auth.qtpl:69 qw422016.N().S(`
      `) -//line views/auth.qtpl:71 +//line views/auth.qtpl:73 } -//line views/auth.qtpl:71 +//line views/auth.qtpl:73 func WriteLogin(qq422016 qtio422016.Writer, lc *l18n.Localizer) { -//line views/auth.qtpl:71 +//line views/auth.qtpl:73 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/auth.qtpl:71 +//line views/auth.qtpl:73 StreamLogin(qw422016, lc) -//line views/auth.qtpl:71 +//line views/auth.qtpl:73 qt422016.ReleaseWriter(qw422016) -//line views/auth.qtpl:71 +//line views/auth.qtpl:73 } -//line views/auth.qtpl:71 +//line views/auth.qtpl:73 func Login(lc *l18n.Localizer) string { -//line views/auth.qtpl:71 +//line views/auth.qtpl:73 qb422016 := qt422016.AcquireByteBuffer() -//line views/auth.qtpl:71 +//line views/auth.qtpl:73 WriteLogin(qb422016, lc) -//line views/auth.qtpl:71 +//line views/auth.qtpl:73 qs422016 := string(qb422016.B) -//line views/auth.qtpl:71 +//line views/auth.qtpl:73 qt422016.ReleaseByteBuffer(qb422016) -//line views/auth.qtpl:71 +//line views/auth.qtpl:73 return qs422016 -//line views/auth.qtpl:71 +//line views/auth.qtpl:73 } // Telegram auth widget was requested by Yogurt. As you can see, we don't offer user administrators control over it. Of course we don't. -//line views/auth.qtpl:74 +//line views/auth.qtpl:76 func streamtelegramWidget(qw422016 *qt422016.Writer, lc *l18n.Localizer) { -//line views/auth.qtpl:74 +//line views/auth.qtpl:76 qw422016.N().S(` `) -//line views/auth.qtpl:75 +//line views/auth.qtpl:77 if cfg.TelegramEnabled { -//line views/auth.qtpl:75 +//line views/auth.qtpl:77 qw422016.N().S(`

      `) -//line views/auth.qtpl:76 +//line views/auth.qtpl:78 qw422016.E().S(lc.Get("auth.telegram_tip")) -//line views/auth.qtpl:76 +//line views/auth.qtpl:78 qw422016.N().S(`

      `) -//line views/auth.qtpl:78 +//line views/auth.qtpl:80 } -//line views/auth.qtpl:78 +//line views/auth.qtpl:80 qw422016.N().S(` `) -//line views/auth.qtpl:79 +//line views/auth.qtpl:81 } -//line views/auth.qtpl:79 +//line views/auth.qtpl:81 func writetelegramWidget(qq422016 qtio422016.Writer, lc *l18n.Localizer) { -//line views/auth.qtpl:79 +//line views/auth.qtpl:81 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/auth.qtpl:79 +//line views/auth.qtpl:81 streamtelegramWidget(qw422016, lc) -//line views/auth.qtpl:79 +//line views/auth.qtpl:81 qt422016.ReleaseWriter(qw422016) -//line views/auth.qtpl:79 +//line views/auth.qtpl:81 } -//line views/auth.qtpl:79 +//line views/auth.qtpl:81 func telegramWidget(lc *l18n.Localizer) string { -//line views/auth.qtpl:79 +//line views/auth.qtpl:81 qb422016 := qt422016.AcquireByteBuffer() -//line views/auth.qtpl:79 +//line views/auth.qtpl:81 writetelegramWidget(qb422016, lc) -//line views/auth.qtpl:79 +//line views/auth.qtpl:81 qs422016 := string(qb422016.B) -//line views/auth.qtpl:79 +//line views/auth.qtpl:81 qt422016.ReleaseByteBuffer(qb422016) -//line views/auth.qtpl:79 +//line views/auth.qtpl:81 return qs422016 -//line views/auth.qtpl:79 +//line views/auth.qtpl:81 } -//line views/auth.qtpl:81 +//line views/auth.qtpl:83 func StreamLoginError(qw422016 *qt422016.Writer, err string, lc *l18n.Localizer) { -//line views/auth.qtpl:81 +//line views/auth.qtpl:83 qw422016.N().S(`
      `) -//line views/auth.qtpl:85 +//line views/auth.qtpl:87 switch err { -//line views/auth.qtpl:86 +//line views/auth.qtpl:88 case "unknown username": -//line views/auth.qtpl:86 +//line views/auth.qtpl:88 qw422016.N().S(`

      `) -//line views/auth.qtpl:87 +//line views/auth.qtpl:89 qw422016.E().S(lc.Get("auth.error_username")) -//line views/auth.qtpl:87 +//line views/auth.qtpl:89 qw422016.N().S(`

      `) -//line views/auth.qtpl:88 +//line views/auth.qtpl:90 case "wrong password": -//line views/auth.qtpl:88 +//line views/auth.qtpl:90 qw422016.N().S(`

      `) -//line views/auth.qtpl:89 +//line views/auth.qtpl:91 qw422016.E().S(lc.Get("auth.error_password")) -//line views/auth.qtpl:89 +//line views/auth.qtpl:91 qw422016.N().S(`

      `) -//line views/auth.qtpl:90 +//line views/auth.qtpl:92 default: -//line views/auth.qtpl:90 +//line views/auth.qtpl:92 qw422016.N().S(`

      `) -//line views/auth.qtpl:91 +//line views/auth.qtpl:93 qw422016.E().S(err) -//line views/auth.qtpl:91 +//line views/auth.qtpl:93 qw422016.N().S(`

      `) -//line views/auth.qtpl:92 +//line views/auth.qtpl:94 } -//line views/auth.qtpl:92 +//line views/auth.qtpl:94 qw422016.N().S(`

      ← `) -//line views/auth.qtpl:93 +//line views/auth.qtpl:95 qw422016.E().S(lc.Get("auth.try_again")) -//line views/auth.qtpl:93 +//line views/auth.qtpl:95 qw422016.N().S(`

      `) -//line views/auth.qtpl:97 +//line views/auth.qtpl:99 } -//line views/auth.qtpl:97 +//line views/auth.qtpl:99 func WriteLoginError(qq422016 qtio422016.Writer, err string, lc *l18n.Localizer) { -//line views/auth.qtpl:97 +//line views/auth.qtpl:99 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/auth.qtpl:97 +//line views/auth.qtpl:99 StreamLoginError(qw422016, err, lc) -//line views/auth.qtpl:97 +//line views/auth.qtpl:99 qt422016.ReleaseWriter(qw422016) -//line views/auth.qtpl:97 +//line views/auth.qtpl:99 } -//line views/auth.qtpl:97 +//line views/auth.qtpl:99 func LoginError(err string, lc *l18n.Localizer) string { -//line views/auth.qtpl:97 +//line views/auth.qtpl:99 qb422016 := qt422016.AcquireByteBuffer() -//line views/auth.qtpl:97 +//line views/auth.qtpl:99 WriteLoginError(qb422016, err, lc) -//line views/auth.qtpl:97 +//line views/auth.qtpl:99 qs422016 := string(qb422016.B) -//line views/auth.qtpl:97 +//line views/auth.qtpl:99 qt422016.ReleaseByteBuffer(qb422016) -//line views/auth.qtpl:97 +//line views/auth.qtpl:99 return qs422016 -//line views/auth.qtpl:97 +//line views/auth.qtpl:99 } -//line views/auth.qtpl:99 +//line views/auth.qtpl:101 func StreamLogout(qw422016 *qt422016.Writer, can bool, lc *l18n.Localizer) { -//line views/auth.qtpl:99 +//line views/auth.qtpl:101 qw422016.N().S(`
      `) -//line views/auth.qtpl:103 +//line views/auth.qtpl:105 if can { -//line views/auth.qtpl:103 +//line views/auth.qtpl:105 qw422016.N().S(`

      `) -//line views/auth.qtpl:104 +//line views/auth.qtpl:106 qw422016.E().S(lc.Get("auth.logout_header")) -//line views/auth.qtpl:104 +//line views/auth.qtpl:106 qw422016.N().S(`

      `) -//line views/auth.qtpl:107 +//line views/auth.qtpl:109 qw422016.E().S(lc.Get("auth.go_home")) -//line views/auth.qtpl:107 +//line views/auth.qtpl:109 qw422016.N().S(`
      `) -//line views/auth.qtpl:109 +//line views/auth.qtpl:111 } else { -//line views/auth.qtpl:109 +//line views/auth.qtpl:111 qw422016.N().S(`

      `) -//line views/auth.qtpl:110 +//line views/auth.qtpl:112 qw422016.E().S(lc.Get("auth.logout_anon")) -//line views/auth.qtpl:110 +//line views/auth.qtpl:112 qw422016.N().S(`

      `) -//line views/auth.qtpl:111 +//line views/auth.qtpl:113 qw422016.E().S(lc.Get("auth.login_title")) -//line views/auth.qtpl:111 +//line views/auth.qtpl:113 qw422016.N().S(`

      ← `) -//line views/auth.qtpl:112 +//line views/auth.qtpl:114 qw422016.E().S(lc.Get("auth.go_home")) -//line views/auth.qtpl:112 +//line views/auth.qtpl:114 qw422016.N().S(`

      `) -//line views/auth.qtpl:113 +//line views/auth.qtpl:115 } -//line views/auth.qtpl:113 +//line views/auth.qtpl:115 qw422016.N().S(`
      `) -//line views/auth.qtpl:117 +//line views/auth.qtpl:119 } -//line views/auth.qtpl:117 +//line views/auth.qtpl:119 func WriteLogout(qq422016 qtio422016.Writer, can bool, lc *l18n.Localizer) { -//line views/auth.qtpl:117 +//line views/auth.qtpl:119 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/auth.qtpl:117 +//line views/auth.qtpl:119 StreamLogout(qw422016, can, lc) -//line views/auth.qtpl:117 +//line views/auth.qtpl:119 qt422016.ReleaseWriter(qw422016) -//line views/auth.qtpl:117 +//line views/auth.qtpl:119 } -//line views/auth.qtpl:117 +//line views/auth.qtpl:119 func Logout(can bool, lc *l18n.Localizer) string { -//line views/auth.qtpl:117 +//line views/auth.qtpl:119 qb422016 := qt422016.AcquireByteBuffer() -//line views/auth.qtpl:117 +//line views/auth.qtpl:119 WriteLogout(qb422016, can, lc) -//line views/auth.qtpl:117 +//line views/auth.qtpl:119 qs422016 := string(qb422016.B) -//line views/auth.qtpl:117 +//line views/auth.qtpl:119 qt422016.ReleaseByteBuffer(qb422016) -//line views/auth.qtpl:117 +//line views/auth.qtpl:119 return qs422016 -//line views/auth.qtpl:117 +//line views/auth.qtpl:119 } -//line views/auth.qtpl:119 +//line views/auth.qtpl:121 func StreamLock(qw422016 *qt422016.Writer, lc *l18n.Localizer) { -//line views/auth.qtpl:119 +//line views/auth.qtpl:121 qw422016.N().S(` @@ -526,9 +532,9 @@ func StreamLock(qw422016 *qt422016.Writer, lc *l18n.Localizer) { 🔒 `) -//line views/auth.qtpl:125 +//line views/auth.qtpl:127 qw422016.E().S(lc.Get("auth.lock_title")) -//line views/auth.qtpl:125 +//line views/auth.qtpl:127 qw422016.N().S(` @@ -538,68 +544,237 @@ func StreamLock(qw422016 *qt422016.Writer, lc *l18n.Localizer) {

      🔒

      `) -//line views/auth.qtpl:133 +//line views/auth.qtpl:135 qw422016.E().S(lc.Get("auth.lock_title")) -//line views/auth.qtpl:133 +//line views/auth.qtpl:135 qw422016.N().S(`

      `) -//line views/auth.qtpl:145 +//line views/auth.qtpl:147 streamtelegramWidget(qw422016, lc) -//line views/auth.qtpl:145 +//line views/auth.qtpl:147 qw422016.N().S(`
      `) -//line views/auth.qtpl:150 +//line views/auth.qtpl:152 } -//line views/auth.qtpl:150 +//line views/auth.qtpl:152 func WriteLock(qq422016 qtio422016.Writer, lc *l18n.Localizer) { -//line views/auth.qtpl:150 +//line views/auth.qtpl:152 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/auth.qtpl:150 +//line views/auth.qtpl:152 StreamLock(qw422016, lc) -//line views/auth.qtpl:150 +//line views/auth.qtpl:152 qt422016.ReleaseWriter(qw422016) -//line views/auth.qtpl:150 +//line views/auth.qtpl:152 } -//line views/auth.qtpl:150 +//line views/auth.qtpl:152 func Lock(lc *l18n.Localizer) string { -//line views/auth.qtpl:150 +//line views/auth.qtpl:152 qb422016 := qt422016.AcquireByteBuffer() -//line views/auth.qtpl:150 +//line views/auth.qtpl:152 WriteLock(qb422016, lc) -//line views/auth.qtpl:150 +//line views/auth.qtpl:152 qs422016 := string(qb422016.B) -//line views/auth.qtpl:150 +//line views/auth.qtpl:152 qt422016.ReleaseByteBuffer(qb422016) -//line views/auth.qtpl:150 +//line views/auth.qtpl:152 return qs422016 -//line views/auth.qtpl:150 +//line views/auth.qtpl:152 +} + +//line views/auth.qtpl:155 +var userListL10n = map[string]l10nEntry{ + "heading": en("List of users").ru("Список пользователей"), + "administrators": en("Administrators").ru("Администраторы"), + "moderators": en("Moderators").ru("Модераторы"), + "editors": en("Editors").ru("Редакторы"), +} + +//line views/auth.qtpl:163 +func StreamUserList(qw422016 *qt422016.Writer, lc *l18n.Localizer) { +//line views/auth.qtpl:163 + qw422016.N().S(` +
      +
      +`) +//line views/auth.qtpl:167 + var get = func(key string) string { + return userListL10n[key].get(lc.Locale) + } + + var ( + admins = make([]string, 0) + moderators = make([]string, 0) + editors = make([]string, 0) + ) + for u := range user.YieldUsers() { + switch u.Group { + // What if we place the users into sorted slices? + case "admin": + admins = append(admins, u.Name) + case "moderator": + moderators = append(moderators, u.Name) + case "editor", "trusted": + editors = append(editors, u.Name) + } + } + sort.Strings(admins) + sort.Strings(moderators) + sort.Strings(editors) + +//line views/auth.qtpl:190 + qw422016.N().S(` +

      `) +//line views/auth.qtpl:191 + qw422016.E().S(get("heading")) +//line views/auth.qtpl:191 + qw422016.N().S(`

      +
      +

      `) +//line views/auth.qtpl:193 + qw422016.E().S(get("administrators")) +//line views/auth.qtpl:193 + qw422016.N().S(`

      +
        `) +//line views/auth.qtpl:194 + for _, name := range admins { +//line views/auth.qtpl:194 + qw422016.N().S(` +
      1. `) +//line views/auth.qtpl:195 + qw422016.E().S(name) +//line views/auth.qtpl:195 + qw422016.N().S(`
      2. + `) +//line views/auth.qtpl:196 + } +//line views/auth.qtpl:196 + qw422016.N().S(`
      +
      +
      +

      `) +//line views/auth.qtpl:199 + qw422016.E().S(get("moderators")) +//line views/auth.qtpl:199 + qw422016.N().S(`

      +
        `) +//line views/auth.qtpl:200 + for _, name := range moderators { +//line views/auth.qtpl:200 + qw422016.N().S(` +
      1. `) +//line views/auth.qtpl:201 + qw422016.E().S(name) +//line views/auth.qtpl:201 + qw422016.N().S(`
      2. + `) +//line views/auth.qtpl:202 + } +//line views/auth.qtpl:202 + qw422016.N().S(`
      +
      +
      +

      `) +//line views/auth.qtpl:205 + qw422016.E().S(get("editors")) +//line views/auth.qtpl:205 + qw422016.N().S(`

      +
        `) +//line views/auth.qtpl:206 + for _, name := range editors { +//line views/auth.qtpl:206 + qw422016.N().S(` +
      1. `) +//line views/auth.qtpl:207 + qw422016.E().S(name) +//line views/auth.qtpl:207 + qw422016.N().S(`
      2. + `) +//line views/auth.qtpl:208 + } +//line views/auth.qtpl:208 + qw422016.N().S(`
      +
      +
      +
      +`) +//line views/auth.qtpl:212 +} + +//line views/auth.qtpl:212 +func WriteUserList(qq422016 qtio422016.Writer, lc *l18n.Localizer) { +//line views/auth.qtpl:212 + qw422016 := qt422016.AcquireWriter(qq422016) +//line views/auth.qtpl:212 + StreamUserList(qw422016, lc) +//line views/auth.qtpl:212 + qt422016.ReleaseWriter(qw422016) +//line views/auth.qtpl:212 +} + +//line views/auth.qtpl:212 +func UserList(lc *l18n.Localizer) string { +//line views/auth.qtpl:212 + qb422016 := qt422016.AcquireByteBuffer() +//line views/auth.qtpl:212 + WriteUserList(qb422016, lc) +//line views/auth.qtpl:212 + qs422016 := string(qb422016.B) +//line views/auth.qtpl:212 + qt422016.ReleaseByteBuffer(qb422016) +//line views/auth.qtpl:212 + return qs422016 +//line views/auth.qtpl:212 } diff --git a/views/stuff.qtpl b/views/stuff.qtpl index 37151c4..99a28db 100644 --- a/views/stuff.qtpl +++ b/views/stuff.qtpl @@ -4,21 +4,6 @@ {% import "github.com/bouncepaw/mycorrhiza/util" %} {% import "github.com/bouncepaw/mycorrhiza/l18n" %} -{% func TitleSearch(query string, generator func(string) <-chan string, lc *l18n.Localizer) %} -
      -
      -

      {%s lc.Get("ui.search_results_query", &l18n.Replacements{"query": query})%}

      -

      {%s lc.Get("ui.search_results_desc")%}

      -
      -
      -{% endfunc %} - {% func Backlinks(hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) %}
      diff --git a/views/stuff.qtpl.go b/views/stuff.qtpl.go index 31ae9ff..5abfcf6 100644 --- a/views/stuff.qtpl.go +++ b/views/stuff.qtpl.go @@ -30,83 +30,13 @@ var ( ) //line views/stuff.qtpl:7 -func StreamTitleSearch(qw422016 *qt422016.Writer, query string, generator func(string) <-chan string, lc *l18n.Localizer) { -//line views/stuff.qtpl:7 - qw422016.N().S(` -
      -
      -

      `) -//line views/stuff.qtpl:10 - qw422016.E().S(lc.Get("ui.search_results_query", &l18n.Replacements{"query": query})) -//line views/stuff.qtpl:10 - qw422016.N().S(`

      -

      `) -//line views/stuff.qtpl:11 - qw422016.E().S(lc.Get("ui.search_results_desc")) -//line views/stuff.qtpl:11 - qw422016.N().S(`

      -
      -
      -`) -//line views/stuff.qtpl:20 -} - -//line views/stuff.qtpl:20 -func WriteTitleSearch(qq422016 qtio422016.Writer, query string, generator func(string) <-chan string, lc *l18n.Localizer) { -//line views/stuff.qtpl:20 - qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:20 - StreamTitleSearch(qw422016, query, generator, lc) -//line views/stuff.qtpl:20 - qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:20 -} - -//line views/stuff.qtpl:20 -func TitleSearch(query string, generator func(string) <-chan string, lc *l18n.Localizer) string { -//line views/stuff.qtpl:20 - qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:20 - WriteTitleSearch(qb422016, query, generator, lc) -//line views/stuff.qtpl:20 - qs422016 := string(qb422016.B) -//line views/stuff.qtpl:20 - qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:20 - return qs422016 -//line views/stuff.qtpl:20 -} - -//line views/stuff.qtpl:22 func StreamBacklinks(qw422016 *qt422016.Writer, hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) { -//line views/stuff.qtpl:22 +//line views/stuff.qtpl:7 qw422016.N().S(`

      `) -//line views/stuff.qtpl:25 +//line views/stuff.qtpl:10 qw422016.N().S(lc.Get( "ui.backlinks_heading", &l18n.Replacements{ @@ -117,220 +47,220 @@ func StreamBacklinks(qw422016 *qt422016.Writer, hyphaName string, generator func ), }, )) -//line views/stuff.qtpl:34 +//line views/stuff.qtpl:19 qw422016.N().S(`

      `) -//line views/stuff.qtpl:35 +//line views/stuff.qtpl:20 qw422016.E().S(lc.Get("ui.backlinks_desc")) -//line views/stuff.qtpl:35 +//line views/stuff.qtpl:20 qw422016.N().S(`

      `) -//line views/stuff.qtpl:45 +//line views/stuff.qtpl:30 } -//line views/stuff.qtpl:45 +//line views/stuff.qtpl:30 func WriteBacklinks(qq422016 qtio422016.Writer, hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) { -//line views/stuff.qtpl:45 +//line views/stuff.qtpl:30 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:45 +//line views/stuff.qtpl:30 StreamBacklinks(qw422016, hyphaName, generator, lc) -//line views/stuff.qtpl:45 +//line views/stuff.qtpl:30 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:45 +//line views/stuff.qtpl:30 } -//line views/stuff.qtpl:45 +//line views/stuff.qtpl:30 func Backlinks(hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) string { -//line views/stuff.qtpl:45 +//line views/stuff.qtpl:30 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:45 +//line views/stuff.qtpl:30 WriteBacklinks(qb422016, hyphaName, generator, lc) -//line views/stuff.qtpl:45 +//line views/stuff.qtpl:30 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:45 +//line views/stuff.qtpl:30 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:45 +//line views/stuff.qtpl:30 return qs422016 -//line views/stuff.qtpl:45 +//line views/stuff.qtpl:30 } -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:32 func StreamHelp(qw422016 *qt422016.Writer, content, lang string, lc *l18n.Localizer) { -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:32 qw422016.N().S(`
      `) -//line views/stuff.qtpl:51 +//line views/stuff.qtpl:36 qw422016.N().S(content) -//line views/stuff.qtpl:51 +//line views/stuff.qtpl:36 qw422016.N().S(`
      `) -//line views/stuff.qtpl:54 +//line views/stuff.qtpl:39 qw422016.N().S(helpTopics(lang, lc)) -//line views/stuff.qtpl:54 +//line views/stuff.qtpl:39 qw422016.N().S(`
      `) -//line views/stuff.qtpl:56 +//line views/stuff.qtpl:41 } -//line views/stuff.qtpl:56 +//line views/stuff.qtpl:41 func WriteHelp(qq422016 qtio422016.Writer, content, lang string, lc *l18n.Localizer) { -//line views/stuff.qtpl:56 +//line views/stuff.qtpl:41 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:56 +//line views/stuff.qtpl:41 StreamHelp(qw422016, content, lang, lc) -//line views/stuff.qtpl:56 +//line views/stuff.qtpl:41 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:56 +//line views/stuff.qtpl:41 } -//line views/stuff.qtpl:56 +//line views/stuff.qtpl:41 func Help(content, lang string, lc *l18n.Localizer) string { -//line views/stuff.qtpl:56 +//line views/stuff.qtpl:41 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:56 +//line views/stuff.qtpl:41 WriteHelp(qb422016, content, lang, lc) -//line views/stuff.qtpl:56 +//line views/stuff.qtpl:41 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:56 +//line views/stuff.qtpl:41 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:56 +//line views/stuff.qtpl:41 return qs422016 -//line views/stuff.qtpl:56 +//line views/stuff.qtpl:41 } -//line views/stuff.qtpl:58 +//line views/stuff.qtpl:43 func StreamHelpEmptyError(qw422016 *qt422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:58 +//line views/stuff.qtpl:43 qw422016.N().S(`

      `) -//line views/stuff.qtpl:59 +//line views/stuff.qtpl:44 qw422016.E().S(lc.Get("help.empty_error_title")) -//line views/stuff.qtpl:59 +//line views/stuff.qtpl:44 qw422016.N().S(`

      `) -//line views/stuff.qtpl:60 +//line views/stuff.qtpl:45 qw422016.E().S(lc.Get("help.empty_error_line_1")) -//line views/stuff.qtpl:60 +//line views/stuff.qtpl:45 qw422016.N().S(`

      `) -//line views/stuff.qtpl:61 +//line views/stuff.qtpl:46 qw422016.E().S(lc.Get("help.empty_error_line_2a")) -//line views/stuff.qtpl:61 +//line views/stuff.qtpl:46 qw422016.N().S(` `) -//line views/stuff.qtpl:61 +//line views/stuff.qtpl:46 qw422016.E().S(lc.Get("help.empty_error_link")) -//line views/stuff.qtpl:61 +//line views/stuff.qtpl:46 qw422016.N().S(` `) -//line views/stuff.qtpl:61 +//line views/stuff.qtpl:46 qw422016.E().S(lc.Get("help.empty_error_line_2b")) -//line views/stuff.qtpl:61 +//line views/stuff.qtpl:46 qw422016.N().S(`

      `) -//line views/stuff.qtpl:62 +//line views/stuff.qtpl:47 } -//line views/stuff.qtpl:62 +//line views/stuff.qtpl:47 func WriteHelpEmptyError(qq422016 qtio422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:62 +//line views/stuff.qtpl:47 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:62 +//line views/stuff.qtpl:47 StreamHelpEmptyError(qw422016, lc) -//line views/stuff.qtpl:62 +//line views/stuff.qtpl:47 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:62 +//line views/stuff.qtpl:47 } -//line views/stuff.qtpl:62 +//line views/stuff.qtpl:47 func HelpEmptyError(lc *l18n.Localizer) string { -//line views/stuff.qtpl:62 +//line views/stuff.qtpl:47 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:62 +//line views/stuff.qtpl:47 WriteHelpEmptyError(qb422016, lc) -//line views/stuff.qtpl:62 +//line views/stuff.qtpl:47 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:62 +//line views/stuff.qtpl:47 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:62 +//line views/stuff.qtpl:47 return qs422016 -//line views/stuff.qtpl:62 +//line views/stuff.qtpl:47 } -//line views/stuff.qtpl:64 +//line views/stuff.qtpl:49 func streamcommonScripts(qw422016 *qt422016.Writer) { -//line views/stuff.qtpl:64 +//line views/stuff.qtpl:49 qw422016.N().S(` `) -//line views/stuff.qtpl:65 +//line views/stuff.qtpl:50 for _, scriptPath := range cfg.CommonScripts { -//line views/stuff.qtpl:65 +//line views/stuff.qtpl:50 qw422016.N().S(` `) -//line views/stuff.qtpl:67 +//line views/stuff.qtpl:52 } -//line views/stuff.qtpl:67 +//line views/stuff.qtpl:52 qw422016.N().S(` `) -//line views/stuff.qtpl:68 +//line views/stuff.qtpl:53 } -//line views/stuff.qtpl:68 +//line views/stuff.qtpl:53 func writecommonScripts(qq422016 qtio422016.Writer) { -//line views/stuff.qtpl:68 +//line views/stuff.qtpl:53 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:68 +//line views/stuff.qtpl:53 streamcommonScripts(qw422016) -//line views/stuff.qtpl:68 +//line views/stuff.qtpl:53 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:68 +//line views/stuff.qtpl:53 } -//line views/stuff.qtpl:68 +//line views/stuff.qtpl:53 func commonScripts() string { -//line views/stuff.qtpl:68 +//line views/stuff.qtpl:53 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:68 +//line views/stuff.qtpl:53 writecommonScripts(qb422016) -//line views/stuff.qtpl:68 +//line views/stuff.qtpl:53 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:68 +//line views/stuff.qtpl:53 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:68 +//line views/stuff.qtpl:53 return qs422016 -//line views/stuff.qtpl:68 +//line views/stuff.qtpl:53 } diff --git a/views/user_list.qtpl b/views/user_list.qtpl deleted file mode 100644 index 2d647d2..0000000 --- a/views/user_list.qtpl +++ /dev/null @@ -1,64 +0,0 @@ -{% import "github.com/bouncepaw/mycorrhiza/cfg" %} -{% import "github.com/bouncepaw/mycorrhiza/l18n" %} -{% import "github.com/bouncepaw/mycorrhiza/user" %} -{% import "sort" %} - -{% code -var hyphaListL10n = map[string]l10nEntry{ - "heading": en("List of users").ru("Список пользователей"), - "administrators": en("Administrators").ru("Администраторы"), - "moderators": en("Moderators").ru("Модераторы"), - "editors": en("Editors").ru("Редакторы"), -} -%} - -{% func UserList(lc *l18n.Localizer) %} -
      -
      -{% code -var get = func(key string) string { - return hyphaListL10n[key].get(lc.Locale) -} - -var ( - admins = make([]string, 0) - moderators = make([]string, 0) - editors = make([]string, 0) -) -for u := range user.YieldUsers() { - switch u.Group { - // What if we place the users into sorted slices? - case "admin": - admins = append(admins, u.Name) - case "moderator": - moderators = append(moderators, u.Name) - case "editor", "trusted": - editors = append(editors, u.Name) - } -} -sort.Strings(admins) -sort.Strings(moderators) -sort.Strings(editors) -%} -

      {%s get("heading") %}

      -
      -

      {%s get("administrators") %}

      -
        {% for _, name := range admins %} -
      1. {%s name %}
      2. - {% endfor %}
      -
      -
      -

      {%s get("moderators") %}

      -
        {% for _, name := range moderators %} -
      1. {%s name %}
      2. - {% endfor %}
      -
      -
      -

      {%s get("editors") %}

      -
        {% for _, name := range editors %} -
      1. {%s name %}
      2. - {% endfor %}
      -
      -
      -
      -{% endfunc %} \ No newline at end of file diff --git a/views/user_list.qtpl.go b/views/user_list.qtpl.go deleted file mode 100644 index 31cdd88..0000000 --- a/views/user_list.qtpl.go +++ /dev/null @@ -1,199 +0,0 @@ -// Code generated by qtc from "user_list.qtpl". DO NOT EDIT. -// See https://github.com/valyala/quicktemplate for details. - -//line views/user_list.qtpl:1 -package views - -//line views/user_list.qtpl:1 -import "github.com/bouncepaw/mycorrhiza/cfg" - -//line views/user_list.qtpl:2 -import "github.com/bouncepaw/mycorrhiza/l18n" - -//line views/user_list.qtpl:3 -import "github.com/bouncepaw/mycorrhiza/user" - -//line views/user_list.qtpl:4 -import "sort" - -//line views/user_list.qtpl:6 -import ( - qtio422016 "io" - - qt422016 "github.com/valyala/quicktemplate" -) - -//line views/user_list.qtpl:6 -var ( - _ = qtio422016.Copy - _ = qt422016.AcquireByteBuffer -) - -//line views/user_list.qtpl:7 -var hyphaListL10n = map[string]l10nEntry{ - "heading": en("List of users").ru("Список пользователей"), - "administrators": en("Administrators").ru("Администраторы"), - "moderators": en("Moderators").ru("Модераторы"), - "editors": en("Editors").ru("Редакторы"), -} - -//line views/user_list.qtpl:15 -func StreamUserList(qw422016 *qt422016.Writer, lc *l18n.Localizer) { -//line views/user_list.qtpl:15 - qw422016.N().S(` -
      -
      -`) -//line views/user_list.qtpl:19 - var get = func(key string) string { - return hyphaListL10n[key].get(lc.Locale) - } - - var ( - admins = make([]string, 0) - moderators = make([]string, 0) - editors = make([]string, 0) - ) - for u := range user.YieldUsers() { - switch u.Group { - // What if we place the users into sorted slices? - case "admin": - admins = append(admins, u.Name) - case "moderator": - moderators = append(moderators, u.Name) - case "editor", "trusted": - editors = append(editors, u.Name) - } - } - sort.Strings(admins) - sort.Strings(moderators) - sort.Strings(editors) - -//line views/user_list.qtpl:42 - qw422016.N().S(` -

      `) -//line views/user_list.qtpl:43 - qw422016.E().S(get("heading")) -//line views/user_list.qtpl:43 - qw422016.N().S(`

      -
      -

      `) -//line views/user_list.qtpl:45 - qw422016.E().S(get("administrators")) -//line views/user_list.qtpl:45 - qw422016.N().S(`

      -
        `) -//line views/user_list.qtpl:46 - for _, name := range admins { -//line views/user_list.qtpl:46 - qw422016.N().S(` -
      1. `) -//line views/user_list.qtpl:47 - qw422016.E().S(name) -//line views/user_list.qtpl:47 - qw422016.N().S(`
      2. - `) -//line views/user_list.qtpl:48 - } -//line views/user_list.qtpl:48 - qw422016.N().S(`
      -
      -
      -

      `) -//line views/user_list.qtpl:51 - qw422016.E().S(get("moderators")) -//line views/user_list.qtpl:51 - qw422016.N().S(`

      -
        `) -//line views/user_list.qtpl:52 - for _, name := range moderators { -//line views/user_list.qtpl:52 - qw422016.N().S(` -
      1. `) -//line views/user_list.qtpl:53 - qw422016.E().S(name) -//line views/user_list.qtpl:53 - qw422016.N().S(`
      2. - `) -//line views/user_list.qtpl:54 - } -//line views/user_list.qtpl:54 - qw422016.N().S(`
      -
      -
      -

      `) -//line views/user_list.qtpl:57 - qw422016.E().S(get("editors")) -//line views/user_list.qtpl:57 - qw422016.N().S(`

      -
        `) -//line views/user_list.qtpl:58 - for _, name := range editors { -//line views/user_list.qtpl:58 - qw422016.N().S(` -
      1. `) -//line views/user_list.qtpl:59 - qw422016.E().S(name) -//line views/user_list.qtpl:59 - qw422016.N().S(`
      2. - `) -//line views/user_list.qtpl:60 - } -//line views/user_list.qtpl:60 - qw422016.N().S(`
      -
      -
      -
      -`) -//line views/user_list.qtpl:64 -} - -//line views/user_list.qtpl:64 -func WriteUserList(qq422016 qtio422016.Writer, lc *l18n.Localizer) { -//line views/user_list.qtpl:64 - qw422016 := qt422016.AcquireWriter(qq422016) -//line views/user_list.qtpl:64 - StreamUserList(qw422016, lc) -//line views/user_list.qtpl:64 - qt422016.ReleaseWriter(qw422016) -//line views/user_list.qtpl:64 -} - -//line views/user_list.qtpl:64 -func UserList(lc *l18n.Localizer) string { -//line views/user_list.qtpl:64 - qb422016 := qt422016.AcquireByteBuffer() -//line views/user_list.qtpl:64 - WriteUserList(qb422016, lc) -//line views/user_list.qtpl:64 - qs422016 := string(qb422016.B) -//line views/user_list.qtpl:64 - qt422016.ReleaseByteBuffer(qb422016) -//line views/user_list.qtpl:64 - return qs422016 -//line views/user_list.qtpl:64 -} diff --git a/web/search.go b/web/search.go deleted file mode 100644 index 0a9b7d4..0000000 --- a/web/search.go +++ /dev/null @@ -1,36 +0,0 @@ -package web - -import ( - "github.com/bouncepaw/mycorrhiza/viewutil" - "io" - "net/http" - - "github.com/gorilla/mux" - - "github.com/bouncepaw/mycorrhiza/l18n" - "github.com/bouncepaw/mycorrhiza/shroom" - "github.com/bouncepaw/mycorrhiza/util" - "github.com/bouncepaw/mycorrhiza/views" -) - -func initSearch(r *mux.Router) { - r.HandleFunc("/title-search/", handlerTitleSearch) -} - -func handlerTitleSearch(w http.ResponseWriter, rq *http.Request) { - util.PrepareRq(rq) - _ = rq.ParseForm() - var ( - query = rq.FormValue("q") - lc = l18n.FromRequest(rq) - ) - w.WriteHeader(http.StatusOK) - _, _ = io.WriteString( - w, - views.Base( - viewutil.MetaFrom(w, rq), - lc.Get("ui.title_search_title", &l18n.Replacements{"query": query}), - views.TitleSearch(query, shroom.YieldHyphaNamesContainingString, lc), - ), - ) -} diff --git a/web/web.go b/web/web.go index 304aeb0..9801a17 100644 --- a/web/web.go +++ b/web/web.go @@ -47,7 +47,6 @@ func Handler() http.Handler { initMutators(wikiRouter) initHistory(wikiRouter) initHelp(wikiRouter) - initSearch(wikiRouter) initBacklinks(wikiRouter) categories.InitHandlers(wikiRouter) misc.InitHandlers(wikiRouter) From 75ded17a039907620ca0a4d489467faa07903db5 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 2 Apr 2022 11:09:37 +0300 Subject: [PATCH 17/23] Please staticcheck I ignored ST1005: error strings should not be capitalized and some others --- cfg/config.go | 2 +- history/revision.go | 2 +- l18n/en/ui.json | 12 +----------- l18n/l18n.go | 6 +++--- l18n/ru/ui.json | 13 +------------ shroom/log.go | 3 --- shroom/upload.go | 4 ++-- views/admin.go | 3 +++ 8 files changed, 12 insertions(+), 33 deletions(-) diff --git a/cfg/config.go b/cfg/config.go index c13f00c..4267068 100644 --- a/cfg/config.go +++ b/cfg/config.go @@ -193,7 +193,7 @@ func ReadConfigFile(path string) error { TelegramEnabled = (TelegramBotToken != "") && (TelegramBotName != "") // This URL makes much more sense. If no URL is set or the protocol is forgotten, assume HTTP. - if (URL == "") || (strings.Index(URL, ":") == -1) { + if (URL == "") || !strings.Contains(URL, ":") { URL = "http://" + ListenAddr } diff --git a/history/revision.go b/history/revision.go index fd9293a..4817aa1 100644 --- a/history/revision.go +++ b/history/revision.go @@ -175,7 +175,7 @@ func (rev *Revision) hyphaeAffected() (hyphae []string) { filesAffected = rev.filesAffected() ) for _, filename := range filesAffected { - if strings.IndexRune(filename, '.') >= 0 { + if strings.ContainsRune(filename, '.') { dotPos := strings.LastIndexByte(filename, '.') hyphaName := string([]byte(filename)[0:dotPos]) // is it safe? if isNewName(hyphaName) { diff --git a/l18n/en/ui.json b/l18n/en/ui.json index 28a1de6..800bf0b 100644 --- a/l18n/en/ui.json +++ b/l18n/en/ui.json @@ -3,21 +3,11 @@ "register": "Register", "title_search": "Search by title", "admin_panel": "Admin panel", - - "search_results_title": "Search: {{.query}}", - "search_results_query": "Search results for ‘{{.query}}’", - "search_results_desc": "Every hypha name has been compared with the query. Hyphae that have matched the query are listed below.", - + "backlinks_title": "Backlinks to {{.hypha_name}}", "backlinks_heading": "Backlinks to {{.hypha_link}}", "backlinks_desc": "Hyphae which have a link to this hypha, embed it as an image or transclude it are listed below.", - "list_title": "List of pages", - "list_heading": "List of hyphae", - "list_desc": "This wiki has {{.n}} %s.", - "list_desc+one": "hypha", - "list_desc+other": "hyphae", - "edit_link": "Edit text", "logout_link": "Log out", "history_link": "View history", diff --git a/l18n/l18n.go b/l18n/l18n.go index 67b347b..da87f53 100644 --- a/l18n/l18n.go +++ b/l18n/l18n.go @@ -118,7 +118,7 @@ func (t Localizer) GetWithLocale(locale, key string, replacements ...*Replacemen // If the str doesn't have any substitutions, no need to // template.Execute. - if strings.Index(str, "}}") == -1 { + if strings.Contains(str, "}}") { return str } @@ -145,7 +145,7 @@ func (t Localizer) GetPlural(key string, n int, replacements ...*Replacements) s // As in the original, we skip templating if have nothing to replace // (however, it's strange case for plurals) - if strings.Index(str, "}}") == -1 { + if strings.Contains(str, "}}") { return str } @@ -164,7 +164,7 @@ func (t Localizer) GetPlural64(key string, n int64, replacements ...*Replacement // As in the original, we skip templating if have nothing to replace // (however, it's strange case for plurals) - if strings.Index(str, "}}") == -1 { + if strings.Contains(str, "}}") { return str } diff --git a/l18n/ru/ui.json b/l18n/ru/ui.json index 43285ac..83ae6ae 100644 --- a/l18n/ru/ui.json +++ b/l18n/ru/ui.json @@ -3,21 +3,10 @@ "register": "Регистрация", "title_search": "Поиск по названию", "admin_panel": "Администрирование", - - "search_results_title": "Поиск: {{.query}}", - "search_results_query": "Результаты поиска для «{{.query}}»", - "search_results_desc": "Название каждой из существующих гиф сопоставлено с запросом. Подходящие гифы приведены ниже.", - + "backlinks_title": "Обратные ссылки на {{.hypha_name}}", "backlinks_heading": "Обратные ссылки на {{.hypha_link}}", "backlinks_desc": "Ниже перечислены гифы, на которых есть ссылка на эту гифу, трансклюзия этой гифы или эта гифа вставлена как изображение.", - - "list_title": "Список страниц", - "list_heading": "Список гиф", - "list_desc": "В этой вики {{.n}} %s.", - "list_desc+one": "гифа", - "list_desc+few": "гифы", - "list_desc+many": "гиф", "edit_link": "Редактировать", "logout_link": "Выйти", diff --git a/shroom/log.go b/shroom/log.go index ecda380..2be9a70 100644 --- a/shroom/log.go +++ b/shroom/log.go @@ -7,9 +7,6 @@ import ( "github.com/bouncepaw/mycorrhiza/user" ) -func rejectDeleteLog(h hyphae.Hypha, u *user.User, errmsg string) { - log.Printf("Reject delete ‘%s’ by @%s: %s\n", h.CanonicalName(), u.Name, errmsg) -} func rejectRenameLog(h hyphae.Hypha, u *user.User, errmsg string) { log.Printf("Reject rename ‘%s’ by @%s: %s\n", h.CanonicalName(), u.Name, errmsg) } diff --git a/shroom/upload.go b/shroom/upload.go index 74e2ba5..df04d7c 100644 --- a/shroom/upload.go +++ b/shroom/upload.go @@ -97,7 +97,7 @@ func UploadText(h hyphae.Hypha, data []byte, userMessage string, u *user.User) e } // TODO: that []byte(...) part should be removed - if bytes.Compare(data, []byte(oldText)) == 0 { + if bytes.Equal(data, []byte(oldText)) { // No changes! Just like cancel button hop.Abort() return nil @@ -118,7 +118,7 @@ func UploadText(h hyphae.Hypha, data []byte, userMessage string, u *user.User) e } // TODO: that []byte(...) part should be removed - if bytes.Compare(data, []byte(oldText)) == 0 { + if bytes.Equal(data, []byte(oldText)) { // No changes! Just like cancel button hop.Abort() return nil diff --git a/views/admin.go b/views/admin.go index e9d8351..f0d9993 100644 --- a/views/admin.go +++ b/views/admin.go @@ -71,4 +71,7 @@ func AdminPanel(meta viewutil.Meta) { templateAsString(localizedAdminTemplates(meta), "panel title"), buf.String(), )) + if err != nil { + log.Println(err) + } } From 2dcb1a5fe7a90072ef457ba41eca976d6e39773b Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 2 Apr 2022 19:58:57 +0300 Subject: [PATCH 18/23] Backlinks: Isolate --- {hyphae/backlinks => backlinks}/backlinks.go | 6 +- {hyphae/backlinks => backlinks}/hooks.go | 0 backlinks/view_backlinks.html | 17 ++ backlinks/web.go | 62 ++++++ l18n/en/ui.json | 4 - l18n/l18n.go | 6 +- main.go | 3 +- misc/handlers.go | 2 +- shroom/delete.go | 3 +- shroom/rename.go | 2 +- shroom/upload.go | 2 +- views/nav.qtpl | 2 +- views/nav.qtpl.go | 2 +- views/stuff.qtpl | 28 --- views/stuff.qtpl.go | 222 ++++++------------- web/backlinks.go | 30 --- web/web.go | 3 +- 17 files changed, 162 insertions(+), 232 deletions(-) rename {hyphae/backlinks => backlinks}/backlinks.go (95%) rename {hyphae/backlinks => backlinks}/hooks.go (100%) create mode 100644 backlinks/view_backlinks.html create mode 100644 backlinks/web.go delete mode 100644 web/backlinks.go diff --git a/hyphae/backlinks/backlinks.go b/backlinks/backlinks.go similarity index 95% rename from hyphae/backlinks/backlinks.go rename to backlinks/backlinks.go index 6ed43b0..605d8bd 100644 --- a/hyphae/backlinks/backlinks.go +++ b/backlinks/backlinks.go @@ -9,8 +9,8 @@ import ( "github.com/bouncepaw/mycorrhiza/util" ) -// YieldHyphaBacklinks gets backlinks for the desired hypha, sorts and yields them one by one. -func YieldHyphaBacklinks(hyphaName string) <-chan string { +// yieldHyphaBacklinks gets backlinks for the desired hypha, sorts and yields them one by one. +func yieldHyphaBacklinks(hyphaName string) <-chan string { hyphaName = util.CanonicalName(hyphaName) out := make(chan string) sorted := hyphae.PathographicSort(out) @@ -147,7 +147,7 @@ type backlinkIndexRenaming struct { links []string } -// Apply changes backlink index respective to the operation data +// apply changes backlink index respective to the operation data func (op backlinkIndexRenaming) apply() { for _, link := range op.links { if lSet, exists := backlinkIndex[link]; exists { diff --git a/hyphae/backlinks/hooks.go b/backlinks/hooks.go similarity index 100% rename from hyphae/backlinks/hooks.go rename to backlinks/hooks.go diff --git a/backlinks/view_backlinks.html b/backlinks/view_backlinks.html new file mode 100644 index 0000000..597fe32 --- /dev/null +++ b/backlinks/view_backlinks.html @@ -0,0 +1,17 @@ +{{define "backlinks to text"}}Backlinks to {{.}}{{end}} +{{define "title"}}{{template "backlinks to text" .HyphaName}}{{end}} +{{define "body"}} +
      +
      +

      {{block "backlinks to link" .HyphaName}}Backlinks to {{beautifulName .}}{{end}}

      +

      {{block "description" .}}Hyphae which have a link to this hypha, embed it as an image or transclude it are listed below.{{end}}

      + +
      +
      +{{end}} \ No newline at end of file diff --git a/backlinks/web.go b/backlinks/web.go new file mode 100644 index 0000000..278b936 --- /dev/null +++ b/backlinks/web.go @@ -0,0 +1,62 @@ +package backlinks + +import ( + "embed" + "github.com/bouncepaw/mycorrhiza/cfg" + "github.com/bouncepaw/mycorrhiza/util" + "github.com/bouncepaw/mycorrhiza/viewutil" + "github.com/gorilla/mux" + "log" + "net/http" + "text/template" +) + +func InitHandlers(rtr *mux.Router) { + rtr.PathPrefix("/backlinks/").HandlerFunc(handlerBacklinks) + chain = viewutil. + En(viewutil.CopyEnWith(fs, "view_backlinks.html")). + Ru(template.Must(viewutil.CopyRuWith(fs, "view_backlinks.html").Parse(ruTranslation))) +} + +// handlerBacklinks lists all backlinks to a hypha. +func handlerBacklinks(w http.ResponseWriter, rq *http.Request) { + var ( + hyphaName = util.HyphaNameFromRq(rq, "backlinks") + backlinks []string + ) + for b := range yieldHyphaBacklinks(hyphaName) { + backlinks = append(backlinks, b) + } + viewBacklinks(viewutil.MetaFrom(w, rq), hyphaName, backlinks) +} + +var ( + //go:embed *.html + fs embed.FS + ruTranslation = ` +{{define "backlinks to text"}}Обратные ссылки на {{.}}{{end}} +{{define "backlinks to link"}}Обратные ссылки на {{beautifulName .}}{{end}} +{{define "description"}}Ниже перечислены гифы, на которых есть ссылка на эту гифу, трансклюзия этой гифы или эта гифа вставлена как изображение.{{end}} +` + chain viewutil.Chain +) + +type backlinksData struct { + viewutil.BaseData + HyphaName string + Backlinks []string +} + +func viewBacklinks(meta viewutil.Meta, hyphaName string, backlinks []string) { + if err := chain.Get(meta).ExecuteTemplate(meta.W, "page", backlinksData{ + BaseData: viewutil.BaseData{ + Meta: meta, + HeaderLinks: cfg.HeaderLinks, + CommonScripts: cfg.CommonScripts, + }, + HyphaName: hyphaName, + Backlinks: backlinks, + }); err != nil { + log.Println(err) + } +} diff --git a/l18n/en/ui.json b/l18n/en/ui.json index 800bf0b..485429a 100644 --- a/l18n/en/ui.json +++ b/l18n/en/ui.json @@ -4,10 +4,6 @@ "title_search": "Search by title", "admin_panel": "Admin panel", - "backlinks_title": "Backlinks to {{.hypha_name}}", - "backlinks_heading": "Backlinks to {{.hypha_link}}", - "backlinks_desc": "Hyphae which have a link to this hypha, embed it as an image or transclude it are listed below.", - "edit_link": "Edit text", "logout_link": "Log out", "history_link": "View history", diff --git a/l18n/l18n.go b/l18n/l18n.go index da87f53..b557de0 100644 --- a/l18n/l18n.go +++ b/l18n/l18n.go @@ -118,7 +118,7 @@ func (t Localizer) GetWithLocale(locale, key string, replacements ...*Replacemen // If the str doesn't have any substitutions, no need to // template.Execute. - if strings.Contains(str, "}}") { + if !strings.Contains(str, "}}") { return str } @@ -145,7 +145,7 @@ func (t Localizer) GetPlural(key string, n int, replacements ...*Replacements) s // As in the original, we skip templating if have nothing to replace // (however, it's strange case for plurals) - if strings.Contains(str, "}}") { + if !strings.Contains(str, "}}") { return str } @@ -164,7 +164,7 @@ func (t Localizer) GetPlural64(key string, n int64, replacements ...*Replacement // As in the original, we skip templating if have nothing to replace // (however, it's strange case for plurals) - if strings.Contains(str, "}}") { + if !strings.Contains(str, "}}") { return str } diff --git a/main.go b/main.go index 3fec678..a67ac4c 100644 --- a/main.go +++ b/main.go @@ -5,14 +5,13 @@ package main import ( + "github.com/bouncepaw/mycorrhiza/backlinks" "github.com/bouncepaw/mycorrhiza/categories" "github.com/bouncepaw/mycorrhiza/migration" "github.com/bouncepaw/mycorrhiza/viewutil" "log" "os" - "github.com/bouncepaw/mycorrhiza/hyphae/backlinks" - "github.com/bouncepaw/mycorrhiza/cfg" "github.com/bouncepaw/mycorrhiza/files" "github.com/bouncepaw/mycorrhiza/history" diff --git a/misc/handlers.go b/misc/handlers.go index cdf81c1..f15a129 100644 --- a/misc/handlers.go +++ b/misc/handlers.go @@ -2,10 +2,10 @@ package misc import ( + "github.com/bouncepaw/mycorrhiza/backlinks" "github.com/bouncepaw/mycorrhiza/cfg" "github.com/bouncepaw/mycorrhiza/files" "github.com/bouncepaw/mycorrhiza/hyphae" - "github.com/bouncepaw/mycorrhiza/hyphae/backlinks" "github.com/bouncepaw/mycorrhiza/l18n" "github.com/bouncepaw/mycorrhiza/shroom" "github.com/bouncepaw/mycorrhiza/static" diff --git a/shroom/delete.go b/shroom/delete.go index 1227dcb..958262e 100644 --- a/shroom/delete.go +++ b/shroom/delete.go @@ -2,8 +2,7 @@ package shroom import ( "fmt" - "github.com/bouncepaw/mycorrhiza/hyphae/backlinks" - + "github.com/bouncepaw/mycorrhiza/backlinks" "github.com/bouncepaw/mycorrhiza/history" "github.com/bouncepaw/mycorrhiza/hyphae" "github.com/bouncepaw/mycorrhiza/user" diff --git a/shroom/rename.go b/shroom/rename.go index b232b63..71b4e9c 100644 --- a/shroom/rename.go +++ b/shroom/rename.go @@ -3,7 +3,7 @@ package shroom import ( "errors" "fmt" - "github.com/bouncepaw/mycorrhiza/hyphae/backlinks" + "github.com/bouncepaw/mycorrhiza/backlinks" "regexp" "github.com/bouncepaw/mycorrhiza/history" diff --git a/shroom/upload.go b/shroom/upload.go index df04d7c..54d34cf 100644 --- a/shroom/upload.go +++ b/shroom/upload.go @@ -4,10 +4,10 @@ import ( "bytes" "errors" "fmt" + "github.com/bouncepaw/mycorrhiza/backlinks" "github.com/bouncepaw/mycorrhiza/files" "github.com/bouncepaw/mycorrhiza/history" "github.com/bouncepaw/mycorrhiza/hyphae" - "github.com/bouncepaw/mycorrhiza/hyphae/backlinks" "github.com/bouncepaw/mycorrhiza/mimetype" "github.com/bouncepaw/mycorrhiza/user" "io" diff --git a/views/nav.qtpl b/views/nav.qtpl index 132beb3..58f94f4 100644 --- a/views/nav.qtpl +++ b/views/nav.qtpl @@ -1,6 +1,6 @@ {% import "strings" %} {% import "github.com/bouncepaw/mycorrhiza/cfg" %} -{% import "github.com/bouncepaw/mycorrhiza/hyphae/backlinks" %} +{% import "github.com/bouncepaw/mycorrhiza/backlinks" %} {% import "github.com/bouncepaw/mycorrhiza/l18n" %} {% import "github.com/bouncepaw/mycorrhiza/user" %} {% import "github.com/bouncepaw/mycorrhiza/hyphae" %} diff --git a/views/nav.qtpl.go b/views/nav.qtpl.go index 3965210..83cc255 100644 --- a/views/nav.qtpl.go +++ b/views/nav.qtpl.go @@ -11,7 +11,7 @@ import "strings" import "github.com/bouncepaw/mycorrhiza/cfg" //line views/nav.qtpl:3 -import "github.com/bouncepaw/mycorrhiza/hyphae/backlinks" +import "github.com/bouncepaw/mycorrhiza/backlinks" //line views/nav.qtpl:4 import "github.com/bouncepaw/mycorrhiza/l18n" diff --git a/views/stuff.qtpl b/views/stuff.qtpl index 99a28db..980c9bd 100644 --- a/views/stuff.qtpl +++ b/views/stuff.qtpl @@ -1,34 +1,6 @@ -{% import "fmt" %} - {% import "github.com/bouncepaw/mycorrhiza/cfg" %} -{% import "github.com/bouncepaw/mycorrhiza/util" %} {% import "github.com/bouncepaw/mycorrhiza/l18n" %} -{% func Backlinks(hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) %} -
      -
      -

      {%s= lc.Get( - "ui.backlinks_heading", - &l18n.Replacements{ - "hypha_link": fmt.Sprintf( - `%s`, - hyphaName, - util.BeautifulName(hyphaName), - ), - }, - )%}

      -

      {%s lc.Get("ui.backlinks_desc")%}

      - -
      -
      -{% endfunc %} - {% func Help(content, lang string, lc *l18n.Localizer) %}
      diff --git a/views/stuff.qtpl.go b/views/stuff.qtpl.go index 5abfcf6..0298658 100644 --- a/views/stuff.qtpl.go +++ b/views/stuff.qtpl.go @@ -5,262 +5,176 @@ package views //line views/stuff.qtpl:1 -import "fmt" - -//line views/stuff.qtpl:3 import "github.com/bouncepaw/mycorrhiza/cfg" -//line views/stuff.qtpl:4 -import "github.com/bouncepaw/mycorrhiza/util" - -//line views/stuff.qtpl:5 +//line views/stuff.qtpl:2 import "github.com/bouncepaw/mycorrhiza/l18n" -//line views/stuff.qtpl:7 +//line views/stuff.qtpl:4 import ( qtio422016 "io" qt422016 "github.com/valyala/quicktemplate" ) -//line views/stuff.qtpl:7 +//line views/stuff.qtpl:4 var ( _ = qtio422016.Copy _ = qt422016.AcquireByteBuffer ) -//line views/stuff.qtpl:7 -func StreamBacklinks(qw422016 *qt422016.Writer, hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) { -//line views/stuff.qtpl:7 - qw422016.N().S(` -
      -
      -

      `) -//line views/stuff.qtpl:10 - qw422016.N().S(lc.Get( - "ui.backlinks_heading", - &l18n.Replacements{ - "hypha_link": fmt.Sprintf( - `%s`, - hyphaName, - util.BeautifulName(hyphaName), - ), - }, - )) -//line views/stuff.qtpl:19 - qw422016.N().S(`

      -

      `) -//line views/stuff.qtpl:20 - qw422016.E().S(lc.Get("ui.backlinks_desc")) -//line views/stuff.qtpl:20 - qw422016.N().S(`

      - -
      -
      -`) -//line views/stuff.qtpl:30 -} - -//line views/stuff.qtpl:30 -func WriteBacklinks(qq422016 qtio422016.Writer, hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) { -//line views/stuff.qtpl:30 - qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:30 - StreamBacklinks(qw422016, hyphaName, generator, lc) -//line views/stuff.qtpl:30 - qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:30 -} - -//line views/stuff.qtpl:30 -func Backlinks(hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) string { -//line views/stuff.qtpl:30 - qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:30 - WriteBacklinks(qb422016, hyphaName, generator, lc) -//line views/stuff.qtpl:30 - qs422016 := string(qb422016.B) -//line views/stuff.qtpl:30 - qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:30 - return qs422016 -//line views/stuff.qtpl:30 -} - -//line views/stuff.qtpl:32 +//line views/stuff.qtpl:4 func StreamHelp(qw422016 *qt422016.Writer, content, lang string, lc *l18n.Localizer) { -//line views/stuff.qtpl:32 +//line views/stuff.qtpl:4 qw422016.N().S(`
      `) -//line views/stuff.qtpl:36 +//line views/stuff.qtpl:8 qw422016.N().S(content) -//line views/stuff.qtpl:36 +//line views/stuff.qtpl:8 qw422016.N().S(`
      `) -//line views/stuff.qtpl:39 +//line views/stuff.qtpl:11 qw422016.N().S(helpTopics(lang, lc)) -//line views/stuff.qtpl:39 +//line views/stuff.qtpl:11 qw422016.N().S(`
      `) -//line views/stuff.qtpl:41 +//line views/stuff.qtpl:13 } -//line views/stuff.qtpl:41 +//line views/stuff.qtpl:13 func WriteHelp(qq422016 qtio422016.Writer, content, lang string, lc *l18n.Localizer) { -//line views/stuff.qtpl:41 +//line views/stuff.qtpl:13 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:41 +//line views/stuff.qtpl:13 StreamHelp(qw422016, content, lang, lc) -//line views/stuff.qtpl:41 +//line views/stuff.qtpl:13 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:41 +//line views/stuff.qtpl:13 } -//line views/stuff.qtpl:41 +//line views/stuff.qtpl:13 func Help(content, lang string, lc *l18n.Localizer) string { -//line views/stuff.qtpl:41 +//line views/stuff.qtpl:13 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:41 +//line views/stuff.qtpl:13 WriteHelp(qb422016, content, lang, lc) -//line views/stuff.qtpl:41 +//line views/stuff.qtpl:13 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:41 +//line views/stuff.qtpl:13 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:41 +//line views/stuff.qtpl:13 return qs422016 -//line views/stuff.qtpl:41 +//line views/stuff.qtpl:13 } -//line views/stuff.qtpl:43 +//line views/stuff.qtpl:15 func StreamHelpEmptyError(qw422016 *qt422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:43 +//line views/stuff.qtpl:15 qw422016.N().S(`

      `) -//line views/stuff.qtpl:44 +//line views/stuff.qtpl:16 qw422016.E().S(lc.Get("help.empty_error_title")) -//line views/stuff.qtpl:44 +//line views/stuff.qtpl:16 qw422016.N().S(`

      `) -//line views/stuff.qtpl:45 +//line views/stuff.qtpl:17 qw422016.E().S(lc.Get("help.empty_error_line_1")) -//line views/stuff.qtpl:45 +//line views/stuff.qtpl:17 qw422016.N().S(`

      `) -//line views/stuff.qtpl:46 +//line views/stuff.qtpl:18 qw422016.E().S(lc.Get("help.empty_error_line_2a")) -//line views/stuff.qtpl:46 +//line views/stuff.qtpl:18 qw422016.N().S(` `) -//line views/stuff.qtpl:46 +//line views/stuff.qtpl:18 qw422016.E().S(lc.Get("help.empty_error_link")) -//line views/stuff.qtpl:46 +//line views/stuff.qtpl:18 qw422016.N().S(` `) -//line views/stuff.qtpl:46 +//line views/stuff.qtpl:18 qw422016.E().S(lc.Get("help.empty_error_line_2b")) -//line views/stuff.qtpl:46 +//line views/stuff.qtpl:18 qw422016.N().S(`

      `) -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:19 } -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:19 func WriteHelpEmptyError(qq422016 qtio422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:19 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:19 StreamHelpEmptyError(qw422016, lc) -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:19 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:19 } -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:19 func HelpEmptyError(lc *l18n.Localizer) string { -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:19 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:19 WriteHelpEmptyError(qb422016, lc) -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:19 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:19 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:19 return qs422016 -//line views/stuff.qtpl:47 +//line views/stuff.qtpl:19 } -//line views/stuff.qtpl:49 +//line views/stuff.qtpl:21 func streamcommonScripts(qw422016 *qt422016.Writer) { -//line views/stuff.qtpl:49 +//line views/stuff.qtpl:21 qw422016.N().S(` `) -//line views/stuff.qtpl:50 +//line views/stuff.qtpl:22 for _, scriptPath := range cfg.CommonScripts { -//line views/stuff.qtpl:50 +//line views/stuff.qtpl:22 qw422016.N().S(` `) -//line views/stuff.qtpl:52 +//line views/stuff.qtpl:24 } -//line views/stuff.qtpl:52 +//line views/stuff.qtpl:24 qw422016.N().S(` `) -//line views/stuff.qtpl:53 +//line views/stuff.qtpl:25 } -//line views/stuff.qtpl:53 +//line views/stuff.qtpl:25 func writecommonScripts(qq422016 qtio422016.Writer) { -//line views/stuff.qtpl:53 +//line views/stuff.qtpl:25 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:53 +//line views/stuff.qtpl:25 streamcommonScripts(qw422016) -//line views/stuff.qtpl:53 +//line views/stuff.qtpl:25 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:53 +//line views/stuff.qtpl:25 } -//line views/stuff.qtpl:53 +//line views/stuff.qtpl:25 func commonScripts() string { -//line views/stuff.qtpl:53 +//line views/stuff.qtpl:25 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:53 +//line views/stuff.qtpl:25 writecommonScripts(qb422016) -//line views/stuff.qtpl:53 +//line views/stuff.qtpl:25 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:53 +//line views/stuff.qtpl:25 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:53 +//line views/stuff.qtpl:25 return qs422016 -//line views/stuff.qtpl:53 +//line views/stuff.qtpl:25 } diff --git a/web/backlinks.go b/web/backlinks.go deleted file mode 100644 index 1bb10d7..0000000 --- a/web/backlinks.go +++ /dev/null @@ -1,30 +0,0 @@ -package web - -import ( - "github.com/bouncepaw/mycorrhiza/hyphae/backlinks" - "github.com/bouncepaw/mycorrhiza/viewutil" - "net/http" - - "github.com/gorilla/mux" - - "github.com/bouncepaw/mycorrhiza/l18n" - "github.com/bouncepaw/mycorrhiza/util" - "github.com/bouncepaw/mycorrhiza/views" -) - -func initBacklinks(r *mux.Router) { - r.PathPrefix("/backlinks/").HandlerFunc(handlerBacklinks) -} - -// handlerBacklinks lists all backlinks to a hypha. -func handlerBacklinks(w http.ResponseWriter, rq *http.Request) { - var ( - hyphaName = util.HyphaNameFromRq(rq, "backlinks") - lc = l18n.FromRequest(rq) - ) - util.HTTP200Page(w, views.Base( - viewutil.MetaFrom(w, rq), - lc.Get("ui.backlinks_title", &l18n.Replacements{"query": util.BeautifulName(hyphaName)}), - views.Backlinks(hyphaName, backlinks.YieldHyphaBacklinks, lc), - )) -} diff --git a/web/web.go b/web/web.go index 9801a17..845a037 100644 --- a/web/web.go +++ b/web/web.go @@ -2,6 +2,7 @@ package web import ( + "github.com/bouncepaw/mycorrhiza/backlinks" "github.com/bouncepaw/mycorrhiza/categories" "github.com/bouncepaw/mycorrhiza/misc" "io" @@ -47,7 +48,7 @@ func Handler() http.Handler { initMutators(wikiRouter) initHistory(wikiRouter) initHelp(wikiRouter) - initBacklinks(wikiRouter) + backlinks.InitHandlers(wikiRouter) categories.InitHandlers(wikiRouter) misc.InitHandlers(wikiRouter) From 17e006322f195aef80158decf11348ae12351409 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Thu, 7 Apr 2022 20:17:59 +0300 Subject: [PATCH 19/23] Mycomarkup: Migrate to v4 --- backlinks/hooks.go | 11 +++++---- cfg/header_links.go | 10 ++++---- go.mod | 4 ++-- go.sum | 6 +++-- migration/rockets.go | 2 +- shroom/mycomarkup_options.go | 46 ++++++++++++++++++++++++++++++++++++ shroom/shroom.go | 38 ----------------------------- util/util.go | 2 +- web/help.go | 7 +++--- web/mutators.go | 6 ++--- web/readers.go | 13 +++++----- 11 files changed, 78 insertions(+), 67 deletions(-) create mode 100644 shroom/mycomarkup_options.go diff --git a/backlinks/hooks.go b/backlinks/hooks.go index 9cc5237..1ad7ebe 100644 --- a/backlinks/hooks.go +++ b/backlinks/hooks.go @@ -1,10 +1,11 @@ package backlinks import ( - "github.com/bouncepaw/mycomarkup/v3" - "github.com/bouncepaw/mycomarkup/v3/links" - "github.com/bouncepaw/mycomarkup/v3/mycocontext" - "github.com/bouncepaw/mycomarkup/v3/tools" + "github.com/bouncepaw/mycomarkup/v4" + "github.com/bouncepaw/mycomarkup/v4/links" + "github.com/bouncepaw/mycomarkup/v4/mycocontext" + "github.com/bouncepaw/mycomarkup/v4/options" + "github.com/bouncepaw/mycomarkup/v4/tools" "github.com/bouncepaw/mycorrhiza/hyphae" ) @@ -34,7 +35,7 @@ func extractHyphaLinks(h hyphae.Hypha) []string { // extractHyphaLinksFromContent extracts local hypha links from the provided text. func extractHyphaLinksFromContent(hyphaName string, contents string) []string { - ctx, _ := mycocontext.ContextFromStringInput(hyphaName, contents) + ctx, _ := mycocontext.ContextFromStringInput(contents, options.Options{HyphaName: hyphaName}.FillTheRest()) linkVisitor, getLinks := tools.LinkVisitor(ctx) // Ignore the result of BlockTree because we call it for linkVisitor. _ = mycomarkup.BlockTree(ctx, linkVisitor) diff --git a/cfg/header_links.go b/cfg/header_links.go index 3d284aa..fcb51c8 100644 --- a/cfg/header_links.go +++ b/cfg/header_links.go @@ -1,10 +1,10 @@ package cfg -// See https://mycorrhiza.wiki/hypha/configuration/header import ( - "github.com/bouncepaw/mycomarkup/v3" - "github.com/bouncepaw/mycomarkup/v3/blocks" - "github.com/bouncepaw/mycomarkup/v3/mycocontext" + "github.com/bouncepaw/mycomarkup/v4" + "github.com/bouncepaw/mycomarkup/v4/blocks" + "github.com/bouncepaw/mycomarkup/v4/mycocontext" + "github.com/bouncepaw/mycomarkup/v4/options" ) // 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. @@ -24,7 +24,7 @@ func SetDefaultHeaderLinks() { // ParseHeaderLinks extracts all rocketlinks from the given text and saves them as header links. func ParseHeaderLinks(text string) { HeaderLinks = []HeaderLink{} - ctx, _ := mycocontext.ContextFromStringInput("", text) + ctx, _ := mycocontext.ContextFromStringInput(text, options.Options{}.FillTheRest()) // We call for side-effects _ = mycomarkup.BlockTree(ctx, func(block blocks.Block) { switch launchpad := block.(type) { diff --git a/go.mod b/go.mod index f58fb3c..6f52df7 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/bouncepaw/mycorrhiza go 1.18 require ( - github.com/bouncepaw/mycomarkup/v3 v3.6.2 + github.com/bouncepaw/mycomarkup/v4 v4.0.0 github.com/go-ini/ini v1.63.2 github.com/gorilla/feeds v1.1.1 github.com/gorilla/mux v1.8.0 @@ -22,7 +22,7 @@ require ( // Use this trick to test local Mycomarkup changes, replace the path with yours, // but do not commit the change to the path: -// replace github.com/bouncepaw/mycomarkup/v3 v3.6.2 => "/Users/bouncepaw/GolandProjects/mycomarkup" +// replace github.com/bouncepaw/mycomarkup/v4 v4.0.0 => "/Users/bouncepaw/GolandProjects/mycomarkup" // Use this utility every time Mycomarkup gets a major update: // https://github.com/marwan-at-work/mod diff --git a/go.sum b/go.sum index 0103904..bd53870 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,9 @@ github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= -github.com/bouncepaw/mycomarkup/v3 v3.6.2 h1:5zqb12aOw19xg8/0QIvgoA8oEW2doSdWqCbXltPEaPQ= -github.com/bouncepaw/mycomarkup/v3 v3.6.2/go.mod h1:BpiGUVsYCgRZCDxF0iIdc08LJokm/Ab36S/Hif0J6D0= +github.com/bouncepaw/mycomarkup/v4 v3.6.2 h1:5zqb12aOw19xg8/0QIvgoA8oEW2doSdWqCbXltPEaPQ= +github.com/bouncepaw/mycomarkup/v4 v3.6.2/go.mod h1:BpiGUVsYCgRZCDxF0iIdc08LJokm/Ab36S/Hif0J6D0= +github.com/bouncepaw/mycomarkup/v4 v4.0.0 h1:qokseZ+otcFuQ5vARdvxKqjlEZFMvsjFJ7YpJ4sUr8c= +github.com/bouncepaw/mycomarkup/v4 v4.0.0/go.mod h1:y0b8U6Xfnh3KfNUpG3QuAXRJwqFPPpmS2kYvLzaf688= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-ini/ini v1.63.2 h1:kwN3umicd2HF3Tgvap4um1ZG52/WyKT9GGdPx0CJk6Y= diff --git a/migration/rockets.go b/migration/rockets.go index f68ce97..3895aec 100644 --- a/migration/rockets.go +++ b/migration/rockets.go @@ -4,7 +4,7 @@ package migration import ( - "github.com/bouncepaw/mycomarkup/v3/tools" + "github.com/bouncepaw/mycomarkup/v4/tools" "io" "io/ioutil" "log" diff --git a/shroom/mycomarkup_options.go b/shroom/mycomarkup_options.go new file mode 100644 index 0000000..05595e0 --- /dev/null +++ b/shroom/mycomarkup_options.go @@ -0,0 +1,46 @@ +package shroom + +import ( + "errors" + "github.com/bouncepaw/mycomarkup/v4/options" + "github.com/bouncepaw/mycorrhiza/cfg" + "github.com/bouncepaw/mycorrhiza/hyphae" + "github.com/bouncepaw/mycorrhiza/views" +) + +func MarkupOptions(hyphaName string) options.Options { + return fillMycomarkupOptions(options.Options{ + HyphaName: hyphaName, + WebSiteURL: cfg.URL, + TransclusionSupported: true, + }) +} + +func fillMycomarkupOptions(opts options.Options) options.Options { + opts.HyphaExists = func(hyphaName string) bool { + switch hyphae.ByName(hyphaName).(type) { + case *hyphae.EmptyHypha: + return false + default: + return true + } + } + opts.HyphaHTMLData = func(hyphaName string) (rawText, binaryBlock string, err error) { + switch h := hyphae.ByName(hyphaName).(type) { + case *hyphae.EmptyHypha: + err = errors.New("Hypha " + hyphaName + " does not exist") + case *hyphae.TextualHypha: + rawText, err = FetchTextFile(h) + case *hyphae.MediaHypha: + rawText, err = FetchTextFile(h) + binaryBlock = views.MediaRaw(h) + } + return + } + opts.IterateHyphaNamesWith = func(λ func(string)) { + for h := range hyphae.YieldExistingHyphae() { + λ(h.CanonicalName()) + } + } + return opts.FillTheRest() +} diff --git a/shroom/shroom.go b/shroom/shroom.go index 6269694..469307c 100644 --- a/shroom/shroom.go +++ b/shroom/shroom.go @@ -2,41 +2,3 @@ // // Some of them are wrappers around functions provided by package hyphae. They manage history for you. package shroom - -import ( - "errors" - - "github.com/bouncepaw/mycorrhiza/hyphae" - "github.com/bouncepaw/mycorrhiza/views" - - "github.com/bouncepaw/mycomarkup/v3/globals" -) - -func init() { - // TODO: clean this complete and utter mess - globals.HyphaExists = func(hyphaName string) bool { - switch hyphae.ByName(hyphaName).(type) { - case *hyphae.EmptyHypha: - return false - default: - return true - } - } - globals.HyphaAccess = func(hyphaName string) (rawText, binaryBlock string, err error) { - switch h := hyphae.ByName(hyphaName).(type) { - case *hyphae.EmptyHypha: - err = errors.New("Hypha " + hyphaName + " does not exist") - case *hyphae.TextualHypha: - rawText, err = FetchTextFile(h) - case *hyphae.MediaHypha: - rawText, err = FetchTextFile(h) - binaryBlock = views.MediaRaw(h) - } - return - } - globals.HyphaIterate = func(λ func(string)) { - for h := range hyphae.YieldExistingHyphae() { - λ(h.CanonicalName()) - } - } -} diff --git a/util/util.go b/util/util.go index 66fedd0..9af0361 100644 --- a/util/util.go +++ b/util/util.go @@ -8,7 +8,7 @@ import ( "net/http" "strings" - "github.com/bouncepaw/mycomarkup/v3/util" + "github.com/bouncepaw/mycomarkup/v4/util" "github.com/bouncepaw/mycorrhiza/cfg" ) diff --git a/web/help.go b/web/help.go index 8227b5b..11bccce 100644 --- a/web/help.go +++ b/web/help.go @@ -2,6 +2,8 @@ package web // stuff.go is used for meta stuff about the wiki or all hyphae at once. import ( + "github.com/bouncepaw/mycomarkup/v4" + "github.com/bouncepaw/mycorrhiza/shroom" "github.com/bouncepaw/mycorrhiza/viewutil" "io" "net/http" @@ -13,8 +15,7 @@ import ( "github.com/bouncepaw/mycorrhiza/l18n" "github.com/bouncepaw/mycorrhiza/views" - "github.com/bouncepaw/mycomarkup/v3" - "github.com/bouncepaw/mycomarkup/v3/mycocontext" + "github.com/bouncepaw/mycomarkup/v4/mycocontext" ) func initHelp(r *mux.Router) { @@ -64,7 +65,7 @@ func handlerHelp(w http.ResponseWriter, rq *http.Request) { } // TODO: change for the function that uses byte array when there is such function in mycomarkup. - ctx, _ := mycocontext.ContextFromStringInput(articlePath, string(content)) + ctx, _ := mycocontext.ContextFromStringInput(string(content), shroom.MarkupOptions(articlePath)) ast := mycomarkup.BlockTree(ctx) result := mycomarkup.BlocksToHTML(ctx, ast) w.WriteHeader(http.StatusOK) diff --git a/web/mutators.go b/web/mutators.go index 331464d..8c3ad02 100644 --- a/web/mutators.go +++ b/web/mutators.go @@ -2,12 +2,12 @@ package web import ( "fmt" + "github.com/bouncepaw/mycomarkup/v4" "github.com/bouncepaw/mycorrhiza/viewutil" "log" "net/http" - "github.com/bouncepaw/mycomarkup/v3" - "github.com/bouncepaw/mycomarkup/v3/mycocontext" + "github.com/bouncepaw/mycomarkup/v4/mycocontext" "github.com/gorilla/mux" @@ -208,7 +208,7 @@ func handlerUploadText(w http.ResponseWriter, rq *http.Request) { } if action == "Preview" { - ctx, _ := mycocontext.ContextFromStringInput(hyphaName, textData) + ctx, _ := mycocontext.ContextFromStringInput(textData, shroom.MarkupOptions(hyphaName)) util.HTTP200Page( w, diff --git a/web/readers.go b/web/readers.go index c5e1ba6..acccb33 100644 --- a/web/readers.go +++ b/web/readers.go @@ -3,6 +3,8 @@ package web import ( "encoding/hex" "fmt" + "github.com/bouncepaw/mycomarkup/v4" + "github.com/bouncepaw/mycorrhiza/shroom" "github.com/bouncepaw/mycorrhiza/viewutil" "io" "log" @@ -13,7 +15,6 @@ import ( "github.com/gorilla/mux" - "github.com/bouncepaw/mycorrhiza/cfg" "github.com/bouncepaw/mycorrhiza/history" "github.com/bouncepaw/mycorrhiza/hyphae" "github.com/bouncepaw/mycorrhiza/l18n" @@ -22,9 +23,8 @@ import ( "github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/views" - "github.com/bouncepaw/mycomarkup/v3" - "github.com/bouncepaw/mycomarkup/v3/mycocontext" - "github.com/bouncepaw/mycomarkup/v3/tools" + "github.com/bouncepaw/mycomarkup/v4/mycocontext" + "github.com/bouncepaw/mycomarkup/v4/tools" ) func initReaders(r *mux.Router) { @@ -140,7 +140,7 @@ func handlerRevision(w http.ResponseWriter, rq *http.Request) { var textContents, err = history.FileAtRevision(h.TextFilePath(), revHash) if err == nil { - ctx, _ := mycocontext.ContextFromStringInput(hyphaName, textContents) + ctx, _ := mycocontext.ContextFromStringInput(textContents, shroom.MarkupOptions(hyphaName)) contents = mycomarkup.BlocksToHTML(ctx, mycomarkup.BlockTree(ctx)) } } @@ -213,8 +213,7 @@ func handlerHypha(w http.ResponseWriter, rq *http.Request) { case hyphae.ExistingHypha: fileContentsT, errT := os.ReadFile(h.TextFilePath()) if errT == nil { - ctx, _ := mycocontext.ContextFromStringInput(hyphaName, string(fileContentsT)) - ctx = mycocontext.WithWebSiteURL(ctx, cfg.URL) + ctx, _ := mycocontext.ContextFromStringInput(string(fileContentsT), shroom.MarkupOptions(hyphaName)) getOpenGraph, descVisitor, imgVisitor := tools.OpenGraphVisitors(ctx) ast := mycomarkup.BlockTree(ctx, descVisitor, imgVisitor) contents = mycomarkup.BlocksToHTML(ctx, ast) From a15eeca1178822c77c8504bab292ed6afa4230d9 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 9 Apr 2022 11:28:57 +0300 Subject: [PATCH 20/23] Isolate help --- help/help.go | 2 +- help/view_help.html | 16 +++++ help/web.go | 96 +++++++++++++++++++++++++++ views/help.go | 2 +- views/stuff.qtpl | 18 ----- views/stuff.qtpl.go | 156 +++++++------------------------------------- web/help.go | 80 ----------------------- web/web.go | 3 +- 8 files changed, 139 insertions(+), 234 deletions(-) create mode 100644 help/view_help.html create mode 100644 help/web.go delete mode 100644 web/help.go diff --git a/help/help.go b/help/help.go index bc12477..057d3c1 100644 --- a/help/help.go +++ b/help/help.go @@ -5,7 +5,7 @@ import ( "embed" ) -//go:embed en en.myco +//go:embed en en.myco *.html var fs embed.FS // Get determines what help text you need and returns it. The path is a substring from URL, it follows this form: diff --git a/help/view_help.html b/help/view_help.html new file mode 100644 index 0000000..17f1d7f --- /dev/null +++ b/help/view_help.html @@ -0,0 +1,16 @@ +{{define "title"}}Help{{end}} +{{define "body"}} +
      +
      +
      + {{if .ContentsHTML}} + {{.ContentsHTML}} + {{else}} +

      {{block "entry not found" .}}Entry not found{{end}}

      +

      {{block "entry not found invitation" .}}If you want to write this entry by yourself, consider contributing it directly.{{end}}

      + {{end}} +
      +
      + {{.HelpTopicsHTML}} +
      +{{end}} diff --git a/help/web.go b/help/web.go new file mode 100644 index 0000000..8c904cd --- /dev/null +++ b/help/web.go @@ -0,0 +1,96 @@ +package help + +// stuff.go is used for meta stuff about the wiki or all hyphae at once. +import ( + "github.com/bouncepaw/mycomarkup/v4" + "github.com/bouncepaw/mycorrhiza/cfg" + "github.com/bouncepaw/mycorrhiza/shroom" + "github.com/bouncepaw/mycorrhiza/viewutil" + "io" + "log" + "net/http" + "strings" + "text/template" + + "github.com/gorilla/mux" + + "github.com/bouncepaw/mycorrhiza/views" + + "github.com/bouncepaw/mycomarkup/v4/mycocontext" +) + +var ( + chain viewutil.Chain + ruTranslation = ` +{{define "title"}}Справка{{end}} +{{define "entry not found"}}Статья не найдена{{end}} +{{define "entry not found invitation"}}Если вы хотите написать эту статью сами, то будем рады вашим правкам в репозитории Миокризы.{{end}} +` +) + +func InitHandlers(r *mux.Router) { + r.PathPrefix("/help").HandlerFunc(handlerHelp) + chain = viewutil. + En(viewutil.CopyEnWith(fs, "view_help.html")). + Ru(template.Must(viewutil.CopyRuWith(fs, "view_help.html").Parse(ruTranslation))) +} + +// handlerHelp gets the appropriate documentation or tells you where you (personally) have failed. +func handlerHelp(w http.ResponseWriter, rq *http.Request) { + // See the history of this file to resurrect the old algorithm that supported multiple languages + var ( + meta = viewutil.MetaFrom(w, rq) + articlePath = strings.TrimPrefix(strings.TrimPrefix(rq.URL.Path, "/help/"), "/help") + lang = "en" + ) + if articlePath == "" { + articlePath = "en" + } + + if !strings.HasPrefix(articlePath, "en") { + w.WriteHeader(http.StatusNotFound) + _, _ = io.WriteString(w, "404 Not found") + return + } + + content, err := Get(articlePath) + if err != nil && strings.HasPrefix(err.Error(), "open") { + w.WriteHeader(http.StatusNotFound) + viewHelp(meta, lang, "") + return + } + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + viewHelp(meta, lang, err.Error()) + return + } + + // TODO: change for the function that uses byte array when there is such function in mycomarkup. + ctx, _ := mycocontext.ContextFromStringInput(string(content), shroom.MarkupOptions(articlePath)) + ast := mycomarkup.BlockTree(ctx) + result := mycomarkup.BlocksToHTML(ctx, ast) + w.WriteHeader(http.StatusOK) + viewHelp(meta, lang, result) +} + +type helpData struct { + viewutil.BaseData + ContentsHTML string + HelpTopicsHTML string + Lang string +} + +func viewHelp(meta viewutil.Meta, lang, contentsHTML string) { + if err := chain.Get(meta).ExecuteTemplate(meta.W, "page", helpData{ + BaseData: viewutil.BaseData{ + Meta: meta, + HeaderLinks: cfg.HeaderLinks, + CommonScripts: cfg.CommonScripts, + }, + ContentsHTML: contentsHTML, + HelpTopicsHTML: views.HelpTopics(lang, meta.Lc), + Lang: lang, + }); err != nil { + log.Println(err) + } +} diff --git a/views/help.go b/views/help.go index e637c88..41de7b7 100644 --- a/views/help.go +++ b/views/help.go @@ -81,7 +81,7 @@ func helpTopicsLocalizedTopic(lang string) func(string) string { } } -func helpTopics(lang string, lc *l18n.Localizer) string { +func HelpTopics(lang string, lc *l18n.Localizer) string { temp, err := template. New("help topics"). Funcs(template.FuncMap{ diff --git a/views/stuff.qtpl b/views/stuff.qtpl index 980c9bd..acb68a5 100644 --- a/views/stuff.qtpl +++ b/views/stuff.qtpl @@ -1,22 +1,4 @@ {% import "github.com/bouncepaw/mycorrhiza/cfg" %} -{% import "github.com/bouncepaw/mycorrhiza/l18n" %} - -{% func Help(content, lang string, lc *l18n.Localizer) %} -
      -
      -
      - {%s= content %} -
      -
      -{%s= helpTopics(lang, lc) %} -
      -{% endfunc %} - -{% func HelpEmptyError(lc *l18n.Localizer) %} -

      {%s lc.Get("help.empty_error_title") %}

      -

      {%s lc.Get("help.empty_error_line_1") %}

      -

      {%s lc.Get("help.empty_error_line_2a") %} {%s lc.Get("help.empty_error_link") %} {%s lc.Get("help.empty_error_line_2b") %}

      -{% endfunc %} {% func commonScripts() %} {% for _, scriptPath := range cfg.CommonScripts %} diff --git a/views/stuff.qtpl.go b/views/stuff.qtpl.go index 0298658..c0b4e29 100644 --- a/views/stuff.qtpl.go +++ b/views/stuff.qtpl.go @@ -7,174 +7,64 @@ package views //line views/stuff.qtpl:1 import "github.com/bouncepaw/mycorrhiza/cfg" -//line views/stuff.qtpl:2 -import "github.com/bouncepaw/mycorrhiza/l18n" - -//line views/stuff.qtpl:4 +//line views/stuff.qtpl:3 import ( qtio422016 "io" qt422016 "github.com/valyala/quicktemplate" ) -//line views/stuff.qtpl:4 +//line views/stuff.qtpl:3 var ( _ = qtio422016.Copy _ = qt422016.AcquireByteBuffer ) -//line views/stuff.qtpl:4 -func StreamHelp(qw422016 *qt422016.Writer, content, lang string, lc *l18n.Localizer) { -//line views/stuff.qtpl:4 - qw422016.N().S(` -
      -
      -
      - `) -//line views/stuff.qtpl:8 - qw422016.N().S(content) -//line views/stuff.qtpl:8 - qw422016.N().S(` -
      -
      -`) -//line views/stuff.qtpl:11 - qw422016.N().S(helpTopics(lang, lc)) -//line views/stuff.qtpl:11 - qw422016.N().S(` -
      -`) -//line views/stuff.qtpl:13 -} - -//line views/stuff.qtpl:13 -func WriteHelp(qq422016 qtio422016.Writer, content, lang string, lc *l18n.Localizer) { -//line views/stuff.qtpl:13 - qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:13 - StreamHelp(qw422016, content, lang, lc) -//line views/stuff.qtpl:13 - qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:13 -} - -//line views/stuff.qtpl:13 -func Help(content, lang string, lc *l18n.Localizer) string { -//line views/stuff.qtpl:13 - qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:13 - WriteHelp(qb422016, content, lang, lc) -//line views/stuff.qtpl:13 - qs422016 := string(qb422016.B) -//line views/stuff.qtpl:13 - qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:13 - return qs422016 -//line views/stuff.qtpl:13 -} - -//line views/stuff.qtpl:15 -func StreamHelpEmptyError(qw422016 *qt422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:15 - qw422016.N().S(` -

      `) -//line views/stuff.qtpl:16 - qw422016.E().S(lc.Get("help.empty_error_title")) -//line views/stuff.qtpl:16 - qw422016.N().S(`

      -

      `) -//line views/stuff.qtpl:17 - qw422016.E().S(lc.Get("help.empty_error_line_1")) -//line views/stuff.qtpl:17 - qw422016.N().S(`

      -

      `) -//line views/stuff.qtpl:18 - qw422016.E().S(lc.Get("help.empty_error_line_2a")) -//line views/stuff.qtpl:18 - qw422016.N().S(` `) -//line views/stuff.qtpl:18 - qw422016.E().S(lc.Get("help.empty_error_link")) -//line views/stuff.qtpl:18 - qw422016.N().S(` `) -//line views/stuff.qtpl:18 - qw422016.E().S(lc.Get("help.empty_error_line_2b")) -//line views/stuff.qtpl:18 - qw422016.N().S(`

      -`) -//line views/stuff.qtpl:19 -} - -//line views/stuff.qtpl:19 -func WriteHelpEmptyError(qq422016 qtio422016.Writer, lc *l18n.Localizer) { -//line views/stuff.qtpl:19 - qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:19 - StreamHelpEmptyError(qw422016, lc) -//line views/stuff.qtpl:19 - qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:19 -} - -//line views/stuff.qtpl:19 -func HelpEmptyError(lc *l18n.Localizer) string { -//line views/stuff.qtpl:19 - qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:19 - WriteHelpEmptyError(qb422016, lc) -//line views/stuff.qtpl:19 - qs422016 := string(qb422016.B) -//line views/stuff.qtpl:19 - qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:19 - return qs422016 -//line views/stuff.qtpl:19 -} - -//line views/stuff.qtpl:21 +//line views/stuff.qtpl:3 func streamcommonScripts(qw422016 *qt422016.Writer) { -//line views/stuff.qtpl:21 +//line views/stuff.qtpl:3 qw422016.N().S(` `) -//line views/stuff.qtpl:22 +//line views/stuff.qtpl:4 for _, scriptPath := range cfg.CommonScripts { -//line views/stuff.qtpl:22 +//line views/stuff.qtpl:4 qw422016.N().S(` `) -//line views/stuff.qtpl:24 +//line views/stuff.qtpl:6 } -//line views/stuff.qtpl:24 +//line views/stuff.qtpl:6 qw422016.N().S(` `) -//line views/stuff.qtpl:25 +//line views/stuff.qtpl:7 } -//line views/stuff.qtpl:25 +//line views/stuff.qtpl:7 func writecommonScripts(qq422016 qtio422016.Writer) { -//line views/stuff.qtpl:25 +//line views/stuff.qtpl:7 qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:25 +//line views/stuff.qtpl:7 streamcommonScripts(qw422016) -//line views/stuff.qtpl:25 +//line views/stuff.qtpl:7 qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:25 +//line views/stuff.qtpl:7 } -//line views/stuff.qtpl:25 +//line views/stuff.qtpl:7 func commonScripts() string { -//line views/stuff.qtpl:25 +//line views/stuff.qtpl:7 qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:25 +//line views/stuff.qtpl:7 writecommonScripts(qb422016) -//line views/stuff.qtpl:25 +//line views/stuff.qtpl:7 qs422016 := string(qb422016.B) -//line views/stuff.qtpl:25 +//line views/stuff.qtpl:7 qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:25 +//line views/stuff.qtpl:7 return qs422016 -//line views/stuff.qtpl:25 +//line views/stuff.qtpl:7 } diff --git a/web/help.go b/web/help.go deleted file mode 100644 index 11bccce..0000000 --- a/web/help.go +++ /dev/null @@ -1,80 +0,0 @@ -package web - -// stuff.go is used for meta stuff about the wiki or all hyphae at once. -import ( - "github.com/bouncepaw/mycomarkup/v4" - "github.com/bouncepaw/mycorrhiza/shroom" - "github.com/bouncepaw/mycorrhiza/viewutil" - "io" - "net/http" - "strings" - - "github.com/gorilla/mux" - - "github.com/bouncepaw/mycorrhiza/help" - "github.com/bouncepaw/mycorrhiza/l18n" - "github.com/bouncepaw/mycorrhiza/views" - - "github.com/bouncepaw/mycomarkup/v4/mycocontext" -) - -func initHelp(r *mux.Router) { - r.PathPrefix("/help").HandlerFunc(handlerHelp) -} - -// handlerHelp gets the appropriate documentation or tells you where you (personally) have failed. -func handlerHelp(w http.ResponseWriter, rq *http.Request) { - lc := l18n.FromRequest(rq) - articlePath := strings.TrimPrefix(strings.TrimPrefix(rq.URL.Path, "/help/"), "/help") - // See the history of this file to resurrect the old algorithm that supported multiple languages - lang := "en" - if articlePath == "" { - articlePath = "en" - } - - if !strings.HasPrefix(articlePath, "en") { - w.WriteHeader(http.StatusNotFound) - _, _ = io.WriteString(w, "404 Not found") - return - } - - content, err := help.Get(articlePath) - if err != nil && strings.HasPrefix(err.Error(), "open") { - w.WriteHeader(http.StatusNotFound) - _, _ = io.WriteString( - w, - views.Base( - viewutil.MetaFrom(w, rq), - lc.Get("help.entry_not_found"), - views.Help(views.HelpEmptyError(lc), lang, lc), - ), - ) - return - } - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - _, _ = io.WriteString( - w, - views.Base( - viewutil.MetaFrom(w, rq), - err.Error(), - views.Help(err.Error(), lang, lc), - ), - ) - return - } - - // TODO: change for the function that uses byte array when there is such function in mycomarkup. - ctx, _ := mycocontext.ContextFromStringInput(string(content), shroom.MarkupOptions(articlePath)) - ast := mycomarkup.BlockTree(ctx) - result := mycomarkup.BlocksToHTML(ctx, ast) - w.WriteHeader(http.StatusOK) - _, _ = io.WriteString( - w, - views.Base( - viewutil.MetaFrom(w, rq), - lc.Get("help.title"), - views.Help(result, lang, lc), - ), - ) -} diff --git a/web/web.go b/web/web.go index 845a037..2511e6b 100644 --- a/web/web.go +++ b/web/web.go @@ -4,6 +4,7 @@ package web import ( "github.com/bouncepaw/mycorrhiza/backlinks" "github.com/bouncepaw/mycorrhiza/categories" + "github.com/bouncepaw/mycorrhiza/help" "github.com/bouncepaw/mycorrhiza/misc" "io" "net/http" @@ -47,7 +48,7 @@ func Handler() http.Handler { initReaders(wikiRouter) initMutators(wikiRouter) initHistory(wikiRouter) - initHelp(wikiRouter) + help.InitHandlers(wikiRouter) backlinks.InitHandlers(wikiRouter) categories.InitHandlers(wikiRouter) misc.InitHandlers(wikiRouter) From 8702660484ea8a5ee9bea2dd356f86692a883176 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 9 Apr 2022 11:30:11 +0300 Subject: [PATCH 21/23] Help: Wording --- help/en/top_bar.myco | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/help/en/top_bar.myco b/help/en/top_bar.myco index 523f684..65214c0 100644 --- a/help/en/top_bar.myco +++ b/help/en/top_bar.myco @@ -15,6 +15,7 @@ On big screens, the top bar is spread onto two lines. ** All hyphae ** Random ** Help +** Categories On small screens, the authorization section and the most-used-links section are hidden behind a menu. Click the button to see them. If your browser does not support JavaScript, they are always shown. @@ -40,9 +41,11 @@ Reload the wiki. ---- -Edit the hypha. You can put any markup there. Rocket links will be used for generating the top bar: +Edit the hypha. You can put any markup there. Only rocket links will be used for generating the top bar: ```myco +This paragraph is unused. + => /recent-changes | Recent changes => Highlights => Philosophy | Our views on life From e2b570615ed9281593f392ae62090fa08ae2e4e3 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 9 Apr 2022 14:55:55 +0300 Subject: [PATCH 22/23] Help: Bring the topic sidebar closer --- help/view_help.html | 36 +++++++++++++++- help/web.go | 31 ++++++++++---- views/help.go | 101 -------------------------------------------- views/nav.qtpl | 6 +++ views/nav.qtpl.go | 49 +++++++++++++++++++++ views/stuff.qtpl | 7 --- views/stuff.qtpl.go | 70 ------------------------------ 7 files changed, 113 insertions(+), 187 deletions(-) delete mode 100644 views/help.go delete mode 100644 views/stuff.qtpl delete mode 100644 views/stuff.qtpl.go diff --git a/help/view_help.html b/help/view_help.html index 17f1d7f..ed426b7 100644 --- a/help/view_help.html +++ b/help/view_help.html @@ -11,6 +11,40 @@ {{end}}
      - {{.HelpTopicsHTML}} +
      {{end}} + diff --git a/help/web.go b/help/web.go index 8c904cd..a717435 100644 --- a/help/web.go +++ b/help/web.go @@ -14,8 +14,6 @@ import ( "github.com/gorilla/mux" - "github.com/bouncepaw/mycorrhiza/views" - "github.com/bouncepaw/mycomarkup/v4/mycocontext" ) @@ -25,6 +23,25 @@ var ( {{define "title"}}Справка{{end}} {{define "entry not found"}}Статья не найдена{{end}} {{define "entry not found invitation"}}Если вы хотите написать эту статью сами, то будем рады вашим правкам в репозитории Миокризы.{{end}} + +{{define "topics"}}Темы справки{{end}} +{{define "main"}}Введение{{end}} +{{define "hypha"}}Гифа{{end}} +{{define "media"}}Медиа{{end}} +{{define "mycomarkup"}}Микоразметка{{end}} +{{define "category"}}Категории{{end}} +{{define "interface"}}Интерфейс{{end}} +{{define "prevnext"}}Пред/след{{end}} +{{define "top_bar"}}Верхняя панель{{end}} +{{define "sibling_hyphae"}}Гифы-сиблинги{{end}} +{{define "special pages"}}Специальные страницы{{end}} +{{define "recent_changes"}}Недавние изменения{{end}} +{{define "feeds"}}Ленты{{end}} +{{define "configuration"}}Конфигурация (для администраторов){{end}} +{{define "config_file"}}Файл конфигурации{{end}} +{{define "lock"}}Замок{{end}} +{{define "whitelist"}}Белый список{{end}} +{{define "telegram"}}Вход через Телеграм{{end}} ` ) @@ -75,9 +92,8 @@ func handlerHelp(w http.ResponseWriter, rq *http.Request) { type helpData struct { viewutil.BaseData - ContentsHTML string - HelpTopicsHTML string - Lang string + ContentsHTML string + Lang string } func viewHelp(meta viewutil.Meta, lang, contentsHTML string) { @@ -87,9 +103,8 @@ func viewHelp(meta viewutil.Meta, lang, contentsHTML string) { HeaderLinks: cfg.HeaderLinks, CommonScripts: cfg.CommonScripts, }, - ContentsHTML: contentsHTML, - HelpTopicsHTML: views.HelpTopics(lang, meta.Lc), - Lang: lang, + ContentsHTML: contentsHTML, + Lang: lang, }); err != nil { log.Println(err) } diff --git a/views/help.go b/views/help.go deleted file mode 100644 index 41de7b7..0000000 --- a/views/help.go +++ /dev/null @@ -1,101 +0,0 @@ -package views - -import ( - "fmt" - "github.com/bouncepaw/mycorrhiza/l18n" - "log" - "strings" - "text/template" -) - -var helpTopicsL10n = map[string][]string{ - "topics": {"Help topics", "Темы справки"}, - "main": {"Main", "Введение"}, - "hypha": {"Hypha", "Гифа"}, - "media": {"Media", "Медиа"}, - "mycomarkup": {"Mycomarkup", "Микоразметка"}, - "interface": {"Interface", "Интерфейс"}, - "prevnext": {"Previous/next", "Назад/далее"}, // пред след? - "top_bar": {"Top bar", "Верхняя панель"}, - "sibling_hyphae": {"Sibling hyphae", "Гифы-сиблинги"}, - "special_pages": {"Special pages", "Специальные страницы"}, - "recent_changes": {"Recent changes", "Недавние изменения"}, // так ли? В медиавики свежие правки - "feeds": {"Feeds", "Ленты"}, - "configuration": {"Configuration (for administrators)", "Конфигурация (для администраторов)"}, - "config_file": {"Configuration file", "Файл конфигурации"}, - "lock": {"Lock", "Блокировка"}, // Не Замок ли? - "whitelist": {"Whitelist", "Белый список"}, - "telegram": {"Telegram authentication", "Вход через Телеграм"}, - "category": {"Categories", "Категории"}, -} - -const helpTopicTemplate = `` - -// helpTopicsLinkWrapper wraps in -func helpTopicsLinkWrapper(lang string) func(string, string) string { - return func(path, contents string) string { - return fmt.Sprintf(`%s`, lang, path, contents) - } -} - -func helpTopicsLocalizedTopic(lang string) func(string) string { - pos := 0 - if lang == "ru" { - pos = 1 - } - return func(topic string) string { - return helpTopicsL10n[topic][pos] - } -} - -func HelpTopics(lang string, lc *l18n.Localizer) string { - temp, err := template. - New("help topics"). - Funcs(template.FuncMap{ - "a": helpTopicsLinkWrapper(lang), - "l": helpTopicsLocalizedTopic(lc.Locale), - }). - Parse(helpTopicTemplate) - if err != nil { - log.Println(err) - return "" - } - - // TODO: one day, it should write to a better place - var out strings.Builder - _ = temp.Execute(&out, nil) // Shall not fail! - return out.String() -} diff --git a/views/nav.qtpl b/views/nav.qtpl index 58f94f4..32353e8 100644 --- a/views/nav.qtpl +++ b/views/nav.qtpl @@ -53,3 +53,9 @@ {% endif %} {% endfunc %} + +{% func commonScripts() %} +{% for _, scriptPath := range cfg.CommonScripts %} + +{% endfor %} +{% endfunc %} diff --git a/views/nav.qtpl.go b/views/nav.qtpl.go index 83cc255..de41b2d 100644 --- a/views/nav.qtpl.go +++ b/views/nav.qtpl.go @@ -292,3 +292,52 @@ func Subhyphae(subhyphae string, lc *l18n.Localizer) string { return qs422016 //line views/nav.qtpl:55 } + +//line views/nav.qtpl:57 +func streamcommonScripts(qw422016 *qt422016.Writer) { +//line views/nav.qtpl:57 + qw422016.N().S(` +`) +//line views/nav.qtpl:58 + for _, scriptPath := range cfg.CommonScripts { +//line views/nav.qtpl:58 + qw422016.N().S(` + +`) +//line views/nav.qtpl:60 + } +//line views/nav.qtpl:60 + qw422016.N().S(` +`) +//line views/nav.qtpl:61 +} + +//line views/nav.qtpl:61 +func writecommonScripts(qq422016 qtio422016.Writer) { +//line views/nav.qtpl:61 + qw422016 := qt422016.AcquireWriter(qq422016) +//line views/nav.qtpl:61 + streamcommonScripts(qw422016) +//line views/nav.qtpl:61 + qt422016.ReleaseWriter(qw422016) +//line views/nav.qtpl:61 +} + +//line views/nav.qtpl:61 +func commonScripts() string { +//line views/nav.qtpl:61 + qb422016 := qt422016.AcquireByteBuffer() +//line views/nav.qtpl:61 + writecommonScripts(qb422016) +//line views/nav.qtpl:61 + qs422016 := string(qb422016.B) +//line views/nav.qtpl:61 + qt422016.ReleaseByteBuffer(qb422016) +//line views/nav.qtpl:61 + return qs422016 +//line views/nav.qtpl:61 +} diff --git a/views/stuff.qtpl b/views/stuff.qtpl deleted file mode 100644 index acb68a5..0000000 --- a/views/stuff.qtpl +++ /dev/null @@ -1,7 +0,0 @@ -{% import "github.com/bouncepaw/mycorrhiza/cfg" %} - -{% func commonScripts() %} -{% for _, scriptPath := range cfg.CommonScripts %} - -{% endfor %} -{% endfunc %} diff --git a/views/stuff.qtpl.go b/views/stuff.qtpl.go deleted file mode 100644 index c0b4e29..0000000 --- a/views/stuff.qtpl.go +++ /dev/null @@ -1,70 +0,0 @@ -// Code generated by qtc from "stuff.qtpl". DO NOT EDIT. -// See https://github.com/valyala/quicktemplate for details. - -//line views/stuff.qtpl:1 -package views - -//line views/stuff.qtpl:1 -import "github.com/bouncepaw/mycorrhiza/cfg" - -//line views/stuff.qtpl:3 -import ( - qtio422016 "io" - - qt422016 "github.com/valyala/quicktemplate" -) - -//line views/stuff.qtpl:3 -var ( - _ = qtio422016.Copy - _ = qt422016.AcquireByteBuffer -) - -//line views/stuff.qtpl:3 -func streamcommonScripts(qw422016 *qt422016.Writer) { -//line views/stuff.qtpl:3 - qw422016.N().S(` -`) -//line views/stuff.qtpl:4 - for _, scriptPath := range cfg.CommonScripts { -//line views/stuff.qtpl:4 - qw422016.N().S(` - -`) -//line views/stuff.qtpl:6 - } -//line views/stuff.qtpl:6 - qw422016.N().S(` -`) -//line views/stuff.qtpl:7 -} - -//line views/stuff.qtpl:7 -func writecommonScripts(qq422016 qtio422016.Writer) { -//line views/stuff.qtpl:7 - qw422016 := qt422016.AcquireWriter(qq422016) -//line views/stuff.qtpl:7 - streamcommonScripts(qw422016) -//line views/stuff.qtpl:7 - qt422016.ReleaseWriter(qw422016) -//line views/stuff.qtpl:7 -} - -//line views/stuff.qtpl:7 -func commonScripts() string { -//line views/stuff.qtpl:7 - qb422016 := qt422016.AcquireByteBuffer() -//line views/stuff.qtpl:7 - writecommonScripts(qb422016) -//line views/stuff.qtpl:7 - qs422016 := string(qb422016.B) -//line views/stuff.qtpl:7 - qt422016.ReleaseByteBuffer(qb422016) -//line views/stuff.qtpl:7 - return qs422016 -//line views/stuff.qtpl:7 -} From a11c69027dfa99ad3a7231e745e9f0e2e05f2222 Mon Sep 17 00:00:00 2001 From: Timur Ismagilov Date: Sat, 9 Apr 2022 15:01:03 +0300 Subject: [PATCH 23/23] About: Wording --- views/about.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/views/about.go b/views/about.go index e5c2793..7aa29ce 100644 --- a/views/about.go +++ b/views/about.go @@ -47,7 +47,7 @@ const aboutTemplateString = `
    • {{ get .L.Version }} 1.9.0
    • {{ if .Cfg.UseAuth }}
    • {{ get .L.UserCount }} {{ .UserCount }}
    • -
    • {{ get .L.HomePage }} {{ .Cfg.HomeHypha }}
    • +
    • {{ get .L.HomeHypha }} {{ .Cfg.HomeHypha }}
    • {{ get .L.Admins }} {{$cfg := .Cfg}}{{ range $i, $username := .Admins }} {{ if gt $i 0 }}{{ end }} {{ $username }} @@ -71,7 +71,7 @@ var aboutData = struct { "Title": e().en("About %s").ru("О %s"), "Version": e().en("Mycorrhiza Wiki version:").ru("Версия Микоризы:"), "UserCount": e().en("User count:").ru("Число пользователей:"), - "HomePage": e().en("Home page:").ru("Домашняя гифа:"), + "HomeHypha": e().en("Home hypha:").ru("Домашняя гифа:"), "Admins": e().en("Administrators:").ru("Администраторы:"), "NoAuth": e().en("This wiki does not use authorization").ru("На этой вики не используется авторизация"), "AboutHyphae": e().en("See /list for information about hyphae on this wiki.").ru("См. /list, чтобы узнать о гифах в этой вики."),