mirror of
https://github.com/osmarks/mycorrhiza.git
synced 2025-01-31 11:29:09 +00:00
commit
b6896829c0
10
README.md
10
README.md
@ -1,6 +1,13 @@
|
|||||||
# 🍄 MycorrhizaWiki 0.8
|
# 🍄 MycorrhizaWiki 0.9
|
||||||
A wiki engine.
|
A wiki engine.
|
||||||
|
|
||||||
|
## 0.9
|
||||||
|
This is a development branch for 0.9 version. Features I want to implement in this release:
|
||||||
|
* [x] Recent changes page.
|
||||||
|
* [x] Hypha deletion.
|
||||||
|
* [x] Hypha renaming.
|
||||||
|
* [x] Support async git ops.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
```sh
|
```sh
|
||||||
git clone --recurse-submodules https://github.com/bouncepaw/mycorrhiza
|
git clone --recurse-submodules https://github.com/bouncepaw/mycorrhiza
|
||||||
@ -31,5 +38,4 @@ Help is always needed. We have a [tg chat](https://t.me/mycorrhizadev) where som
|
|||||||
* Tagging system
|
* Tagging system
|
||||||
* Authorization
|
* Authorization
|
||||||
* Better history viewing
|
* Better history viewing
|
||||||
* Recent changes page
|
|
||||||
* More markups
|
* More markups
|
||||||
|
2
go.mod
2
go.mod
@ -2,4 +2,4 @@ module github.com/bouncepaw/mycorrhiza
|
|||||||
|
|
||||||
go 1.14
|
go 1.14
|
||||||
|
|
||||||
require github.com/valyala/quicktemplate v1.6.2
|
require github.com/valyala/quicktemplate v1.6.3
|
||||||
|
8
go.sum
8
go.sum
@ -1,11 +1,11 @@
|
|||||||
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||||
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.10.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasthttp v1.15.1/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA=
|
github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA=
|
||||||
github.com/valyala/quicktemplate v1.6.2 h1:k0vgK7zlmFzqAoIBIOrhrfmZ6JoTGJlLRPLbkPGr2/M=
|
github.com/valyala/quicktemplate v1.6.3 h1:O7EuMwuH7Q94U2CXD6sOX8AYHqQqWtmIk690IhmpkKA=
|
||||||
github.com/valyala/quicktemplate v1.6.2/go.mod h1:mtEJpQtUiBV0SHhMX6RtiJtqxncgrfmjcUy5T68X8TM=
|
github.com/valyala/quicktemplate v1.6.3/go.mod h1:fwPzK2fHuYEODzJ9pkw0ipCPNHZ2tD5KW4lOuSdPKzY=
|
||||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/bouncepaw/mycorrhiza/util"
|
"github.com/bouncepaw/mycorrhiza/util"
|
||||||
@ -31,6 +32,58 @@ type Revision struct {
|
|||||||
Message string
|
Message string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TimeString returns a human readable time representation.
|
||||||
|
func (rev Revision) TimeString() string {
|
||||||
|
return rev.Time.Format(time.RFC822)
|
||||||
|
}
|
||||||
|
|
||||||
|
// HyphaeLinks returns a comma-separated list of hyphae that were affected by this revision as HTML string.
|
||||||
|
func (rev Revision) HyphaeLinks() (html string) {
|
||||||
|
// diff-tree --no-commit-id --name-only -r
|
||||||
|
var (
|
||||||
|
// List of files affected by this revision, one per line.
|
||||||
|
out, err = gitsh("diff-tree", "--no-commit-id", "--name-only", "-r", rev.Hash)
|
||||||
|
// set is used to determine if a certain hypha has been already noted (hyphae are stored in 2 files at most).
|
||||||
|
set = make(map[string]bool)
|
||||||
|
isNewName = func(hyphaName string) bool {
|
||||||
|
if _, present := set[hyphaName]; present {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
set[hyphaName] = true
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
for _, filename := range strings.Split(out.String(), "\n") {
|
||||||
|
// If filename has an ampersand:
|
||||||
|
if strings.IndexRune(filename, '&') >= 0 {
|
||||||
|
// Remove ampersanded suffix from filename:
|
||||||
|
ampersandPos := strings.LastIndexByte(filename, '&')
|
||||||
|
hyphaName := string([]byte(filename)[0:ampersandPos]) // is it safe?
|
||||||
|
if isNewName(hyphaName) {
|
||||||
|
// Entries are separated by commas
|
||||||
|
if len(set) > 1 {
|
||||||
|
html += `<span aria-hidden="true">, </span>`
|
||||||
|
}
|
||||||
|
html += fmt.Sprintf(`<a href="/rev/%[1]s/%[2]s">%[2]s</a>`, rev.Hash, hyphaName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return html
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rev Revision) RecentChangesEntry() (html string) {
|
||||||
|
return fmt.Sprintf(`
|
||||||
|
<li><time>%s</time></li>
|
||||||
|
<li>%s</li>
|
||||||
|
<li>%s</li>
|
||||||
|
<li>%s</li>
|
||||||
|
`, rev.TimeString(), rev.Hash, rev.HyphaeLinks(), rev.Message)
|
||||||
|
}
|
||||||
|
|
||||||
// Path to git executable. Set at init()
|
// Path to git executable. Set at init()
|
||||||
var gitpath string
|
var gitpath string
|
||||||
|
|
||||||
@ -46,10 +99,10 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// I pronounce it as [gɪt͡ʃ].
|
// I pronounce it as [gɪt͡ʃ].
|
||||||
|
// gitsh is async-safe, therefore all other git-related functions in this module are too.
|
||||||
func gitsh(args ...string) (out bytes.Buffer, err error) {
|
func gitsh(args ...string) (out bytes.Buffer, err error) {
|
||||||
fmt.Printf("$ %v\n", args)
|
fmt.Printf("$ %v\n", args)
|
||||||
cmd := exec.Command(gitpath, args...)
|
cmd := exec.Command(gitpath, args...)
|
||||||
|
|
||||||
cmd.Dir = util.WikiDir
|
cmd.Dir = util.WikiDir
|
||||||
|
|
||||||
b, err := cmd.CombinedOutput()
|
b, err := cmd.CombinedOutput()
|
||||||
|
@ -5,10 +5,33 @@ package history
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
"github.com/bouncepaw/mycorrhiza/templates"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func RecentChanges(n int) string {
|
||||||
|
var (
|
||||||
|
out, err = gitsh(
|
||||||
|
"log", "--oneline", "--no-merges",
|
||||||
|
"--pretty=format:\"%h\t%ce\t%ct\t%s\"",
|
||||||
|
"--max-count="+strconv.Itoa(n),
|
||||||
|
)
|
||||||
|
revs []Revision
|
||||||
|
)
|
||||||
|
if err == nil {
|
||||||
|
for _, line := range strings.Split(out.String(), "\n") {
|
||||||
|
revs = append(revs, parseRevisionLine(line))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entries := make([]string, len(revs))
|
||||||
|
for i, rev := range revs {
|
||||||
|
entries[i] = rev.RecentChangesEntry()
|
||||||
|
}
|
||||||
|
return templates.RecentChangesHTML(entries, n)
|
||||||
|
}
|
||||||
|
|
||||||
// Revisions returns slice of revisions for the given hypha name.
|
// Revisions returns slice of revisions for the given hypha name.
|
||||||
func Revisions(hyphaName string) ([]Revision, error) {
|
func Revisions(hyphaName string) ([]Revision, error) {
|
||||||
var (
|
var (
|
||||||
@ -22,7 +45,9 @@ func Revisions(hyphaName string) ([]Revision, error) {
|
|||||||
)
|
)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
for _, line := range strings.Split(out.String(), "\n") {
|
for _, line := range strings.Split(out.String(), "\n") {
|
||||||
revs = append(revs, parseRevisionLine(line))
|
if line != "" {
|
||||||
|
revs = append(revs, parseRevisionLine(line))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return revs, err
|
return revs, err
|
||||||
@ -48,7 +73,7 @@ func (rev *Revision) AsHtmlTableRow(hyphaName string) string {
|
|||||||
<td><time>%s</time></td>
|
<td><time>%s</time></td>
|
||||||
<td><a href="/rev/%s/%s">%s</a></td>
|
<td><a href="/rev/%s/%s">%s</a></td>
|
||||||
<td>%s</td>
|
<td>%s</td>
|
||||||
</tr>`, rev.Time.Format(time.RFC822), rev.Hash, hyphaName, rev.Hash, rev.Message)
|
</tr>`, rev.TimeString(), rev.Hash, hyphaName, rev.Hash, rev.Message)
|
||||||
}
|
}
|
||||||
|
|
||||||
// See how the file with `filepath` looked at commit with `hash`.
|
// See how the file with `filepath` looked at commit with `hash`.
|
||||||
|
@ -4,10 +4,16 @@ package history
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/bouncepaw/mycorrhiza/util"
|
"github.com/bouncepaw/mycorrhiza/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// gitMutex is used for blocking git operations to avoid clashes.
|
||||||
|
var gitMutex = sync.Mutex{}
|
||||||
|
|
||||||
// OpType is the type a history operation has. Callers shall set appropriate optypes when creating history operations.
|
// OpType is the type a history operation has. Callers shall set appropriate optypes when creating history operations.
|
||||||
type OpType int
|
type OpType int
|
||||||
|
|
||||||
@ -15,6 +21,8 @@ const (
|
|||||||
TypeNone OpType = iota
|
TypeNone OpType = iota
|
||||||
TypeEditText
|
TypeEditText
|
||||||
TypeEditBinary
|
TypeEditBinary
|
||||||
|
TypeDeleteHypha
|
||||||
|
TypeRenameHypha
|
||||||
)
|
)
|
||||||
|
|
||||||
// HistoryOp is an object representing a history operation.
|
// HistoryOp is an object representing a history operation.
|
||||||
@ -29,6 +37,7 @@ type HistoryOp struct {
|
|||||||
|
|
||||||
// Operation is a constructor of a history operation.
|
// Operation is a constructor of a history operation.
|
||||||
func Operation(opType OpType) *HistoryOp {
|
func Operation(opType OpType) *HistoryOp {
|
||||||
|
gitMutex.Lock()
|
||||||
hop := &HistoryOp{
|
hop := &HistoryOp{
|
||||||
Errs: []error{},
|
Errs: []error{},
|
||||||
opType: opType,
|
opType: opType,
|
||||||
@ -46,6 +55,28 @@ func (hop *HistoryOp) gitop(args ...string) *HistoryOp {
|
|||||||
return hop
|
return hop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithFilesRemoved git-rm-s all passed `paths`. Paths can be rooted or not. Paths that are empty strings are ignored.
|
||||||
|
func (hop *HistoryOp) WithFilesRemoved(paths ...string) *HistoryOp {
|
||||||
|
args := []string{"rm", "--quiet", "--"}
|
||||||
|
for _, path := range paths {
|
||||||
|
if path != "" {
|
||||||
|
args = append(args, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hop.gitop(args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithFilesRenamed git-mv-s all passed keys of `pairs` to values of `pairs`. Paths can be rooted ot not. Empty keys are ignored.
|
||||||
|
func (hop *HistoryOp) WithFilesRenamed(pairs map[string]string) *HistoryOp {
|
||||||
|
for from, to := range pairs {
|
||||||
|
if from != "" {
|
||||||
|
os.MkdirAll(filepath.Dir(to), 0777)
|
||||||
|
hop.gitop(append([]string{"mv"}, from, to)...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return hop
|
||||||
|
}
|
||||||
|
|
||||||
// WithFiles stages all passed `paths`. Paths can be rooted or not.
|
// WithFiles stages all passed `paths`. Paths can be rooted or not.
|
||||||
func (hop *HistoryOp) WithFiles(paths ...string) *HistoryOp {
|
func (hop *HistoryOp) WithFiles(paths ...string) *HistoryOp {
|
||||||
for i, path := range paths {
|
for i, path := range paths {
|
||||||
@ -62,6 +93,7 @@ func (hop *HistoryOp) Apply() *HistoryOp {
|
|||||||
"--author='"+hop.name+" <"+hop.email+">'",
|
"--author='"+hop.name+" <"+hop.email+">'",
|
||||||
"--message="+hop.userMsg,
|
"--message="+hop.userMsg,
|
||||||
)
|
)
|
||||||
|
gitMutex.Unlock()
|
||||||
return hop
|
return hop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,89 @@ func init() {
|
|||||||
http.HandleFunc("/upload-binary/", handlerUploadBinary)
|
http.HandleFunc("/upload-binary/", handlerUploadBinary)
|
||||||
http.HandleFunc("/upload-text/", handlerUploadText)
|
http.HandleFunc("/upload-text/", handlerUploadText)
|
||||||
http.HandleFunc("/edit/", handlerEdit)
|
http.HandleFunc("/edit/", handlerEdit)
|
||||||
|
http.HandleFunc("/delete-ask/", handlerDeleteAsk)
|
||||||
|
http.HandleFunc("/delete-confirm/", handlerDeleteConfirm)
|
||||||
|
http.HandleFunc("/rename-ask/", handlerRenameAsk)
|
||||||
|
http.HandleFunc("/rename-confirm/", handlerRenameConfirm)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handlerRenameAsk(w http.ResponseWriter, rq *http.Request) {
|
||||||
|
log.Println(rq.URL)
|
||||||
|
var (
|
||||||
|
hyphaName = HyphaNameFromRq(rq, "rename-ask")
|
||||||
|
_, isOld = HyphaStorage[hyphaName]
|
||||||
|
)
|
||||||
|
util.HTTP200Page(w, base("Rename "+hyphaName+"?", templates.RenameAskHTML(hyphaName, isOld)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func handlerRenameConfirm(w http.ResponseWriter, rq *http.Request) {
|
||||||
|
log.Println(rq.URL)
|
||||||
|
var (
|
||||||
|
hyphaName = HyphaNameFromRq(rq, "rename-confirm")
|
||||||
|
hyphaData, isOld = HyphaStorage[hyphaName]
|
||||||
|
newName = CanonicalName(rq.PostFormValue("new-name"))
|
||||||
|
_, newNameIsUsed = HyphaStorage[newName]
|
||||||
|
recursive bool
|
||||||
|
)
|
||||||
|
if rq.PostFormValue("recursive") == "true" {
|
||||||
|
recursive = true
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case newNameIsUsed:
|
||||||
|
HttpErr(w, http.StatusBadRequest, hyphaName, "Error: hypha exists",
|
||||||
|
fmt.Sprintf("Hypha named <a href='/page/%s'>%s</a> already exists.", hyphaName, hyphaName))
|
||||||
|
case newName == "":
|
||||||
|
HttpErr(w, http.StatusBadRequest, hyphaName, "Error: no name",
|
||||||
|
"No new name is given.")
|
||||||
|
case !isOld:
|
||||||
|
HttpErr(w, http.StatusBadRequest, hyphaName, "Error: no such hypha",
|
||||||
|
"Cannot rename a hypha that does not exist yet.")
|
||||||
|
case !HyphaPattern.MatchString(newName):
|
||||||
|
HttpErr(w, http.StatusBadRequest, hyphaName, "Error: invalid name",
|
||||||
|
"Invalid new name. Names cannot contain characters <code>^?!:#@><*|\"\\'&%</code>")
|
||||||
|
default:
|
||||||
|
if hop := hyphaData.RenameHypha(hyphaName, newName, recursive); len(hop.Errs) == 0 {
|
||||||
|
http.Redirect(w, rq, "/page/"+newName, http.StatusSeeOther)
|
||||||
|
} else {
|
||||||
|
HttpErr(w, http.StatusInternalServerError, hyphaName,
|
||||||
|
"Error: could not rename hypha",
|
||||||
|
fmt.Sprintf("Could not rename this hypha due to an internal error. Server errors: <code>%v</code>", hop.Errs))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// handlerDeleteAsk shows a delete dialog.
|
||||||
|
func handlerDeleteAsk(w http.ResponseWriter, rq *http.Request) {
|
||||||
|
log.Println(rq.URL)
|
||||||
|
var (
|
||||||
|
hyphaName = HyphaNameFromRq(rq, "delete-ask")
|
||||||
|
_, isOld = HyphaStorage[hyphaName]
|
||||||
|
)
|
||||||
|
util.HTTP200Page(w, base("Delete "+hyphaName+"?", templates.DeleteAskHTML(hyphaName, isOld)))
|
||||||
|
}
|
||||||
|
|
||||||
|
// handlerDeleteConfirm deletes a hypha for sure
|
||||||
|
func handlerDeleteConfirm(w http.ResponseWriter, rq *http.Request) {
|
||||||
|
log.Println(rq.URL)
|
||||||
|
var (
|
||||||
|
hyphaName = HyphaNameFromRq(rq, "delete-confirm")
|
||||||
|
hyphaData, isOld = HyphaStorage[hyphaName]
|
||||||
|
)
|
||||||
|
if isOld {
|
||||||
|
// If deleted successfully
|
||||||
|
if hop := hyphaData.DeleteHypha(hyphaName); len(hop.Errs) == 0 {
|
||||||
|
http.Redirect(w, rq, "/page/"+hyphaName, http.StatusSeeOther)
|
||||||
|
} else {
|
||||||
|
HttpErr(w, http.StatusInternalServerError, hyphaName,
|
||||||
|
"Error: could not delete hypha",
|
||||||
|
fmt.Sprintf("Could not delete this hypha due to an internal error. Server errors: <code>%v</code>", hop.Errs))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The precondition is to have the hypha in the first place.
|
||||||
|
HttpErr(w, http.StatusPreconditionFailed, hyphaName,
|
||||||
|
"Error: no such hypha",
|
||||||
|
"Could not delete this hypha because it does not exist.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handlerEdit shows the edit form. It doesn't edit anything actually.
|
// handlerEdit shows the edit form. It doesn't edit anything actually.
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/bouncepaw/mycorrhiza/gemtext"
|
"github.com/bouncepaw/mycorrhiza/gemtext"
|
||||||
@ -29,8 +28,9 @@ func handlerRevision(w http.ResponseWriter, rq *http.Request) {
|
|||||||
log.Println(rq.URL)
|
log.Println(rq.URL)
|
||||||
var (
|
var (
|
||||||
shorterUrl = strings.TrimPrefix(rq.URL.Path, "/rev/")
|
shorterUrl = strings.TrimPrefix(rq.URL.Path, "/rev/")
|
||||||
revHash = path.Dir(shorterUrl)
|
firstSlashIndex = strings.IndexRune(shorterUrl, '/')
|
||||||
hyphaName = CanonicalName(strings.TrimPrefix(shorterUrl, revHash+"/"))
|
revHash = shorterUrl[:firstSlashIndex]
|
||||||
|
hyphaName = CanonicalName(shorterUrl[firstSlashIndex+1:])
|
||||||
contents = fmt.Sprintf(`<p>This hypha had no text at this revision.</p>`)
|
contents = fmt.Sprintf(`<p>This hypha had no text at this revision.</p>`)
|
||||||
textPath = hyphaName + "&.gmi"
|
textPath = hyphaName + "&.gmi"
|
||||||
textContents, err = history.FileAtRevision(textPath, revHash)
|
textContents, err = history.FileAtRevision(textPath, revHash)
|
||||||
@ -55,15 +55,15 @@ func handlerHistory(w http.ResponseWriter, rq *http.Request) {
|
|||||||
log.Println(rq.URL)
|
log.Println(rq.URL)
|
||||||
hyphaName := HyphaNameFromRq(rq, "history")
|
hyphaName := HyphaNameFromRq(rq, "history")
|
||||||
var tbody string
|
var tbody string
|
||||||
if _, ok := HyphaStorage[hyphaName]; ok {
|
|
||||||
revs, err := history.Revisions(hyphaName)
|
// History can be found for files that do not exist anymore.
|
||||||
if err == nil {
|
revs, err := history.Revisions(hyphaName)
|
||||||
for _, rev := range revs {
|
if err == nil {
|
||||||
tbody += rev.AsHtmlTableRow(hyphaName)
|
for _, rev := range revs {
|
||||||
}
|
tbody += rev.AsHtmlTableRow(hyphaName)
|
||||||
}
|
}
|
||||||
log.Println(revs)
|
|
||||||
}
|
}
|
||||||
|
log.Println("Found", len(revs), "revisions for", hyphaName)
|
||||||
|
|
||||||
util.HTTP200Page(w,
|
util.HTTP200Page(w,
|
||||||
base(hyphaName, templates.HistoryHTML(hyphaName, tbody)))
|
base(hyphaName, templates.HistoryHTML(hyphaName, tbody)))
|
||||||
|
75
hypha.go
75
hypha.go
@ -7,8 +7,11 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/bouncepaw/mycorrhiza/gemtext"
|
"github.com/bouncepaw/mycorrhiza/gemtext"
|
||||||
|
"github.com/bouncepaw/mycorrhiza/history"
|
||||||
|
"github.com/bouncepaw/mycorrhiza/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -37,6 +40,78 @@ type HyphaData struct {
|
|||||||
binaryType BinaryType
|
binaryType BinaryType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DeleteHypha deletes hypha and makes a history record about that.
|
||||||
|
func (hd *HyphaData) DeleteHypha(hyphaName string) *history.HistoryOp {
|
||||||
|
hop := history.Operation(history.TypeDeleteHypha).
|
||||||
|
WithFilesRemoved(hd.textPath, hd.binaryPath).
|
||||||
|
WithMsg(fmt.Sprintf("Delete ‘%s’", hyphaName)).
|
||||||
|
WithSignature("anon").
|
||||||
|
Apply()
|
||||||
|
if len(hop.Errs) == 0 {
|
||||||
|
delete(HyphaStorage, hyphaName)
|
||||||
|
}
|
||||||
|
return hop
|
||||||
|
}
|
||||||
|
|
||||||
|
func findHyphaeToRename(hyphaName string, recursive bool) []string {
|
||||||
|
hyphae := []string{hyphaName}
|
||||||
|
if recursive {
|
||||||
|
hyphae = append(hyphae, util.FindSubhyphae(hyphaName, IterateHyphaNamesWith)...)
|
||||||
|
}
|
||||||
|
return hyphae
|
||||||
|
}
|
||||||
|
|
||||||
|
func renamingPairs(hyphaNames []string, replaceName func(string) string) map[string]string {
|
||||||
|
renameMap := make(map[string]string)
|
||||||
|
for _, hn := range hyphaNames {
|
||||||
|
if hd, ok := HyphaStorage[hn]; ok {
|
||||||
|
if hd.textPath != "" {
|
||||||
|
renameMap[hd.textPath] = replaceName(hd.textPath)
|
||||||
|
}
|
||||||
|
if hd.binaryPath != "" {
|
||||||
|
renameMap[hd.binaryPath] = replaceName(hd.binaryPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return renameMap
|
||||||
|
}
|
||||||
|
|
||||||
|
// word Data is plural here
|
||||||
|
func relocateHyphaData(hyphaNames []string, replaceName func(string) string) {
|
||||||
|
for _, hyphaName := range hyphaNames {
|
||||||
|
if hd, ok := HyphaStorage[hyphaName]; ok {
|
||||||
|
hd.textPath = replaceName(hd.textPath)
|
||||||
|
hd.binaryPath = replaceName(hd.binaryPath)
|
||||||
|
HyphaStorage[replaceName(hyphaName)] = hd
|
||||||
|
delete(HyphaStorage, hyphaName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RenameHypha renames hypha from old name `hyphaName` to `newName` and makes a history record about that. If `recursive` is `true`, its subhyphae will be renamed the same way.
|
||||||
|
func (hd *HyphaData) RenameHypha(hyphaName, newName string, recursive bool) *history.HistoryOp {
|
||||||
|
var (
|
||||||
|
replaceName = func(str string) string {
|
||||||
|
return strings.Replace(str, hyphaName, newName, 1)
|
||||||
|
}
|
||||||
|
hyphaNames = findHyphaeToRename(hyphaName, recursive)
|
||||||
|
renameMap = renamingPairs(hyphaNames, replaceName)
|
||||||
|
renameMsg = "Rename ‘%s’ to ‘%s’"
|
||||||
|
hop = history.Operation(history.TypeRenameHypha)
|
||||||
|
)
|
||||||
|
if recursive {
|
||||||
|
renameMsg += " recursively"
|
||||||
|
}
|
||||||
|
hop.WithFilesRenamed(renameMap).
|
||||||
|
WithMsg(fmt.Sprintf(renameMsg, hyphaName, newName)).
|
||||||
|
WithSignature("anon").
|
||||||
|
Apply()
|
||||||
|
if len(hop.Errs) == 0 {
|
||||||
|
relocateHyphaData(hyphaNames, replaceName)
|
||||||
|
}
|
||||||
|
return hop
|
||||||
|
}
|
||||||
|
|
||||||
// binaryHtmlBlock creates an html block for binary part of the hypha.
|
// binaryHtmlBlock creates an html block for binary part of the hypha.
|
||||||
func binaryHtmlBlock(hyphaName string, d *HyphaData) string {
|
func binaryHtmlBlock(hyphaName string, d *HyphaData) string {
|
||||||
switch d.binaryType {
|
switch d.binaryType {
|
||||||
|
21
main.go
21
main.go
@ -10,6 +10,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/bouncepaw/mycorrhiza/history"
|
"github.com/bouncepaw/mycorrhiza/history"
|
||||||
"github.com/bouncepaw/mycorrhiza/templates"
|
"github.com/bouncepaw/mycorrhiza/templates"
|
||||||
@ -19,7 +21,7 @@ import (
|
|||||||
// WikiDir is a rooted path to the wiki storage directory.
|
// WikiDir is a rooted path to the wiki storage directory.
|
||||||
var WikiDir string
|
var WikiDir string
|
||||||
|
|
||||||
// HyphaPattern is a pattern which all hyphae must match. Not used currently.
|
// HyphaPattern is a pattern which all hyphae must match.
|
||||||
var HyphaPattern = regexp.MustCompile(`[^?!:#@><*|"\'&%]+`)
|
var HyphaPattern = regexp.MustCompile(`[^?!:#@><*|"\'&%]+`)
|
||||||
|
|
||||||
// HyphaStorage is a mapping between canonical hypha names and their meta information.
|
// HyphaStorage is a mapping between canonical hypha names and their meta information.
|
||||||
@ -83,6 +85,20 @@ func handlerRandom(w http.ResponseWriter, rq *http.Request) {
|
|||||||
http.Redirect(w, rq, "/page/"+randomHyphaName, http.StatusSeeOther)
|
http.Redirect(w, rq, "/page/"+randomHyphaName, http.StatusSeeOther)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Recent changes
|
||||||
|
func handlerRecentChanges(w http.ResponseWriter, rq *http.Request) {
|
||||||
|
log.Println(rq.URL)
|
||||||
|
var (
|
||||||
|
noPrefix = strings.TrimPrefix(rq.URL.String(), "/recent-changes/")
|
||||||
|
n, err = strconv.Atoi(noPrefix)
|
||||||
|
)
|
||||||
|
if err == nil {
|
||||||
|
util.HTTP200Page(w, base(strconv.Itoa(n)+" recent changes", history.RecentChanges(n)))
|
||||||
|
} else {
|
||||||
|
http.Redirect(w, rq, "/recent-changes/20", http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
log.Println("Running MycorrhizaWiki β")
|
log.Println("Running MycorrhizaWiki β")
|
||||||
|
|
||||||
@ -104,10 +120,11 @@ func main() {
|
|||||||
|
|
||||||
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(WikiDir+"/static"))))
|
http.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(WikiDir+"/static"))))
|
||||||
// See http_readers.go for /page/, /text/, /binary/, /history/.
|
// See http_readers.go for /page/, /text/, /binary/, /history/.
|
||||||
// See http_mutators.go for /upload-binary/, /upload-text/, /edit/.
|
// See http_mutators.go for /upload-binary/, /upload-text/, /edit/, /delete-ask/, /delete-confirm/, /rename-ask/, /rename-confirm/.
|
||||||
http.HandleFunc("/list", handlerList)
|
http.HandleFunc("/list", handlerList)
|
||||||
http.HandleFunc("/reindex", handlerReindex)
|
http.HandleFunc("/reindex", handlerReindex)
|
||||||
http.HandleFunc("/random", handlerRandom)
|
http.HandleFunc("/random", handlerRandom)
|
||||||
|
http.HandleFunc("/recent-changes/", handlerRecentChanges)
|
||||||
http.HandleFunc("/favicon.ico", func(w http.ResponseWriter, rq *http.Request) {
|
http.HandleFunc("/favicon.ico", func(w http.ResponseWriter, rq *http.Request) {
|
||||||
http.ServeFile(w, rq, WikiDir+"/static/favicon.ico")
|
http.ServeFile(w, rq, WikiDir+"/static/favicon.ico")
|
||||||
})
|
})
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit bdaaab62574023487610d608d1e9f2f351707a7f
|
Subproject commit 2c0e43199ed28f7022a38463a0eec3af3ecb03c9
|
32
templates/common.qtpl
Normal file
32
templates/common.qtpl
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
This is the <nav> seen on top of many pages.
|
||||||
|
{% code
|
||||||
|
type navEntry struct {
|
||||||
|
path string
|
||||||
|
title string
|
||||||
|
}
|
||||||
|
var navEntries = []navEntry{
|
||||||
|
{"page", "Hypha"},
|
||||||
|
{"edit", "Edit"},
|
||||||
|
{"text", "Raw text"},
|
||||||
|
{"history", "History"},
|
||||||
|
{"revision", "NOT REACHED"},
|
||||||
|
{"delete-ask", "Delete"},
|
||||||
|
{"rename-ask", "Rename"},
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
{% func navHTML(hyphaName, navType string, revisionHash ...string) %}
|
||||||
|
<nav>
|
||||||
|
<ul>
|
||||||
|
{%- for _, entry := range navEntries -%}
|
||||||
|
{%- if navType == "revision" && entry.path == "revision" -%}
|
||||||
|
<li><b>{%s revisionHash[0] %}</b></li>
|
||||||
|
{%- elseif navType == entry.path -%}
|
||||||
|
<li><b>{%s entry.title %}</b></li>
|
||||||
|
{%- elseif entry.path != "revision"-%}
|
||||||
|
<li><a href="/{%s entry.path %}/{%s hyphaName %}">{%s entry.title %}</a></li>
|
||||||
|
{%- endif -%}
|
||||||
|
{%- endfor -%}
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
{% endfunc %}
|
117
templates/common.qtpl.go
Normal file
117
templates/common.qtpl.go
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
// Code generated by qtc from "common.qtpl". DO NOT EDIT.
|
||||||
|
// See https://github.com/valyala/quicktemplate for details.
|
||||||
|
|
||||||
|
// This is the <nav> seen on top of many pages.
|
||||||
|
|
||||||
|
//line templates/common.qtpl:2
|
||||||
|
package templates
|
||||||
|
|
||||||
|
//line templates/common.qtpl:2
|
||||||
|
import (
|
||||||
|
qtio422016 "io"
|
||||||
|
|
||||||
|
qt422016 "github.com/valyala/quicktemplate"
|
||||||
|
)
|
||||||
|
|
||||||
|
//line templates/common.qtpl:2
|
||||||
|
var (
|
||||||
|
_ = qtio422016.Copy
|
||||||
|
_ = qt422016.AcquireByteBuffer
|
||||||
|
)
|
||||||
|
|
||||||
|
//line templates/common.qtpl:3
|
||||||
|
type navEntry struct {
|
||||||
|
path string
|
||||||
|
title string
|
||||||
|
}
|
||||||
|
|
||||||
|
var navEntries = []navEntry{
|
||||||
|
{"page", "Hypha"},
|
||||||
|
{"edit", "Edit"},
|
||||||
|
{"text", "Raw text"},
|
||||||
|
{"history", "History"},
|
||||||
|
{"revision", "NOT REACHED"},
|
||||||
|
{"delete-ask", "Delete"},
|
||||||
|
{"rename-ask", "Rename"},
|
||||||
|
}
|
||||||
|
|
||||||
|
//line templates/common.qtpl:18
|
||||||
|
func streamnavHTML(qw422016 *qt422016.Writer, hyphaName, navType string, revisionHash ...string) {
|
||||||
|
//line templates/common.qtpl:18
|
||||||
|
qw422016.N().S(`
|
||||||
|
<nav>
|
||||||
|
<ul>
|
||||||
|
`)
|
||||||
|
//line templates/common.qtpl:21
|
||||||
|
for _, entry := range navEntries {
|
||||||
|
//line templates/common.qtpl:22
|
||||||
|
if navType == "revision" && entry.path == "revision" {
|
||||||
|
//line templates/common.qtpl:22
|
||||||
|
qw422016.N().S(` <li><b>`)
|
||||||
|
//line templates/common.qtpl:23
|
||||||
|
qw422016.E().S(revisionHash[0])
|
||||||
|
//line templates/common.qtpl:23
|
||||||
|
qw422016.N().S(`</b></li>
|
||||||
|
`)
|
||||||
|
//line templates/common.qtpl:24
|
||||||
|
} else if navType == entry.path {
|
||||||
|
//line templates/common.qtpl:24
|
||||||
|
qw422016.N().S(` <li><b>`)
|
||||||
|
//line templates/common.qtpl:25
|
||||||
|
qw422016.E().S(entry.title)
|
||||||
|
//line templates/common.qtpl:25
|
||||||
|
qw422016.N().S(`</b></li>
|
||||||
|
`)
|
||||||
|
//line templates/common.qtpl:26
|
||||||
|
} else if entry.path != "revision" {
|
||||||
|
//line templates/common.qtpl:26
|
||||||
|
qw422016.N().S(` <li><a href="/`)
|
||||||
|
//line templates/common.qtpl:27
|
||||||
|
qw422016.E().S(entry.path)
|
||||||
|
//line templates/common.qtpl:27
|
||||||
|
qw422016.N().S(`/`)
|
||||||
|
//line templates/common.qtpl:27
|
||||||
|
qw422016.E().S(hyphaName)
|
||||||
|
//line templates/common.qtpl:27
|
||||||
|
qw422016.N().S(`">`)
|
||||||
|
//line templates/common.qtpl:27
|
||||||
|
qw422016.E().S(entry.title)
|
||||||
|
//line templates/common.qtpl:27
|
||||||
|
qw422016.N().S(`</a></li>
|
||||||
|
`)
|
||||||
|
//line templates/common.qtpl:28
|
||||||
|
}
|
||||||
|
//line templates/common.qtpl:29
|
||||||
|
}
|
||||||
|
//line templates/common.qtpl:29
|
||||||
|
qw422016.N().S(` </ul>
|
||||||
|
</nav>
|
||||||
|
`)
|
||||||
|
//line templates/common.qtpl:32
|
||||||
|
}
|
||||||
|
|
||||||
|
//line templates/common.qtpl:32
|
||||||
|
func writenavHTML(qq422016 qtio422016.Writer, hyphaName, navType string, revisionHash ...string) {
|
||||||
|
//line templates/common.qtpl:32
|
||||||
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
|
//line templates/common.qtpl:32
|
||||||
|
streamnavHTML(qw422016, hyphaName, navType, revisionHash...)
|
||||||
|
//line templates/common.qtpl:32
|
||||||
|
qt422016.ReleaseWriter(qw422016)
|
||||||
|
//line templates/common.qtpl:32
|
||||||
|
}
|
||||||
|
|
||||||
|
//line templates/common.qtpl:32
|
||||||
|
func navHTML(hyphaName, navType string, revisionHash ...string) string {
|
||||||
|
//line templates/common.qtpl:32
|
||||||
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
|
//line templates/common.qtpl:32
|
||||||
|
writenavHTML(qb422016, hyphaName, navType, revisionHash...)
|
||||||
|
//line templates/common.qtpl:32
|
||||||
|
qs422016 := string(qb422016.B)
|
||||||
|
//line templates/common.qtpl:32
|
||||||
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
|
//line templates/common.qtpl:32
|
||||||
|
return qs422016
|
||||||
|
//line templates/common.qtpl:32
|
||||||
|
}
|
25
templates/http_delete.qtpl
Normal file
25
templates/http_delete.qtpl
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
This dialog is to be shown to a user when they try to delete a hypha.
|
||||||
|
{% func DeleteAskHTML(hyphaName string, isOld bool) %}
|
||||||
|
<main>
|
||||||
|
{%= navHTML(hyphaName, "delete-ask") %}
|
||||||
|
{% if isOld %}
|
||||||
|
<section>
|
||||||
|
<h1>Delete {%s hyphaName %}?</h1>
|
||||||
|
<p>Do you really want to delete hypha <em>{%s hyphaName %}</em>?</p>
|
||||||
|
<p>In this version of MycorrhizaWiki you cannot undelete a deleted hypha but the history can still be accessed.</p>
|
||||||
|
<p><a href="/delete-confirm/{%s hyphaName %}"><strong>Confirm</strong></a></p>
|
||||||
|
<p><a href="/page/{%s hyphaName %}">Cancel</a></p>
|
||||||
|
</section>
|
||||||
|
{% else %}
|
||||||
|
{%= cannotDeleteDueToNonExistence(hyphaName) %}
|
||||||
|
{% endif %}
|
||||||
|
</main>
|
||||||
|
{% endfunc %}
|
||||||
|
|
||||||
|
{% func cannotDeleteDueToNonExistence(hyphaName string) %}
|
||||||
|
<section>
|
||||||
|
<h1>Cannot delete {%s hyphaName %}</h1>
|
||||||
|
<p>This hypha does not exist.</p>
|
||||||
|
<p><a href="/page/{%s hyphaName %}">Go back</a></p>
|
||||||
|
</section>
|
||||||
|
{% endfunc %}
|
151
templates/http_delete.qtpl.go
Normal file
151
templates/http_delete.qtpl.go
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
// Code generated by qtc from "http_delete.qtpl". DO NOT EDIT.
|
||||||
|
// See https://github.com/valyala/quicktemplate for details.
|
||||||
|
|
||||||
|
// This dialog is to be shown to a user when they try to delete a hypha.
|
||||||
|
|
||||||
|
//line templates/http_delete.qtpl:2
|
||||||
|
package templates
|
||||||
|
|
||||||
|
//line templates/http_delete.qtpl:2
|
||||||
|
import (
|
||||||
|
qtio422016 "io"
|
||||||
|
|
||||||
|
qt422016 "github.com/valyala/quicktemplate"
|
||||||
|
)
|
||||||
|
|
||||||
|
//line templates/http_delete.qtpl:2
|
||||||
|
var (
|
||||||
|
_ = qtio422016.Copy
|
||||||
|
_ = qt422016.AcquireByteBuffer
|
||||||
|
)
|
||||||
|
|
||||||
|
//line templates/http_delete.qtpl:2
|
||||||
|
func StreamDeleteAskHTML(qw422016 *qt422016.Writer, hyphaName string, isOld bool) {
|
||||||
|
//line templates/http_delete.qtpl:2
|
||||||
|
qw422016.N().S(`
|
||||||
|
<main>
|
||||||
|
`)
|
||||||
|
//line templates/http_delete.qtpl:4
|
||||||
|
streamnavHTML(qw422016, hyphaName, "delete-ask")
|
||||||
|
//line templates/http_delete.qtpl:4
|
||||||
|
qw422016.N().S(`
|
||||||
|
`)
|
||||||
|
//line templates/http_delete.qtpl:5
|
||||||
|
if isOld {
|
||||||
|
//line templates/http_delete.qtpl:5
|
||||||
|
qw422016.N().S(`
|
||||||
|
<section>
|
||||||
|
<h1>Delete `)
|
||||||
|
//line templates/http_delete.qtpl:7
|
||||||
|
qw422016.E().S(hyphaName)
|
||||||
|
//line templates/http_delete.qtpl:7
|
||||||
|
qw422016.N().S(`?</h1>
|
||||||
|
<p>Do you really want to delete hypha <em>`)
|
||||||
|
//line templates/http_delete.qtpl:8
|
||||||
|
qw422016.E().S(hyphaName)
|
||||||
|
//line templates/http_delete.qtpl:8
|
||||||
|
qw422016.N().S(`</em>?</p>
|
||||||
|
<p>In this version of MycorrhizaWiki you cannot undelete a deleted hypha but the history can still be accessed.</p>
|
||||||
|
<p><a href="/delete-confirm/`)
|
||||||
|
//line templates/http_delete.qtpl:10
|
||||||
|
qw422016.E().S(hyphaName)
|
||||||
|
//line templates/http_delete.qtpl:10
|
||||||
|
qw422016.N().S(`"><strong>Confirm</strong></a></p>
|
||||||
|
<p><a href="/page/`)
|
||||||
|
//line templates/http_delete.qtpl:11
|
||||||
|
qw422016.E().S(hyphaName)
|
||||||
|
//line templates/http_delete.qtpl:11
|
||||||
|
qw422016.N().S(`">Cancel</a></p>
|
||||||
|
</section>
|
||||||
|
`)
|
||||||
|
//line templates/http_delete.qtpl:13
|
||||||
|
} else {
|
||||||
|
//line templates/http_delete.qtpl:13
|
||||||
|
qw422016.N().S(`
|
||||||
|
`)
|
||||||
|
//line templates/http_delete.qtpl:14
|
||||||
|
streamcannotDeleteDueToNonExistence(qw422016, hyphaName)
|
||||||
|
//line templates/http_delete.qtpl:14
|
||||||
|
qw422016.N().S(`
|
||||||
|
`)
|
||||||
|
//line templates/http_delete.qtpl:15
|
||||||
|
}
|
||||||
|
//line templates/http_delete.qtpl:15
|
||||||
|
qw422016.N().S(`
|
||||||
|
</main>
|
||||||
|
`)
|
||||||
|
//line templates/http_delete.qtpl:17
|
||||||
|
}
|
||||||
|
|
||||||
|
//line templates/http_delete.qtpl:17
|
||||||
|
func WriteDeleteAskHTML(qq422016 qtio422016.Writer, hyphaName string, isOld bool) {
|
||||||
|
//line templates/http_delete.qtpl:17
|
||||||
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
|
//line templates/http_delete.qtpl:17
|
||||||
|
StreamDeleteAskHTML(qw422016, hyphaName, isOld)
|
||||||
|
//line templates/http_delete.qtpl:17
|
||||||
|
qt422016.ReleaseWriter(qw422016)
|
||||||
|
//line templates/http_delete.qtpl:17
|
||||||
|
}
|
||||||
|
|
||||||
|
//line templates/http_delete.qtpl:17
|
||||||
|
func DeleteAskHTML(hyphaName string, isOld bool) string {
|
||||||
|
//line templates/http_delete.qtpl:17
|
||||||
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
|
//line templates/http_delete.qtpl:17
|
||||||
|
WriteDeleteAskHTML(qb422016, hyphaName, isOld)
|
||||||
|
//line templates/http_delete.qtpl:17
|
||||||
|
qs422016 := string(qb422016.B)
|
||||||
|
//line templates/http_delete.qtpl:17
|
||||||
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
|
//line templates/http_delete.qtpl:17
|
||||||
|
return qs422016
|
||||||
|
//line templates/http_delete.qtpl:17
|
||||||
|
}
|
||||||
|
|
||||||
|
//line templates/http_delete.qtpl:19
|
||||||
|
func streamcannotDeleteDueToNonExistence(qw422016 *qt422016.Writer, hyphaName string) {
|
||||||
|
//line templates/http_delete.qtpl:19
|
||||||
|
qw422016.N().S(`
|
||||||
|
<section>
|
||||||
|
<h1>Cannot delete `)
|
||||||
|
//line templates/http_delete.qtpl:21
|
||||||
|
qw422016.E().S(hyphaName)
|
||||||
|
//line templates/http_delete.qtpl:21
|
||||||
|
qw422016.N().S(`</h1>
|
||||||
|
<p>This hypha does not exist.</p>
|
||||||
|
<p><a href="/page/`)
|
||||||
|
//line templates/http_delete.qtpl:23
|
||||||
|
qw422016.E().S(hyphaName)
|
||||||
|
//line templates/http_delete.qtpl:23
|
||||||
|
qw422016.N().S(`">Go back</a></p>
|
||||||
|
</section>
|
||||||
|
`)
|
||||||
|
//line templates/http_delete.qtpl:25
|
||||||
|
}
|
||||||
|
|
||||||
|
//line templates/http_delete.qtpl:25
|
||||||
|
func writecannotDeleteDueToNonExistence(qq422016 qtio422016.Writer, hyphaName string) {
|
||||||
|
//line templates/http_delete.qtpl:25
|
||||||
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
|
//line templates/http_delete.qtpl:25
|
||||||
|
streamcannotDeleteDueToNonExistence(qw422016, hyphaName)
|
||||||
|
//line templates/http_delete.qtpl:25
|
||||||
|
qt422016.ReleaseWriter(qw422016)
|
||||||
|
//line templates/http_delete.qtpl:25
|
||||||
|
}
|
||||||
|
|
||||||
|
//line templates/http_delete.qtpl:25
|
||||||
|
func cannotDeleteDueToNonExistence(hyphaName string) string {
|
||||||
|
//line templates/http_delete.qtpl:25
|
||||||
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
|
//line templates/http_delete.qtpl:25
|
||||||
|
writecannotDeleteDueToNonExistence(qb422016, hyphaName)
|
||||||
|
//line templates/http_delete.qtpl:25
|
||||||
|
qs422016 := string(qb422016.B)
|
||||||
|
//line templates/http_delete.qtpl:25
|
||||||
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
|
//line templates/http_delete.qtpl:25
|
||||||
|
return qs422016
|
||||||
|
//line templates/http_delete.qtpl:25
|
||||||
|
}
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
{% func EditHTML(hyphaName, textAreaFill, warning string) %}
|
{% func EditHTML(hyphaName, textAreaFill, warning string) %}
|
||||||
<main>
|
<main>
|
||||||
<h1>Edit {%s hyphaName %}</h1>
|
<h1>Edit {%s hyphaName %}</h1>
|
||||||
|
@ -1,83 +1,83 @@
|
|||||||
// Code generated by qtc from "http_mutators.qtpl". DO NOT EDIT.
|
// Code generated by qtc from "http_mutators.qtpl". DO NOT EDIT.
|
||||||
// See https://github.com/valyala/quicktemplate for details.
|
// See https://github.com/valyala/quicktemplate for details.
|
||||||
|
|
||||||
//line templates/http_mutators.qtpl:2
|
//line templates/http_mutators.qtpl:1
|
||||||
package templates
|
package templates
|
||||||
|
|
||||||
//line templates/http_mutators.qtpl:2
|
//line templates/http_mutators.qtpl:1
|
||||||
import (
|
import (
|
||||||
qtio422016 "io"
|
qtio422016 "io"
|
||||||
|
|
||||||
qt422016 "github.com/valyala/quicktemplate"
|
qt422016 "github.com/valyala/quicktemplate"
|
||||||
)
|
)
|
||||||
|
|
||||||
//line templates/http_mutators.qtpl:2
|
//line templates/http_mutators.qtpl:1
|
||||||
var (
|
var (
|
||||||
_ = qtio422016.Copy
|
_ = qtio422016.Copy
|
||||||
_ = qt422016.AcquireByteBuffer
|
_ = qt422016.AcquireByteBuffer
|
||||||
)
|
)
|
||||||
|
|
||||||
//line templates/http_mutators.qtpl:2
|
//line templates/http_mutators.qtpl:1
|
||||||
func StreamEditHTML(qw422016 *qt422016.Writer, hyphaName, textAreaFill, warning string) {
|
func StreamEditHTML(qw422016 *qt422016.Writer, hyphaName, textAreaFill, warning string) {
|
||||||
//line templates/http_mutators.qtpl:2
|
//line templates/http_mutators.qtpl:1
|
||||||
qw422016.N().S(`
|
qw422016.N().S(`
|
||||||
<main>
|
<main>
|
||||||
<h1>Edit `)
|
<h1>Edit `)
|
||||||
//line templates/http_mutators.qtpl:4
|
//line templates/http_mutators.qtpl:3
|
||||||
qw422016.E().S(hyphaName)
|
qw422016.E().S(hyphaName)
|
||||||
//line templates/http_mutators.qtpl:4
|
//line templates/http_mutators.qtpl:3
|
||||||
qw422016.N().S(`</h1>
|
qw422016.N().S(`</h1>
|
||||||
`)
|
`)
|
||||||
//line templates/http_mutators.qtpl:5
|
//line templates/http_mutators.qtpl:4
|
||||||
qw422016.N().S(warning)
|
qw422016.N().S(warning)
|
||||||
//line templates/http_mutators.qtpl:5
|
//line templates/http_mutators.qtpl:4
|
||||||
qw422016.N().S(`
|
qw422016.N().S(`
|
||||||
<form method="post" class="upload-text-form"
|
<form method="post" class="upload-text-form"
|
||||||
action="/upload-text/`)
|
action="/upload-text/`)
|
||||||
//line templates/http_mutators.qtpl:7
|
//line templates/http_mutators.qtpl:6
|
||||||
qw422016.E().S(hyphaName)
|
qw422016.E().S(hyphaName)
|
||||||
//line templates/http_mutators.qtpl:7
|
//line templates/http_mutators.qtpl:6
|
||||||
qw422016.N().S(`">
|
qw422016.N().S(`">
|
||||||
<textarea name="text">`)
|
<textarea name="text">`)
|
||||||
//line templates/http_mutators.qtpl:8
|
//line templates/http_mutators.qtpl:7
|
||||||
qw422016.E().S(textAreaFill)
|
qw422016.E().S(textAreaFill)
|
||||||
//line templates/http_mutators.qtpl:8
|
//line templates/http_mutators.qtpl:7
|
||||||
qw422016.N().S(`</textarea>
|
qw422016.N().S(`</textarea>
|
||||||
<br/>
|
<br/>
|
||||||
<input type="submit"/>
|
<input type="submit"/>
|
||||||
<a href="/page/`)
|
<a href="/page/`)
|
||||||
//line templates/http_mutators.qtpl:11
|
//line templates/http_mutators.qtpl:10
|
||||||
qw422016.E().S(hyphaName)
|
qw422016.E().S(hyphaName)
|
||||||
//line templates/http_mutators.qtpl:11
|
//line templates/http_mutators.qtpl:10
|
||||||
qw422016.N().S(`">Cancel</a>
|
qw422016.N().S(`">Cancel</a>
|
||||||
</form>
|
</form>
|
||||||
</main>
|
</main>
|
||||||
`)
|
`)
|
||||||
//line templates/http_mutators.qtpl:14
|
//line templates/http_mutators.qtpl:13
|
||||||
}
|
}
|
||||||
|
|
||||||
//line templates/http_mutators.qtpl:14
|
//line templates/http_mutators.qtpl:13
|
||||||
func WriteEditHTML(qq422016 qtio422016.Writer, hyphaName, textAreaFill, warning string) {
|
func WriteEditHTML(qq422016 qtio422016.Writer, hyphaName, textAreaFill, warning string) {
|
||||||
//line templates/http_mutators.qtpl:14
|
//line templates/http_mutators.qtpl:13
|
||||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
//line templates/http_mutators.qtpl:14
|
//line templates/http_mutators.qtpl:13
|
||||||
StreamEditHTML(qw422016, hyphaName, textAreaFill, warning)
|
StreamEditHTML(qw422016, hyphaName, textAreaFill, warning)
|
||||||
//line templates/http_mutators.qtpl:14
|
//line templates/http_mutators.qtpl:13
|
||||||
qt422016.ReleaseWriter(qw422016)
|
qt422016.ReleaseWriter(qw422016)
|
||||||
//line templates/http_mutators.qtpl:14
|
//line templates/http_mutators.qtpl:13
|
||||||
}
|
}
|
||||||
|
|
||||||
//line templates/http_mutators.qtpl:14
|
//line templates/http_mutators.qtpl:13
|
||||||
func EditHTML(hyphaName, textAreaFill, warning string) string {
|
func EditHTML(hyphaName, textAreaFill, warning string) string {
|
||||||
//line templates/http_mutators.qtpl:14
|
//line templates/http_mutators.qtpl:13
|
||||||
qb422016 := qt422016.AcquireByteBuffer()
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
//line templates/http_mutators.qtpl:14
|
//line templates/http_mutators.qtpl:13
|
||||||
WriteEditHTML(qb422016, hyphaName, textAreaFill, warning)
|
WriteEditHTML(qb422016, hyphaName, textAreaFill, warning)
|
||||||
//line templates/http_mutators.qtpl:14
|
//line templates/http_mutators.qtpl:13
|
||||||
qs422016 := string(qb422016.B)
|
qs422016 := string(qb422016.B)
|
||||||
//line templates/http_mutators.qtpl:14
|
//line templates/http_mutators.qtpl:13
|
||||||
qt422016.ReleaseByteBuffer(qb422016)
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
//line templates/http_mutators.qtpl:14
|
//line templates/http_mutators.qtpl:13
|
||||||
return qs422016
|
return qs422016
|
||||||
//line templates/http_mutators.qtpl:14
|
//line templates/http_mutators.qtpl:13
|
||||||
}
|
}
|
||||||
|
@ -1,81 +1,59 @@
|
|||||||
{% func HistoryHTML(hyphaName, tbody string) %}
|
{% func HistoryHTML(hyphaName, tbody string) %}
|
||||||
<main>
|
<main>
|
||||||
<nav>
|
{%= navHTML(hyphaName, "history") %}
|
||||||
<ul>
|
<table>
|
||||||
<li><a href="/page/{%s hyphaName %}">Hypha</a></li>
|
<thead>
|
||||||
<li><a href="/edit/{%s hyphaName %}">Edit</a></li>
|
<tr>
|
||||||
<li><a href="/text/{%s hyphaName %}">Raw text</a></li>
|
<th>Time</th>
|
||||||
<li><b>History</b></li>
|
<th>Hash</th>
|
||||||
</ul>
|
<th>Message</th>
|
||||||
</nav>
|
</tr>
|
||||||
<table>
|
</thead>
|
||||||
<thead>
|
<tbody>
|
||||||
<tr>
|
{%s= tbody %}
|
||||||
<th>Time</th>
|
</tbody>
|
||||||
<th>Hash</th>
|
</table>
|
||||||
<th>Message</th>
|
</main>
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{%s= tbody %}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</main>
|
|
||||||
{% endfunc %}
|
{% endfunc %}
|
||||||
|
|
||||||
{% func RevisionHTML(hyphaName, naviTitle, contents, tree, revHash string) %}
|
{% func RevisionHTML(hyphaName, naviTitle, contents, tree, revHash string) %}
|
||||||
<main>
|
<main>
|
||||||
<nav>
|
{%= navHTML(hyphaName, "revision", revHash) %}
|
||||||
<ul>
|
<article>
|
||||||
<li><a href="/page/{%s hyphaName %}">Hypha</a></li>
|
<p>Please note that viewing binary parts of hyphae is not supported in history for now.</p>
|
||||||
<li><a href="/edit/{%s hyphaName %}">Edit</a></li>
|
{%s= naviTitle %}
|
||||||
<li><a href="/text/{%s hyphaName %}">Raw text</a></li>
|
{%s= contents %}
|
||||||
<li><a href="/history/{%s hyphaName %}">History</a></li>
|
</article>
|
||||||
<li><b>{%s revHash %}</b></li>
|
<hr/>
|
||||||
</ul>
|
<aside>
|
||||||
</nav>
|
{%s= tree %}
|
||||||
<article>
|
</aside>
|
||||||
<p>Please note that viewing binary parts of hyphae is not supported in history for now.</p>
|
</main>
|
||||||
{%s= naviTitle %}
|
|
||||||
{%s= contents %}
|
|
||||||
</article>
|
|
||||||
<hr/>
|
|
||||||
<aside>
|
|
||||||
{%s= tree %}
|
|
||||||
</aside>
|
|
||||||
</main>
|
|
||||||
{% endfunc %}
|
{% endfunc %}
|
||||||
|
|
||||||
If `contents` == "", a helpful message is shown instead.
|
If `contents` == "", a helpful message is shown instead.
|
||||||
{% func PageHTML(hyphaName, naviTitle, contents, tree string) %}
|
{% func PageHTML(hyphaName, naviTitle, contents, tree string) %}
|
||||||
<main>
|
<main>
|
||||||
<nav>
|
{%= navHTML(hyphaName, "page") %}
|
||||||
<ul>
|
<article>
|
||||||
<li><b>Hypha</b></li>
|
{%s= naviTitle %}
|
||||||
<li><a href="/edit/{%s hyphaName %}">Edit</a></li>
|
{% if contents == "" %}
|
||||||
<li><a href="/text/{%s hyphaName %}">Raw text</a></li>
|
<p>This hypha has no text. Why not <a href="/edit/{%s hyphaName %}">create it</a>?</p>
|
||||||
<li><a href="/history/{%s hyphaName %}">History</a></li>
|
{% else %}
|
||||||
</ul>
|
{%s= contents %}
|
||||||
</nav>
|
{% endif %}
|
||||||
<article>
|
</article>
|
||||||
{%s= naviTitle %}
|
<hr/>
|
||||||
{% if contents == "" %}
|
<form action="/upload-binary/{%s hyphaName %}"
|
||||||
<p>This hypha has no text. Why not <a href="/edit/{%s hyphaName %}">create it</a>?</p>
|
method="post" enctype="multipart/form-data">
|
||||||
{% else %}
|
<label for="upload-binary__input">Upload new binary part</label>
|
||||||
{%s= contents %}
|
<br>
|
||||||
{% endif %}
|
<input type="file" id="upload-binary__input" name="binary"/>
|
||||||
</article>
|
<input type="submit"/>
|
||||||
<hr/>
|
</form>
|
||||||
<form action="/upload-binary/{%s hyphaName %}"
|
<hr/>
|
||||||
method="post" enctype="multipart/form-data">
|
<aside>
|
||||||
<label for="upload-binary__input">Upload new binary part</label>
|
{%s= tree %}
|
||||||
<br>
|
</aside>
|
||||||
<input type="file" id="upload-binary__input" name="binary"/>
|
</main>
|
||||||
<input type="submit"/>
|
|
||||||
</form>
|
|
||||||
<hr/>
|
|
||||||
<aside>
|
|
||||||
{%s= tree %}
|
|
||||||
</aside>
|
|
||||||
</main>
|
|
||||||
{% endfunc %}
|
{% endfunc %}
|
||||||
|
@ -21,266 +21,212 @@ var (
|
|||||||
func StreamHistoryHTML(qw422016 *qt422016.Writer, hyphaName, tbody string) {
|
func StreamHistoryHTML(qw422016 *qt422016.Writer, hyphaName, tbody string) {
|
||||||
//line templates/http_readers.qtpl:1
|
//line templates/http_readers.qtpl:1
|
||||||
qw422016.N().S(`
|
qw422016.N().S(`
|
||||||
<main>
|
<main>
|
||||||
<nav>
|
`)
|
||||||
<ul>
|
//line templates/http_readers.qtpl:3
|
||||||
<li><a href="/page/`)
|
streamnavHTML(qw422016, hyphaName, "history")
|
||||||
//line templates/http_readers.qtpl:5
|
//line templates/http_readers.qtpl:3
|
||||||
qw422016.E().S(hyphaName)
|
qw422016.N().S(`
|
||||||
//line templates/http_readers.qtpl:5
|
<table>
|
||||||
qw422016.N().S(`">Hypha</a></li>
|
<thead>
|
||||||
<li><a href="/edit/`)
|
<tr>
|
||||||
//line templates/http_readers.qtpl:6
|
<th>Time</th>
|
||||||
qw422016.E().S(hyphaName)
|
<th>Hash</th>
|
||||||
//line templates/http_readers.qtpl:6
|
<th>Message</th>
|
||||||
qw422016.N().S(`">Edit</a></li>
|
</tr>
|
||||||
<li><a href="/text/`)
|
</thead>
|
||||||
//line templates/http_readers.qtpl:7
|
<tbody>
|
||||||
qw422016.E().S(hyphaName)
|
`)
|
||||||
//line templates/http_readers.qtpl:7
|
//line templates/http_readers.qtpl:13
|
||||||
qw422016.N().S(`">Raw text</a></li>
|
|
||||||
<li><b>History</b></li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Time</th>
|
|
||||||
<th>Hash</th>
|
|
||||||
<th>Message</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
`)
|
|
||||||
//line templates/http_readers.qtpl:20
|
|
||||||
qw422016.N().S(tbody)
|
qw422016.N().S(tbody)
|
||||||
//line templates/http_readers.qtpl:20
|
//line templates/http_readers.qtpl:13
|
||||||
qw422016.N().S(`
|
qw422016.N().S(`
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</main>
|
</main>
|
||||||
`)
|
`)
|
||||||
//line templates/http_readers.qtpl:24
|
//line templates/http_readers.qtpl:17
|
||||||
}
|
}
|
||||||
|
|
||||||
//line templates/http_readers.qtpl:24
|
//line templates/http_readers.qtpl:17
|
||||||
func WriteHistoryHTML(qq422016 qtio422016.Writer, hyphaName, tbody string) {
|
func WriteHistoryHTML(qq422016 qtio422016.Writer, hyphaName, tbody string) {
|
||||||
//line templates/http_readers.qtpl:24
|
//line templates/http_readers.qtpl:17
|
||||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
//line templates/http_readers.qtpl:24
|
//line templates/http_readers.qtpl:17
|
||||||
StreamHistoryHTML(qw422016, hyphaName, tbody)
|
StreamHistoryHTML(qw422016, hyphaName, tbody)
|
||||||
//line templates/http_readers.qtpl:24
|
//line templates/http_readers.qtpl:17
|
||||||
qt422016.ReleaseWriter(qw422016)
|
qt422016.ReleaseWriter(qw422016)
|
||||||
//line templates/http_readers.qtpl:24
|
//line templates/http_readers.qtpl:17
|
||||||
}
|
}
|
||||||
|
|
||||||
//line templates/http_readers.qtpl:24
|
//line templates/http_readers.qtpl:17
|
||||||
func HistoryHTML(hyphaName, tbody string) string {
|
func HistoryHTML(hyphaName, tbody string) string {
|
||||||
//line templates/http_readers.qtpl:24
|
//line templates/http_readers.qtpl:17
|
||||||
qb422016 := qt422016.AcquireByteBuffer()
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
//line templates/http_readers.qtpl:24
|
//line templates/http_readers.qtpl:17
|
||||||
WriteHistoryHTML(qb422016, hyphaName, tbody)
|
WriteHistoryHTML(qb422016, hyphaName, tbody)
|
||||||
//line templates/http_readers.qtpl:24
|
//line templates/http_readers.qtpl:17
|
||||||
qs422016 := string(qb422016.B)
|
qs422016 := string(qb422016.B)
|
||||||
//line templates/http_readers.qtpl:24
|
//line templates/http_readers.qtpl:17
|
||||||
qt422016.ReleaseByteBuffer(qb422016)
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
//line templates/http_readers.qtpl:24
|
//line templates/http_readers.qtpl:17
|
||||||
return qs422016
|
return qs422016
|
||||||
//line templates/http_readers.qtpl:24
|
//line templates/http_readers.qtpl:17
|
||||||
}
|
}
|
||||||
|
|
||||||
//line templates/http_readers.qtpl:26
|
//line templates/http_readers.qtpl:19
|
||||||
func StreamRevisionHTML(qw422016 *qt422016.Writer, hyphaName, naviTitle, contents, tree, revHash string) {
|
func StreamRevisionHTML(qw422016 *qt422016.Writer, hyphaName, naviTitle, contents, tree, revHash string) {
|
||||||
//line templates/http_readers.qtpl:26
|
//line templates/http_readers.qtpl:19
|
||||||
qw422016.N().S(`
|
qw422016.N().S(`
|
||||||
<main>
|
<main>
|
||||||
<nav>
|
|
||||||
<ul>
|
|
||||||
<li><a href="/page/`)
|
|
||||||
//line templates/http_readers.qtpl:30
|
|
||||||
qw422016.E().S(hyphaName)
|
|
||||||
//line templates/http_readers.qtpl:30
|
|
||||||
qw422016.N().S(`">Hypha</a></li>
|
|
||||||
<li><a href="/edit/`)
|
|
||||||
//line templates/http_readers.qtpl:31
|
|
||||||
qw422016.E().S(hyphaName)
|
|
||||||
//line templates/http_readers.qtpl:31
|
|
||||||
qw422016.N().S(`">Edit</a></li>
|
|
||||||
<li><a href="/text/`)
|
|
||||||
//line templates/http_readers.qtpl:32
|
|
||||||
qw422016.E().S(hyphaName)
|
|
||||||
//line templates/http_readers.qtpl:32
|
|
||||||
qw422016.N().S(`">Raw text</a></li>
|
|
||||||
<li><a href="/history/`)
|
|
||||||
//line templates/http_readers.qtpl:33
|
|
||||||
qw422016.E().S(hyphaName)
|
|
||||||
//line templates/http_readers.qtpl:33
|
|
||||||
qw422016.N().S(`">History</a></li>
|
|
||||||
<li><b>`)
|
|
||||||
//line templates/http_readers.qtpl:34
|
|
||||||
qw422016.E().S(revHash)
|
|
||||||
//line templates/http_readers.qtpl:34
|
|
||||||
qw422016.N().S(`</b></li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
<article>
|
|
||||||
<p>Please note that viewing binary parts of hyphae is not supported in history for now.</p>
|
|
||||||
`)
|
|
||||||
//line templates/http_readers.qtpl:39
|
|
||||||
qw422016.N().S(naviTitle)
|
|
||||||
//line templates/http_readers.qtpl:39
|
|
||||||
qw422016.N().S(`
|
|
||||||
`)
|
|
||||||
//line templates/http_readers.qtpl:40
|
|
||||||
qw422016.N().S(contents)
|
|
||||||
//line templates/http_readers.qtpl:40
|
|
||||||
qw422016.N().S(`
|
|
||||||
</article>
|
|
||||||
<hr/>
|
|
||||||
<aside>
|
|
||||||
`)
|
|
||||||
//line templates/http_readers.qtpl:44
|
|
||||||
qw422016.N().S(tree)
|
|
||||||
//line templates/http_readers.qtpl:44
|
|
||||||
qw422016.N().S(`
|
|
||||||
</aside>
|
|
||||||
</main>
|
|
||||||
`)
|
`)
|
||||||
//line templates/http_readers.qtpl:47
|
//line templates/http_readers.qtpl:21
|
||||||
|
streamnavHTML(qw422016, hyphaName, "revision", revHash)
|
||||||
|
//line templates/http_readers.qtpl:21
|
||||||
|
qw422016.N().S(`
|
||||||
|
<article>
|
||||||
|
<p>Please note that viewing binary parts of hyphae is not supported in history for now.</p>
|
||||||
|
`)
|
||||||
|
//line templates/http_readers.qtpl:24
|
||||||
|
qw422016.N().S(naviTitle)
|
||||||
|
//line templates/http_readers.qtpl:24
|
||||||
|
qw422016.N().S(`
|
||||||
|
`)
|
||||||
|
//line templates/http_readers.qtpl:25
|
||||||
|
qw422016.N().S(contents)
|
||||||
|
//line templates/http_readers.qtpl:25
|
||||||
|
qw422016.N().S(`
|
||||||
|
</article>
|
||||||
|
<hr/>
|
||||||
|
<aside>
|
||||||
|
`)
|
||||||
|
//line templates/http_readers.qtpl:29
|
||||||
|
qw422016.N().S(tree)
|
||||||
|
//line templates/http_readers.qtpl:29
|
||||||
|
qw422016.N().S(`
|
||||||
|
</aside>
|
||||||
|
</main>
|
||||||
|
`)
|
||||||
|
//line templates/http_readers.qtpl:32
|
||||||
}
|
}
|
||||||
|
|
||||||
//line templates/http_readers.qtpl:47
|
//line templates/http_readers.qtpl:32
|
||||||
func WriteRevisionHTML(qq422016 qtio422016.Writer, hyphaName, naviTitle, contents, tree, revHash string) {
|
func WriteRevisionHTML(qq422016 qtio422016.Writer, hyphaName, naviTitle, contents, tree, revHash string) {
|
||||||
//line templates/http_readers.qtpl:47
|
//line templates/http_readers.qtpl:32
|
||||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
//line templates/http_readers.qtpl:47
|
//line templates/http_readers.qtpl:32
|
||||||
StreamRevisionHTML(qw422016, hyphaName, naviTitle, contents, tree, revHash)
|
StreamRevisionHTML(qw422016, hyphaName, naviTitle, contents, tree, revHash)
|
||||||
//line templates/http_readers.qtpl:47
|
//line templates/http_readers.qtpl:32
|
||||||
qt422016.ReleaseWriter(qw422016)
|
qt422016.ReleaseWriter(qw422016)
|
||||||
//line templates/http_readers.qtpl:47
|
//line templates/http_readers.qtpl:32
|
||||||
}
|
}
|
||||||
|
|
||||||
//line templates/http_readers.qtpl:47
|
//line templates/http_readers.qtpl:32
|
||||||
func RevisionHTML(hyphaName, naviTitle, contents, tree, revHash string) string {
|
func RevisionHTML(hyphaName, naviTitle, contents, tree, revHash string) string {
|
||||||
//line templates/http_readers.qtpl:47
|
//line templates/http_readers.qtpl:32
|
||||||
qb422016 := qt422016.AcquireByteBuffer()
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
//line templates/http_readers.qtpl:47
|
//line templates/http_readers.qtpl:32
|
||||||
WriteRevisionHTML(qb422016, hyphaName, naviTitle, contents, tree, revHash)
|
WriteRevisionHTML(qb422016, hyphaName, naviTitle, contents, tree, revHash)
|
||||||
//line templates/http_readers.qtpl:47
|
//line templates/http_readers.qtpl:32
|
||||||
qs422016 := string(qb422016.B)
|
qs422016 := string(qb422016.B)
|
||||||
//line templates/http_readers.qtpl:47
|
//line templates/http_readers.qtpl:32
|
||||||
qt422016.ReleaseByteBuffer(qb422016)
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
//line templates/http_readers.qtpl:47
|
//line templates/http_readers.qtpl:32
|
||||||
return qs422016
|
return qs422016
|
||||||
//line templates/http_readers.qtpl:47
|
//line templates/http_readers.qtpl:32
|
||||||
}
|
}
|
||||||
|
|
||||||
// If `contents` == "", a helpful message is shown instead.
|
// If `contents` == "", a helpful message is shown instead.
|
||||||
|
|
||||||
//line templates/http_readers.qtpl:50
|
//line templates/http_readers.qtpl:35
|
||||||
func StreamPageHTML(qw422016 *qt422016.Writer, hyphaName, naviTitle, contents, tree string) {
|
func StreamPageHTML(qw422016 *qt422016.Writer, hyphaName, naviTitle, contents, tree string) {
|
||||||
//line templates/http_readers.qtpl:50
|
//line templates/http_readers.qtpl:35
|
||||||
qw422016.N().S(`
|
qw422016.N().S(`
|
||||||
<main>
|
<main>
|
||||||
<nav>
|
|
||||||
<ul>
|
|
||||||
<li><b>Hypha</b></li>
|
|
||||||
<li><a href="/edit/`)
|
|
||||||
//line templates/http_readers.qtpl:55
|
|
||||||
qw422016.E().S(hyphaName)
|
|
||||||
//line templates/http_readers.qtpl:55
|
|
||||||
qw422016.N().S(`">Edit</a></li>
|
|
||||||
<li><a href="/text/`)
|
|
||||||
//line templates/http_readers.qtpl:56
|
|
||||||
qw422016.E().S(hyphaName)
|
|
||||||
//line templates/http_readers.qtpl:56
|
|
||||||
qw422016.N().S(`">Raw text</a></li>
|
|
||||||
<li><a href="/history/`)
|
|
||||||
//line templates/http_readers.qtpl:57
|
|
||||||
qw422016.E().S(hyphaName)
|
|
||||||
//line templates/http_readers.qtpl:57
|
|
||||||
qw422016.N().S(`">History</a></li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
<article>
|
|
||||||
`)
|
|
||||||
//line templates/http_readers.qtpl:61
|
|
||||||
qw422016.N().S(naviTitle)
|
|
||||||
//line templates/http_readers.qtpl:61
|
|
||||||
qw422016.N().S(`
|
|
||||||
`)
|
|
||||||
//line templates/http_readers.qtpl:62
|
|
||||||
if contents == "" {
|
|
||||||
//line templates/http_readers.qtpl:62
|
|
||||||
qw422016.N().S(`
|
|
||||||
<p>This hypha has no text. Why not <a href="/edit/`)
|
|
||||||
//line templates/http_readers.qtpl:63
|
|
||||||
qw422016.E().S(hyphaName)
|
|
||||||
//line templates/http_readers.qtpl:63
|
|
||||||
qw422016.N().S(`">create it</a>?</p>
|
|
||||||
`)
|
|
||||||
//line templates/http_readers.qtpl:64
|
|
||||||
} else {
|
|
||||||
//line templates/http_readers.qtpl:64
|
|
||||||
qw422016.N().S(`
|
|
||||||
`)
|
|
||||||
//line templates/http_readers.qtpl:65
|
|
||||||
qw422016.N().S(contents)
|
|
||||||
//line templates/http_readers.qtpl:65
|
|
||||||
qw422016.N().S(`
|
|
||||||
`)
|
|
||||||
//line templates/http_readers.qtpl:66
|
|
||||||
}
|
|
||||||
//line templates/http_readers.qtpl:66
|
|
||||||
qw422016.N().S(`
|
|
||||||
</article>
|
|
||||||
<hr/>
|
|
||||||
<form action="/upload-binary/`)
|
|
||||||
//line templates/http_readers.qtpl:69
|
|
||||||
qw422016.E().S(hyphaName)
|
|
||||||
//line templates/http_readers.qtpl:69
|
|
||||||
qw422016.N().S(`"
|
|
||||||
method="post" enctype="multipart/form-data">
|
|
||||||
<label for="upload-binary__input">Upload new binary part</label>
|
|
||||||
<br>
|
|
||||||
<input type="file" id="upload-binary__input" name="binary"/>
|
|
||||||
<input type="submit"/>
|
|
||||||
</form>
|
|
||||||
<hr/>
|
|
||||||
<aside>
|
|
||||||
`)
|
|
||||||
//line templates/http_readers.qtpl:78
|
|
||||||
qw422016.N().S(tree)
|
|
||||||
//line templates/http_readers.qtpl:78
|
|
||||||
qw422016.N().S(`
|
|
||||||
</aside>
|
|
||||||
</main>
|
|
||||||
`)
|
`)
|
||||||
//line templates/http_readers.qtpl:81
|
//line templates/http_readers.qtpl:37
|
||||||
|
streamnavHTML(qw422016, hyphaName, "page")
|
||||||
|
//line templates/http_readers.qtpl:37
|
||||||
|
qw422016.N().S(`
|
||||||
|
<article>
|
||||||
|
`)
|
||||||
|
//line templates/http_readers.qtpl:39
|
||||||
|
qw422016.N().S(naviTitle)
|
||||||
|
//line templates/http_readers.qtpl:39
|
||||||
|
qw422016.N().S(`
|
||||||
|
`)
|
||||||
|
//line templates/http_readers.qtpl:40
|
||||||
|
if contents == "" {
|
||||||
|
//line templates/http_readers.qtpl:40
|
||||||
|
qw422016.N().S(`
|
||||||
|
<p>This hypha has no text. Why not <a href="/edit/`)
|
||||||
|
//line templates/http_readers.qtpl:41
|
||||||
|
qw422016.E().S(hyphaName)
|
||||||
|
//line templates/http_readers.qtpl:41
|
||||||
|
qw422016.N().S(`">create it</a>?</p>
|
||||||
|
`)
|
||||||
|
//line templates/http_readers.qtpl:42
|
||||||
|
} else {
|
||||||
|
//line templates/http_readers.qtpl:42
|
||||||
|
qw422016.N().S(`
|
||||||
|
`)
|
||||||
|
//line templates/http_readers.qtpl:43
|
||||||
|
qw422016.N().S(contents)
|
||||||
|
//line templates/http_readers.qtpl:43
|
||||||
|
qw422016.N().S(`
|
||||||
|
`)
|
||||||
|
//line templates/http_readers.qtpl:44
|
||||||
|
}
|
||||||
|
//line templates/http_readers.qtpl:44
|
||||||
|
qw422016.N().S(`
|
||||||
|
</article>
|
||||||
|
<hr/>
|
||||||
|
<form action="/upload-binary/`)
|
||||||
|
//line templates/http_readers.qtpl:47
|
||||||
|
qw422016.E().S(hyphaName)
|
||||||
|
//line templates/http_readers.qtpl:47
|
||||||
|
qw422016.N().S(`"
|
||||||
|
method="post" enctype="multipart/form-data">
|
||||||
|
<label for="upload-binary__input">Upload new binary part</label>
|
||||||
|
<br>
|
||||||
|
<input type="file" id="upload-binary__input" name="binary"/>
|
||||||
|
<input type="submit"/>
|
||||||
|
</form>
|
||||||
|
<hr/>
|
||||||
|
<aside>
|
||||||
|
`)
|
||||||
|
//line templates/http_readers.qtpl:56
|
||||||
|
qw422016.N().S(tree)
|
||||||
|
//line templates/http_readers.qtpl:56
|
||||||
|
qw422016.N().S(`
|
||||||
|
</aside>
|
||||||
|
</main>
|
||||||
|
`)
|
||||||
|
//line templates/http_readers.qtpl:59
|
||||||
}
|
}
|
||||||
|
|
||||||
//line templates/http_readers.qtpl:81
|
//line templates/http_readers.qtpl:59
|
||||||
func WritePageHTML(qq422016 qtio422016.Writer, hyphaName, naviTitle, contents, tree string) {
|
func WritePageHTML(qq422016 qtio422016.Writer, hyphaName, naviTitle, contents, tree string) {
|
||||||
//line templates/http_readers.qtpl:81
|
//line templates/http_readers.qtpl:59
|
||||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
//line templates/http_readers.qtpl:81
|
//line templates/http_readers.qtpl:59
|
||||||
StreamPageHTML(qw422016, hyphaName, naviTitle, contents, tree)
|
StreamPageHTML(qw422016, hyphaName, naviTitle, contents, tree)
|
||||||
//line templates/http_readers.qtpl:81
|
//line templates/http_readers.qtpl:59
|
||||||
qt422016.ReleaseWriter(qw422016)
|
qt422016.ReleaseWriter(qw422016)
|
||||||
//line templates/http_readers.qtpl:81
|
//line templates/http_readers.qtpl:59
|
||||||
}
|
}
|
||||||
|
|
||||||
//line templates/http_readers.qtpl:81
|
//line templates/http_readers.qtpl:59
|
||||||
func PageHTML(hyphaName, naviTitle, contents, tree string) string {
|
func PageHTML(hyphaName, naviTitle, contents, tree string) string {
|
||||||
//line templates/http_readers.qtpl:81
|
//line templates/http_readers.qtpl:59
|
||||||
qb422016 := qt422016.AcquireByteBuffer()
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
//line templates/http_readers.qtpl:81
|
//line templates/http_readers.qtpl:59
|
||||||
WritePageHTML(qb422016, hyphaName, naviTitle, contents, tree)
|
WritePageHTML(qb422016, hyphaName, naviTitle, contents, tree)
|
||||||
//line templates/http_readers.qtpl:81
|
//line templates/http_readers.qtpl:59
|
||||||
qs422016 := string(qb422016.B)
|
qs422016 := string(qb422016.B)
|
||||||
//line templates/http_readers.qtpl:81
|
//line templates/http_readers.qtpl:59
|
||||||
qt422016.ReleaseByteBuffer(qb422016)
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
//line templates/http_readers.qtpl:81
|
//line templates/http_readers.qtpl:59
|
||||||
return qs422016
|
return qs422016
|
||||||
//line templates/http_readers.qtpl:81
|
//line templates/http_readers.qtpl:59
|
||||||
}
|
}
|
||||||
|
40
templates/recent_changes.qtpl
Normal file
40
templates/recent_changes.qtpl
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{% func RecentChangesHTML(changes []string, n int) %}
|
||||||
|
<main class="recent-changes">
|
||||||
|
<h1>Recent Changes</h1>
|
||||||
|
|
||||||
|
<nav class="recent-changes__count">
|
||||||
|
See
|
||||||
|
{% for _, m := range []int{20, 0, 50, 0, 100} %}
|
||||||
|
{% switch m %}
|
||||||
|
{% case 0 %}
|
||||||
|
<span aria-hidden="true">|</span>
|
||||||
|
{% case n %}
|
||||||
|
<b>{%d n %}</b>
|
||||||
|
{% default %}
|
||||||
|
<a href="/recent-changes/{%d m %}">{%d m %}</a>
|
||||||
|
{% endswitch %}
|
||||||
|
{% endfor %}
|
||||||
|
recent changes
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
{% comment %}
|
||||||
|
Here I am, willing to add some accesibility using ARIA. Turns out,
|
||||||
|
role="feed" is not supported in any screen reader as of September
|
||||||
|
2020. At least web search says so. Even JAWS doesn't support it!
|
||||||
|
How come? I'll add the role anyway. -- bouncepaw
|
||||||
|
{% endcomment %}
|
||||||
|
|
||||||
|
<section class="recent-changes__list" role="feed">
|
||||||
|
{% if len(changes) == 0 %}
|
||||||
|
<p>Could not find any recent changes.</p>
|
||||||
|
{% else %}
|
||||||
|
{% for i, entry := range changes %}
|
||||||
|
<ul class="recent-changes__entry" role="article"
|
||||||
|
aria-setsize="{%d n %}" aria-posinset="{%d i %}">
|
||||||
|
{%s= entry %}
|
||||||
|
</ul>
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
{% endfunc %}
|
156
templates/recent_changes.qtpl.go
Normal file
156
templates/recent_changes.qtpl.go
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
// Code generated by qtc from "recent_changes.qtpl". DO NOT EDIT.
|
||||||
|
// See https://github.com/valyala/quicktemplate for details.
|
||||||
|
|
||||||
|
//line templates/recent_changes.qtpl:1
|
||||||
|
package templates
|
||||||
|
|
||||||
|
//line templates/recent_changes.qtpl:1
|
||||||
|
import (
|
||||||
|
qtio422016 "io"
|
||||||
|
|
||||||
|
qt422016 "github.com/valyala/quicktemplate"
|
||||||
|
)
|
||||||
|
|
||||||
|
//line templates/recent_changes.qtpl:1
|
||||||
|
var (
|
||||||
|
_ = qtio422016.Copy
|
||||||
|
_ = qt422016.AcquireByteBuffer
|
||||||
|
)
|
||||||
|
|
||||||
|
//line templates/recent_changes.qtpl:1
|
||||||
|
func StreamRecentChangesHTML(qw422016 *qt422016.Writer, changes []string, n int) {
|
||||||
|
//line templates/recent_changes.qtpl:1
|
||||||
|
qw422016.N().S(`
|
||||||
|
<main class="recent-changes">
|
||||||
|
<h1>Recent Changes</h1>
|
||||||
|
|
||||||
|
<nav class="recent-changes__count">
|
||||||
|
See
|
||||||
|
`)
|
||||||
|
//line templates/recent_changes.qtpl:7
|
||||||
|
for _, m := range []int{20, 0, 50, 0, 100} {
|
||||||
|
//line templates/recent_changes.qtpl:7
|
||||||
|
qw422016.N().S(`
|
||||||
|
`)
|
||||||
|
//line templates/recent_changes.qtpl:8
|
||||||
|
switch m {
|
||||||
|
//line templates/recent_changes.qtpl:9
|
||||||
|
case 0:
|
||||||
|
//line templates/recent_changes.qtpl:9
|
||||||
|
qw422016.N().S(`
|
||||||
|
<span aria-hidden="true">|</span>
|
||||||
|
`)
|
||||||
|
//line templates/recent_changes.qtpl:11
|
||||||
|
case n:
|
||||||
|
//line templates/recent_changes.qtpl:11
|
||||||
|
qw422016.N().S(`
|
||||||
|
<b>`)
|
||||||
|
//line templates/recent_changes.qtpl:12
|
||||||
|
qw422016.N().D(n)
|
||||||
|
//line templates/recent_changes.qtpl:12
|
||||||
|
qw422016.N().S(`</b>
|
||||||
|
`)
|
||||||
|
//line templates/recent_changes.qtpl:13
|
||||||
|
default:
|
||||||
|
//line templates/recent_changes.qtpl:13
|
||||||
|
qw422016.N().S(`
|
||||||
|
<a href="/recent-changes/`)
|
||||||
|
//line templates/recent_changes.qtpl:14
|
||||||
|
qw422016.N().D(m)
|
||||||
|
//line templates/recent_changes.qtpl:14
|
||||||
|
qw422016.N().S(`">`)
|
||||||
|
//line templates/recent_changes.qtpl:14
|
||||||
|
qw422016.N().D(m)
|
||||||
|
//line templates/recent_changes.qtpl:14
|
||||||
|
qw422016.N().S(`</a>
|
||||||
|
`)
|
||||||
|
//line templates/recent_changes.qtpl:15
|
||||||
|
}
|
||||||
|
//line templates/recent_changes.qtpl:15
|
||||||
|
qw422016.N().S(`
|
||||||
|
`)
|
||||||
|
//line templates/recent_changes.qtpl:16
|
||||||
|
}
|
||||||
|
//line templates/recent_changes.qtpl:16
|
||||||
|
qw422016.N().S(`
|
||||||
|
recent changes
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
`)
|
||||||
|
//line templates/recent_changes.qtpl:25
|
||||||
|
qw422016.N().S(`
|
||||||
|
|
||||||
|
<section class="recent-changes__list" role="feed">
|
||||||
|
`)
|
||||||
|
//line templates/recent_changes.qtpl:28
|
||||||
|
if len(changes) == 0 {
|
||||||
|
//line templates/recent_changes.qtpl:28
|
||||||
|
qw422016.N().S(`
|
||||||
|
<p>Could not find any recent changes.</p>
|
||||||
|
`)
|
||||||
|
//line templates/recent_changes.qtpl:30
|
||||||
|
} else {
|
||||||
|
//line templates/recent_changes.qtpl:30
|
||||||
|
qw422016.N().S(`
|
||||||
|
`)
|
||||||
|
//line templates/recent_changes.qtpl:31
|
||||||
|
for i, entry := range changes {
|
||||||
|
//line templates/recent_changes.qtpl:31
|
||||||
|
qw422016.N().S(`
|
||||||
|
<ul class="recent-changes__entry" role="article"
|
||||||
|
aria-setsize="`)
|
||||||
|
//line templates/recent_changes.qtpl:33
|
||||||
|
qw422016.N().D(n)
|
||||||
|
//line templates/recent_changes.qtpl:33
|
||||||
|
qw422016.N().S(`" aria-posinset="`)
|
||||||
|
//line templates/recent_changes.qtpl:33
|
||||||
|
qw422016.N().D(i)
|
||||||
|
//line templates/recent_changes.qtpl:33
|
||||||
|
qw422016.N().S(`">
|
||||||
|
`)
|
||||||
|
//line templates/recent_changes.qtpl:34
|
||||||
|
qw422016.N().S(entry)
|
||||||
|
//line templates/recent_changes.qtpl:34
|
||||||
|
qw422016.N().S(`
|
||||||
|
</ul>
|
||||||
|
`)
|
||||||
|
//line templates/recent_changes.qtpl:36
|
||||||
|
}
|
||||||
|
//line templates/recent_changes.qtpl:36
|
||||||
|
qw422016.N().S(`
|
||||||
|
`)
|
||||||
|
//line templates/recent_changes.qtpl:37
|
||||||
|
}
|
||||||
|
//line templates/recent_changes.qtpl:37
|
||||||
|
qw422016.N().S(`
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
`)
|
||||||
|
//line templates/recent_changes.qtpl:40
|
||||||
|
}
|
||||||
|
|
||||||
|
//line templates/recent_changes.qtpl:40
|
||||||
|
func WriteRecentChangesHTML(qq422016 qtio422016.Writer, changes []string, n int) {
|
||||||
|
//line templates/recent_changes.qtpl:40
|
||||||
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
|
//line templates/recent_changes.qtpl:40
|
||||||
|
StreamRecentChangesHTML(qw422016, changes, n)
|
||||||
|
//line templates/recent_changes.qtpl:40
|
||||||
|
qt422016.ReleaseWriter(qw422016)
|
||||||
|
//line templates/recent_changes.qtpl:40
|
||||||
|
}
|
||||||
|
|
||||||
|
//line templates/recent_changes.qtpl:40
|
||||||
|
func RecentChangesHTML(changes []string, n int) string {
|
||||||
|
//line templates/recent_changes.qtpl:40
|
||||||
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
|
//line templates/recent_changes.qtpl:40
|
||||||
|
WriteRecentChangesHTML(qb422016, changes, n)
|
||||||
|
//line templates/recent_changes.qtpl:40
|
||||||
|
qs422016 := string(qb422016.B)
|
||||||
|
//line templates/recent_changes.qtpl:40
|
||||||
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
|
//line templates/recent_changes.qtpl:40
|
||||||
|
return qs422016
|
||||||
|
//line templates/recent_changes.qtpl:40
|
||||||
|
}
|
36
templates/rename.qtpl
Normal file
36
templates/rename.qtpl
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
This dialog is to be shown to a user when they try to rename a hypha.
|
||||||
|
{% func RenameAskHTML(hyphaName string, isOld bool) %}
|
||||||
|
<main>
|
||||||
|
{%= navHTML(hyphaName, "rename-ask") %}
|
||||||
|
{%- if isOld -%}
|
||||||
|
<section>
|
||||||
|
<h1>Rename {%s hyphaName %}</h1>
|
||||||
|
<form action="/rename-confirm/{%s hyphaName %}" method="post" enctype="multipart/form-data">
|
||||||
|
<fieldset>
|
||||||
|
<legend>New name</legend>
|
||||||
|
<input type="text" value="{%s hyphaName %}" required autofocus id="new-name" name="new-name"/>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>Settings</legend>
|
||||||
|
<input type="checkbox" id="recursive" name="recursive" value="true" checked/>
|
||||||
|
<label for="recursive">Keep subhyphae</label>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<p>If you rename this hypha, all incoming links and all relative outcoming links will break. You will also lose all history for the new name. Rename carefully.</p>
|
||||||
|
<input type="submit"/>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
{%- else -%}
|
||||||
|
{%= cannotRenameDueToNonExistence(hyphaName) %}
|
||||||
|
{%- endif -%}
|
||||||
|
</main>
|
||||||
|
{% endfunc %}
|
||||||
|
|
||||||
|
{% func cannotRenameDueToNonExistence(hyphaName string) %}
|
||||||
|
<section>
|
||||||
|
<h1>Cannot rename {%s hyphaName %}</h1>
|
||||||
|
<p>This hypha does not exist.</p>
|
||||||
|
<p><a href="/page/{%s hyphaName %}">Go back</a></p>
|
||||||
|
</section>
|
||||||
|
{% endfunc %}
|
155
templates/rename.qtpl.go
Normal file
155
templates/rename.qtpl.go
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
// Code generated by qtc from "rename.qtpl". DO NOT EDIT.
|
||||||
|
// See https://github.com/valyala/quicktemplate for details.
|
||||||
|
|
||||||
|
// This dialog is to be shown to a user when they try to rename a hypha.
|
||||||
|
|
||||||
|
//line templates/rename.qtpl:2
|
||||||
|
package templates
|
||||||
|
|
||||||
|
//line templates/rename.qtpl:2
|
||||||
|
import (
|
||||||
|
qtio422016 "io"
|
||||||
|
|
||||||
|
qt422016 "github.com/valyala/quicktemplate"
|
||||||
|
)
|
||||||
|
|
||||||
|
//line templates/rename.qtpl:2
|
||||||
|
var (
|
||||||
|
_ = qtio422016.Copy
|
||||||
|
_ = qt422016.AcquireByteBuffer
|
||||||
|
)
|
||||||
|
|
||||||
|
//line templates/rename.qtpl:2
|
||||||
|
func StreamRenameAskHTML(qw422016 *qt422016.Writer, hyphaName string, isOld bool) {
|
||||||
|
//line templates/rename.qtpl:2
|
||||||
|
qw422016.N().S(`
|
||||||
|
<main>
|
||||||
|
`)
|
||||||
|
//line templates/rename.qtpl:4
|
||||||
|
streamnavHTML(qw422016, hyphaName, "rename-ask")
|
||||||
|
//line templates/rename.qtpl:4
|
||||||
|
qw422016.N().S(`
|
||||||
|
`)
|
||||||
|
//line templates/rename.qtpl:5
|
||||||
|
if isOld {
|
||||||
|
//line templates/rename.qtpl:5
|
||||||
|
qw422016.N().S(` <section>
|
||||||
|
<h1>Rename `)
|
||||||
|
//line templates/rename.qtpl:7
|
||||||
|
qw422016.E().S(hyphaName)
|
||||||
|
//line templates/rename.qtpl:7
|
||||||
|
qw422016.N().S(`</h1>
|
||||||
|
<form action="/rename-confirm/`)
|
||||||
|
//line templates/rename.qtpl:8
|
||||||
|
qw422016.E().S(hyphaName)
|
||||||
|
//line templates/rename.qtpl:8
|
||||||
|
qw422016.N().S(`" method="post" enctype="multipart/form-data">
|
||||||
|
<fieldset>
|
||||||
|
<legend>New name</legend>
|
||||||
|
<input type="text" value="`)
|
||||||
|
//line templates/rename.qtpl:11
|
||||||
|
qw422016.E().S(hyphaName)
|
||||||
|
//line templates/rename.qtpl:11
|
||||||
|
qw422016.N().S(`" required autofocus id="new-name" name="new-name"/>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<legend>Settings</legend>
|
||||||
|
<input type="checkbox" id="recursive" name="recursive" value="true" checked/>
|
||||||
|
<label for="recursive">Keep subhyphae</label>
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<p>If you rename this hypha, all incoming links and all relative outcoming links will break. You will also lose all history for the new name. Rename carefully.</p>
|
||||||
|
<input type="submit"/>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
`)
|
||||||
|
//line templates/rename.qtpl:24
|
||||||
|
} else {
|
||||||
|
//line templates/rename.qtpl:24
|
||||||
|
qw422016.N().S(` `)
|
||||||
|
//line templates/rename.qtpl:25
|
||||||
|
streamcannotRenameDueToNonExistence(qw422016, hyphaName)
|
||||||
|
//line templates/rename.qtpl:25
|
||||||
|
qw422016.N().S(`
|
||||||
|
`)
|
||||||
|
//line templates/rename.qtpl:26
|
||||||
|
}
|
||||||
|
//line templates/rename.qtpl:26
|
||||||
|
qw422016.N().S(`</main>
|
||||||
|
`)
|
||||||
|
//line templates/rename.qtpl:28
|
||||||
|
}
|
||||||
|
|
||||||
|
//line templates/rename.qtpl:28
|
||||||
|
func WriteRenameAskHTML(qq422016 qtio422016.Writer, hyphaName string, isOld bool) {
|
||||||
|
//line templates/rename.qtpl:28
|
||||||
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
|
//line templates/rename.qtpl:28
|
||||||
|
StreamRenameAskHTML(qw422016, hyphaName, isOld)
|
||||||
|
//line templates/rename.qtpl:28
|
||||||
|
qt422016.ReleaseWriter(qw422016)
|
||||||
|
//line templates/rename.qtpl:28
|
||||||
|
}
|
||||||
|
|
||||||
|
//line templates/rename.qtpl:28
|
||||||
|
func RenameAskHTML(hyphaName string, isOld bool) string {
|
||||||
|
//line templates/rename.qtpl:28
|
||||||
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
|
//line templates/rename.qtpl:28
|
||||||
|
WriteRenameAskHTML(qb422016, hyphaName, isOld)
|
||||||
|
//line templates/rename.qtpl:28
|
||||||
|
qs422016 := string(qb422016.B)
|
||||||
|
//line templates/rename.qtpl:28
|
||||||
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
|
//line templates/rename.qtpl:28
|
||||||
|
return qs422016
|
||||||
|
//line templates/rename.qtpl:28
|
||||||
|
}
|
||||||
|
|
||||||
|
//line templates/rename.qtpl:30
|
||||||
|
func streamcannotRenameDueToNonExistence(qw422016 *qt422016.Writer, hyphaName string) {
|
||||||
|
//line templates/rename.qtpl:30
|
||||||
|
qw422016.N().S(`
|
||||||
|
<section>
|
||||||
|
<h1>Cannot rename `)
|
||||||
|
//line templates/rename.qtpl:32
|
||||||
|
qw422016.E().S(hyphaName)
|
||||||
|
//line templates/rename.qtpl:32
|
||||||
|
qw422016.N().S(`</h1>
|
||||||
|
<p>This hypha does not exist.</p>
|
||||||
|
<p><a href="/page/`)
|
||||||
|
//line templates/rename.qtpl:34
|
||||||
|
qw422016.E().S(hyphaName)
|
||||||
|
//line templates/rename.qtpl:34
|
||||||
|
qw422016.N().S(`">Go back</a></p>
|
||||||
|
</section>
|
||||||
|
`)
|
||||||
|
//line templates/rename.qtpl:36
|
||||||
|
}
|
||||||
|
|
||||||
|
//line templates/rename.qtpl:36
|
||||||
|
func writecannotRenameDueToNonExistence(qq422016 qtio422016.Writer, hyphaName string) {
|
||||||
|
//line templates/rename.qtpl:36
|
||||||
|
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||||
|
//line templates/rename.qtpl:36
|
||||||
|
streamcannotRenameDueToNonExistence(qw422016, hyphaName)
|
||||||
|
//line templates/rename.qtpl:36
|
||||||
|
qt422016.ReleaseWriter(qw422016)
|
||||||
|
//line templates/rename.qtpl:36
|
||||||
|
}
|
||||||
|
|
||||||
|
//line templates/rename.qtpl:36
|
||||||
|
func cannotRenameDueToNonExistence(hyphaName string) string {
|
||||||
|
//line templates/rename.qtpl:36
|
||||||
|
qb422016 := qt422016.AcquireByteBuffer()
|
||||||
|
//line templates/rename.qtpl:36
|
||||||
|
writecannotRenameDueToNonExistence(qb422016, hyphaName)
|
||||||
|
//line templates/rename.qtpl:36
|
||||||
|
qs422016 := string(qb422016.B)
|
||||||
|
//line templates/rename.qtpl:36
|
||||||
|
qt422016.ReleaseByteBuffer(qb422016)
|
||||||
|
//line templates/rename.qtpl:36
|
||||||
|
return qs422016
|
||||||
|
//line templates/rename.qtpl:36
|
||||||
|
}
|
11
util/util.go
11
util/util.go
@ -25,3 +25,14 @@ func HTTP200Page(w http.ResponseWriter, page string) {
|
|||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write([]byte(page))
|
w.Write([]byte(page))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindSubhyphae finds names of existing hyphae given the `hyphaIterator`.
|
||||||
|
func FindSubhyphae(hyphaName string, hyphaIterator func(func(string))) []string {
|
||||||
|
subhyphae := make([]string, 0)
|
||||||
|
hyphaIterator(func(otherHyphaName string) {
|
||||||
|
if strings.HasPrefix(otherHyphaName, hyphaName+"/") {
|
||||||
|
subhyphae = append(subhyphae, otherHyphaName)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return subhyphae
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user