From 05c12e8452eae1be101ac23b688ebf73173fece7 Mon Sep 17 00:00:00 2001 From: bouncepaw Date: Sun, 29 Nov 2020 16:32:52 +0500 Subject: [PATCH] Show prev/next links --- README.md | 2 +- http_readers.go | 6 +- templates/asset.qtpl | 3 + templates/{css.qtpl.go => asset.qtpl.go} | 53 +++--- templates/{css.qtpl => default.css} | 10 +- templates/http_readers.qtpl | 13 +- templates/http_readers.qtpl.go | 217 ++++++++++++++--------- tree/tree.go | 20 ++- 8 files changed, 205 insertions(+), 119 deletions(-) create mode 100644 templates/asset.qtpl rename templates/{css.qtpl.go => asset.qtpl.go} (75%) rename templates/{css.qtpl => default.css} (88%) diff --git a/README.md b/README.md index 82876c6..784c616 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 🍄 MycorrhizaWiki 0.11 +# 🍄 MycorrhizaWiki 0.12 A wiki engine. ## Building diff --git a/http_readers.go b/http_readers.go index b8887e9..759f05d 100644 --- a/http_readers.go +++ b/http_readers.go @@ -39,12 +39,13 @@ func handlerRevision(w http.ResponseWriter, rq *http.Request) { if err == nil { contents = markup.ToHtml(hyphaName, textContents) } + treeHTML, _, _ := tree.Tree(hyphaName, IterateHyphaNamesWith) page := templates.RevisionHTML( rq, hyphaName, naviTitle(hyphaName), contents, - tree.TreeAsHtml(hyphaName, IterateHyphaNamesWith), + treeHTML, revHash, ) w.Header().Set("Content-Type", "text/html;charset=utf-8") @@ -111,8 +112,9 @@ func handlerPage(w http.ResponseWriter, rq *http.Request) { contents = binaryHtmlBlock(hyphaName, data) + contents } } + treeHTML, prevHypha, nextHypha := tree.Tree(hyphaName, IterateHyphaNamesWith) util.HTTP200Page(w, base(hyphaName, templates.PageHTML(rq, hyphaName, naviTitle(hyphaName), contents, - tree.TreeAsHtml(hyphaName, IterateHyphaNamesWith)))) + treeHTML, prevHypha, nextHypha))) } diff --git a/templates/asset.qtpl b/templates/asset.qtpl new file mode 100644 index 0000000..91e873f --- /dev/null +++ b/templates/asset.qtpl @@ -0,0 +1,3 @@ +{% func DefaultCSS() %} +{% cat "default.css" %} +{% endfunc %} diff --git a/templates/css.qtpl.go b/templates/asset.qtpl.go similarity index 75% rename from templates/css.qtpl.go rename to templates/asset.qtpl.go index 72a25fc..2004603 100644 --- a/templates/css.qtpl.go +++ b/templates/asset.qtpl.go @@ -1,27 +1,29 @@ -// Code generated by qtc from "css.qtpl". DO NOT EDIT. +// Code generated by qtc from "asset.qtpl". DO NOT EDIT. // See https://github.com/valyala/quicktemplate for details. -//line templates/css.qtpl:1 +//line templates/asset.qtpl:1 package templates -//line templates/css.qtpl:1 +//line templates/asset.qtpl:1 import ( qtio422016 "io" qt422016 "github.com/valyala/quicktemplate" ) -//line templates/css.qtpl:1 +//line templates/asset.qtpl:1 var ( _ = qtio422016.Copy _ = qt422016.AcquireByteBuffer ) -//line templates/css.qtpl:1 +//line templates/asset.qtpl:1 func StreamDefaultCSS(qw422016 *qt422016.Writer) { -//line templates/css.qtpl:1 +//line templates/asset.qtpl:1 qw422016.N().S(` -@media screen and (min-width: 700px) { +`) +//line templates/asset.qtpl:2 + qw422016.N().S(`@media screen and (min-width: 700px) { main {margin: 0 auto; width: 700px;} } @media screen and (max-width: 700px) { @@ -56,7 +58,7 @@ article pre.codeblock {background-color:#eee; padding:.5rem; white-space: pre-wr .binary-container_with-video video, .binary-container_with-audio audio {width: 100%} .navi-title a {text-decoration:none;} -.img-gallery { text-align: center; margin-top: .25rem; } +.img-gallery { text-align: center; margin-top: .25rem; margin-bottom: .25rem; } .img-gallery_many-images { background-color: #eee; border-radius: .25rem; padding: .5rem; } .img-gallery img { max-width: 100%; max-height: 50vh; } figure { margin: 0; } @@ -73,32 +75,41 @@ nav ul li {list-style-type:none;margin-right:1rem;} .rc-entry__hash { font-style: italic; text-align: right; } .rc-entry__links { grid-column: 1 / span 2; } .rc-entry__author { font-style: italic; } + +.prevnext__el { display: block-inline; min-width: 40%; padding: .5rem; margin-bottom: .25rem; text-decoration: none; background-color: #eee; border-radius: .25rem; } +.prevnext__prev { float: left; } +.prevnext__next { float: right; text-align: right; } + +.page-separator { clear: both; } `) -//line templates/css.qtpl:54 +//line templates/asset.qtpl:2 + qw422016.N().S(` +`) +//line templates/asset.qtpl:3 } -//line templates/css.qtpl:54 +//line templates/asset.qtpl:3 func WriteDefaultCSS(qq422016 qtio422016.Writer) { -//line templates/css.qtpl:54 +//line templates/asset.qtpl:3 qw422016 := qt422016.AcquireWriter(qq422016) -//line templates/css.qtpl:54 +//line templates/asset.qtpl:3 StreamDefaultCSS(qw422016) -//line templates/css.qtpl:54 +//line templates/asset.qtpl:3 qt422016.ReleaseWriter(qw422016) -//line templates/css.qtpl:54 +//line templates/asset.qtpl:3 } -//line templates/css.qtpl:54 +//line templates/asset.qtpl:3 func DefaultCSS() string { -//line templates/css.qtpl:54 +//line templates/asset.qtpl:3 qb422016 := qt422016.AcquireByteBuffer() -//line templates/css.qtpl:54 +//line templates/asset.qtpl:3 WriteDefaultCSS(qb422016) -//line templates/css.qtpl:54 +//line templates/asset.qtpl:3 qs422016 := string(qb422016.B) -//line templates/css.qtpl:54 +//line templates/asset.qtpl:3 qt422016.ReleaseByteBuffer(qb422016) -//line templates/css.qtpl:54 +//line templates/asset.qtpl:3 return qs422016 -//line templates/css.qtpl:54 +//line templates/asset.qtpl:3 } diff --git a/templates/css.qtpl b/templates/default.css similarity index 88% rename from templates/css.qtpl rename to templates/default.css index 7a6f6e3..060a814 100644 --- a/templates/css.qtpl +++ b/templates/default.css @@ -1,4 +1,3 @@ -{% func DefaultCSS() %} @media screen and (min-width: 700px) { main {margin: 0 auto; width: 700px;} } @@ -34,7 +33,7 @@ article pre.codeblock {background-color:#eee; padding:.5rem; white-space: pre-wr .binary-container_with-video video, .binary-container_with-audio audio {width: 100%} .navi-title a {text-decoration:none;} -.img-gallery { text-align: center; margin-top: .25rem; } +.img-gallery { text-align: center; margin-top: .25rem; margin-bottom: .25rem; } .img-gallery_many-images { background-color: #eee; border-radius: .25rem; padding: .5rem; } .img-gallery img { max-width: 100%; max-height: 50vh; } figure { margin: 0; } @@ -51,4 +50,9 @@ nav ul li {list-style-type:none;margin-right:1rem;} .rc-entry__hash { font-style: italic; text-align: right; } .rc-entry__links { grid-column: 1 / span 2; } .rc-entry__author { font-style: italic; } -{% endfunc %} + +.prevnext__el { display: block-inline; min-width: 40%; padding: .5rem; margin-bottom: .25rem; text-decoration: none; background-color: #eee; border-radius: .25rem; } +.prevnext__prev { float: left; } +.prevnext__next { float: right; text-align: right; } + +.page-separator { clear: both; } diff --git a/templates/http_readers.qtpl b/templates/http_readers.qtpl index a1cb2f3..da82cf9 100644 --- a/templates/http_readers.qtpl +++ b/templates/http_readers.qtpl @@ -1,4 +1,5 @@ {% import "net/http" %} +{% import "path" %} {% import "github.com/bouncepaw/mycorrhiza/user" %} {% func HistoryHTML(rq *http.Request, hyphaName, tbody string) %} @@ -35,7 +36,7 @@ {% endfunc %} If `contents` == "", a helpful message is shown instead. -{% func PageHTML(rq *http.Request, hyphaName, naviTitle, contents, tree string) %} +{% func PageHTML(rq *http.Request, hyphaName, naviTitle, contents, tree, prevHyphaName, nextHyphaName string) %}
{%= navHTML(rq, hyphaName, "page") %}
@@ -46,7 +47,15 @@ If `contents` == "", a helpful message is shown instead. {%s= contents %} {% endif %}
-
+
+ {% if prevHyphaName != "" %} + ← {%s path.Base(prevHyphaName) %} + {% endif %} + {% if nextHyphaName != "" %} + {%s path.Base(nextHyphaName) %} → + {% endif %} +
+
{% if u := user.FromRequest(rq).OrAnon(); !user.AuthUsed || u.Group > user.UserAnon %}
diff --git a/templates/http_readers.qtpl.go b/templates/http_readers.qtpl.go index 3ffac47..335b3d2 100644 --- a/templates/http_readers.qtpl.go +++ b/templates/http_readers.qtpl.go @@ -8,30 +8,33 @@ package templates import "net/http" //line templates/http_readers.qtpl:2 +import "path" + +//line templates/http_readers.qtpl:3 import "github.com/bouncepaw/mycorrhiza/user" -//line templates/http_readers.qtpl:4 +//line templates/http_readers.qtpl:5 import ( qtio422016 "io" qt422016 "github.com/valyala/quicktemplate" ) -//line templates/http_readers.qtpl:4 +//line templates/http_readers.qtpl:5 var ( _ = qtio422016.Copy _ = qt422016.AcquireByteBuffer ) -//line templates/http_readers.qtpl:4 +//line templates/http_readers.qtpl:5 func StreamHistoryHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName, tbody string) { -//line templates/http_readers.qtpl:4 +//line templates/http_readers.qtpl:5 qw422016.N().S(`
`) -//line templates/http_readers.qtpl:6 +//line templates/http_readers.qtpl:7 streamnavHTML(qw422016, rq, hyphaName, "history") -//line templates/http_readers.qtpl:6 +//line templates/http_readers.qtpl:7 qw422016.N().S(` @@ -43,159 +46,199 @@ func StreamHistoryHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName, t `) -//line templates/http_readers.qtpl:16 +//line templates/http_readers.qtpl:17 qw422016.N().S(tbody) -//line templates/http_readers.qtpl:16 +//line templates/http_readers.qtpl:17 qw422016.N().S(`
`) -//line templates/http_readers.qtpl:20 +//line templates/http_readers.qtpl:21 } -//line templates/http_readers.qtpl:20 +//line templates/http_readers.qtpl:21 func WriteHistoryHTML(qq422016 qtio422016.Writer, rq *http.Request, hyphaName, tbody string) { -//line templates/http_readers.qtpl:20 +//line templates/http_readers.qtpl:21 qw422016 := qt422016.AcquireWriter(qq422016) -//line templates/http_readers.qtpl:20 +//line templates/http_readers.qtpl:21 StreamHistoryHTML(qw422016, rq, hyphaName, tbody) -//line templates/http_readers.qtpl:20 +//line templates/http_readers.qtpl:21 qt422016.ReleaseWriter(qw422016) -//line templates/http_readers.qtpl:20 +//line templates/http_readers.qtpl:21 } -//line templates/http_readers.qtpl:20 +//line templates/http_readers.qtpl:21 func HistoryHTML(rq *http.Request, hyphaName, tbody string) string { -//line templates/http_readers.qtpl:20 +//line templates/http_readers.qtpl:21 qb422016 := qt422016.AcquireByteBuffer() -//line templates/http_readers.qtpl:20 +//line templates/http_readers.qtpl:21 WriteHistoryHTML(qb422016, rq, hyphaName, tbody) -//line templates/http_readers.qtpl:20 +//line templates/http_readers.qtpl:21 qs422016 := string(qb422016.B) -//line templates/http_readers.qtpl:20 +//line templates/http_readers.qtpl:21 qt422016.ReleaseByteBuffer(qb422016) -//line templates/http_readers.qtpl:20 +//line templates/http_readers.qtpl:21 return qs422016 -//line templates/http_readers.qtpl:20 +//line templates/http_readers.qtpl:21 } -//line templates/http_readers.qtpl:22 +//line templates/http_readers.qtpl:23 func StreamRevisionHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName, naviTitle, contents, tree, revHash string) { -//line templates/http_readers.qtpl:22 +//line templates/http_readers.qtpl:23 qw422016.N().S(`
`) -//line templates/http_readers.qtpl:24 +//line templates/http_readers.qtpl:25 streamnavHTML(qw422016, rq, hyphaName, "revision", revHash) -//line templates/http_readers.qtpl:24 +//line templates/http_readers.qtpl:25 qw422016.N().S(`

Please note that viewing binary parts of hyphae is not supported in history for now.

`) -//line templates/http_readers.qtpl:27 +//line templates/http_readers.qtpl:28 qw422016.N().S(naviTitle) -//line templates/http_readers.qtpl:27 +//line templates/http_readers.qtpl:28 qw422016.N().S(` `) -//line templates/http_readers.qtpl:28 +//line templates/http_readers.qtpl:29 qw422016.N().S(contents) -//line templates/http_readers.qtpl:28 +//line templates/http_readers.qtpl:29 qw422016.N().S(`

`) -//line templates/http_readers.qtpl:35 +//line templates/http_readers.qtpl:36 } -//line templates/http_readers.qtpl:35 +//line templates/http_readers.qtpl:36 func WriteRevisionHTML(qq422016 qtio422016.Writer, rq *http.Request, hyphaName, naviTitle, contents, tree, revHash string) { -//line templates/http_readers.qtpl:35 +//line templates/http_readers.qtpl:36 qw422016 := qt422016.AcquireWriter(qq422016) -//line templates/http_readers.qtpl:35 +//line templates/http_readers.qtpl:36 StreamRevisionHTML(qw422016, rq, hyphaName, naviTitle, contents, tree, revHash) -//line templates/http_readers.qtpl:35 +//line templates/http_readers.qtpl:36 qt422016.ReleaseWriter(qw422016) -//line templates/http_readers.qtpl:35 +//line templates/http_readers.qtpl:36 } -//line templates/http_readers.qtpl:35 +//line templates/http_readers.qtpl:36 func RevisionHTML(rq *http.Request, hyphaName, naviTitle, contents, tree, revHash string) string { -//line templates/http_readers.qtpl:35 +//line templates/http_readers.qtpl:36 qb422016 := qt422016.AcquireByteBuffer() -//line templates/http_readers.qtpl:35 +//line templates/http_readers.qtpl:36 WriteRevisionHTML(qb422016, rq, hyphaName, naviTitle, contents, tree, revHash) -//line templates/http_readers.qtpl:35 +//line templates/http_readers.qtpl:36 qs422016 := string(qb422016.B) -//line templates/http_readers.qtpl:35 +//line templates/http_readers.qtpl:36 qt422016.ReleaseByteBuffer(qb422016) -//line templates/http_readers.qtpl:35 +//line templates/http_readers.qtpl:36 return qs422016 -//line templates/http_readers.qtpl:35 +//line templates/http_readers.qtpl:36 } // If `contents` == "", a helpful message is shown instead. -//line templates/http_readers.qtpl:38 -func StreamPageHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName, naviTitle, contents, tree string) { -//line templates/http_readers.qtpl:38 +//line templates/http_readers.qtpl:39 +func StreamPageHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName, naviTitle, contents, tree, prevHyphaName, nextHyphaName string) { +//line templates/http_readers.qtpl:39 qw422016.N().S(`
`) -//line templates/http_readers.qtpl:40 +//line templates/http_readers.qtpl:41 streamnavHTML(qw422016, rq, hyphaName, "page") -//line templates/http_readers.qtpl:40 +//line templates/http_readers.qtpl:41 qw422016.N().S(`
`) -//line templates/http_readers.qtpl:42 +//line templates/http_readers.qtpl:43 qw422016.N().S(naviTitle) -//line templates/http_readers.qtpl:42 +//line templates/http_readers.qtpl:43 qw422016.N().S(` `) -//line templates/http_readers.qtpl:43 +//line templates/http_readers.qtpl:44 if contents == "" { -//line templates/http_readers.qtpl:43 +//line templates/http_readers.qtpl:44 qw422016.N().S(`

This hypha has no text. Why not create it?

`) -//line templates/http_readers.qtpl:45 +//line templates/http_readers.qtpl:46 } else { -//line templates/http_readers.qtpl:45 +//line templates/http_readers.qtpl:46 qw422016.N().S(` `) -//line templates/http_readers.qtpl:46 +//line templates/http_readers.qtpl:47 qw422016.N().S(contents) -//line templates/http_readers.qtpl:46 +//line templates/http_readers.qtpl:47 qw422016.N().S(` `) -//line templates/http_readers.qtpl:47 +//line templates/http_readers.qtpl:48 } -//line templates/http_readers.qtpl:47 +//line templates/http_readers.qtpl:48 qw422016.N().S(`
-
+
+ `) +//line templates/http_readers.qtpl:51 + if prevHyphaName != "" { +//line templates/http_readers.qtpl:51 + qw422016.N().S(` + ← `) +//line templates/http_readers.qtpl:52 + qw422016.E().S(path.Base(prevHyphaName)) +//line templates/http_readers.qtpl:52 + qw422016.N().S(` + `) +//line templates/http_readers.qtpl:53 + } +//line templates/http_readers.qtpl:53 + qw422016.N().S(` + `) +//line templates/http_readers.qtpl:54 + if nextHyphaName != "" { +//line templates/http_readers.qtpl:54 + qw422016.N().S(` + `) +//line templates/http_readers.qtpl:55 + qw422016.E().S(path.Base(nextHyphaName)) +//line templates/http_readers.qtpl:55 + qw422016.N().S(` → + `) +//line templates/http_readers.qtpl:56 + } +//line templates/http_readers.qtpl:56 + qw422016.N().S(` +
+
`) -//line templates/http_readers.qtpl:50 +//line templates/http_readers.qtpl:59 if u := user.FromRequest(rq).OrAnon(); !user.AuthUsed || u.Group > user.UserAnon { -//line templates/http_readers.qtpl:50 +//line templates/http_readers.qtpl:59 qw422016.N().S(` @@ -205,44 +248,44 @@ func StreamPageHTML(qw422016 *qt422016.Writer, rq *http.Request, hyphaName, navi
`) -//line templates/http_readers.qtpl:59 +//line templates/http_readers.qtpl:68 } -//line templates/http_readers.qtpl:59 +//line templates/http_readers.qtpl:68 qw422016.N().S(`
`) -//line templates/http_readers.qtpl:64 +//line templates/http_readers.qtpl:73 } -//line templates/http_readers.qtpl:64 -func WritePageHTML(qq422016 qtio422016.Writer, rq *http.Request, hyphaName, naviTitle, contents, tree string) { -//line templates/http_readers.qtpl:64 +//line templates/http_readers.qtpl:73 +func WritePageHTML(qq422016 qtio422016.Writer, rq *http.Request, hyphaName, naviTitle, contents, tree, prevHyphaName, nextHyphaName string) { +//line templates/http_readers.qtpl:73 qw422016 := qt422016.AcquireWriter(qq422016) -//line templates/http_readers.qtpl:64 - StreamPageHTML(qw422016, rq, hyphaName, naviTitle, contents, tree) -//line templates/http_readers.qtpl:64 +//line templates/http_readers.qtpl:73 + StreamPageHTML(qw422016, rq, hyphaName, naviTitle, contents, tree, prevHyphaName, nextHyphaName) +//line templates/http_readers.qtpl:73 qt422016.ReleaseWriter(qw422016) -//line templates/http_readers.qtpl:64 +//line templates/http_readers.qtpl:73 } -//line templates/http_readers.qtpl:64 -func PageHTML(rq *http.Request, hyphaName, naviTitle, contents, tree string) string { -//line templates/http_readers.qtpl:64 +//line templates/http_readers.qtpl:73 +func PageHTML(rq *http.Request, hyphaName, naviTitle, contents, tree, prevHyphaName, nextHyphaName string) string { +//line templates/http_readers.qtpl:73 qb422016 := qt422016.AcquireByteBuffer() -//line templates/http_readers.qtpl:64 - WritePageHTML(qb422016, rq, hyphaName, naviTitle, contents, tree) -//line templates/http_readers.qtpl:64 +//line templates/http_readers.qtpl:73 + WritePageHTML(qb422016, rq, hyphaName, naviTitle, contents, tree, prevHyphaName, nextHyphaName) +//line templates/http_readers.qtpl:73 qs422016 := string(qb422016.B) -//line templates/http_readers.qtpl:64 +//line templates/http_readers.qtpl:73 qt422016.ReleaseByteBuffer(qb422016) -//line templates/http_readers.qtpl:64 +//line templates/http_readers.qtpl:73 return qs422016 -//line templates/http_readers.qtpl:64 +//line templates/http_readers.qtpl:73 } diff --git a/tree/tree.go b/tree/tree.go index 1655664..982fed7 100644 --- a/tree/tree.go +++ b/tree/tree.go @@ -10,17 +10,20 @@ import ( // If Name == "", the tree is empty. type tree struct { name string + exists bool + prevSibling string + nextSibling string siblings []string descendants []*tree root bool hyphaIterator func(func(string)) } -// TreeAsHtml generates a tree for `hyphaName`. `hyphaStorage` has this type because package `tree` has no access to `HyphaData` data type. One day it shall have it, I guess. -func TreeAsHtml(hyphaName string, hyphaIterator func(func(string))) string { +// Tree generates a tree for `hyphaName` as html and returns next and previous hyphae if any. +func Tree(hyphaName string, hyphaIterator func(func(string))) (html, prev, next string) { t := &tree{name: hyphaName, root: true, hyphaIterator: hyphaIterator} t.fill() - return t.asHtml() + return t.asHtml(), t.prevSibling, t.nextSibling } // subtree adds a descendant tree to `t` and returns that tree. @@ -34,11 +37,22 @@ func (t *tree) fork(descendantName string) *tree { return subt } +// Compare current prev next hyphae and decide if any of them should be set to `name2`. +func (t *tree) prevNextDetermine(name2 string) { + if name2 < t.name && (name2 > t.prevSibling || t.prevSibling == "") { + t.prevSibling = name2 + } else if name2 > t.name && (name2 < t.nextSibling || t.nextSibling == "") { + t.nextSibling = name2 + } +} + // Compares names and does something with them, may generate a subtree. func (t *tree) compareNamesAndAppend(name2 string) { switch { case t.name == name2: + t.exists = true case t.root && path.Dir(t.name) == path.Dir(name2): + t.prevNextDetermine(name2) t.siblings = append(t.siblings, name2) case t.name == path.Dir(name2): t.fork(name2).fill()