mirror of
https://github.com/osmarks/mycorrhiza.git
synced 2024-12-05 02:29:54 +00:00
commit
4713c1e569
@ -9,8 +9,8 @@ import (
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
)
|
||||
|
||||
// YieldHyphaBacklinks gets backlinks for the desired hypha, sorts and yields them one by one.
|
||||
func YieldHyphaBacklinks(hyphaName string) <-chan string {
|
||||
// yieldHyphaBacklinks gets backlinks for the desired hypha, sorts and yields them one by one.
|
||||
func yieldHyphaBacklinks(hyphaName string) <-chan string {
|
||||
hyphaName = util.CanonicalName(hyphaName)
|
||||
out := make(chan string)
|
||||
sorted := hyphae.PathographicSort(out)
|
||||
@ -147,7 +147,7 @@ type backlinkIndexRenaming struct {
|
||||
links []string
|
||||
}
|
||||
|
||||
// Apply changes backlink index respective to the operation data
|
||||
// apply changes backlink index respective to the operation data
|
||||
func (op backlinkIndexRenaming) apply() {
|
||||
for _, link := range op.links {
|
||||
if lSet, exists := backlinkIndex[link]; exists {
|
@ -1,10 +1,11 @@
|
||||
package backlinks
|
||||
|
||||
import (
|
||||
"github.com/bouncepaw/mycomarkup/v3"
|
||||
"github.com/bouncepaw/mycomarkup/v3/links"
|
||||
"github.com/bouncepaw/mycomarkup/v3/mycocontext"
|
||||
"github.com/bouncepaw/mycomarkup/v3/tools"
|
||||
"github.com/bouncepaw/mycomarkup/v4"
|
||||
"github.com/bouncepaw/mycomarkup/v4/links"
|
||||
"github.com/bouncepaw/mycomarkup/v4/mycocontext"
|
||||
"github.com/bouncepaw/mycomarkup/v4/options"
|
||||
"github.com/bouncepaw/mycomarkup/v4/tools"
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae"
|
||||
)
|
||||
|
||||
@ -34,7 +35,7 @@ func extractHyphaLinks(h hyphae.Hypha) []string {
|
||||
|
||||
// extractHyphaLinksFromContent extracts local hypha links from the provided text.
|
||||
func extractHyphaLinksFromContent(hyphaName string, contents string) []string {
|
||||
ctx, _ := mycocontext.ContextFromStringInput(hyphaName, contents)
|
||||
ctx, _ := mycocontext.ContextFromStringInput(contents, options.Options{HyphaName: hyphaName}.FillTheRest())
|
||||
linkVisitor, getLinks := tools.LinkVisitor(ctx)
|
||||
// Ignore the result of BlockTree because we call it for linkVisitor.
|
||||
_ = mycomarkup.BlockTree(ctx, linkVisitor)
|
17
backlinks/view_backlinks.html
Normal file
17
backlinks/view_backlinks.html
Normal file
@ -0,0 +1,17 @@
|
||||
{{define "backlinks to text"}}Backlinks to {{.}}{{end}}
|
||||
{{define "title"}}{{template "backlinks to text" .HyphaName}}{{end}}
|
||||
{{define "body"}}
|
||||
<div class="layout">
|
||||
<main class="main-width backlinks">
|
||||
<h1>{{block "backlinks to link" .HyphaName}}Backlinks to <a href="/hypha/{{.}}">{{beautifulName .}}</a>{{end}}</h1>
|
||||
<p>{{block "description" .}}Hyphae which have a link to this hypha, embed it as an image or transclude it are listed below.{{end}}</p>
|
||||
<ul class="backlinks__list">
|
||||
{{range .Backlinks}}
|
||||
<li class="backlinks__entry">
|
||||
<a class="backlinks__link wikilink" href="/hypha/{{.}}">{{beautifulName .}}</a>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
</main>
|
||||
</div>
|
||||
{{end}}
|
62
backlinks/web.go
Normal file
62
backlinks/web.go
Normal file
@ -0,0 +1,62 @@
|
||||
package backlinks
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
"github.com/gorilla/mux"
|
||||
"log"
|
||||
"net/http"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
func InitHandlers(rtr *mux.Router) {
|
||||
rtr.PathPrefix("/backlinks/").HandlerFunc(handlerBacklinks)
|
||||
chain = viewutil.
|
||||
En(viewutil.CopyEnWith(fs, "view_backlinks.html")).
|
||||
Ru(template.Must(viewutil.CopyRuWith(fs, "view_backlinks.html").Parse(ruTranslation)))
|
||||
}
|
||||
|
||||
// handlerBacklinks lists all backlinks to a hypha.
|
||||
func handlerBacklinks(w http.ResponseWriter, rq *http.Request) {
|
||||
var (
|
||||
hyphaName = util.HyphaNameFromRq(rq, "backlinks")
|
||||
backlinks []string
|
||||
)
|
||||
for b := range yieldHyphaBacklinks(hyphaName) {
|
||||
backlinks = append(backlinks, b)
|
||||
}
|
||||
viewBacklinks(viewutil.MetaFrom(w, rq), hyphaName, backlinks)
|
||||
}
|
||||
|
||||
var (
|
||||
//go:embed *.html
|
||||
fs embed.FS
|
||||
ruTranslation = `
|
||||
{{define "backlinks to text"}}Обратные ссылки на {{.}}{{end}}
|
||||
{{define "backlinks to link"}}Обратные ссылки на <a href="/hypha/{{.}}">{{beautifulName .}}</a>{{end}}
|
||||
{{define "description"}}Ниже перечислены гифы, на которых есть ссылка на эту гифу, трансклюзия этой гифы или эта гифа вставлена как изображение.{{end}}
|
||||
`
|
||||
chain viewutil.Chain
|
||||
)
|
||||
|
||||
type backlinksData struct {
|
||||
viewutil.BaseData
|
||||
HyphaName string
|
||||
Backlinks []string
|
||||
}
|
||||
|
||||
func viewBacklinks(meta viewutil.Meta, hyphaName string, backlinks []string) {
|
||||
if err := chain.Get(meta).ExecuteTemplate(meta.W, "page", backlinksData{
|
||||
BaseData: viewutil.BaseData{
|
||||
Meta: meta,
|
||||
HeaderLinks: cfg.HeaderLinks,
|
||||
CommonScripts: cfg.CommonScripts,
|
||||
},
|
||||
HyphaName: hyphaName,
|
||||
Backlinks: backlinks,
|
||||
}); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
// Package categories provides category management. All operations in this package are mutexed.
|
||||
// Package categories provides category management.
|
||||
//
|
||||
// As per the long pondering, this is how categories (cats for short)
|
||||
// work in Mycorrhiza:
|
||||
@ -12,12 +12,19 @@
|
||||
// cat operations are not mentioned on the recent changes page.
|
||||
// - For cat A, if there are 0 hyphae in the cat, cat A does not
|
||||
// exist. If there are 1 or more hyphae in the cat, cat A exists.
|
||||
//
|
||||
// List of things to do with categories later:
|
||||
//
|
||||
// - Forbid / in cat names.
|
||||
// - Rename categories.
|
||||
// - Delete categories.
|
||||
// - Bind hyphae.
|
||||
package categories
|
||||
|
||||
import "sync"
|
||||
|
||||
// List returns names of all categories.
|
||||
func List() (categoryList []string) {
|
||||
// listOfCategories returns names of all categories.
|
||||
func listOfCategories() (categoryList []string) {
|
||||
mutex.RLock()
|
||||
for cat, _ := range categoryToHyphae {
|
||||
categoryList = append(categoryList, cat)
|
||||
@ -26,8 +33,8 @@ func List() (categoryList []string) {
|
||||
return categoryList
|
||||
}
|
||||
|
||||
// WithHypha returns what categories have the given hypha. The hypha name must be canonical.
|
||||
func WithHypha(hyphaName string) (categoryList []string) {
|
||||
// categoriesWithHypha returns what categories have the given hypha. The hypha name must be canonical.
|
||||
func categoriesWithHypha(hyphaName string) (categoryList []string) {
|
||||
mutex.RLock()
|
||||
defer mutex.RUnlock()
|
||||
if node, ok := hyphaToCategories[hyphaName]; ok {
|
||||
@ -37,8 +44,8 @@ func WithHypha(hyphaName string) (categoryList []string) {
|
||||
}
|
||||
}
|
||||
|
||||
// Contents returns what hyphae are in the category. If the returned slice is empty, the category does not exist, and vice versa. The category name must be canonical.
|
||||
func Contents(catName string) (hyphaList []string) {
|
||||
// hyphaeInCategory returns what hyphae are in the category. If the returned slice is empty, the category does not exist, and vice versa. The category name must be canonical.
|
||||
func hyphaeInCategory(catName string) (hyphaList []string) {
|
||||
mutex.RLock()
|
||||
defer mutex.RUnlock()
|
||||
if node, ok := categoryToHyphae[catName]; ok {
|
||||
@ -50,8 +57,8 @@ func Contents(catName string) (hyphaList []string) {
|
||||
|
||||
var mutex sync.RWMutex
|
||||
|
||||
// AddHyphaToCategory adds the hypha to the category and updates the records on the disk. If the hypha is already in the category, nothing happens. Pass canonical names.
|
||||
func AddHyphaToCategory(hyphaName, catName string) {
|
||||
// addHyphaToCategory adds the hypha to the category and updates the records on the disk. If the hypha is already in the category, nothing happens. Pass canonical names.
|
||||
func addHyphaToCategory(hyphaName, catName string) {
|
||||
mutex.Lock()
|
||||
if node, ok := hyphaToCategories[hyphaName]; ok {
|
||||
node.storeCategory(catName)
|
||||
@ -68,8 +75,8 @@ func AddHyphaToCategory(hyphaName, catName string) {
|
||||
go saveToDisk()
|
||||
}
|
||||
|
||||
// RemoveHyphaFromCategory removes the hypha from the category and updates the records on the disk. If the hypha is not in the category, nothing happens. Pass canonical names.
|
||||
func RemoveHyphaFromCategory(hyphaName, catName string) {
|
||||
// removeHyphaFromCategory removes the hypha from the category and updates the records on the disk. If the hypha is not in the category, nothing happens. Pass canonical names.
|
||||
func removeHyphaFromCategory(hyphaName, catName string) {
|
||||
mutex.Lock()
|
||||
if node, ok := hyphaToCategories[hyphaName]; ok {
|
||||
node.removeCategory(catName)
|
@ -12,8 +12,8 @@ import (
|
||||
var categoryToHyphae = map[string]*categoryNode{}
|
||||
var hyphaToCategories = map[string]*hyphaNode{}
|
||||
|
||||
// InitCategories initializes the category system. Call it after the Structure is initialized. This function might terminate the program in case of a bad mood or filesystem faults.
|
||||
func InitCategories() {
|
||||
// Init initializes the category system. Call it after the Structure is initialized. This function might terminate the program in case of a bad mood or filesystem faults.
|
||||
func Init() {
|
||||
var (
|
||||
record, err = readCategoriesFromDisk()
|
||||
)
|
@ -1,10 +1,9 @@
|
||||
package web
|
||||
package categories
|
||||
|
||||
import (
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae/categories"
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
"github.com/bouncepaw/mycorrhiza/views"
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
"github.com/gorilla/mux"
|
||||
"io"
|
||||
"log"
|
||||
@ -12,16 +11,18 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func initCategories(r *mux.Router) {
|
||||
// InitHandlers initializes HTTP handlers for the given router. Call somewhere in package web.
|
||||
func InitHandlers(r *mux.Router) {
|
||||
r.PathPrefix("/add-to-category").HandlerFunc(handlerAddToCategory).Methods("POST")
|
||||
r.PathPrefix("/remove-from-category").HandlerFunc(handlerRemoveFromCategory).Methods("POST")
|
||||
r.PathPrefix("/category/").HandlerFunc(handlerCategory).Methods("GET")
|
||||
r.PathPrefix("/category").HandlerFunc(handlerListCategory).Methods("GET")
|
||||
prepareViews()
|
||||
}
|
||||
|
||||
func handlerListCategory(w http.ResponseWriter, rq *http.Request) {
|
||||
log.Println("Viewing list of categories")
|
||||
views.CategoryList(views.MetaFrom(w, rq))
|
||||
categoryList(viewutil.MetaFrom(w, rq))
|
||||
}
|
||||
|
||||
func handlerCategory(w http.ResponseWriter, rq *http.Request) {
|
||||
@ -32,7 +33,7 @@ func handlerCategory(w http.ResponseWriter, rq *http.Request) {
|
||||
return
|
||||
}
|
||||
log.Println("Viewing category", catName)
|
||||
views.CategoryPage(views.MetaFrom(w, rq), catName)
|
||||
categoryPage(viewutil.MetaFrom(w, rq), catName)
|
||||
}
|
||||
|
||||
func handlerRemoveFromCategory(w http.ResponseWriter, rq *http.Request) {
|
||||
@ -51,7 +52,8 @@ func handlerRemoveFromCategory(w http.ResponseWriter, rq *http.Request) {
|
||||
http.Redirect(w, rq, redirectTo, http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
categories.RemoveHyphaFromCategory(hyphaName, catName)
|
||||
log.Println(user.FromRequest(rq).Name, "removed", hyphaName, "from", catName)
|
||||
removeHyphaFromCategory(hyphaName, catName)
|
||||
http.Redirect(w, rq, redirectTo, http.StatusSeeOther)
|
||||
}
|
||||
|
||||
@ -71,6 +73,7 @@ func handlerAddToCategory(w http.ResponseWriter, rq *http.Request) {
|
||||
http.Redirect(w, rq, redirectTo, http.StatusSeeOther)
|
||||
return
|
||||
}
|
||||
categories.AddHyphaToCategory(hyphaName, catName)
|
||||
log.Println(user.FromRequest(rq).Name, "added", hyphaName, "to", catName)
|
||||
addHyphaToCategory(hyphaName, catName)
|
||||
http.Redirect(w, rq, redirectTo, http.StatusSeeOther)
|
||||
}
|
35
categories/view_card.html
Normal file
35
categories/view_card.html
Normal file
@ -0,0 +1,35 @@
|
||||
{{define "category card"}}
|
||||
{{$hyphaName := .HyphaName}}
|
||||
{{$givenPermission := .GivenPermissionToModify}}
|
||||
<aside class="layout-card categories-card">
|
||||
<h2 class="layout-card__title">{{block `categories` .}}Categories{{end}}</h2>
|
||||
<ul class="categories-card__entries">
|
||||
{{range .Categories}}
|
||||
<li class="categories-card__entry">
|
||||
<a class="categories-card__link" href="/category/{{.}}">{{beautifulName .}}</a>
|
||||
<form method="POST" action="/remove-from-category" class="categories-card__remove-form">
|
||||
<input type="hidden" name="cat" value="{{.}}">
|
||||
<input type="hidden" name="hypha" value="{{$hyphaName}}">
|
||||
<input type="hidden" name="redirect-to" value="/hypha/{{$hyphaName}}">
|
||||
{{if $givenPermission}}
|
||||
<input type="submit" value="x" class="btn categories-card__btn"
|
||||
title="{{block `remove from category title` .}}Remove the hypha from this category{{end}}">
|
||||
{{end}}
|
||||
</form>
|
||||
</li>
|
||||
{{end}}
|
||||
{{if .GivenPermissionToModify}}
|
||||
<li class="categories-card__entry categories-card__add-to-cat">
|
||||
<form method="POST" action="/add-to-category" class="categories-card__add-form">
|
||||
<input type="text" name="cat" id="_cat-name"
|
||||
placeholder="{{block `placeholder` .}}Category name...{{end}}">
|
||||
<input type="hidden" name="hypha" value="{{$hyphaName}}">
|
||||
<input type="hidden" name="redirect-to" value="/hypha/{{$hyphaName}}">
|
||||
<input type="submit" class="btn categories-card__btn" value="+"
|
||||
title="{{block `add to category title` .}}Add the hypha to this category{{end}}">
|
||||
</form>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
</aside>
|
||||
{{end}}
|
18
categories/view_list.html
Normal file
18
categories/view_list.html
Normal file
@ -0,0 +1,18 @@
|
||||
{{define "category list"}}Category list{{end}}
|
||||
{{define "title"}}{{template "category list"}}{{end}}
|
||||
{{define "body"}}
|
||||
<main class="main-width category-list">
|
||||
<h1>{{template "title"}}</h1>
|
||||
{{if len .Categories}}
|
||||
<ul class="category-list__entries">
|
||||
{{range .Categories}}
|
||||
<li class="category-list__entry">
|
||||
<a class="category-list__link" href="/category/{{.}}">{{beautifulName .}}</a>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<p>{{block `no categories` .}}This wiki has no categories.{{end}}</p>
|
||||
{{end}}
|
||||
</main>
|
||||
{{end}}
|
29
categories/view_page.html
Normal file
29
categories/view_page.html
Normal file
@ -0,0 +1,29 @@
|
||||
{{define "category x"}}Category {{. | beautifulName}}{{end}}
|
||||
{{define "title"}}{{template "category x" .CatName}}{{end}}
|
||||
{{define "body"}}
|
||||
{{$catName := .CatName}}
|
||||
<main class="main-width category">
|
||||
<h1>{{block "cat" .}}Category{{end}} <i>{{beautifulName $catName}}</i></h1>
|
||||
{{if len .Hyphae | not}}
|
||||
<p>{{block "empty cat" .}}This category is empty{{end}}</p>
|
||||
{{end}}
|
||||
<ul class="category__entries">
|
||||
{{range .Hyphae}}
|
||||
<li class="category__entry">
|
||||
<a class="category__link" href="/hypha/{{.}}">{{beautifulName .}}</a>
|
||||
</li>
|
||||
{{end}}
|
||||
{{if .GivenPermissionToModify}}
|
||||
<li class="category__entry category__add-to-cat">
|
||||
<form method="POST" action="/add-to-category" class="category__add-form">
|
||||
<input type="text" name="hypha" id="_hypha-name"
|
||||
placeholder="{{block `hypha name` .}}Hypha name{{end}}">
|
||||
<input type="hidden" name="cat" value="{{$catName}}">
|
||||
<input type="hidden" name="redirect-to" value="/category/{{$catName}}">
|
||||
<input type="submit" class="btn" value="{{block `add hypha` .}}Add to the category{{end}}">
|
||||
</form>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
</main>
|
||||
{{end}}
|
104
categories/views.go
Normal file
104
categories/views.go
Normal file
@ -0,0 +1,104 @@
|
||||
package categories
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
"log"
|
||||
"strings"
|
||||
"text/template" // TODO: Fight
|
||||
)
|
||||
|
||||
const ruTranslation = `
|
||||
{{define "empty cat"}}Эта категория пуста.{{end}}
|
||||
{{define "add hypha"}}Добавить в категорию{{end}}
|
||||
{{define "cat"}}Категория{{end}}
|
||||
{{define "hypha name"}}Имя гифы{{end}}
|
||||
{{define "categories"}}Категории{{end}}
|
||||
{{define "placeholder"}}Имя категории...{{end}}
|
||||
{{define "remove from category title"}}Убрать гифу из этой категории{{end}}
|
||||
{{define "add to category title"}}Добавить гифу в эту категорию{{end}}
|
||||
{{define "category list"}}Список категорий{{end}}
|
||||
{{define "no categories"}}В этой вики нет категорий.{{end}}
|
||||
{{define "category x"}}Категория {{. | beautifulName}}{{end}}
|
||||
`
|
||||
|
||||
var (
|
||||
//go:embed *.html
|
||||
fs embed.FS
|
||||
viewListChain, viewPageChain, viewCardChain viewutil.Chain
|
||||
)
|
||||
|
||||
func prepareViews() {
|
||||
m := template.Must
|
||||
|
||||
viewCardChain = viewutil.
|
||||
En(viewutil.CopyEnWith(fs, "view_card.html")).
|
||||
Ru(m(viewutil.CopyRuWith(fs, "view_card.html").Parse(ruTranslation)))
|
||||
viewListChain = viewutil.
|
||||
En(viewutil.CopyEnWith(fs, "view_list.html")).
|
||||
Ru(m(viewutil.CopyRuWith(fs, "view_list.html").Parse(ruTranslation)))
|
||||
viewPageChain = viewutil.
|
||||
En(viewutil.CopyEnWith(fs, "view_page.html")).
|
||||
Ru(m(viewutil.CopyRuWith(fs, "view_page.html").Parse(ruTranslation)))
|
||||
}
|
||||
|
||||
type cardData struct {
|
||||
HyphaName string
|
||||
Categories []string
|
||||
GivenPermissionToModify bool
|
||||
}
|
||||
|
||||
// CategoryCard is the little sidebar that is shown nearby the hypha view.
|
||||
func CategoryCard(meta viewutil.Meta, hyphaName string) string {
|
||||
var buf strings.Builder
|
||||
err := viewCardChain.Get(meta).ExecuteTemplate(&buf, "category card", cardData{
|
||||
hyphaName,
|
||||
categoriesWithHypha(hyphaName),
|
||||
meta.U.CanProceed("add-to-category"),
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
type pageData struct {
|
||||
viewutil.BaseData
|
||||
CatName string
|
||||
Hyphae []string
|
||||
GivenPermissionToModify bool
|
||||
}
|
||||
|
||||
func categoryPage(meta viewutil.Meta, catName string) {
|
||||
if err := viewPageChain.Get(meta).ExecuteTemplate(meta.W, "page", pageData{
|
||||
BaseData: viewutil.BaseData{
|
||||
Meta: meta,
|
||||
HeaderLinks: cfg.HeaderLinks,
|
||||
CommonScripts: cfg.CommonScripts,
|
||||
},
|
||||
CatName: catName,
|
||||
Hyphae: hyphaeInCategory(catName),
|
||||
GivenPermissionToModify: meta.U.CanProceed("add-to-category"),
|
||||
}); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
type listData struct {
|
||||
viewutil.BaseData
|
||||
Categories []string
|
||||
}
|
||||
|
||||
func categoryList(meta viewutil.Meta) {
|
||||
if err := viewListChain.Get(meta).ExecuteTemplate(meta.W, "page", listData{
|
||||
BaseData: viewutil.BaseData{
|
||||
Meta: meta,
|
||||
HeaderLinks: cfg.HeaderLinks,
|
||||
CommonScripts: cfg.CommonScripts,
|
||||
},
|
||||
Categories: listOfCategories(),
|
||||
}); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
@ -193,7 +193,7 @@ func ReadConfigFile(path string) error {
|
||||
TelegramEnabled = (TelegramBotToken != "") && (TelegramBotName != "")
|
||||
|
||||
// This URL makes much more sense. If no URL is set or the protocol is forgotten, assume HTTP.
|
||||
if (URL == "") || (strings.Index(URL, ":") == -1) {
|
||||
if (URL == "") || !strings.Contains(URL, ":") {
|
||||
URL = "http://" + ListenAddr
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
package cfg
|
||||
|
||||
// See https://mycorrhiza.wiki/hypha/configuration/header
|
||||
import (
|
||||
"github.com/bouncepaw/mycomarkup/v3"
|
||||
"github.com/bouncepaw/mycomarkup/v3/blocks"
|
||||
"github.com/bouncepaw/mycomarkup/v3/mycocontext"
|
||||
"github.com/bouncepaw/mycomarkup/v4"
|
||||
"github.com/bouncepaw/mycomarkup/v4/blocks"
|
||||
"github.com/bouncepaw/mycomarkup/v4/mycocontext"
|
||||
"github.com/bouncepaw/mycomarkup/v4/options"
|
||||
)
|
||||
|
||||
// HeaderLinks is a list off current header links. Feel free to iterate it directly but do not modify it by yourself. Call ParseHeaderLinks if you need to set new header links.
|
||||
@ -24,7 +24,7 @@ func SetDefaultHeaderLinks() {
|
||||
// ParseHeaderLinks extracts all rocketlinks from the given text and saves them as header links.
|
||||
func ParseHeaderLinks(text string) {
|
||||
HeaderLinks = []HeaderLink{}
|
||||
ctx, _ := mycocontext.ContextFromStringInput("", text)
|
||||
ctx, _ := mycocontext.ContextFromStringInput(text, options.Options{}.FillTheRest())
|
||||
// We call for side-effects
|
||||
_ = mycomarkup.BlockTree(ctx, func(block blocks.Block) {
|
||||
switch launchpad := block.(type) {
|
||||
|
5
go.mod
5
go.mod
@ -3,7 +3,7 @@ module github.com/bouncepaw/mycorrhiza
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/bouncepaw/mycomarkup/v3 v3.6.3
|
||||
github.com/bouncepaw/mycomarkup/v4 v4.0.0
|
||||
github.com/go-ini/ini v1.63.2
|
||||
github.com/gorilla/feeds v1.1.1
|
||||
github.com/gorilla/mux v1.8.0
|
||||
@ -22,7 +22,8 @@ require (
|
||||
|
||||
// Use this trick to test local Mycomarkup changes, replace the path with yours,
|
||||
// but do not commit the change to the path:
|
||||
// replace github.com/bouncepaw/mycomarkup/v3 v3.6.3 => "/Users/bouncepaw/GolandProjects/mycomarkup"
|
||||
// replace github.com/bouncepaw/mycomarkup/v4 v4.0.0 => "/Users/bouncepaw/GolandProjects/mycomarkup"
|
||||
|
||||
|
||||
// Use this utility every time Mycomarkup gets a major update:
|
||||
// https://github.com/marwan-at-work/mod
|
||||
|
6
go.sum
6
go.sum
@ -1,7 +1,9 @@
|
||||
github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/bouncepaw/mycomarkup/v3 v3.6.3 h1:FQzzCxrHAEFBjPKFF/7R9gamyeU/8Cn+cFZEgngYtjE=
|
||||
github.com/bouncepaw/mycomarkup/v3 v3.6.3/go.mod h1:BpiGUVsYCgRZCDxF0iIdc08LJokm/Ab36S/Hif0J6D0=
|
||||
github.com/bouncepaw/mycomarkup/v4 v3.6.2 h1:5zqb12aOw19xg8/0QIvgoA8oEW2doSdWqCbXltPEaPQ=
|
||||
github.com/bouncepaw/mycomarkup/v4 v3.6.2/go.mod h1:BpiGUVsYCgRZCDxF0iIdc08LJokm/Ab36S/Hif0J6D0=
|
||||
github.com/bouncepaw/mycomarkup/v4 v4.0.0 h1:qokseZ+otcFuQ5vARdvxKqjlEZFMvsjFJ7YpJ4sUr8c=
|
||||
github.com/bouncepaw/mycomarkup/v4 v4.0.0/go.mod h1:y0b8U6Xfnh3KfNUpG3QuAXRJwqFPPpmS2kYvLzaf688=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-ini/ini v1.63.2 h1:kwN3umicd2HF3Tgvap4um1ZG52/WyKT9GGdPx0CJk6Y=
|
||||
|
@ -15,6 +15,7 @@ On big screens, the top bar is spread onto two lines.
|
||||
** All hyphae
|
||||
** Random
|
||||
** Help
|
||||
** Categories
|
||||
|
||||
On small screens, the authorization section and the most-used-links section are hidden behind a menu. Click the button to see them. If your browser does not support JavaScript, they are always shown.
|
||||
|
||||
@ -40,9 +41,11 @@ Reload the wiki.
|
||||
|
||||
----
|
||||
|
||||
Edit the hypha. You can put any markup there. Rocket links will be used for generating the top bar:
|
||||
Edit the hypha. You can put any markup there. Only rocket links will be used for generating the top bar:
|
||||
|
||||
```myco
|
||||
This paragraph is unused.
|
||||
|
||||
=> /recent-changes | Recent changes
|
||||
=> Highlights
|
||||
=> Philosophy | Our views on life
|
||||
|
@ -5,7 +5,7 @@ import (
|
||||
"embed"
|
||||
)
|
||||
|
||||
//go:embed en en.myco
|
||||
//go:embed en en.myco *.html
|
||||
var fs embed.FS
|
||||
|
||||
// Get determines what help text you need and returns it. The path is a substring from URL, it follows this form:
|
||||
|
50
help/view_help.html
Normal file
50
help/view_help.html
Normal file
@ -0,0 +1,50 @@
|
||||
{{define "title"}}Help{{end}}
|
||||
{{define "body"}}
|
||||
<div class="layout">
|
||||
<main class="main-width help">
|
||||
<article>
|
||||
{{if .ContentsHTML}}
|
||||
{{.ContentsHTML}}
|
||||
{{else}}
|
||||
<h1>{{block "entry not found" .}}Entry not found{{end}}</h1>
|
||||
<p>{{block "entry not found invitation" .}}If you want to write this entry by yourself, consider <a class="wikilink wikilink_external wikilink_https" href="https://github.com/bouncepaw/mycorrhiza">contributing</a> it directly.{{end}}</p>
|
||||
{{end}}
|
||||
</article>
|
||||
</main>
|
||||
<aside class="help-topics layout-card">
|
||||
<h2 class="layout-card__title">{{block "topics" .}}Help topics{{end}}</h2>
|
||||
<ul class="help-topics__list">
|
||||
<li><a href="/help/en">{{block "main" .}}Main{{end}}</a></li>
|
||||
<li><a href="/help/en/hypha">{{block "hypha" .}}Hypha{{end}}</a>
|
||||
<ul>
|
||||
<a href="/help/en/media">{{block "media" .}}Media{{end}}</a>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="/help/en/mycomarkup">{{block "mycomarkup" .}}Mycomarkup{{end}}</a></li>
|
||||
<li><a href="/help/en/category">{{block "category" .}}Categories{{end}}</a></li>
|
||||
<li>{{block "interface" .}}Interface{{end}}
|
||||
<ul>
|
||||
<li><a href="/help/en/prevnext">{{block "prevnext" .}}Previous/next{{end}}</a></li>
|
||||
<li><a href="/help/en/top_bar">{{block "top_bar" .}}Top bar{{end}}</a></li>
|
||||
<li><a href="/help/en/sibling_hyphae_section">{{block "sibling_hyphae" .}}Sibling hyphae{{end}}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>{{block "special pages" .}}Special pages{{end}}
|
||||
<ul>
|
||||
<li><a href="/help/en/recent_changes">{{block "recent_changes" .}}Recent changes{{end}}</a></li>
|
||||
<li><a href="/help/en/feeds">{{block "feeds" .}}Feeds{{end}}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>{{block "configuration" .}}Configuration (for administrators){{end}}
|
||||
<ul>
|
||||
<li><a href="/help/en/config_file">{{block "config_file" .}}Configuration file{{end}}</a></li>
|
||||
<li><a href="/help/en/lock">{{block "lock" .}}Lock{{end}}</a></li>
|
||||
<li><a href="/help/en/whitelist">{{block "whitelist" .}}Whitelist{{end}}</a></li>
|
||||
<li><a href="/help/en/telegram">{{block "telegram" .}}Telegram authentication{{end}}</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</aside>
|
||||
</div>
|
||||
{{end}}
|
||||
|
111
help/web.go
Normal file
111
help/web.go
Normal file
@ -0,0 +1,111 @@
|
||||
package help
|
||||
|
||||
// stuff.go is used for meta stuff about the wiki or all hyphae at once.
|
||||
import (
|
||||
"github.com/bouncepaw/mycomarkup/v4"
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/shroom"
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/bouncepaw/mycomarkup/v4/mycocontext"
|
||||
)
|
||||
|
||||
var (
|
||||
chain viewutil.Chain
|
||||
ruTranslation = `
|
||||
{{define "title"}}Справка{{end}}
|
||||
{{define "entry not found"}}Статья не найдена{{end}}
|
||||
{{define "entry not found invitation"}}Если вы хотите написать эту статью сами, то будем рады вашим правкам <a class="wikilink wikilink_external wikilink_https" href="https://github.com/bouncepaw/mycorrhiza">в репозитории Миокризы</a>.{{end}}
|
||||
|
||||
{{define "topics"}}Темы справки{{end}}
|
||||
{{define "main"}}Введение{{end}}
|
||||
{{define "hypha"}}Гифа{{end}}
|
||||
{{define "media"}}Медиа{{end}}
|
||||
{{define "mycomarkup"}}Микоразметка{{end}}
|
||||
{{define "category"}}Категории{{end}}
|
||||
{{define "interface"}}Интерфейс{{end}}
|
||||
{{define "prevnext"}}Пред/след{{end}}
|
||||
{{define "top_bar"}}Верхняя панель{{end}}
|
||||
{{define "sibling_hyphae"}}Гифы-сиблинги{{end}}
|
||||
{{define "special pages"}}Специальные страницы{{end}}
|
||||
{{define "recent_changes"}}Недавние изменения{{end}}
|
||||
{{define "feeds"}}Ленты{{end}}
|
||||
{{define "configuration"}}Конфигурация (для администраторов){{end}}
|
||||
{{define "config_file"}}Файл конфигурации{{end}}
|
||||
{{define "lock"}}Замок{{end}}
|
||||
{{define "whitelist"}}Белый список{{end}}
|
||||
{{define "telegram"}}Вход через Телеграм{{end}}
|
||||
`
|
||||
)
|
||||
|
||||
func InitHandlers(r *mux.Router) {
|
||||
r.PathPrefix("/help").HandlerFunc(handlerHelp)
|
||||
chain = viewutil.
|
||||
En(viewutil.CopyEnWith(fs, "view_help.html")).
|
||||
Ru(template.Must(viewutil.CopyRuWith(fs, "view_help.html").Parse(ruTranslation)))
|
||||
}
|
||||
|
||||
// handlerHelp gets the appropriate documentation or tells you where you (personally) have failed.
|
||||
func handlerHelp(w http.ResponseWriter, rq *http.Request) {
|
||||
// See the history of this file to resurrect the old algorithm that supported multiple languages
|
||||
var (
|
||||
meta = viewutil.MetaFrom(w, rq)
|
||||
articlePath = strings.TrimPrefix(strings.TrimPrefix(rq.URL.Path, "/help/"), "/help")
|
||||
lang = "en"
|
||||
)
|
||||
if articlePath == "" {
|
||||
articlePath = "en"
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(articlePath, "en") {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
_, _ = io.WriteString(w, "404 Not found")
|
||||
return
|
||||
}
|
||||
|
||||
content, err := Get(articlePath)
|
||||
if err != nil && strings.HasPrefix(err.Error(), "open") {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
viewHelp(meta, lang, "")
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
viewHelp(meta, lang, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: change for the function that uses byte array when there is such function in mycomarkup.
|
||||
ctx, _ := mycocontext.ContextFromStringInput(string(content), shroom.MarkupOptions(articlePath))
|
||||
ast := mycomarkup.BlockTree(ctx)
|
||||
result := mycomarkup.BlocksToHTML(ctx, ast)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
viewHelp(meta, lang, result)
|
||||
}
|
||||
|
||||
type helpData struct {
|
||||
viewutil.BaseData
|
||||
ContentsHTML string
|
||||
Lang string
|
||||
}
|
||||
|
||||
func viewHelp(meta viewutil.Meta, lang, contentsHTML string) {
|
||||
if err := chain.Get(meta).ExecuteTemplate(meta.W, "page", helpData{
|
||||
BaseData: viewutil.BaseData{
|
||||
Meta: meta,
|
||||
HeaderLinks: cfg.HeaderLinks,
|
||||
CommonScripts: cfg.CommonScripts,
|
||||
},
|
||||
ContentsHTML: contentsHTML,
|
||||
Lang: lang,
|
||||
}); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
@ -175,7 +175,7 @@ func (rev *Revision) hyphaeAffected() (hyphae []string) {
|
||||
filesAffected = rev.filesAffected()
|
||||
)
|
||||
for _, filename := range filesAffected {
|
||||
if strings.IndexRune(filename, '.') >= 0 {
|
||||
if strings.ContainsRune(filename, '.') {
|
||||
dotPos := strings.LastIndexByte(filename, '.')
|
||||
hyphaName := string([]byte(filename)[0:dotPos]) // is it safe?
|
||||
if isNewName(hyphaName) {
|
||||
|
@ -3,20 +3,6 @@
|
||||
"register": "Register",
|
||||
"title_search": "Search by title",
|
||||
"admin_panel": "Admin panel",
|
||||
|
||||
"search_results_title": "Search: {{.query}}",
|
||||
"search_results_query": "Search results for ‘{{.query}}’",
|
||||
"search_results_desc": "Every hypha name has been compared with the query. Hyphae that have matched the query are listed below.",
|
||||
|
||||
"backlinks_title": "Backlinks to {{.hypha_name}}",
|
||||
"backlinks_heading": "Backlinks to {{.hypha_link}}",
|
||||
"backlinks_desc": "Hyphae which have a link to this hypha, embed it as an image or transclude it are listed below.",
|
||||
|
||||
"list_title": "List of pages",
|
||||
"list_heading": "List of hyphae",
|
||||
"list_desc": "This wiki has {{.n}} %s.",
|
||||
"list_desc+one": "hypha",
|
||||
"list_desc+other": "hyphae",
|
||||
|
||||
"edit_link": "Edit text",
|
||||
"logout_link": "Log out",
|
||||
|
@ -118,7 +118,7 @@ func (t Localizer) GetWithLocale(locale, key string, replacements ...*Replacemen
|
||||
|
||||
// If the str doesn't have any substitutions, no need to
|
||||
// template.Execute.
|
||||
if strings.Index(str, "}}") == -1 {
|
||||
if !strings.Contains(str, "}}") {
|
||||
return str
|
||||
}
|
||||
|
||||
@ -145,7 +145,7 @@ func (t Localizer) GetPlural(key string, n int, replacements ...*Replacements) s
|
||||
|
||||
// As in the original, we skip templating if have nothing to replace
|
||||
// (however, it's strange case for plurals)
|
||||
if strings.Index(str, "}}") == -1 {
|
||||
if !strings.Contains(str, "}}") {
|
||||
return str
|
||||
}
|
||||
|
||||
@ -164,7 +164,7 @@ func (t Localizer) GetPlural64(key string, n int64, replacements ...*Replacement
|
||||
|
||||
// As in the original, we skip templating if have nothing to replace
|
||||
// (however, it's strange case for plurals)
|
||||
if strings.Index(str, "}}") == -1 {
|
||||
if !strings.Contains(str, "}}") {
|
||||
return str
|
||||
}
|
||||
|
||||
|
@ -3,21 +3,10 @@
|
||||
"register": "Регистрация",
|
||||
"title_search": "Поиск по названию",
|
||||
"admin_panel": "Администрирование",
|
||||
|
||||
"search_results_title": "Поиск: {{.query}}",
|
||||
"search_results_query": "Результаты поиска для «{{.query}}»",
|
||||
"search_results_desc": "Название каждой из существующих гиф сопоставлено с запросом. Подходящие гифы приведены ниже.",
|
||||
|
||||
|
||||
"backlinks_title": "Обратные ссылки на {{.hypha_name}}",
|
||||
"backlinks_heading": "Обратные ссылки на {{.hypha_link}}",
|
||||
"backlinks_desc": "Ниже перечислены гифы, на которых есть ссылка на эту гифу, трансклюзия этой гифы или эта гифа вставлена как изображение.",
|
||||
|
||||
"list_title": "Список страниц",
|
||||
"list_heading": "Список гиф",
|
||||
"list_desc": "В этой вики {{.n}} %s.",
|
||||
"list_desc+one": "гифа",
|
||||
"list_desc+few": "гифы",
|
||||
"list_desc+many": "гиф",
|
||||
|
||||
"edit_link": "Редактировать",
|
||||
"logout_link": "Выйти",
|
||||
|
9
main.go
9
main.go
@ -5,13 +5,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae/categories"
|
||||
"github.com/bouncepaw/mycorrhiza/backlinks"
|
||||
"github.com/bouncepaw/mycorrhiza/categories"
|
||||
"github.com/bouncepaw/mycorrhiza/migration"
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae/backlinks"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/files"
|
||||
"github.com/bouncepaw/mycorrhiza/history"
|
||||
@ -41,6 +41,7 @@ func main() {
|
||||
log.Println("Using Git storage at", files.HyphaeDir())
|
||||
|
||||
// Init the subsystems:
|
||||
viewutil.Init()
|
||||
hyphae.Index(files.HyphaeDir())
|
||||
backlinks.IndexBacklinks()
|
||||
go backlinks.RunBacklinksConveyor()
|
||||
@ -49,7 +50,7 @@ func main() {
|
||||
history.InitGitRepo()
|
||||
migration.MigrateRocketsMaybe()
|
||||
shroom.SetHeaderLinks()
|
||||
categories.InitCategories()
|
||||
categories.Init()
|
||||
|
||||
// Static files:
|
||||
static.InitFS(files.StaticFiles())
|
||||
|
@ -4,7 +4,7 @@
|
||||
package migration
|
||||
|
||||
import (
|
||||
"github.com/bouncepaw/mycomarkup/v3/tools"
|
||||
"github.com/bouncepaw/mycomarkup/v4/tools"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
|
159
misc/handlers.go
Normal file
159
misc/handlers.go
Normal file
@ -0,0 +1,159 @@
|
||||
// Package misc provides miscellaneous informative views.
|
||||
package misc
|
||||
|
||||
import (
|
||||
"github.com/bouncepaw/mycorrhiza/backlinks"
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/files"
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae"
|
||||
"github.com/bouncepaw/mycorrhiza/l18n"
|
||||
"github.com/bouncepaw/mycorrhiza/shroom"
|
||||
"github.com/bouncepaw/mycorrhiza/static"
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
"github.com/bouncepaw/mycorrhiza/views"
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
"github.com/gorilla/mux"
|
||||
"io"
|
||||
"log"
|
||||
"math/rand"
|
||||
"mime"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func InitHandlers(rtr *mux.Router) {
|
||||
rtr.HandleFunc("/robots.txt", handlerRobotsTxt)
|
||||
rtr.HandleFunc("/static/style.css", handlerStyle)
|
||||
rtr.PathPrefix("/static/").
|
||||
Handler(http.StripPrefix("/static/", http.FileServer(http.FS(static.FS))))
|
||||
rtr.HandleFunc("/list", handlerList)
|
||||
rtr.HandleFunc("/reindex", handlerReindex)
|
||||
rtr.HandleFunc("/update-header-links", handlerUpdateHeaderLinks)
|
||||
rtr.HandleFunc("/random", handlerRandom)
|
||||
rtr.HandleFunc("/about", handlerAbout)
|
||||
rtr.HandleFunc("/favicon.ico", func(w http.ResponseWriter, rq *http.Request) {
|
||||
http.Redirect(w, rq, "/static/favicon.ico", http.StatusSeeOther)
|
||||
})
|
||||
rtr.HandleFunc("/title-search/", handlerTitleSearch)
|
||||
initViews()
|
||||
}
|
||||
|
||||
// handlerList shows a list of all hyphae in the wiki in random order.
|
||||
func handlerList(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
viewList(viewutil.MetaFrom(w, rq))
|
||||
}
|
||||
|
||||
// handlerReindex reindexes all hyphae by checking the wiki storage directory anew.
|
||||
func handlerReindex(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
if ok := user.CanProceed(rq, "reindex"); !ok {
|
||||
var lc = l18n.FromRequest(rq)
|
||||
viewutil.HttpErr(viewutil.MetaFrom(w, rq), http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.reindex_no_rights"))
|
||||
log.Println("Rejected", rq.URL)
|
||||
return
|
||||
}
|
||||
hyphae.ResetCount()
|
||||
log.Println("Reindexing hyphae in", files.HyphaeDir())
|
||||
hyphae.Index(files.HyphaeDir())
|
||||
backlinks.IndexBacklinks()
|
||||
http.Redirect(w, rq, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// handlerUpdateHeaderLinks updates header links by reading the configured hypha, if there is any, or resorting to default values.
|
||||
func handlerUpdateHeaderLinks(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
if ok := user.CanProceed(rq, "update-header-links"); !ok {
|
||||
var lc = l18n.FromRequest(rq)
|
||||
viewutil.HttpErr(viewutil.MetaFrom(w, rq), http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.header_no_rights"))
|
||||
log.Println("Rejected", rq.URL)
|
||||
return
|
||||
}
|
||||
shroom.SetHeaderLinks()
|
||||
http.Redirect(w, rq, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// handlerRandom redirects to a random hypha.
|
||||
func handlerRandom(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
var (
|
||||
randomHyphaName string
|
||||
amountOfHyphae = hyphae.Count()
|
||||
)
|
||||
if amountOfHyphae == 0 {
|
||||
var lc = l18n.FromRequest(rq)
|
||||
viewutil.HttpErr(viewutil.MetaFrom(w, rq), http.StatusNotFound, cfg.HomeHypha, lc.Get("ui.random_no_hyphae_tip"))
|
||||
return
|
||||
}
|
||||
i := rand.Intn(amountOfHyphae)
|
||||
for h := range hyphae.YieldExistingHyphae() {
|
||||
if i == 0 {
|
||||
randomHyphaName = h.CanonicalName()
|
||||
}
|
||||
i--
|
||||
}
|
||||
http.Redirect(w, rq, "/hypha/"+randomHyphaName, http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// handlerAbout shows a summary of wiki's software.
|
||||
func handlerAbout(w http.ResponseWriter, rq *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/html;charset=utf-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
var (
|
||||
lc = l18n.FromRequest(rq)
|
||||
title = lc.Get("ui.about_title", &l18n.Replacements{"name": cfg.WikiName})
|
||||
)
|
||||
_, err := io.WriteString(w, views.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
title,
|
||||
views.AboutHTML(lc),
|
||||
))
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
var stylesheets = []string{"default.css", "custom.css"}
|
||||
|
||||
func handlerStyle(w http.ResponseWriter, rq *http.Request) {
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(".css"))
|
||||
for _, name := range stylesheets {
|
||||
file, err := static.FS.Open(name)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
_, err = io.Copy(w, file)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
_ = file.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func handlerRobotsTxt(w http.ResponseWriter, rq *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||
|
||||
file, err := static.FS.Open("robots.txt")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = io.Copy(w, file)
|
||||
if err != nil {
|
||||
log.Println()
|
||||
}
|
||||
_ = file.Close()
|
||||
}
|
||||
|
||||
func handlerTitleSearch(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
_ = rq.ParseForm()
|
||||
var (
|
||||
query = rq.FormValue("q")
|
||||
results []string
|
||||
)
|
||||
for hyphaName := range shroom.YieldHyphaNamesContainingString(query) {
|
||||
results = append(results, hyphaName)
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
viewTitleSearch(viewutil.MetaFrom(w, rq), query, results)
|
||||
}
|
21
misc/view_list.html
Normal file
21
misc/view_list.html
Normal file
@ -0,0 +1,21 @@
|
||||
{{define "list of hyphae"}}List of hyphae{{end}}
|
||||
{{define "title"}}{{template "list of hyphae"}}{{end}}
|
||||
{{define "body"}}
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
<h1>{{template "list of hyphae"}}</h1>
|
||||
<ol class="hypha-list">
|
||||
{{range .Entries}}
|
||||
<li class="hypha-list__entry">
|
||||
<a class="hypha-list__link" href="/hypha/{{.Name}}">
|
||||
{{beautifulName .Name}}
|
||||
</a>
|
||||
{{if .Ext}}
|
||||
<span class="hypha-list__amnt-type">{{.Ext}}</span>
|
||||
{{end}}
|
||||
</li>
|
||||
{{end}}
|
||||
</ol>
|
||||
</main>
|
||||
</div>
|
||||
{{end}}
|
16
misc/view_title_search.html
Normal file
16
misc/view_title_search.html
Normal file
@ -0,0 +1,16 @@
|
||||
{{define "search:"}}Search: {{.}}{{end}}
|
||||
{{define "title"}}{{template "search:" .Query}}{{end}}
|
||||
{{define "body"}}
|
||||
<div class="layout"><main class="main-width title-search">
|
||||
<h1>{{block "search results for" .Query}}Search results for ‘{{.}}’{{end}}</h1>
|
||||
<p>{{block "search desc" .}}Every hypha name has been compared with the query. Hyphae that have matched the query are listed below.{{end}}</p>
|
||||
<ul class="title-search__results">
|
||||
{{range .Results}}
|
||||
<li class="title-search__entry">
|
||||
<a class="title-search__link wikilink" href="/hypha/{%s hyphaName %}">{{beautifulName .}}</a>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
</main>
|
||||
</div>
|
||||
{{end}}
|
95
misc/views.go
Normal file
95
misc/views.go
Normal file
@ -0,0 +1,95 @@
|
||||
package misc
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae"
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
"log"
|
||||
"path/filepath"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed *html
|
||||
fs embed.FS
|
||||
chainList, chainTitleSearch viewutil.Chain
|
||||
ruTranslation = `
|
||||
{{define "list of hyphae"}}Список гиф{{end}}
|
||||
{{define "search:"}}Поиск:{{end}}
|
||||
{{define "search results for"}}Результаты поиска для «{{.}}»{{end}}
|
||||
{{define "search desc"}}Название каждой из существующих гиф сопоставлено с запросом. Подходящие гифы приведены ниже.{{end}}
|
||||
`
|
||||
)
|
||||
|
||||
func initViews() {
|
||||
m := template.Must
|
||||
chainList = viewutil.
|
||||
En(viewutil.CopyEnWith(fs, "view_list.html")).
|
||||
Ru(m(viewutil.CopyRuWith(fs, "view_list.html").Parse(ruTranslation)))
|
||||
chainTitleSearch = viewutil.
|
||||
En(viewutil.CopyEnWith(fs, "view_title_search.html")).
|
||||
Ru(m(viewutil.CopyRuWith(fs, "view_title_search.html").Parse(ruTranslation)))
|
||||
}
|
||||
|
||||
type listDatum struct {
|
||||
Name string
|
||||
Ext string
|
||||
}
|
||||
|
||||
type listData struct {
|
||||
viewutil.BaseData
|
||||
Entries []listDatum
|
||||
}
|
||||
|
||||
func viewList(meta viewutil.Meta) {
|
||||
// TODO: make this more effective, there are too many loops and vars
|
||||
var (
|
||||
hyphaNames = make(chan string)
|
||||
sortedHypha = hyphae.PathographicSort(hyphaNames)
|
||||
data []listDatum
|
||||
)
|
||||
for hypha := range hyphae.YieldExistingHyphae() {
|
||||
hyphaNames <- hypha.CanonicalName()
|
||||
}
|
||||
close(hyphaNames)
|
||||
for hyphaName := range sortedHypha {
|
||||
switch h := hyphae.ByName(hyphaName).(type) {
|
||||
case *hyphae.TextualHypha:
|
||||
data = append(data, listDatum{h.CanonicalName(), ""})
|
||||
case *hyphae.MediaHypha:
|
||||
data = append(data, listDatum{h.CanonicalName(), filepath.Ext(h.MediaFilePath())[1:]})
|
||||
}
|
||||
}
|
||||
|
||||
if err := chainList.Get(meta).ExecuteTemplate(meta.W, "page", listData{
|
||||
BaseData: viewutil.BaseData{
|
||||
Meta: meta,
|
||||
HeaderLinks: cfg.HeaderLinks,
|
||||
CommonScripts: cfg.CommonScripts,
|
||||
},
|
||||
Entries: data,
|
||||
}); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
type titleSearchData struct {
|
||||
viewutil.BaseData
|
||||
Query string
|
||||
Results []string
|
||||
}
|
||||
|
||||
func viewTitleSearch(meta viewutil.Meta, query string, results []string) {
|
||||
if err := chainTitleSearch.Get(meta).ExecuteTemplate(meta.W, "page", titleSearchData{
|
||||
BaseData: viewutil.BaseData{
|
||||
Meta: meta,
|
||||
HeaderLinks: cfg.HeaderLinks,
|
||||
CommonScripts: cfg.CommonScripts,
|
||||
},
|
||||
Query: query,
|
||||
Results: results,
|
||||
}); err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
@ -2,8 +2,7 @@ package shroom
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae/backlinks"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/backlinks"
|
||||
"github.com/bouncepaw/mycorrhiza/history"
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae"
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
|
@ -7,9 +7,6 @@ import (
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
)
|
||||
|
||||
func rejectDeleteLog(h hyphae.Hypha, u *user.User, errmsg string) {
|
||||
log.Printf("Reject delete ‘%s’ by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
|
||||
}
|
||||
func rejectRenameLog(h hyphae.Hypha, u *user.User, errmsg string) {
|
||||
log.Printf("Reject rename ‘%s’ by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
|
||||
}
|
||||
|
46
shroom/mycomarkup_options.go
Normal file
46
shroom/mycomarkup_options.go
Normal file
@ -0,0 +1,46 @@
|
||||
package shroom
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/bouncepaw/mycomarkup/v4/options"
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae"
|
||||
"github.com/bouncepaw/mycorrhiza/views"
|
||||
)
|
||||
|
||||
func MarkupOptions(hyphaName string) options.Options {
|
||||
return fillMycomarkupOptions(options.Options{
|
||||
HyphaName: hyphaName,
|
||||
WebSiteURL: cfg.URL,
|
||||
TransclusionSupported: true,
|
||||
})
|
||||
}
|
||||
|
||||
func fillMycomarkupOptions(opts options.Options) options.Options {
|
||||
opts.HyphaExists = func(hyphaName string) bool {
|
||||
switch hyphae.ByName(hyphaName).(type) {
|
||||
case *hyphae.EmptyHypha:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
opts.HyphaHTMLData = func(hyphaName string) (rawText, binaryBlock string, err error) {
|
||||
switch h := hyphae.ByName(hyphaName).(type) {
|
||||
case *hyphae.EmptyHypha:
|
||||
err = errors.New("Hypha " + hyphaName + " does not exist")
|
||||
case *hyphae.TextualHypha:
|
||||
rawText, err = FetchTextFile(h)
|
||||
case *hyphae.MediaHypha:
|
||||
rawText, err = FetchTextFile(h)
|
||||
binaryBlock = views.MediaRaw(h)
|
||||
}
|
||||
return
|
||||
}
|
||||
opts.IterateHyphaNamesWith = func(λ func(string)) {
|
||||
for h := range hyphae.YieldExistingHyphae() {
|
||||
λ(h.CanonicalName())
|
||||
}
|
||||
}
|
||||
return opts.FillTheRest()
|
||||
}
|
@ -3,7 +3,7 @@ package shroom
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae/backlinks"
|
||||
"github.com/bouncepaw/mycorrhiza/backlinks"
|
||||
"regexp"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/history"
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
)
|
||||
|
||||
// YieldHyphaNamesContainingString picks hyphae with have a string in their title, sorts and iterates over them.
|
||||
// YieldHyphaNamesContainingString picks hyphae with have a string in their title, sorts and iterates over them in alphabetical order.
|
||||
func YieldHyphaNamesContainingString(query string) <-chan string {
|
||||
query = util.CanonicalName(strings.TrimSpace(query))
|
||||
out := make(chan string)
|
||||
|
@ -2,41 +2,3 @@
|
||||
//
|
||||
// Some of them are wrappers around functions provided by package hyphae. They manage history for you.
|
||||
package shroom
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae"
|
||||
"github.com/bouncepaw/mycorrhiza/views"
|
||||
|
||||
"github.com/bouncepaw/mycomarkup/v3/globals"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// TODO: clean this complete and utter mess
|
||||
globals.HyphaExists = func(hyphaName string) bool {
|
||||
switch hyphae.ByName(hyphaName).(type) {
|
||||
case *hyphae.EmptyHypha:
|
||||
return false
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
globals.HyphaAccess = func(hyphaName string) (rawText, binaryBlock string, err error) {
|
||||
switch h := hyphae.ByName(hyphaName).(type) {
|
||||
case *hyphae.EmptyHypha:
|
||||
err = errors.New("Hypha " + hyphaName + " does not exist")
|
||||
case *hyphae.TextualHypha:
|
||||
rawText, err = FetchTextFile(h)
|
||||
case *hyphae.MediaHypha:
|
||||
rawText, err = FetchTextFile(h)
|
||||
binaryBlock = views.MediaRaw(h)
|
||||
}
|
||||
return
|
||||
}
|
||||
globals.HyphaIterate = func(λ func(string)) {
|
||||
for h := range hyphae.YieldExistingHyphae() {
|
||||
λ(h.CanonicalName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4,10 +4,10 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/bouncepaw/mycorrhiza/backlinks"
|
||||
"github.com/bouncepaw/mycorrhiza/files"
|
||||
"github.com/bouncepaw/mycorrhiza/history"
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae"
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae/backlinks"
|
||||
"github.com/bouncepaw/mycorrhiza/mimetype"
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
"io"
|
||||
@ -97,7 +97,7 @@ func UploadText(h hyphae.Hypha, data []byte, userMessage string, u *user.User) e
|
||||
}
|
||||
|
||||
// TODO: that []byte(...) part should be removed
|
||||
if bytes.Compare(data, []byte(oldText)) == 0 {
|
||||
if bytes.Equal(data, []byte(oldText)) {
|
||||
// No changes! Just like cancel button
|
||||
hop.Abort()
|
||||
return nil
|
||||
@ -118,7 +118,7 @@ func UploadText(h hyphae.Hypha, data []byte, userMessage string, u *user.User) e
|
||||
}
|
||||
|
||||
// TODO: that []byte(...) part should be removed
|
||||
if bytes.Compare(data, []byte(oldText)) == 0 {
|
||||
if bytes.Equal(data, []byte(oldText)) {
|
||||
// No changes! Just like cancel button
|
||||
hop.Abort()
|
||||
return nil
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/bouncepaw/mycomarkup/v3/util"
|
||||
"github.com/bouncepaw/mycomarkup/v4/util"
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
)
|
||||
|
||||
|
@ -47,7 +47,7 @@ const aboutTemplateString = `<div class="layout">
|
||||
<li><b>{{ get .L.Version }}</b> 1.9.0</li>
|
||||
{{ if .Cfg.UseAuth }}
|
||||
<li><b>{{ get .L.UserCount }}</b> {{ .UserCount }}</li>
|
||||
<li><b>{{ get .L.HomePage }}</b> <a href="/">{{ .Cfg.HomeHypha }}</a></li>
|
||||
<li><b>{{ get .L.HomeHypha }}</b> <a href="/">{{ .Cfg.HomeHypha }}</a></li>
|
||||
<li><b>{{ get .L.Admins }}</b> {{$cfg := .Cfg}}{{ range $i, $username := .Admins }}
|
||||
{{ if gt $i 0 }}<span aria-hidden="true">, </span>{{ end }}
|
||||
<a href="/hypha/{{ $cfg.UserHypha }}/{{ $username }}">{{ $username }}</a>
|
||||
@ -71,7 +71,7 @@ var aboutData = struct {
|
||||
"Title": e().en("About %s").ru("О %s"),
|
||||
"Version": e().en("<a href=\"https://mycorrhiza.wiki\">Mycorrhiza Wiki</a> version:").ru("Версия <a href=\"https://mycorrhiza.wiki\">Микоризы</a>:"),
|
||||
"UserCount": e().en("User count:").ru("Число пользователей:"),
|
||||
"HomePage": e().en("Home page:").ru("Домашняя гифа:"),
|
||||
"HomeHypha": e().en("Home hypha:").ru("Домашняя гифа:"),
|
||||
"Admins": e().en("Administrators:").ru("Администраторы:"),
|
||||
"NoAuth": e().en("This wiki does not use authorization").ru("На этой вики не используется авторизация"),
|
||||
"AboutHyphae": e().en("See <a href=\"/list\">/list</a> for information about hyphae on this wiki.").ru("См. <a href=\"/list\">/list</a>, чтобы узнать о гифах в этой вики."),
|
||||
|
@ -2,6 +2,7 @@ package views
|
||||
|
||||
import (
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
"html/template"
|
||||
"io"
|
||||
"log"
|
||||
@ -25,7 +26,7 @@ var (
|
||||
adminTemplatesRu *template.Template
|
||||
)
|
||||
|
||||
func localizedAdminTemplates(meta Meta) *template.Template {
|
||||
func localizedAdminTemplates(meta viewutil.Meta) *template.Template {
|
||||
if meta.Lc.Locale == "ru" {
|
||||
return adminTemplatesRu
|
||||
}
|
||||
@ -59,16 +60,18 @@ func init() {
|
||||
template.Must(adminTemplatesEn.Clone()).Parse(adminTranslationRu))
|
||||
}
|
||||
|
||||
func AdminPanel(meta Meta) {
|
||||
func AdminPanel(meta viewutil.Meta) {
|
||||
var buf strings.Builder
|
||||
err := localizedAdminTemplates(meta).ExecuteTemplate(&buf, "panel", nil)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
_, err = io.WriteString(meta.W, Base(
|
||||
meta,
|
||||
templateAsString(localizedAdminTemplates(meta), "panel title"),
|
||||
buf.String(),
|
||||
meta.Lc,
|
||||
meta.U,
|
||||
))
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
{% import "net/http" %}
|
||||
{% import "sort" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/cfg" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/l18n" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/user" %}
|
||||
|
||||
{% func Register(rq *http.Request) %}
|
||||
{% code
|
||||
@ -148,3 +150,63 @@ Telegram auth widget was requested by Yogurt. As you can see, we don't offer use
|
||||
</body>
|
||||
</html>
|
||||
{% endfunc %}
|
||||
|
||||
{% code
|
||||
var userListL10n = map[string]l10nEntry{
|
||||
"heading": en("List of users").ru("Список пользователей"),
|
||||
"administrators": en("Administrators").ru("Администраторы"),
|
||||
"moderators": en("Moderators").ru("Модераторы"),
|
||||
"editors": en("Editors").ru("Редакторы"),
|
||||
}
|
||||
%}
|
||||
|
||||
{% func UserList(lc *l18n.Localizer) %}
|
||||
<div class="layout">
|
||||
<main class="main-width user-list">
|
||||
{% code
|
||||
var get = func(key string) string {
|
||||
return userListL10n[key].get(lc.Locale)
|
||||
}
|
||||
|
||||
var (
|
||||
admins = make([]string, 0)
|
||||
moderators = make([]string, 0)
|
||||
editors = make([]string, 0)
|
||||
)
|
||||
for u := range user.YieldUsers() {
|
||||
switch u.Group {
|
||||
// What if we place the users into sorted slices?
|
||||
case "admin":
|
||||
admins = append(admins, u.Name)
|
||||
case "moderator":
|
||||
moderators = append(moderators, u.Name)
|
||||
case "editor", "trusted":
|
||||
editors = append(editors, u.Name)
|
||||
}
|
||||
}
|
||||
sort.Strings(admins)
|
||||
sort.Strings(moderators)
|
||||
sort.Strings(editors)
|
||||
%}
|
||||
<h1>{%s get("heading") %}</h1>
|
||||
<section>
|
||||
<h2>{%s get("administrators") %}</h2>
|
||||
<ol>{% for _, name := range admins %}
|
||||
<li><a href="/hypha/{%s cfg.UserHypha %}/{%s name %}">{%s name %}</a></li>
|
||||
{% endfor %}</ol>
|
||||
</section>
|
||||
<section>
|
||||
<h2>{%s get("moderators") %}</h2>
|
||||
<ol>{% for _, name := range moderators %}
|
||||
<li><a href="/hypha/{%s cfg.UserHypha %}/{%s name %}">{%s name %}</a></li>
|
||||
{% endfor %}</ol>
|
||||
</section>
|
||||
<section>
|
||||
<h2>{%s get("editors") %}</h2>
|
||||
<ol>{% for _, name := range editors %}
|
||||
<li><a href="/hypha/{%s cfg.UserHypha %}/{%s name %}">{%s name %}</a></li>
|
||||
{% endfor %}</ol>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
{% endfunc %}
|
@ -8,517 +8,523 @@ package views
|
||||
import "net/http"
|
||||
|
||||
//line views/auth.qtpl:2
|
||||
import "github.com/bouncepaw/mycorrhiza/cfg"
|
||||
import "sort"
|
||||
|
||||
//line views/auth.qtpl:3
|
||||
import "github.com/bouncepaw/mycorrhiza/cfg"
|
||||
|
||||
//line views/auth.qtpl:4
|
||||
import "github.com/bouncepaw/mycorrhiza/l18n"
|
||||
|
||||
//line views/auth.qtpl:5
|
||||
import "github.com/bouncepaw/mycorrhiza/user"
|
||||
|
||||
//line views/auth.qtpl:7
|
||||
import (
|
||||
qtio422016 "io"
|
||||
|
||||
qt422016 "github.com/valyala/quicktemplate"
|
||||
)
|
||||
|
||||
//line views/auth.qtpl:5
|
||||
//line views/auth.qtpl:7
|
||||
var (
|
||||
_ = qtio422016.Copy
|
||||
_ = qt422016.AcquireByteBuffer
|
||||
)
|
||||
|
||||
//line views/auth.qtpl:5
|
||||
//line views/auth.qtpl:7
|
||||
func StreamRegister(qw422016 *qt422016.Writer, rq *http.Request) {
|
||||
//line views/auth.qtpl:5
|
||||
//line views/auth.qtpl:7
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/auth.qtpl:7
|
||||
//line views/auth.qtpl:9
|
||||
lc := l18n.FromRequest(rq)
|
||||
|
||||
//line views/auth.qtpl:8
|
||||
//line views/auth.qtpl:10
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
<section>
|
||||
`)
|
||||
//line views/auth.qtpl:12
|
||||
//line views/auth.qtpl:14
|
||||
if cfg.AllowRegistration {
|
||||
//line views/auth.qtpl:12
|
||||
//line views/auth.qtpl:14
|
||||
qw422016.N().S(`
|
||||
<form class="modal" method="post" action="/register?`)
|
||||
//line views/auth.qtpl:13
|
||||
//line views/auth.qtpl:15
|
||||
qw422016.E().S(rq.URL.RawQuery)
|
||||
//line views/auth.qtpl:13
|
||||
//line views/auth.qtpl:15
|
||||
qw422016.N().S(`" id="register-form" enctype="multipart/form-data" autocomplete="off">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title">`)
|
||||
//line views/auth.qtpl:15
|
||||
//line views/auth.qtpl:17
|
||||
qw422016.E().S(lc.Get("auth.register_header", &l18n.Replacements{"name": cfg.WikiName}))
|
||||
//line views/auth.qtpl:15
|
||||
//line views/auth.qtpl:17
|
||||
qw422016.N().S(`</legend>
|
||||
|
||||
<label for="register-form__username">`)
|
||||
//line views/auth.qtpl:17
|
||||
//line views/auth.qtpl:19
|
||||
qw422016.E().S(lc.Get("auth.username"))
|
||||
//line views/auth.qtpl:17
|
||||
//line views/auth.qtpl:19
|
||||
qw422016.N().S(`</label>
|
||||
<br>
|
||||
<input type="text" required autofocus id="login-form__username" name="username">
|
||||
<br>
|
||||
<label for="login-form__password">`)
|
||||
//line views/auth.qtpl:21
|
||||
//line views/auth.qtpl:23
|
||||
qw422016.E().S(lc.Get("auth.password"))
|
||||
//line views/auth.qtpl:21
|
||||
//line views/auth.qtpl:23
|
||||
qw422016.N().S(`</label>
|
||||
<br>
|
||||
<input type="password" required name="password">
|
||||
<p>`)
|
||||
//line views/auth.qtpl:24
|
||||
//line views/auth.qtpl:26
|
||||
qw422016.E().S(lc.Get("auth.password_tip"))
|
||||
//line views/auth.qtpl:24
|
||||
//line views/auth.qtpl:26
|
||||
qw422016.N().S(`</p>
|
||||
<p>`)
|
||||
//line views/auth.qtpl:25
|
||||
//line views/auth.qtpl:27
|
||||
qw422016.E().S(lc.Get("auth.cookie_tip"))
|
||||
//line views/auth.qtpl:25
|
||||
//line views/auth.qtpl:27
|
||||
qw422016.N().S(`</p>
|
||||
<button class="btn" type="submit" value="Register">`)
|
||||
//line views/auth.qtpl:26
|
||||
//line views/auth.qtpl:28
|
||||
qw422016.E().S(lc.Get("auth.register_button"))
|
||||
//line views/auth.qtpl:26
|
||||
//line views/auth.qtpl:28
|
||||
qw422016.N().S(`</button>
|
||||
<a class="btn btn_weak" href="/`)
|
||||
//line views/auth.qtpl:27
|
||||
//line views/auth.qtpl:29
|
||||
qw422016.E().S(rq.URL.RawQuery)
|
||||
//line views/auth.qtpl:27
|
||||
//line views/auth.qtpl:29
|
||||
qw422016.N().S(`">`)
|
||||
//line views/auth.qtpl:27
|
||||
//line views/auth.qtpl:29
|
||||
qw422016.E().S(lc.Get("ui.cancel"))
|
||||
//line views/auth.qtpl:27
|
||||
//line views/auth.qtpl:29
|
||||
qw422016.N().S(`</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
`)
|
||||
//line views/auth.qtpl:30
|
||||
//line views/auth.qtpl:32
|
||||
streamtelegramWidget(qw422016, lc)
|
||||
//line views/auth.qtpl:30
|
||||
//line views/auth.qtpl:32
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/auth.qtpl:31
|
||||
//line views/auth.qtpl:33
|
||||
} else if cfg.UseAuth {
|
||||
//line views/auth.qtpl:31
|
||||
//line views/auth.qtpl:33
|
||||
qw422016.N().S(`
|
||||
<p>`)
|
||||
//line views/auth.qtpl:32
|
||||
//line views/auth.qtpl:34
|
||||
qw422016.E().S(lc.Get("auth.noregister"))
|
||||
//line views/auth.qtpl:32
|
||||
//line views/auth.qtpl:34
|
||||
qw422016.N().S(`</p>
|
||||
<p><a href="/`)
|
||||
//line views/auth.qtpl:33
|
||||
//line views/auth.qtpl:35
|
||||
qw422016.E().S(rq.URL.RawQuery)
|
||||
//line views/auth.qtpl:33
|
||||
//line views/auth.qtpl:35
|
||||
qw422016.N().S(`">← `)
|
||||
//line views/auth.qtpl:33
|
||||
//line views/auth.qtpl:35
|
||||
qw422016.E().S(lc.Get("auth.go_back"))
|
||||
//line views/auth.qtpl:33
|
||||
//line views/auth.qtpl:35
|
||||
qw422016.N().S(`</a></p>
|
||||
`)
|
||||
//line views/auth.qtpl:34
|
||||
//line views/auth.qtpl:36
|
||||
} else {
|
||||
//line views/auth.qtpl:34
|
||||
//line views/auth.qtpl:36
|
||||
qw422016.N().S(`
|
||||
<p>`)
|
||||
//line views/auth.qtpl:35
|
||||
//line views/auth.qtpl:37
|
||||
qw422016.E().S(lc.Get("auth.noauth"))
|
||||
//line views/auth.qtpl:35
|
||||
//line views/auth.qtpl:37
|
||||
qw422016.N().S(`</p>
|
||||
<p><a href="/`)
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:38
|
||||
qw422016.E().S(rq.URL.RawQuery)
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:38
|
||||
qw422016.N().S(`">← `)
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:38
|
||||
qw422016.E().S(lc.Get("auth.go_back"))
|
||||
//line views/auth.qtpl:36
|
||||
//line views/auth.qtpl:38
|
||||
qw422016.N().S(`</a></p>
|
||||
`)
|
||||
//line views/auth.qtpl:37
|
||||
//line views/auth.qtpl:39
|
||||
}
|
||||
//line views/auth.qtpl:37
|
||||
//line views/auth.qtpl:39
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/auth.qtpl:41
|
||||
//line views/auth.qtpl:43
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:41
|
||||
//line views/auth.qtpl:43
|
||||
func WriteRegister(qq422016 qtio422016.Writer, rq *http.Request) {
|
||||
//line views/auth.qtpl:41
|
||||
//line views/auth.qtpl:43
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/auth.qtpl:41
|
||||
//line views/auth.qtpl:43
|
||||
StreamRegister(qw422016, rq)
|
||||
//line views/auth.qtpl:41
|
||||
//line views/auth.qtpl:43
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/auth.qtpl:41
|
||||
//line views/auth.qtpl:43
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:41
|
||||
//line views/auth.qtpl:43
|
||||
func Register(rq *http.Request) string {
|
||||
//line views/auth.qtpl:41
|
||||
//line views/auth.qtpl:43
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/auth.qtpl:41
|
||||
//line views/auth.qtpl:43
|
||||
WriteRegister(qb422016, rq)
|
||||
//line views/auth.qtpl:41
|
||||
//line views/auth.qtpl:43
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/auth.qtpl:41
|
||||
//line views/auth.qtpl:43
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/auth.qtpl:41
|
||||
//line views/auth.qtpl:43
|
||||
return qs422016
|
||||
//line views/auth.qtpl:41
|
||||
//line views/auth.qtpl:43
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:43
|
||||
//line views/auth.qtpl:45
|
||||
func StreamLogin(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
|
||||
//line views/auth.qtpl:43
|
||||
//line views/auth.qtpl:45
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
<section>
|
||||
`)
|
||||
//line views/auth.qtpl:47
|
||||
//line views/auth.qtpl:49
|
||||
if cfg.UseAuth {
|
||||
//line views/auth.qtpl:47
|
||||
//line views/auth.qtpl:49
|
||||
qw422016.N().S(`
|
||||
<form class="modal" method="post" action="/login" id="login-form" enctype="multipart/form-data" autocomplete="on">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title">`)
|
||||
//line views/auth.qtpl:50
|
||||
//line views/auth.qtpl:52
|
||||
qw422016.E().S(lc.Get("auth.login_header", &l18n.Replacements{"name": cfg.WikiName}))
|
||||
//line views/auth.qtpl:50
|
||||
//line views/auth.qtpl:52
|
||||
qw422016.N().S(`</legend>
|
||||
<label for="login-form__username">`)
|
||||
//line views/auth.qtpl:51
|
||||
//line views/auth.qtpl:53
|
||||
qw422016.E().S(lc.Get("auth.username"))
|
||||
//line views/auth.qtpl:51
|
||||
//line views/auth.qtpl:53
|
||||
qw422016.N().S(`</label>
|
||||
<br>
|
||||
<input type="text" required autofocus id="login-form__username" name="username" autocomplete="username">
|
||||
<br>
|
||||
<label for="login-form__password">`)
|
||||
//line views/auth.qtpl:55
|
||||
//line views/auth.qtpl:57
|
||||
qw422016.E().S(lc.Get("auth.password"))
|
||||
//line views/auth.qtpl:55
|
||||
//line views/auth.qtpl:57
|
||||
qw422016.N().S(`</label>
|
||||
<br>
|
||||
<input type="password" required name="password" autocomplete="current-password">
|
||||
<p>`)
|
||||
//line views/auth.qtpl:58
|
||||
//line views/auth.qtpl:60
|
||||
qw422016.E().S(lc.Get("auth.cookie_tip"))
|
||||
//line views/auth.qtpl:58
|
||||
//line views/auth.qtpl:60
|
||||
qw422016.N().S(`</p>
|
||||
<button class="btn" type="submit" value="Log in">`)
|
||||
//line views/auth.qtpl:59
|
||||
//line views/auth.qtpl:61
|
||||
qw422016.E().S(lc.Get("auth.login_button"))
|
||||
//line views/auth.qtpl:59
|
||||
//line views/auth.qtpl:61
|
||||
qw422016.N().S(`</button>
|
||||
<a class="btn btn_weak" href="/">`)
|
||||
//line views/auth.qtpl:60
|
||||
//line views/auth.qtpl:62
|
||||
qw422016.E().S(lc.Get("ui.cancel"))
|
||||
//line views/auth.qtpl:60
|
||||
//line views/auth.qtpl:62
|
||||
qw422016.N().S(`</a>
|
||||
</fieldset>
|
||||
</form>
|
||||
`)
|
||||
//line views/auth.qtpl:63
|
||||
//line views/auth.qtpl:65
|
||||
streamtelegramWidget(qw422016, lc)
|
||||
//line views/auth.qtpl:63
|
||||
//line views/auth.qtpl:65
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/auth.qtpl:64
|
||||
//line views/auth.qtpl:66
|
||||
} else {
|
||||
//line views/auth.qtpl:64
|
||||
//line views/auth.qtpl:66
|
||||
qw422016.N().S(`
|
||||
<p>`)
|
||||
//line views/auth.qtpl:65
|
||||
//line views/auth.qtpl:67
|
||||
qw422016.E().S(lc.Get("auth.noauth"))
|
||||
//line views/auth.qtpl:65
|
||||
//line views/auth.qtpl:67
|
||||
qw422016.N().S(`</p>
|
||||
<p><a class="btn btn_weak" href="/">← `)
|
||||
//line views/auth.qtpl:66
|
||||
//line views/auth.qtpl:68
|
||||
qw422016.E().S(lc.Get("auth.go_home"))
|
||||
//line views/auth.qtpl:66
|
||||
//line views/auth.qtpl:68
|
||||
qw422016.N().S(`</a></p>
|
||||
`)
|
||||
//line views/auth.qtpl:67
|
||||
//line views/auth.qtpl:69
|
||||
}
|
||||
//line views/auth.qtpl:67
|
||||
//line views/auth.qtpl:69
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/auth.qtpl:71
|
||||
//line views/auth.qtpl:73
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:71
|
||||
//line views/auth.qtpl:73
|
||||
func WriteLogin(qq422016 qtio422016.Writer, lc *l18n.Localizer) {
|
||||
//line views/auth.qtpl:71
|
||||
//line views/auth.qtpl:73
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/auth.qtpl:71
|
||||
//line views/auth.qtpl:73
|
||||
StreamLogin(qw422016, lc)
|
||||
//line views/auth.qtpl:71
|
||||
//line views/auth.qtpl:73
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/auth.qtpl:71
|
||||
//line views/auth.qtpl:73
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:71
|
||||
//line views/auth.qtpl:73
|
||||
func Login(lc *l18n.Localizer) string {
|
||||
//line views/auth.qtpl:71
|
||||
//line views/auth.qtpl:73
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/auth.qtpl:71
|
||||
//line views/auth.qtpl:73
|
||||
WriteLogin(qb422016, lc)
|
||||
//line views/auth.qtpl:71
|
||||
//line views/auth.qtpl:73
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/auth.qtpl:71
|
||||
//line views/auth.qtpl:73
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/auth.qtpl:71
|
||||
//line views/auth.qtpl:73
|
||||
return qs422016
|
||||
//line views/auth.qtpl:71
|
||||
//line views/auth.qtpl:73
|
||||
}
|
||||
|
||||
// Telegram auth widget was requested by Yogurt. As you can see, we don't offer user administrators control over it. Of course we don't.
|
||||
|
||||
//line views/auth.qtpl:74
|
||||
//line views/auth.qtpl:76
|
||||
func streamtelegramWidget(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
|
||||
//line views/auth.qtpl:74
|
||||
//line views/auth.qtpl:76
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/auth.qtpl:75
|
||||
//line views/auth.qtpl:77
|
||||
if cfg.TelegramEnabled {
|
||||
//line views/auth.qtpl:75
|
||||
//line views/auth.qtpl:77
|
||||
qw422016.N().S(`
|
||||
<p class="telegram-notice">`)
|
||||
//line views/auth.qtpl:76
|
||||
//line views/auth.qtpl:78
|
||||
qw422016.E().S(lc.Get("auth.telegram_tip"))
|
||||
//line views/auth.qtpl:76
|
||||
//line views/auth.qtpl:78
|
||||
qw422016.N().S(`</p>
|
||||
<script async src="https://telegram.org/js/telegram-widget.js?15" data-telegram-login="`)
|
||||
//line views/auth.qtpl:77
|
||||
//line views/auth.qtpl:79
|
||||
qw422016.E().S(cfg.TelegramBotName)
|
||||
//line views/auth.qtpl:77
|
||||
//line views/auth.qtpl:79
|
||||
qw422016.N().S(`" data-size="medium" data-userpic="false" data-auth-url="`)
|
||||
//line views/auth.qtpl:77
|
||||
//line views/auth.qtpl:79
|
||||
qw422016.E().S(cfg.URL)
|
||||
//line views/auth.qtpl:77
|
||||
//line views/auth.qtpl:79
|
||||
qw422016.N().S(`/telegram-login"></script>
|
||||
`)
|
||||
//line views/auth.qtpl:78
|
||||
//line views/auth.qtpl:80
|
||||
}
|
||||
//line views/auth.qtpl:78
|
||||
//line views/auth.qtpl:80
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/auth.qtpl:79
|
||||
//line views/auth.qtpl:81
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:79
|
||||
//line views/auth.qtpl:81
|
||||
func writetelegramWidget(qq422016 qtio422016.Writer, lc *l18n.Localizer) {
|
||||
//line views/auth.qtpl:79
|
||||
//line views/auth.qtpl:81
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/auth.qtpl:79
|
||||
//line views/auth.qtpl:81
|
||||
streamtelegramWidget(qw422016, lc)
|
||||
//line views/auth.qtpl:79
|
||||
//line views/auth.qtpl:81
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/auth.qtpl:79
|
||||
//line views/auth.qtpl:81
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:79
|
||||
//line views/auth.qtpl:81
|
||||
func telegramWidget(lc *l18n.Localizer) string {
|
||||
//line views/auth.qtpl:79
|
||||
//line views/auth.qtpl:81
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/auth.qtpl:79
|
||||
//line views/auth.qtpl:81
|
||||
writetelegramWidget(qb422016, lc)
|
||||
//line views/auth.qtpl:79
|
||||
//line views/auth.qtpl:81
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/auth.qtpl:79
|
||||
//line views/auth.qtpl:81
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/auth.qtpl:79
|
||||
//line views/auth.qtpl:81
|
||||
return qs422016
|
||||
//line views/auth.qtpl:79
|
||||
//line views/auth.qtpl:81
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:81
|
||||
//line views/auth.qtpl:83
|
||||
func StreamLoginError(qw422016 *qt422016.Writer, err string, lc *l18n.Localizer) {
|
||||
//line views/auth.qtpl:81
|
||||
//line views/auth.qtpl:83
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
<section>
|
||||
`)
|
||||
//line views/auth.qtpl:85
|
||||
//line views/auth.qtpl:87
|
||||
switch err {
|
||||
//line views/auth.qtpl:86
|
||||
//line views/auth.qtpl:88
|
||||
case "unknown username":
|
||||
//line views/auth.qtpl:86
|
||||
//line views/auth.qtpl:88
|
||||
qw422016.N().S(`
|
||||
<p class="error">`)
|
||||
//line views/auth.qtpl:87
|
||||
//line views/auth.qtpl:89
|
||||
qw422016.E().S(lc.Get("auth.error_username"))
|
||||
//line views/auth.qtpl:87
|
||||
//line views/auth.qtpl:89
|
||||
qw422016.N().S(`</p>
|
||||
`)
|
||||
//line views/auth.qtpl:88
|
||||
//line views/auth.qtpl:90
|
||||
case "wrong password":
|
||||
//line views/auth.qtpl:88
|
||||
//line views/auth.qtpl:90
|
||||
qw422016.N().S(`
|
||||
<p class="error">`)
|
||||
//line views/auth.qtpl:89
|
||||
//line views/auth.qtpl:91
|
||||
qw422016.E().S(lc.Get("auth.error_password"))
|
||||
//line views/auth.qtpl:89
|
||||
//line views/auth.qtpl:91
|
||||
qw422016.N().S(`</p>
|
||||
`)
|
||||
//line views/auth.qtpl:90
|
||||
//line views/auth.qtpl:92
|
||||
default:
|
||||
//line views/auth.qtpl:90
|
||||
//line views/auth.qtpl:92
|
||||
qw422016.N().S(`
|
||||
<p class="error">`)
|
||||
//line views/auth.qtpl:91
|
||||
//line views/auth.qtpl:93
|
||||
qw422016.E().S(err)
|
||||
//line views/auth.qtpl:91
|
||||
//line views/auth.qtpl:93
|
||||
qw422016.N().S(`</p>
|
||||
`)
|
||||
//line views/auth.qtpl:92
|
||||
//line views/auth.qtpl:94
|
||||
}
|
||||
//line views/auth.qtpl:92
|
||||
//line views/auth.qtpl:94
|
||||
qw422016.N().S(`
|
||||
<p><a href="/login">← `)
|
||||
//line views/auth.qtpl:93
|
||||
//line views/auth.qtpl:95
|
||||
qw422016.E().S(lc.Get("auth.try_again"))
|
||||
//line views/auth.qtpl:93
|
||||
//line views/auth.qtpl:95
|
||||
qw422016.N().S(`</a></p>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/auth.qtpl:97
|
||||
//line views/auth.qtpl:99
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:97
|
||||
//line views/auth.qtpl:99
|
||||
func WriteLoginError(qq422016 qtio422016.Writer, err string, lc *l18n.Localizer) {
|
||||
//line views/auth.qtpl:97
|
||||
//line views/auth.qtpl:99
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/auth.qtpl:97
|
||||
//line views/auth.qtpl:99
|
||||
StreamLoginError(qw422016, err, lc)
|
||||
//line views/auth.qtpl:97
|
||||
//line views/auth.qtpl:99
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/auth.qtpl:97
|
||||
//line views/auth.qtpl:99
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:97
|
||||
//line views/auth.qtpl:99
|
||||
func LoginError(err string, lc *l18n.Localizer) string {
|
||||
//line views/auth.qtpl:97
|
||||
//line views/auth.qtpl:99
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/auth.qtpl:97
|
||||
//line views/auth.qtpl:99
|
||||
WriteLoginError(qb422016, err, lc)
|
||||
//line views/auth.qtpl:97
|
||||
//line views/auth.qtpl:99
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/auth.qtpl:97
|
||||
//line views/auth.qtpl:99
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/auth.qtpl:97
|
||||
//line views/auth.qtpl:99
|
||||
return qs422016
|
||||
//line views/auth.qtpl:97
|
||||
//line views/auth.qtpl:99
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:99
|
||||
//line views/auth.qtpl:101
|
||||
func StreamLogout(qw422016 *qt422016.Writer, can bool, lc *l18n.Localizer) {
|
||||
//line views/auth.qtpl:99
|
||||
//line views/auth.qtpl:101
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
<section>
|
||||
`)
|
||||
//line views/auth.qtpl:103
|
||||
//line views/auth.qtpl:105
|
||||
if can {
|
||||
//line views/auth.qtpl:103
|
||||
//line views/auth.qtpl:105
|
||||
qw422016.N().S(`
|
||||
<h1>`)
|
||||
//line views/auth.qtpl:104
|
||||
//line views/auth.qtpl:106
|
||||
qw422016.E().S(lc.Get("auth.logout_header"))
|
||||
//line views/auth.qtpl:104
|
||||
//line views/auth.qtpl:106
|
||||
qw422016.N().S(`</h1>
|
||||
<form method="POST" action="/logout">
|
||||
<input class="btn btn_accent" type="submit" value="`)
|
||||
//line views/auth.qtpl:106
|
||||
//line views/auth.qtpl:108
|
||||
qw422016.E().S(lc.Get("auth.logout_button"))
|
||||
//line views/auth.qtpl:106
|
||||
//line views/auth.qtpl:108
|
||||
qw422016.N().S(`"/>
|
||||
<a class="btn btn_weak" href="/">`)
|
||||
//line views/auth.qtpl:107
|
||||
//line views/auth.qtpl:109
|
||||
qw422016.E().S(lc.Get("auth.go_home"))
|
||||
//line views/auth.qtpl:107
|
||||
//line views/auth.qtpl:109
|
||||
qw422016.N().S(`</a>
|
||||
</form>
|
||||
`)
|
||||
//line views/auth.qtpl:109
|
||||
//line views/auth.qtpl:111
|
||||
} else {
|
||||
//line views/auth.qtpl:109
|
||||
//line views/auth.qtpl:111
|
||||
qw422016.N().S(`
|
||||
<p>`)
|
||||
//line views/auth.qtpl:110
|
||||
//line views/auth.qtpl:112
|
||||
qw422016.E().S(lc.Get("auth.logout_anon"))
|
||||
//line views/auth.qtpl:110
|
||||
//line views/auth.qtpl:112
|
||||
qw422016.N().S(`</p>
|
||||
<p><a href="/login">`)
|
||||
//line views/auth.qtpl:111
|
||||
//line views/auth.qtpl:113
|
||||
qw422016.E().S(lc.Get("auth.login_title"))
|
||||
//line views/auth.qtpl:111
|
||||
//line views/auth.qtpl:113
|
||||
qw422016.N().S(`</a></p>
|
||||
<p><a href="/">← `)
|
||||
//line views/auth.qtpl:112
|
||||
//line views/auth.qtpl:114
|
||||
qw422016.E().S(lc.Get("auth.go_home"))
|
||||
//line views/auth.qtpl:112
|
||||
//line views/auth.qtpl:114
|
||||
qw422016.N().S(`</a></p>
|
||||
`)
|
||||
//line views/auth.qtpl:113
|
||||
//line views/auth.qtpl:115
|
||||
}
|
||||
//line views/auth.qtpl:113
|
||||
//line views/auth.qtpl:115
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/auth.qtpl:117
|
||||
//line views/auth.qtpl:119
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:117
|
||||
//line views/auth.qtpl:119
|
||||
func WriteLogout(qq422016 qtio422016.Writer, can bool, lc *l18n.Localizer) {
|
||||
//line views/auth.qtpl:117
|
||||
//line views/auth.qtpl:119
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/auth.qtpl:117
|
||||
//line views/auth.qtpl:119
|
||||
StreamLogout(qw422016, can, lc)
|
||||
//line views/auth.qtpl:117
|
||||
//line views/auth.qtpl:119
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/auth.qtpl:117
|
||||
//line views/auth.qtpl:119
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:117
|
||||
//line views/auth.qtpl:119
|
||||
func Logout(can bool, lc *l18n.Localizer) string {
|
||||
//line views/auth.qtpl:117
|
||||
//line views/auth.qtpl:119
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/auth.qtpl:117
|
||||
//line views/auth.qtpl:119
|
||||
WriteLogout(qb422016, can, lc)
|
||||
//line views/auth.qtpl:117
|
||||
//line views/auth.qtpl:119
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/auth.qtpl:117
|
||||
//line views/auth.qtpl:119
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/auth.qtpl:117
|
||||
//line views/auth.qtpl:119
|
||||
return qs422016
|
||||
//line views/auth.qtpl:117
|
||||
//line views/auth.qtpl:119
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:119
|
||||
//line views/auth.qtpl:121
|
||||
func StreamLock(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
|
||||
//line views/auth.qtpl:119
|
||||
//line views/auth.qtpl:121
|
||||
qw422016.N().S(`
|
||||
<!doctype html>
|
||||
<html>
|
||||
@ -526,9 +532,9 @@ func StreamLock(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>🔒 `)
|
||||
//line views/auth.qtpl:125
|
||||
//line views/auth.qtpl:127
|
||||
qw422016.E().S(lc.Get("auth.lock_title"))
|
||||
//line views/auth.qtpl:125
|
||||
//line views/auth.qtpl:127
|
||||
qw422016.N().S(`</title>
|
||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
@ -538,68 +544,237 @@ func StreamLock(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
|
||||
<section class="locked-notice__message">
|
||||
<p class="locked-notice__lock">🔒</p>
|
||||
<h1 class="locked-notice__title">`)
|
||||
//line views/auth.qtpl:133
|
||||
//line views/auth.qtpl:135
|
||||
qw422016.E().S(lc.Get("auth.lock_title"))
|
||||
//line views/auth.qtpl:133
|
||||
//line views/auth.qtpl:135
|
||||
qw422016.N().S(`</h1>
|
||||
<form class="locked-notice__login-form" method="post" action="/login" id="login-form" enctype="multipart/form-data" autocomplete="on">
|
||||
<label for="login-form__username">`)
|
||||
//line views/auth.qtpl:135
|
||||
//line views/auth.qtpl:137
|
||||
qw422016.E().S(lc.Get("auth.username"))
|
||||
//line views/auth.qtpl:135
|
||||
//line views/auth.qtpl:137
|
||||
qw422016.N().S(`</label>
|
||||
<br>
|
||||
<input type="text" required autofocus id="login-form__username" name="username" autocomplete="username">
|
||||
<br>
|
||||
<label for="login-form__password">`)
|
||||
//line views/auth.qtpl:139
|
||||
//line views/auth.qtpl:141
|
||||
qw422016.E().S(lc.Get("auth.password"))
|
||||
//line views/auth.qtpl:139
|
||||
//line views/auth.qtpl:141
|
||||
qw422016.N().S(`</label>
|
||||
<br>
|
||||
<input type="password" required name="password" autocomplete="current-password">
|
||||
<br>
|
||||
<button class="btn" type="submit" value="Log in">`)
|
||||
//line views/auth.qtpl:143
|
||||
//line views/auth.qtpl:145
|
||||
qw422016.E().S(lc.Get("auth.login_button"))
|
||||
//line views/auth.qtpl:143
|
||||
//line views/auth.qtpl:145
|
||||
qw422016.N().S(`</button>
|
||||
</form>
|
||||
`)
|
||||
//line views/auth.qtpl:145
|
||||
//line views/auth.qtpl:147
|
||||
streamtelegramWidget(qw422016, lc)
|
||||
//line views/auth.qtpl:145
|
||||
//line views/auth.qtpl:147
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
`)
|
||||
//line views/auth.qtpl:150
|
||||
//line views/auth.qtpl:152
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:150
|
||||
//line views/auth.qtpl:152
|
||||
func WriteLock(qq422016 qtio422016.Writer, lc *l18n.Localizer) {
|
||||
//line views/auth.qtpl:150
|
||||
//line views/auth.qtpl:152
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/auth.qtpl:150
|
||||
//line views/auth.qtpl:152
|
||||
StreamLock(qw422016, lc)
|
||||
//line views/auth.qtpl:150
|
||||
//line views/auth.qtpl:152
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/auth.qtpl:150
|
||||
//line views/auth.qtpl:152
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:150
|
||||
//line views/auth.qtpl:152
|
||||
func Lock(lc *l18n.Localizer) string {
|
||||
//line views/auth.qtpl:150
|
||||
//line views/auth.qtpl:152
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/auth.qtpl:150
|
||||
//line views/auth.qtpl:152
|
||||
WriteLock(qb422016, lc)
|
||||
//line views/auth.qtpl:150
|
||||
//line views/auth.qtpl:152
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/auth.qtpl:150
|
||||
//line views/auth.qtpl:152
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/auth.qtpl:150
|
||||
//line views/auth.qtpl:152
|
||||
return qs422016
|
||||
//line views/auth.qtpl:150
|
||||
//line views/auth.qtpl:152
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:155
|
||||
var userListL10n = map[string]l10nEntry{
|
||||
"heading": en("List of users").ru("Список пользователей"),
|
||||
"administrators": en("Administrators").ru("Администраторы"),
|
||||
"moderators": en("Moderators").ru("Модераторы"),
|
||||
"editors": en("Editors").ru("Редакторы"),
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:163
|
||||
func StreamUserList(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
|
||||
//line views/auth.qtpl:163
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width user-list">
|
||||
`)
|
||||
//line views/auth.qtpl:167
|
||||
var get = func(key string) string {
|
||||
return userListL10n[key].get(lc.Locale)
|
||||
}
|
||||
|
||||
var (
|
||||
admins = make([]string, 0)
|
||||
moderators = make([]string, 0)
|
||||
editors = make([]string, 0)
|
||||
)
|
||||
for u := range user.YieldUsers() {
|
||||
switch u.Group {
|
||||
// What if we place the users into sorted slices?
|
||||
case "admin":
|
||||
admins = append(admins, u.Name)
|
||||
case "moderator":
|
||||
moderators = append(moderators, u.Name)
|
||||
case "editor", "trusted":
|
||||
editors = append(editors, u.Name)
|
||||
}
|
||||
}
|
||||
sort.Strings(admins)
|
||||
sort.Strings(moderators)
|
||||
sort.Strings(editors)
|
||||
|
||||
//line views/auth.qtpl:190
|
||||
qw422016.N().S(`
|
||||
<h1>`)
|
||||
//line views/auth.qtpl:191
|
||||
qw422016.E().S(get("heading"))
|
||||
//line views/auth.qtpl:191
|
||||
qw422016.N().S(`</h1>
|
||||
<section>
|
||||
<h2>`)
|
||||
//line views/auth.qtpl:193
|
||||
qw422016.E().S(get("administrators"))
|
||||
//line views/auth.qtpl:193
|
||||
qw422016.N().S(`</h2>
|
||||
<ol>`)
|
||||
//line views/auth.qtpl:194
|
||||
for _, name := range admins {
|
||||
//line views/auth.qtpl:194
|
||||
qw422016.N().S(`
|
||||
<li><a href="/hypha/`)
|
||||
//line views/auth.qtpl:195
|
||||
qw422016.E().S(cfg.UserHypha)
|
||||
//line views/auth.qtpl:195
|
||||
qw422016.N().S(`/`)
|
||||
//line views/auth.qtpl:195
|
||||
qw422016.E().S(name)
|
||||
//line views/auth.qtpl:195
|
||||
qw422016.N().S(`">`)
|
||||
//line views/auth.qtpl:195
|
||||
qw422016.E().S(name)
|
||||
//line views/auth.qtpl:195
|
||||
qw422016.N().S(`</a></li>
|
||||
`)
|
||||
//line views/auth.qtpl:196
|
||||
}
|
||||
//line views/auth.qtpl:196
|
||||
qw422016.N().S(`</ol>
|
||||
</section>
|
||||
<section>
|
||||
<h2>`)
|
||||
//line views/auth.qtpl:199
|
||||
qw422016.E().S(get("moderators"))
|
||||
//line views/auth.qtpl:199
|
||||
qw422016.N().S(`</h2>
|
||||
<ol>`)
|
||||
//line views/auth.qtpl:200
|
||||
for _, name := range moderators {
|
||||
//line views/auth.qtpl:200
|
||||
qw422016.N().S(`
|
||||
<li><a href="/hypha/`)
|
||||
//line views/auth.qtpl:201
|
||||
qw422016.E().S(cfg.UserHypha)
|
||||
//line views/auth.qtpl:201
|
||||
qw422016.N().S(`/`)
|
||||
//line views/auth.qtpl:201
|
||||
qw422016.E().S(name)
|
||||
//line views/auth.qtpl:201
|
||||
qw422016.N().S(`">`)
|
||||
//line views/auth.qtpl:201
|
||||
qw422016.E().S(name)
|
||||
//line views/auth.qtpl:201
|
||||
qw422016.N().S(`</a></li>
|
||||
`)
|
||||
//line views/auth.qtpl:202
|
||||
}
|
||||
//line views/auth.qtpl:202
|
||||
qw422016.N().S(`</ol>
|
||||
</section>
|
||||
<section>
|
||||
<h2>`)
|
||||
//line views/auth.qtpl:205
|
||||
qw422016.E().S(get("editors"))
|
||||
//line views/auth.qtpl:205
|
||||
qw422016.N().S(`</h2>
|
||||
<ol>`)
|
||||
//line views/auth.qtpl:206
|
||||
for _, name := range editors {
|
||||
//line views/auth.qtpl:206
|
||||
qw422016.N().S(`
|
||||
<li><a href="/hypha/`)
|
||||
//line views/auth.qtpl:207
|
||||
qw422016.E().S(cfg.UserHypha)
|
||||
//line views/auth.qtpl:207
|
||||
qw422016.N().S(`/`)
|
||||
//line views/auth.qtpl:207
|
||||
qw422016.E().S(name)
|
||||
//line views/auth.qtpl:207
|
||||
qw422016.N().S(`">`)
|
||||
//line views/auth.qtpl:207
|
||||
qw422016.E().S(name)
|
||||
//line views/auth.qtpl:207
|
||||
qw422016.N().S(`</a></li>
|
||||
`)
|
||||
//line views/auth.qtpl:208
|
||||
}
|
||||
//line views/auth.qtpl:208
|
||||
qw422016.N().S(`</ol>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/auth.qtpl:212
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:212
|
||||
func WriteUserList(qq422016 qtio422016.Writer, lc *l18n.Localizer) {
|
||||
//line views/auth.qtpl:212
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/auth.qtpl:212
|
||||
StreamUserList(qw422016, lc)
|
||||
//line views/auth.qtpl:212
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/auth.qtpl:212
|
||||
}
|
||||
|
||||
//line views/auth.qtpl:212
|
||||
func UserList(lc *l18n.Localizer) string {
|
||||
//line views/auth.qtpl:212
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/auth.qtpl:212
|
||||
WriteUserList(qb422016, lc)
|
||||
//line views/auth.qtpl:212
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/auth.qtpl:212
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/auth.qtpl:212
|
||||
return qs422016
|
||||
//line views/auth.qtpl:212
|
||||
}
|
||||
|
@ -2,28 +2,11 @@ package views
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"github.com/bouncepaw/mycorrhiza/l18n"
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
"io"
|
||||
"net/http"
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
)
|
||||
|
||||
// Meta is a bundle of common stuffs used by views, templates.
|
||||
type Meta struct {
|
||||
Lc *l18n.Localizer
|
||||
U *user.User
|
||||
W io.Writer
|
||||
PageTitle string
|
||||
}
|
||||
|
||||
// MetaFrom makes a Meta from the given data. You are meant to further modify it.
|
||||
func MetaFrom(w http.ResponseWriter, rq *http.Request) Meta {
|
||||
return Meta{
|
||||
Lc: l18n.FromRequest(rq),
|
||||
U: user.FromRequest(rq),
|
||||
W: w,
|
||||
}
|
||||
}
|
||||
|
||||
//go:embed *.html
|
||||
var fs embed.FS
|
||||
var (
|
||||
//go:embed *.html
|
||||
fs embed.FS
|
||||
Base = viewutil.Base
|
||||
)
|
||||
|
@ -1,125 +0,0 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae/categories"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
"html/template"
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const categoriesRu = `
|
||||
{{define "empty cat"}}Эта категория пуста.{{end}}
|
||||
{{define "add hypha"}}Добавить в категорию{{end}}
|
||||
{{define "cat"}}Категория{{end}}
|
||||
{{define "hypha name"}}Имя гифы{{end}}
|
||||
{{define "categories"}}Категории{{end}}
|
||||
{{define "placeholder"}}Имя категории...{{end}}
|
||||
{{define "remove from category title"}}Убрать гифу из этой категории{{end}}
|
||||
{{define "add to category title"}}Добавить гифу в эту категорию{{end}}
|
||||
{{define "category list heading"}}Список категорий{{end}}
|
||||
{{define "no categories"}}В этой вики нет категорий.{{end}}
|
||||
{{define "category x"}}Категория {{. | beautifulName}}{{end}}
|
||||
`
|
||||
|
||||
var (
|
||||
categoryTemplatesEn *template.Template
|
||||
categoryTemplatesRu *template.Template
|
||||
)
|
||||
|
||||
func init() {
|
||||
categoryTemplatesEn = template.Must(template.
|
||||
New("category").
|
||||
Funcs(
|
||||
template.FuncMap{
|
||||
"beautifulName": util.BeautifulName,
|
||||
}).
|
||||
ParseFS(fs, "categories.html"))
|
||||
categoryTemplatesRu = template.Must(template.Must(categoryTemplatesEn.Clone()).Parse(categoriesRu))
|
||||
}
|
||||
|
||||
func localizedCatTemplates(meta Meta) *template.Template {
|
||||
if meta.Lc.Locale == "ru" {
|
||||
return categoryTemplatesRu
|
||||
}
|
||||
return categoryTemplatesEn
|
||||
}
|
||||
|
||||
func localizedCatTemplateAsString(meta Meta, name string, datum ...interface{}) string {
|
||||
var buf strings.Builder
|
||||
var err error
|
||||
if len(datum) == 1 {
|
||||
err = localizedCatTemplates(meta).ExecuteTemplate(&buf, name, datum[0])
|
||||
} else {
|
||||
err = localizedCatTemplates(meta).ExecuteTemplate(&buf, name, nil)
|
||||
}
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return ""
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func categoryCard(meta Meta, hyphaName string) string {
|
||||
var buf strings.Builder
|
||||
err := localizedCatTemplates(meta).ExecuteTemplate(&buf, "category card", struct {
|
||||
HyphaName string
|
||||
Categories []string
|
||||
GivenPermissionToModify bool
|
||||
}{
|
||||
hyphaName,
|
||||
categories.WithHypha(hyphaName),
|
||||
meta.U.CanProceed("add-to-category"),
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func CategoryPage(meta Meta, catName string) {
|
||||
var buf strings.Builder
|
||||
err := localizedCatTemplates(meta).ExecuteTemplate(&buf, "category page", struct {
|
||||
CatName string
|
||||
Hyphae []string
|
||||
GivenPermissionToModify bool
|
||||
}{
|
||||
catName,
|
||||
categories.Contents(catName),
|
||||
meta.U.CanProceed("add-to-category"),
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
_, err = io.WriteString(meta.W, Base(
|
||||
localizedCatTemplateAsString(meta, "category x", catName),
|
||||
buf.String(),
|
||||
meta.Lc,
|
||||
meta.U,
|
||||
))
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
||||
|
||||
func CategoryList(meta Meta) {
|
||||
var buf strings.Builder
|
||||
err := localizedCatTemplates(meta).ExecuteTemplate(&buf, "category list", struct {
|
||||
Categories []string
|
||||
}{
|
||||
categories.List(),
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
_, err = io.WriteString(meta.W, Base(
|
||||
localizedCatTemplateAsString(meta, "category list heading"),
|
||||
buf.String(),
|
||||
meta.Lc,
|
||||
meta.U,
|
||||
))
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
{{define "category x"}}Category {{. | beautifulName}}{{end}}
|
||||
|
||||
{{define "category card"}}
|
||||
{{$hyphaName := .HyphaName}}
|
||||
{{$givenPermission := .GivenPermissionToModify}}
|
||||
<aside class="layout-card categories-card">
|
||||
<h2 class="layout-card__title">{{block `categories` .}}Categories{{end}}</h2>
|
||||
<ul class="categories-card__entries">
|
||||
{{range .Categories}}
|
||||
<li class="categories-card__entry">
|
||||
<a class="categories-card__link" href="/category/{{.}}">{{beautifulName .}}</a>
|
||||
<form method="POST" action="/remove-from-category" class="categories-card__remove-form">
|
||||
<input type="hidden" name="cat" value="{{.}}">
|
||||
<input type="hidden" name="hypha" value="{{$hyphaName}}">
|
||||
<input type="hidden" name="redirect-to" value="/hypha/{{$hyphaName}}">
|
||||
{{if $givenPermission}}
|
||||
<input type="submit" value="x" class="btn categories-card__btn"
|
||||
title="{{block `remove from category title` .}}Remove the hypha from this category{{end}}">
|
||||
{{end}}
|
||||
</form>
|
||||
</li>
|
||||
{{end}}
|
||||
{{if .GivenPermissionToModify}}
|
||||
<li class="categories-card__entry categories-card__add-to-cat">
|
||||
<form method="POST" action="/add-to-category" class="categories-card__add-form">
|
||||
<input type="text" name="cat" id="_cat-name"
|
||||
placeholder="{{block `placeholder` .}}Category name...{{end}}">
|
||||
<input type="hidden" name="hypha" value="{{$hyphaName}}">
|
||||
<input type="hidden" name="redirect-to" value="/hypha/{{$hyphaName}}">
|
||||
<input type="submit" class="btn categories-card__btn" value="+"
|
||||
title="{{block `add to category title` .}}Add the hypha to this category{{end}}">
|
||||
</form>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
</aside>
|
||||
{{end}}
|
||||
|
||||
{{define "category page"}}
|
||||
{{$catName := .CatName}}
|
||||
<main class="main-width category">
|
||||
<h1>{{block "cat" .}}Category{{end}} <i>{{beautifulName $catName}}</i></h1>
|
||||
{{if len .Hyphae | not}}
|
||||
<p>{{block "empty cat" .}}This category is empty{{end}}</p>
|
||||
{{end}}
|
||||
<ul class="category__entries">
|
||||
{{range .Hyphae}}
|
||||
<li class="category__entry">
|
||||
<a class="category__link" href="/hypha/{{.}}">{{beautifulName .}}</a>
|
||||
</li>
|
||||
{{end}}
|
||||
{{if .GivenPermissionToModify}}
|
||||
<li class="category__entry category__add-to-cat">
|
||||
<form method="POST" action="/add-to-category" class="category__add-form">
|
||||
<input type="text" name="hypha" id="_hypha-name"
|
||||
placeholder="{{block `hypha name` .}}Hypha name{{end}}">
|
||||
<input type="hidden" name="cat" value="{{$catName}}">
|
||||
<input type="hidden" name="redirect-to" value="/category/{{$catName}}">
|
||||
<input type="submit" class="btn" value="{{block `add hypha` .}}Add to the category{{end}}">
|
||||
</form>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
</main>
|
||||
{{end}}
|
||||
|
||||
{{define "category list"}}
|
||||
<main class="main-width category-list">
|
||||
<h1>{{block `category list heading` .}}Category list{{end}}</h1>
|
||||
{{if len .Categories}}
|
||||
<ul class="category-list__entries">
|
||||
{{range .Categories}}
|
||||
<li class="category-list__entry">
|
||||
<a class="category-list__link" href="/category/{{.}}">{{beautifulName .}}</a>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<p>{{block `no categories` .}}This wiki has no categories.{{end}}</p>
|
||||
{{end}}
|
||||
</main>
|
||||
{{end}}
|
101
views/help.go
101
views/help.go
@ -1,101 +0,0 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/bouncepaw/mycorrhiza/l18n"
|
||||
"log"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
var helpTopicsL10n = map[string][]string{
|
||||
"topics": {"Help topics", "Темы справки"},
|
||||
"main": {"Main", "Введение"},
|
||||
"hypha": {"Hypha", "Гифа"},
|
||||
"media": {"Media", "Медиа"},
|
||||
"mycomarkup": {"Mycomarkup", "Микоразметка"},
|
||||
"interface": {"Interface", "Интерфейс"},
|
||||
"prevnext": {"Previous/next", "Назад/далее"}, // пред след?
|
||||
"top_bar": {"Top bar", "Верхняя панель"},
|
||||
"sibling_hyphae": {"Sibling hyphae", "Гифы-сиблинги"},
|
||||
"special_pages": {"Special pages", "Специальные страницы"},
|
||||
"recent_changes": {"Recent changes", "Недавние изменения"}, // так ли? В медиавики свежие правки
|
||||
"feeds": {"Feeds", "Ленты"},
|
||||
"configuration": {"Configuration (for administrators)", "Конфигурация (для администраторов)"},
|
||||
"config_file": {"Configuration file", "Файл конфигурации"},
|
||||
"lock": {"Lock", "Блокировка"}, // Не Замок ли?
|
||||
"whitelist": {"Whitelist", "Белый список"},
|
||||
"telegram": {"Telegram authentication", "Вход через Телеграм"},
|
||||
"category": {"Categories", "Категории"},
|
||||
}
|
||||
|
||||
const helpTopicTemplate = `<aside class="help-topics layout-card">
|
||||
<h2 class="layout-card__title">{{l "topics"}}</h2>
|
||||
<ul class="help-topics__list">
|
||||
<li>{{l "main" | a ""}}</li>
|
||||
<li>{{l "hypha" | a "/hypha"}}
|
||||
<ul>
|
||||
{{l "media" | a "/media"}}
|
||||
</ul>
|
||||
</li>
|
||||
<li>{{l "mycomarkup" | a "/mycomarkup"}}</li>
|
||||
<li>{{l "category" | a "/category"}}</li>
|
||||
<li>{{l "interface"}}
|
||||
<ul>
|
||||
<li>{{l "prevnext" | a "/prevnext"}}</li>
|
||||
<li>{{l "top_bar" | a "/top_bar"}}</li>
|
||||
<li>{{l "sibling_hyphae" | a "/sibling_hyphae_section"}}</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>{{l "special_pages"}}
|
||||
<ul>
|
||||
<li>{{l "recent_changes" | a "/recent_changes"}}</li>
|
||||
<li>{{l "feeds" | a "/feeds"}}</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>{{l "configuration"}}
|
||||
<ul>
|
||||
<li>{{l "config_file" | a "/config_file"}}</li>
|
||||
<li>{{l "lock" | a "/lock"}}</li>
|
||||
<li>{{l "whitelist" | a "/whitelist"}}</li>
|
||||
<li>{{l "telegram" | a "/telegram"}}</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</aside>`
|
||||
|
||||
// helpTopicsLinkWrapper wraps in <a>
|
||||
func helpTopicsLinkWrapper(lang string) func(string, string) string {
|
||||
return func(path, contents string) string {
|
||||
return fmt.Sprintf(`<a href="/help/%s%s">%s</a>`, lang, path, contents)
|
||||
}
|
||||
}
|
||||
|
||||
func helpTopicsLocalizedTopic(lang string) func(string) string {
|
||||
pos := 0
|
||||
if lang == "ru" {
|
||||
pos = 1
|
||||
}
|
||||
return func(topic string) string {
|
||||
return helpTopicsL10n[topic][pos]
|
||||
}
|
||||
}
|
||||
|
||||
func helpTopics(lang string, lc *l18n.Localizer) string {
|
||||
temp, err := template.
|
||||
New("help topics").
|
||||
Funcs(template.FuncMap{
|
||||
"a": helpTopicsLinkWrapper(lang),
|
||||
"l": helpTopicsLocalizedTopic(lc.Locale),
|
||||
}).
|
||||
Parse(helpTopicTemplate)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return ""
|
||||
}
|
||||
|
||||
// TODO: one day, it should write to a better place
|
||||
var out strings.Builder
|
||||
_ = temp.Execute(&out, nil) // Shall not fail!
|
||||
return out.String()
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
{% import "strings" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/cfg" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/hyphae/backlinks" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/backlinks" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/l18n" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/user" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/hyphae" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/viewutil" %}
|
||||
|
||||
{% func hyphaInfoEntry(h hyphae.Hypha, u *user.User, action, displayText string) %}
|
||||
{% if u.CanProceed(action) %}
|
||||
@ -13,7 +14,7 @@
|
||||
{% endif %}
|
||||
{% endfunc %}
|
||||
|
||||
{% func hyphaInfo(meta Meta, h hyphae.Hypha) %}
|
||||
{% func hyphaInfo(meta viewutil.Meta, h hyphae.Hypha) %}
|
||||
{% code
|
||||
u := meta.U
|
||||
lc := meta.Lc
|
||||
@ -52,3 +53,9 @@
|
||||
</section>
|
||||
{% endif %}
|
||||
{% endfunc %}
|
||||
|
||||
{% func commonScripts() %}
|
||||
{% for _, scriptPath := range cfg.CommonScripts %}
|
||||
<script src="{%s scriptPath %}"></script>
|
||||
{% endfor %}
|
||||
{% endfunc %}
|
||||
|
@ -11,7 +11,7 @@ import "strings"
|
||||
import "github.com/bouncepaw/mycorrhiza/cfg"
|
||||
|
||||
//line views/nav.qtpl:3
|
||||
import "github.com/bouncepaw/mycorrhiza/hyphae/backlinks"
|
||||
import "github.com/bouncepaw/mycorrhiza/backlinks"
|
||||
|
||||
//line views/nav.qtpl:4
|
||||
import "github.com/bouncepaw/mycorrhiza/l18n"
|
||||
@ -22,270 +22,322 @@ import "github.com/bouncepaw/mycorrhiza/user"
|
||||
//line views/nav.qtpl:6
|
||||
import "github.com/bouncepaw/mycorrhiza/hyphae"
|
||||
|
||||
//line views/nav.qtpl:8
|
||||
//line views/nav.qtpl:7
|
||||
import "github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
|
||||
//line views/nav.qtpl:9
|
||||
import (
|
||||
qtio422016 "io"
|
||||
|
||||
qt422016 "github.com/valyala/quicktemplate"
|
||||
)
|
||||
|
||||
//line views/nav.qtpl:8
|
||||
//line views/nav.qtpl:9
|
||||
var (
|
||||
_ = qtio422016.Copy
|
||||
_ = qt422016.AcquireByteBuffer
|
||||
)
|
||||
|
||||
//line views/nav.qtpl:8
|
||||
//line views/nav.qtpl:9
|
||||
func streamhyphaInfoEntry(qw422016 *qt422016.Writer, h hyphae.Hypha, u *user.User, action, displayText string) {
|
||||
//line views/nav.qtpl:8
|
||||
//line views/nav.qtpl:9
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/nav.qtpl:9
|
||||
//line views/nav.qtpl:10
|
||||
if u.CanProceed(action) {
|
||||
//line views/nav.qtpl:9
|
||||
//line views/nav.qtpl:10
|
||||
qw422016.N().S(`
|
||||
<li class="hypha-info__entry hypha-info__entry_`)
|
||||
//line views/nav.qtpl:10
|
||||
//line views/nav.qtpl:11
|
||||
qw422016.E().S(action)
|
||||
//line views/nav.qtpl:10
|
||||
//line views/nav.qtpl:11
|
||||
qw422016.N().S(`">
|
||||
<a class="hypha-info__link" href="/`)
|
||||
//line views/nav.qtpl:11
|
||||
//line views/nav.qtpl:12
|
||||
qw422016.E().S(action)
|
||||
//line views/nav.qtpl:11
|
||||
//line views/nav.qtpl:12
|
||||
qw422016.N().S(`/`)
|
||||
//line views/nav.qtpl:11
|
||||
//line views/nav.qtpl:12
|
||||
qw422016.E().S(h.CanonicalName())
|
||||
//line views/nav.qtpl:11
|
||||
//line views/nav.qtpl:12
|
||||
qw422016.N().S(`">`)
|
||||
//line views/nav.qtpl:11
|
||||
//line views/nav.qtpl:12
|
||||
qw422016.E().S(displayText)
|
||||
//line views/nav.qtpl:11
|
||||
//line views/nav.qtpl:12
|
||||
qw422016.N().S(`</a>
|
||||
</li>
|
||||
`)
|
||||
//line views/nav.qtpl:13
|
||||
//line views/nav.qtpl:14
|
||||
}
|
||||
//line views/nav.qtpl:13
|
||||
//line views/nav.qtpl:14
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/nav.qtpl:14
|
||||
//line views/nav.qtpl:15
|
||||
}
|
||||
|
||||
//line views/nav.qtpl:14
|
||||
//line views/nav.qtpl:15
|
||||
func writehyphaInfoEntry(qq422016 qtio422016.Writer, h hyphae.Hypha, u *user.User, action, displayText string) {
|
||||
//line views/nav.qtpl:14
|
||||
//line views/nav.qtpl:15
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/nav.qtpl:14
|
||||
//line views/nav.qtpl:15
|
||||
streamhyphaInfoEntry(qw422016, h, u, action, displayText)
|
||||
//line views/nav.qtpl:14
|
||||
//line views/nav.qtpl:15
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/nav.qtpl:14
|
||||
//line views/nav.qtpl:15
|
||||
}
|
||||
|
||||
//line views/nav.qtpl:14
|
||||
//line views/nav.qtpl:15
|
||||
func hyphaInfoEntry(h hyphae.Hypha, u *user.User, action, displayText string) string {
|
||||
//line views/nav.qtpl:14
|
||||
//line views/nav.qtpl:15
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/nav.qtpl:14
|
||||
//line views/nav.qtpl:15
|
||||
writehyphaInfoEntry(qb422016, h, u, action, displayText)
|
||||
//line views/nav.qtpl:14
|
||||
//line views/nav.qtpl:15
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/nav.qtpl:14
|
||||
//line views/nav.qtpl:15
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/nav.qtpl:14
|
||||
//line views/nav.qtpl:15
|
||||
return qs422016
|
||||
//line views/nav.qtpl:14
|
||||
//line views/nav.qtpl:15
|
||||
}
|
||||
|
||||
//line views/nav.qtpl:16
|
||||
func streamhyphaInfo(qw422016 *qt422016.Writer, meta Meta, h hyphae.Hypha) {
|
||||
//line views/nav.qtpl:16
|
||||
//line views/nav.qtpl:17
|
||||
func streamhyphaInfo(qw422016 *qt422016.Writer, meta viewutil.Meta, h hyphae.Hypha) {
|
||||
//line views/nav.qtpl:17
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/nav.qtpl:18
|
||||
//line views/nav.qtpl:19
|
||||
u := meta.U
|
||||
lc := meta.Lc
|
||||
backs := backlinks.BacklinksCount(h)
|
||||
|
||||
//line views/nav.qtpl:21
|
||||
//line views/nav.qtpl:22
|
||||
qw422016.N().S(`
|
||||
<nav class="hypha-info">
|
||||
<ul class="hypha-info__list">
|
||||
`)
|
||||
//line views/nav.qtpl:24
|
||||
//line views/nav.qtpl:25
|
||||
streamhyphaInfoEntry(qw422016, h, u, "history", lc.Get("ui.history_link"))
|
||||
//line views/nav.qtpl:24
|
||||
//line views/nav.qtpl:25
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/nav.qtpl:25
|
||||
//line views/nav.qtpl:26
|
||||
streamhyphaInfoEntry(qw422016, h, u, "rename", lc.Get("ui.rename_link"))
|
||||
//line views/nav.qtpl:25
|
||||
//line views/nav.qtpl:26
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/nav.qtpl:26
|
||||
//line views/nav.qtpl:27
|
||||
streamhyphaInfoEntry(qw422016, h, u, "delete", lc.Get("ui.delete_link"))
|
||||
//line views/nav.qtpl:26
|
||||
//line views/nav.qtpl:27
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/nav.qtpl:27
|
||||
//line views/nav.qtpl:28
|
||||
streamhyphaInfoEntry(qw422016, h, u, "text", lc.Get("ui.text_link"))
|
||||
//line views/nav.qtpl:27
|
||||
//line views/nav.qtpl:28
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/nav.qtpl:28
|
||||
//line views/nav.qtpl:29
|
||||
streamhyphaInfoEntry(qw422016, h, u, "media", lc.Get("ui.media_link"))
|
||||
//line views/nav.qtpl:28
|
||||
//line views/nav.qtpl:29
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/nav.qtpl:29
|
||||
//line views/nav.qtpl:30
|
||||
streamhyphaInfoEntry(qw422016, h, u, "backlinks", lc.GetPlural("ui.backlinks_link", backs))
|
||||
//line views/nav.qtpl:29
|
||||
//line views/nav.qtpl:30
|
||||
qw422016.N().S(`
|
||||
</ul>
|
||||
</nav>
|
||||
`)
|
||||
//line views/nav.qtpl:32
|
||||
//line views/nav.qtpl:33
|
||||
}
|
||||
|
||||
//line views/nav.qtpl:32
|
||||
func writehyphaInfo(qq422016 qtio422016.Writer, meta Meta, h hyphae.Hypha) {
|
||||
//line views/nav.qtpl:32
|
||||
//line views/nav.qtpl:33
|
||||
func writehyphaInfo(qq422016 qtio422016.Writer, meta viewutil.Meta, h hyphae.Hypha) {
|
||||
//line views/nav.qtpl:33
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/nav.qtpl:32
|
||||
//line views/nav.qtpl:33
|
||||
streamhyphaInfo(qw422016, meta, h)
|
||||
//line views/nav.qtpl:32
|
||||
//line views/nav.qtpl:33
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/nav.qtpl:32
|
||||
//line views/nav.qtpl:33
|
||||
}
|
||||
|
||||
//line views/nav.qtpl:32
|
||||
func hyphaInfo(meta Meta, h hyphae.Hypha) string {
|
||||
//line views/nav.qtpl:32
|
||||
//line views/nav.qtpl:33
|
||||
func hyphaInfo(meta viewutil.Meta, h hyphae.Hypha) string {
|
||||
//line views/nav.qtpl:33
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/nav.qtpl:32
|
||||
//line views/nav.qtpl:33
|
||||
writehyphaInfo(qb422016, meta, h)
|
||||
//line views/nav.qtpl:32
|
||||
//line views/nav.qtpl:33
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/nav.qtpl:32
|
||||
//line views/nav.qtpl:33
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/nav.qtpl:32
|
||||
//line views/nav.qtpl:33
|
||||
return qs422016
|
||||
//line views/nav.qtpl:32
|
||||
//line views/nav.qtpl:33
|
||||
}
|
||||
|
||||
//line views/nav.qtpl:34
|
||||
//line views/nav.qtpl:35
|
||||
func streamsiblingHyphae(qw422016 *qt422016.Writer, siblings string, lc *l18n.Localizer) {
|
||||
//line views/nav.qtpl:34
|
||||
//line views/nav.qtpl:35
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/nav.qtpl:35
|
||||
//line views/nav.qtpl:36
|
||||
if cfg.UseSiblingHyphaeSidebar {
|
||||
//line views/nav.qtpl:35
|
||||
//line views/nav.qtpl:36
|
||||
qw422016.N().S(`
|
||||
<aside class="sibling-hyphae layout-card">
|
||||
<h2 class="sibling-hyphae__title layout-card__title">`)
|
||||
//line views/nav.qtpl:37
|
||||
//line views/nav.qtpl:38
|
||||
qw422016.E().S(lc.Get("ui.sibling_hyphae"))
|
||||
//line views/nav.qtpl:37
|
||||
//line views/nav.qtpl:38
|
||||
qw422016.N().S(`</h2>
|
||||
`)
|
||||
//line views/nav.qtpl:38
|
||||
//line views/nav.qtpl:39
|
||||
qw422016.N().S(siblings)
|
||||
//line views/nav.qtpl:38
|
||||
//line views/nav.qtpl:39
|
||||
qw422016.N().S(`
|
||||
</aside>
|
||||
`)
|
||||
//line views/nav.qtpl:40
|
||||
//line views/nav.qtpl:41
|
||||
}
|
||||
//line views/nav.qtpl:40
|
||||
//line views/nav.qtpl:41
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/nav.qtpl:41
|
||||
//line views/nav.qtpl:42
|
||||
}
|
||||
|
||||
//line views/nav.qtpl:41
|
||||
//line views/nav.qtpl:42
|
||||
func writesiblingHyphae(qq422016 qtio422016.Writer, siblings string, lc *l18n.Localizer) {
|
||||
//line views/nav.qtpl:41
|
||||
//line views/nav.qtpl:42
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/nav.qtpl:41
|
||||
//line views/nav.qtpl:42
|
||||
streamsiblingHyphae(qw422016, siblings, lc)
|
||||
//line views/nav.qtpl:41
|
||||
//line views/nav.qtpl:42
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/nav.qtpl:41
|
||||
//line views/nav.qtpl:42
|
||||
}
|
||||
|
||||
//line views/nav.qtpl:41
|
||||
//line views/nav.qtpl:42
|
||||
func siblingHyphae(siblings string, lc *l18n.Localizer) string {
|
||||
//line views/nav.qtpl:41
|
||||
//line views/nav.qtpl:42
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/nav.qtpl:41
|
||||
//line views/nav.qtpl:42
|
||||
writesiblingHyphae(qb422016, siblings, lc)
|
||||
//line views/nav.qtpl:41
|
||||
//line views/nav.qtpl:42
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/nav.qtpl:41
|
||||
//line views/nav.qtpl:42
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/nav.qtpl:41
|
||||
//line views/nav.qtpl:42
|
||||
return qs422016
|
||||
//line views/nav.qtpl:41
|
||||
//line views/nav.qtpl:42
|
||||
}
|
||||
|
||||
//line views/nav.qtpl:43
|
||||
//line views/nav.qtpl:44
|
||||
func StreamSubhyphae(qw422016 *qt422016.Writer, subhyphae string, lc *l18n.Localizer) {
|
||||
//line views/nav.qtpl:43
|
||||
//line views/nav.qtpl:44
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/nav.qtpl:44
|
||||
//line views/nav.qtpl:45
|
||||
if strings.TrimSpace(subhyphae) != "" {
|
||||
//line views/nav.qtpl:44
|
||||
//line views/nav.qtpl:45
|
||||
qw422016.N().S(`
|
||||
<section class="subhyphae">
|
||||
<h2 class="subhyphae__title">`)
|
||||
//line views/nav.qtpl:46
|
||||
//line views/nav.qtpl:47
|
||||
qw422016.E().S(lc.Get("ui.subhyphae"))
|
||||
//line views/nav.qtpl:46
|
||||
//line views/nav.qtpl:47
|
||||
qw422016.N().S(`</h2>
|
||||
<nav class="subhyphae__nav">
|
||||
<ul class="subhyphae__list">
|
||||
`)
|
||||
//line views/nav.qtpl:49
|
||||
//line views/nav.qtpl:50
|
||||
qw422016.N().S(subhyphae)
|
||||
//line views/nav.qtpl:49
|
||||
//line views/nav.qtpl:50
|
||||
qw422016.N().S(`
|
||||
</ul>
|
||||
</nav>
|
||||
</section>
|
||||
`)
|
||||
//line views/nav.qtpl:53
|
||||
//line views/nav.qtpl:54
|
||||
}
|
||||
//line views/nav.qtpl:53
|
||||
//line views/nav.qtpl:54
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/nav.qtpl:54
|
||||
//line views/nav.qtpl:55
|
||||
}
|
||||
|
||||
//line views/nav.qtpl:54
|
||||
//line views/nav.qtpl:55
|
||||
func WriteSubhyphae(qq422016 qtio422016.Writer, subhyphae string, lc *l18n.Localizer) {
|
||||
//line views/nav.qtpl:54
|
||||
//line views/nav.qtpl:55
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/nav.qtpl:54
|
||||
//line views/nav.qtpl:55
|
||||
StreamSubhyphae(qw422016, subhyphae, lc)
|
||||
//line views/nav.qtpl:54
|
||||
//line views/nav.qtpl:55
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/nav.qtpl:54
|
||||
//line views/nav.qtpl:55
|
||||
}
|
||||
|
||||
//line views/nav.qtpl:54
|
||||
//line views/nav.qtpl:55
|
||||
func Subhyphae(subhyphae string, lc *l18n.Localizer) string {
|
||||
//line views/nav.qtpl:54
|
||||
//line views/nav.qtpl:55
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/nav.qtpl:54
|
||||
//line views/nav.qtpl:55
|
||||
WriteSubhyphae(qb422016, subhyphae, lc)
|
||||
//line views/nav.qtpl:54
|
||||
//line views/nav.qtpl:55
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/nav.qtpl:54
|
||||
//line views/nav.qtpl:55
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/nav.qtpl:54
|
||||
//line views/nav.qtpl:55
|
||||
return qs422016
|
||||
//line views/nav.qtpl:54
|
||||
//line views/nav.qtpl:55
|
||||
}
|
||||
|
||||
//line views/nav.qtpl:57
|
||||
func streamcommonScripts(qw422016 *qt422016.Writer) {
|
||||
//line views/nav.qtpl:57
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/nav.qtpl:58
|
||||
for _, scriptPath := range cfg.CommonScripts {
|
||||
//line views/nav.qtpl:58
|
||||
qw422016.N().S(`
|
||||
<script src="`)
|
||||
//line views/nav.qtpl:59
|
||||
qw422016.E().S(scriptPath)
|
||||
//line views/nav.qtpl:59
|
||||
qw422016.N().S(`"></script>
|
||||
`)
|
||||
//line views/nav.qtpl:60
|
||||
}
|
||||
//line views/nav.qtpl:60
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/nav.qtpl:61
|
||||
}
|
||||
|
||||
//line views/nav.qtpl:61
|
||||
func writecommonScripts(qq422016 qtio422016.Writer) {
|
||||
//line views/nav.qtpl:61
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/nav.qtpl:61
|
||||
streamcommonScripts(qw422016)
|
||||
//line views/nav.qtpl:61
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/nav.qtpl:61
|
||||
}
|
||||
|
||||
//line views/nav.qtpl:61
|
||||
func commonScripts() string {
|
||||
//line views/nav.qtpl:61
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/nav.qtpl:61
|
||||
writecommonScripts(qb422016)
|
||||
//line views/nav.qtpl:61
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/nav.qtpl:61
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/nav.qtpl:61
|
||||
return qs422016
|
||||
//line views/nav.qtpl:61
|
||||
}
|
||||
|
@ -5,11 +5,13 @@
|
||||
|
||||
{% import "github.com/bouncepaw/mycorrhiza/cfg" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/hyphae" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/categories" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/l18n" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/mimetype" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/tree" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/user" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/util" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/viewutil" %}
|
||||
|
||||
{% func MediaMenu(rq *http.Request, h hyphae.Hypha, u *user.User) %}
|
||||
{% code
|
||||
@ -85,7 +87,7 @@
|
||||
If `contents` == "", a helpful message is shown instead.
|
||||
|
||||
If you rename .prevnext, change the docs too.
|
||||
{% func Hypha(meta Meta, h hyphae.Hypha, contents string) %}
|
||||
{% func Hypha(meta viewutil.Meta, h hyphae.Hypha, contents string) %}
|
||||
{% code
|
||||
siblings, subhyphae, prevHyphaName, nextHyphaName := tree.Tree(h.CanonicalName())
|
||||
lc := meta.Lc
|
||||
@ -131,7 +133,7 @@ If you rename .prevnext, change the docs too.
|
||||
{%= hyphaInfo(meta, h) %}
|
||||
</section>
|
||||
</main>
|
||||
{%s= categoryCard(meta, h.CanonicalName()) %}
|
||||
{%s= categories.CategoryCard(meta, h.CanonicalName()) %}
|
||||
{%= siblingHyphae(siblings, meta.Lc) %}
|
||||
</div>
|
||||
{%= viewScripts() %}
|
||||
|
@ -23,613 +23,619 @@ import "github.com/bouncepaw/mycorrhiza/cfg"
|
||||
import "github.com/bouncepaw/mycorrhiza/hyphae"
|
||||
|
||||
//line views/readers.qtpl:8
|
||||
import "github.com/bouncepaw/mycorrhiza/l18n"
|
||||
import "github.com/bouncepaw/mycorrhiza/categories"
|
||||
|
||||
//line views/readers.qtpl:9
|
||||
import "github.com/bouncepaw/mycorrhiza/mimetype"
|
||||
import "github.com/bouncepaw/mycorrhiza/l18n"
|
||||
|
||||
//line views/readers.qtpl:10
|
||||
import "github.com/bouncepaw/mycorrhiza/tree"
|
||||
import "github.com/bouncepaw/mycorrhiza/mimetype"
|
||||
|
||||
//line views/readers.qtpl:11
|
||||
import "github.com/bouncepaw/mycorrhiza/user"
|
||||
import "github.com/bouncepaw/mycorrhiza/tree"
|
||||
|
||||
//line views/readers.qtpl:12
|
||||
import "github.com/bouncepaw/mycorrhiza/user"
|
||||
|
||||
//line views/readers.qtpl:13
|
||||
import "github.com/bouncepaw/mycorrhiza/util"
|
||||
|
||||
//line views/readers.qtpl:14
|
||||
import "github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
|
||||
//line views/readers.qtpl:16
|
||||
import (
|
||||
qtio422016 "io"
|
||||
|
||||
qt422016 "github.com/valyala/quicktemplate"
|
||||
)
|
||||
|
||||
//line views/readers.qtpl:14
|
||||
//line views/readers.qtpl:16
|
||||
var (
|
||||
_ = qtio422016.Copy
|
||||
_ = qt422016.AcquireByteBuffer
|
||||
)
|
||||
|
||||
//line views/readers.qtpl:14
|
||||
//line views/readers.qtpl:16
|
||||
func StreamMediaMenu(qw422016 *qt422016.Writer, rq *http.Request, h hyphae.Hypha, u *user.User) {
|
||||
//line views/readers.qtpl:14
|
||||
//line views/readers.qtpl:16
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:16
|
||||
//line views/readers.qtpl:18
|
||||
lc := l18n.FromRequest(rq)
|
||||
|
||||
//line views/readers.qtpl:17
|
||||
//line views/readers.qtpl:19
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width media-tab">
|
||||
<h1>`)
|
||||
//line views/readers.qtpl:20
|
||||
//line views/readers.qtpl:22
|
||||
qw422016.N().S(lc.Get("ui.media_title", &l18n.Replacements{"name": beautifulLink(h.CanonicalName())}))
|
||||
//line views/readers.qtpl:20
|
||||
//line views/readers.qtpl:22
|
||||
qw422016.N().S(`</h1>
|
||||
`)
|
||||
//line views/readers.qtpl:21
|
||||
//line views/readers.qtpl:23
|
||||
switch h.(type) {
|
||||
//line views/readers.qtpl:22
|
||||
//line views/readers.qtpl:24
|
||||
case *hyphae.MediaHypha:
|
||||
//line views/readers.qtpl:22
|
||||
//line views/readers.qtpl:24
|
||||
qw422016.N().S(`
|
||||
<p class="explanation">`)
|
||||
//line views/readers.qtpl:23
|
||||
//line views/readers.qtpl:25
|
||||
qw422016.E().S(lc.Get("ui.media_tip"))
|
||||
//line views/readers.qtpl:23
|
||||
//line views/readers.qtpl:25
|
||||
qw422016.N().S(` <a href="/help/en/media" class="shy-link">`)
|
||||
//line views/readers.qtpl:23
|
||||
//line views/readers.qtpl:25
|
||||
qw422016.E().S(lc.Get("ui.media_what_is"))
|
||||
//line views/readers.qtpl:23
|
||||
//line views/readers.qtpl:25
|
||||
qw422016.N().S(`</a></p>
|
||||
`)
|
||||
//line views/readers.qtpl:24
|
||||
//line views/readers.qtpl:26
|
||||
default:
|
||||
//line views/readers.qtpl:24
|
||||
//line views/readers.qtpl:26
|
||||
qw422016.N().S(`
|
||||
<p class="explanation">`)
|
||||
//line views/readers.qtpl:25
|
||||
//line views/readers.qtpl:27
|
||||
qw422016.E().S(lc.Get("ui.media_empty"))
|
||||
//line views/readers.qtpl:25
|
||||
//line views/readers.qtpl:27
|
||||
qw422016.N().S(` <a href="/help/en/media" class="shy-link">`)
|
||||
//line views/readers.qtpl:25
|
||||
//line views/readers.qtpl:27
|
||||
qw422016.E().S(lc.Get("ui.media_what_is"))
|
||||
//line views/readers.qtpl:25
|
||||
//line views/readers.qtpl:27
|
||||
qw422016.N().S(`</a></p>
|
||||
`)
|
||||
//line views/readers.qtpl:26
|
||||
//line views/readers.qtpl:28
|
||||
}
|
||||
//line views/readers.qtpl:26
|
||||
//line views/readers.qtpl:28
|
||||
qw422016.N().S(`
|
||||
|
||||
<section class="amnt-grid">
|
||||
`)
|
||||
//line views/readers.qtpl:29
|
||||
//line views/readers.qtpl:31
|
||||
switch h := h.(type) {
|
||||
//line views/readers.qtpl:30
|
||||
//line views/readers.qtpl:32
|
||||
case *hyphae.MediaHypha:
|
||||
//line views/readers.qtpl:30
|
||||
//line views/readers.qtpl:32
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:32
|
||||
//line views/readers.qtpl:34
|
||||
mime := mimetype.FromExtension(path.Ext(h.MediaFilePath()))
|
||||
fileinfo, err := os.Stat(h.MediaFilePath())
|
||||
|
||||
//line views/readers.qtpl:33
|
||||
//line views/readers.qtpl:35
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:34
|
||||
//line views/readers.qtpl:36
|
||||
if err == nil {
|
||||
//line views/readers.qtpl:34
|
||||
//line views/readers.qtpl:36
|
||||
qw422016.N().S(`
|
||||
<fieldset class="amnt-menu-block">
|
||||
<legend class="modal__title modal__title_small">`)
|
||||
//line views/readers.qtpl:36
|
||||
//line views/readers.qtpl:38
|
||||
qw422016.E().S(lc.Get("ui.media_stat"))
|
||||
//line views/readers.qtpl:36
|
||||
//line views/readers.qtpl:38
|
||||
qw422016.N().S(`</legend>
|
||||
<p class="modal__confirmation-msg"><b>`)
|
||||
//line views/readers.qtpl:37
|
||||
//line views/readers.qtpl:39
|
||||
qw422016.E().S(lc.Get("ui.media_stat_size"))
|
||||
//line views/readers.qtpl:37
|
||||
//line views/readers.qtpl:39
|
||||
qw422016.N().S(`</b> `)
|
||||
//line views/readers.qtpl:37
|
||||
//line views/readers.qtpl:39
|
||||
qw422016.E().S(lc.GetPlural64("ui.media_size_value", fileinfo.Size()))
|
||||
//line views/readers.qtpl:37
|
||||
//line views/readers.qtpl:39
|
||||
qw422016.N().S(`</p>
|
||||
<p><b>`)
|
||||
//line views/readers.qtpl:38
|
||||
//line views/readers.qtpl:40
|
||||
qw422016.E().S(lc.Get("ui.media_stat_mime"))
|
||||
//line views/readers.qtpl:38
|
||||
//line views/readers.qtpl:40
|
||||
qw422016.N().S(`</b> `)
|
||||
//line views/readers.qtpl:38
|
||||
//line views/readers.qtpl:40
|
||||
qw422016.E().S(mime)
|
||||
//line views/readers.qtpl:38
|
||||
//line views/readers.qtpl:40
|
||||
qw422016.N().S(`</p>
|
||||
</fieldset>
|
||||
`)
|
||||
//line views/readers.qtpl:40
|
||||
//line views/readers.qtpl:42
|
||||
}
|
||||
//line views/readers.qtpl:40
|
||||
//line views/readers.qtpl:42
|
||||
qw422016.N().S(`
|
||||
|
||||
`)
|
||||
//line views/readers.qtpl:42
|
||||
//line views/readers.qtpl:44
|
||||
if strings.HasPrefix(mime, "image/") {
|
||||
//line views/readers.qtpl:42
|
||||
//line views/readers.qtpl:44
|
||||
qw422016.N().S(`
|
||||
<fieldset class="amnt-menu-block">
|
||||
<legend class="modal__title modal__title_small">`)
|
||||
//line views/readers.qtpl:44
|
||||
//line views/readers.qtpl:46
|
||||
qw422016.E().S(lc.Get("ui.media_include"))
|
||||
//line views/readers.qtpl:44
|
||||
//line views/readers.qtpl:46
|
||||
qw422016.N().S(`</legend>
|
||||
<p class="modal__confirmation-msg">`)
|
||||
//line views/readers.qtpl:45
|
||||
//line views/readers.qtpl:47
|
||||
qw422016.E().S(lc.Get("ui.media_include_tip"))
|
||||
//line views/readers.qtpl:45
|
||||
//line views/readers.qtpl:47
|
||||
qw422016.N().S(`</p>
|
||||
<pre class="codeblock"><code>img { `)
|
||||
//line views/readers.qtpl:46
|
||||
//line views/readers.qtpl:48
|
||||
qw422016.E().S(h.CanonicalName())
|
||||
//line views/readers.qtpl:46
|
||||
//line views/readers.qtpl:48
|
||||
qw422016.N().S(` }</code></pre>
|
||||
</fieldset>
|
||||
`)
|
||||
//line views/readers.qtpl:48
|
||||
//line views/readers.qtpl:50
|
||||
}
|
||||
//line views/readers.qtpl:48
|
||||
//line views/readers.qtpl:50
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:49
|
||||
//line views/readers.qtpl:51
|
||||
}
|
||||
//line views/readers.qtpl:49
|
||||
//line views/readers.qtpl:51
|
||||
qw422016.N().S(`
|
||||
|
||||
`)
|
||||
//line views/readers.qtpl:51
|
||||
//line views/readers.qtpl:53
|
||||
if u.CanProceed("upload-binary") {
|
||||
//line views/readers.qtpl:51
|
||||
//line views/readers.qtpl:53
|
||||
qw422016.N().S(`
|
||||
<form action="/upload-binary/`)
|
||||
//line views/readers.qtpl:52
|
||||
//line views/readers.qtpl:54
|
||||
qw422016.E().S(h.CanonicalName())
|
||||
//line views/readers.qtpl:52
|
||||
//line views/readers.qtpl:54
|
||||
qw422016.N().S(`"
|
||||
method="post" enctype="multipart/form-data"
|
||||
class="upload-binary modal amnt-menu-block">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title modal__title_small">`)
|
||||
//line views/readers.qtpl:56
|
||||
//line views/readers.qtpl:58
|
||||
qw422016.E().S(lc.Get("ui.media_new"))
|
||||
//line views/readers.qtpl:56
|
||||
//line views/readers.qtpl:58
|
||||
qw422016.N().S(`</legend>
|
||||
<p class="modal__confirmation-msg">`)
|
||||
//line views/readers.qtpl:57
|
||||
//line views/readers.qtpl:59
|
||||
qw422016.E().S(lc.Get("ui.media_new_tip"))
|
||||
//line views/readers.qtpl:57
|
||||
//line views/readers.qtpl:59
|
||||
qw422016.N().S(`</p>
|
||||
<label for="upload-binary__input"></label>
|
||||
<input type="file" id="upload-binary__input" name="binary">
|
||||
|
||||
<button type="submit" class="btn stick-to-bottom" value="Upload">`)
|
||||
//line views/readers.qtpl:61
|
||||
//line views/readers.qtpl:63
|
||||
qw422016.E().S(lc.Get("ui.media_upload"))
|
||||
//line views/readers.qtpl:61
|
||||
//line views/readers.qtpl:63
|
||||
qw422016.N().S(`</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
`)
|
||||
//line views/readers.qtpl:64
|
||||
//line views/readers.qtpl:66
|
||||
}
|
||||
//line views/readers.qtpl:64
|
||||
//line views/readers.qtpl:66
|
||||
qw422016.N().S(`
|
||||
|
||||
|
||||
`)
|
||||
//line views/readers.qtpl:67
|
||||
//line views/readers.qtpl:69
|
||||
switch h := h.(type) {
|
||||
//line views/readers.qtpl:68
|
||||
//line views/readers.qtpl:70
|
||||
case *hyphae.MediaHypha:
|
||||
//line views/readers.qtpl:68
|
||||
//line views/readers.qtpl:70
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:69
|
||||
//line views/readers.qtpl:71
|
||||
if u.CanProceed("remove-media") {
|
||||
//line views/readers.qtpl:69
|
||||
//line views/readers.qtpl:71
|
||||
qw422016.N().S(`
|
||||
<form action="/remove-media/`)
|
||||
//line views/readers.qtpl:70
|
||||
//line views/readers.qtpl:72
|
||||
qw422016.E().S(h.CanonicalName())
|
||||
//line views/readers.qtpl:70
|
||||
//line views/readers.qtpl:72
|
||||
qw422016.N().S(`" method="post" class="modal amnt-menu-block" method="POST">
|
||||
<fieldset class="modal__fieldset">
|
||||
<legend class="modal__title modal__title_small">`)
|
||||
//line views/readers.qtpl:72
|
||||
//line views/readers.qtpl:74
|
||||
qw422016.E().S(lc.Get("ui.media_remove"))
|
||||
//line views/readers.qtpl:72
|
||||
//line views/readers.qtpl:74
|
||||
qw422016.N().S(`</legend>
|
||||
<p class="modal__confirmation-msg">`)
|
||||
//line views/readers.qtpl:73
|
||||
//line views/readers.qtpl:75
|
||||
qw422016.E().S(lc.Get("ui.media_remove_tip"))
|
||||
//line views/readers.qtpl:73
|
||||
//line views/readers.qtpl:75
|
||||
qw422016.N().S(`</p>
|
||||
<button type="submit" class="btn" value="Remove media">`)
|
||||
//line views/readers.qtpl:74
|
||||
//line views/readers.qtpl:76
|
||||
qw422016.E().S(lc.Get("ui.media_remove_button"))
|
||||
//line views/readers.qtpl:74
|
||||
//line views/readers.qtpl:76
|
||||
qw422016.N().S(`</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
`)
|
||||
//line views/readers.qtpl:77
|
||||
//line views/readers.qtpl:79
|
||||
}
|
||||
//line views/readers.qtpl:77
|
||||
//line views/readers.qtpl:79
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:78
|
||||
//line views/readers.qtpl:80
|
||||
}
|
||||
//line views/readers.qtpl:78
|
||||
//line views/readers.qtpl:80
|
||||
qw422016.N().S(`
|
||||
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/readers.qtpl:83
|
||||
//line views/readers.qtpl:85
|
||||
}
|
||||
|
||||
//line views/readers.qtpl:83
|
||||
//line views/readers.qtpl:85
|
||||
func WriteMediaMenu(qq422016 qtio422016.Writer, rq *http.Request, h hyphae.Hypha, u *user.User) {
|
||||
//line views/readers.qtpl:83
|
||||
//line views/readers.qtpl:85
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/readers.qtpl:83
|
||||
//line views/readers.qtpl:85
|
||||
StreamMediaMenu(qw422016, rq, h, u)
|
||||
//line views/readers.qtpl:83
|
||||
//line views/readers.qtpl:85
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/readers.qtpl:83
|
||||
//line views/readers.qtpl:85
|
||||
}
|
||||
|
||||
//line views/readers.qtpl:83
|
||||
//line views/readers.qtpl:85
|
||||
func MediaMenu(rq *http.Request, h hyphae.Hypha, u *user.User) string {
|
||||
//line views/readers.qtpl:83
|
||||
//line views/readers.qtpl:85
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/readers.qtpl:83
|
||||
//line views/readers.qtpl:85
|
||||
WriteMediaMenu(qb422016, rq, h, u)
|
||||
//line views/readers.qtpl:83
|
||||
//line views/readers.qtpl:85
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/readers.qtpl:83
|
||||
//line views/readers.qtpl:85
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/readers.qtpl:83
|
||||
//line views/readers.qtpl:85
|
||||
return qs422016
|
||||
//line views/readers.qtpl:83
|
||||
//line views/readers.qtpl:85
|
||||
}
|
||||
|
||||
// If `contents` == "", a helpful message is shown instead.
|
||||
//
|
||||
// If you rename .prevnext, change the docs too.
|
||||
|
||||
//line views/readers.qtpl:88
|
||||
func StreamHypha(qw422016 *qt422016.Writer, meta Meta, h hyphae.Hypha, contents string) {
|
||||
//line views/readers.qtpl:88
|
||||
//line views/readers.qtpl:90
|
||||
func StreamHypha(qw422016 *qt422016.Writer, meta viewutil.Meta, h hyphae.Hypha, contents string) {
|
||||
//line views/readers.qtpl:90
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:90
|
||||
//line views/readers.qtpl:92
|
||||
siblings, subhyphae, prevHyphaName, nextHyphaName := tree.Tree(h.CanonicalName())
|
||||
lc := meta.Lc
|
||||
|
||||
//line views/readers.qtpl:92
|
||||
//line views/readers.qtpl:94
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
<section id="hypha">
|
||||
`)
|
||||
//line views/readers.qtpl:96
|
||||
//line views/readers.qtpl:98
|
||||
if meta.U.CanProceed("edit") {
|
||||
//line views/readers.qtpl:96
|
||||
//line views/readers.qtpl:98
|
||||
qw422016.N().S(`
|
||||
<div class="btn btn_navititle">
|
||||
<a class="btn__link_navititle" href="/edit/`)
|
||||
//line views/readers.qtpl:98
|
||||
//line views/readers.qtpl:100
|
||||
qw422016.E().S(h.CanonicalName())
|
||||
//line views/readers.qtpl:98
|
||||
//line views/readers.qtpl:100
|
||||
qw422016.N().S(`">`)
|
||||
//line views/readers.qtpl:98
|
||||
//line views/readers.qtpl:100
|
||||
qw422016.E().S(lc.Get("ui.edit_link"))
|
||||
//line views/readers.qtpl:98
|
||||
//line views/readers.qtpl:100
|
||||
qw422016.N().S(`</a>
|
||||
</div>
|
||||
`)
|
||||
//line views/readers.qtpl:100
|
||||
//line views/readers.qtpl:102
|
||||
}
|
||||
//line views/readers.qtpl:100
|
||||
//line views/readers.qtpl:102
|
||||
qw422016.N().S(`
|
||||
|
||||
`)
|
||||
//line views/readers.qtpl:102
|
||||
//line views/readers.qtpl:104
|
||||
if cfg.UseAuth && util.IsProfileName(h.CanonicalName()) && meta.U.Name == strings.TrimPrefix(h.CanonicalName(), cfg.UserHypha+"/") {
|
||||
//line views/readers.qtpl:102
|
||||
//line views/readers.qtpl:104
|
||||
qw422016.N().S(`
|
||||
<div class="btn btn_navititle">
|
||||
<a class="btn__link_navititle" href="/logout">`)
|
||||
//line views/readers.qtpl:104
|
||||
//line views/readers.qtpl:106
|
||||
qw422016.E().S(lc.Get("ui.logout_link"))
|
||||
//line views/readers.qtpl:104
|
||||
//line views/readers.qtpl:106
|
||||
qw422016.N().S(`</a>
|
||||
</div>
|
||||
`)
|
||||
//line views/readers.qtpl:106
|
||||
//line views/readers.qtpl:108
|
||||
if meta.U.Group == "admin" {
|
||||
//line views/readers.qtpl:106
|
||||
//line views/readers.qtpl:108
|
||||
qw422016.N().S(`
|
||||
<div class="btn btn_navititle">
|
||||
<a class="btn__link_navititle" href="/admin">`)
|
||||
//line views/readers.qtpl:108
|
||||
//line views/readers.qtpl:110
|
||||
qw422016.E().S(lc.Get("ui.admin_panel"))
|
||||
//line views/readers.qtpl:108
|
||||
//line views/readers.qtpl:110
|
||||
qw422016.N().S(`<a>
|
||||
</div>
|
||||
`)
|
||||
//line views/readers.qtpl:110
|
||||
//line views/readers.qtpl:112
|
||||
}
|
||||
//line views/readers.qtpl:110
|
||||
//line views/readers.qtpl:112
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:111
|
||||
//line views/readers.qtpl:113
|
||||
}
|
||||
//line views/readers.qtpl:111
|
||||
//line views/readers.qtpl:113
|
||||
qw422016.N().S(`
|
||||
|
||||
`)
|
||||
//line views/readers.qtpl:113
|
||||
//line views/readers.qtpl:115
|
||||
qw422016.N().S(NaviTitle(h))
|
||||
//line views/readers.qtpl:113
|
||||
//line views/readers.qtpl:115
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:114
|
||||
//line views/readers.qtpl:116
|
||||
switch h.(type) {
|
||||
//line views/readers.qtpl:115
|
||||
//line views/readers.qtpl:117
|
||||
case *hyphae.EmptyHypha:
|
||||
//line views/readers.qtpl:115
|
||||
//line views/readers.qtpl:117
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:116
|
||||
//line views/readers.qtpl:118
|
||||
streamnonExistentHyphaNotice(qw422016, h, meta.U, meta.Lc)
|
||||
//line views/readers.qtpl:116
|
||||
//line views/readers.qtpl:118
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:117
|
||||
//line views/readers.qtpl:119
|
||||
default:
|
||||
//line views/readers.qtpl:117
|
||||
//line views/readers.qtpl:119
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:118
|
||||
//line views/readers.qtpl:120
|
||||
qw422016.N().S(contents)
|
||||
//line views/readers.qtpl:118
|
||||
//line views/readers.qtpl:120
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:119
|
||||
//line views/readers.qtpl:121
|
||||
}
|
||||
//line views/readers.qtpl:119
|
||||
//line views/readers.qtpl:121
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
<section class="prevnext">
|
||||
`)
|
||||
//line views/readers.qtpl:122
|
||||
//line views/readers.qtpl:124
|
||||
if prevHyphaName != "" {
|
||||
//line views/readers.qtpl:122
|
||||
//line views/readers.qtpl:124
|
||||
qw422016.N().S(`
|
||||
<a class="prevnext__el prevnext__prev" href="/hypha/`)
|
||||
//line views/readers.qtpl:123
|
||||
//line views/readers.qtpl:125
|
||||
qw422016.E().S(prevHyphaName)
|
||||
//line views/readers.qtpl:123
|
||||
//line views/readers.qtpl:125
|
||||
qw422016.N().S(`" rel="prev">← `)
|
||||
//line views/readers.qtpl:123
|
||||
//line views/readers.qtpl:125
|
||||
qw422016.E().S(util.BeautifulName(path.Base(prevHyphaName)))
|
||||
//line views/readers.qtpl:123
|
||||
//line views/readers.qtpl:125
|
||||
qw422016.N().S(`</a>
|
||||
`)
|
||||
//line views/readers.qtpl:124
|
||||
//line views/readers.qtpl:126
|
||||
}
|
||||
//line views/readers.qtpl:124
|
||||
//line views/readers.qtpl:126
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:125
|
||||
//line views/readers.qtpl:127
|
||||
if nextHyphaName != "" {
|
||||
//line views/readers.qtpl:125
|
||||
//line views/readers.qtpl:127
|
||||
qw422016.N().S(`
|
||||
<a class="prevnext__el prevnext__next" href="/hypha/`)
|
||||
//line views/readers.qtpl:126
|
||||
//line views/readers.qtpl:128
|
||||
qw422016.E().S(nextHyphaName)
|
||||
//line views/readers.qtpl:126
|
||||
//line views/readers.qtpl:128
|
||||
qw422016.N().S(`" rel="next">`)
|
||||
//line views/readers.qtpl:126
|
||||
//line views/readers.qtpl:128
|
||||
qw422016.E().S(util.BeautifulName(path.Base(nextHyphaName)))
|
||||
//line views/readers.qtpl:126
|
||||
//line views/readers.qtpl:128
|
||||
qw422016.N().S(` →</a>
|
||||
`)
|
||||
//line views/readers.qtpl:127
|
||||
//line views/readers.qtpl:129
|
||||
}
|
||||
//line views/readers.qtpl:127
|
||||
//line views/readers.qtpl:129
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
`)
|
||||
//line views/readers.qtpl:129
|
||||
//line views/readers.qtpl:131
|
||||
StreamSubhyphae(qw422016, subhyphae, meta.Lc)
|
||||
//line views/readers.qtpl:129
|
||||
//line views/readers.qtpl:131
|
||||
qw422016.N().S(`
|
||||
<section id="hypha-bottom">
|
||||
`)
|
||||
//line views/readers.qtpl:131
|
||||
//line views/readers.qtpl:133
|
||||
streamhyphaInfo(qw422016, meta, h)
|
||||
//line views/readers.qtpl:131
|
||||
//line views/readers.qtpl:133
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
</main>
|
||||
`)
|
||||
//line views/readers.qtpl:134
|
||||
qw422016.N().S(categoryCard(meta, h.CanonicalName()))
|
||||
//line views/readers.qtpl:134
|
||||
//line views/readers.qtpl:136
|
||||
qw422016.N().S(categories.CategoryCard(meta, h.CanonicalName()))
|
||||
//line views/readers.qtpl:136
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:135
|
||||
//line views/readers.qtpl:137
|
||||
streamsiblingHyphae(qw422016, siblings, meta.Lc)
|
||||
//line views/readers.qtpl:135
|
||||
//line views/readers.qtpl:137
|
||||
qw422016.N().S(`
|
||||
</div>
|
||||
`)
|
||||
//line views/readers.qtpl:137
|
||||
//line views/readers.qtpl:139
|
||||
streamviewScripts(qw422016)
|
||||
//line views/readers.qtpl:137
|
||||
//line views/readers.qtpl:139
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:138
|
||||
//line views/readers.qtpl:140
|
||||
}
|
||||
|
||||
//line views/readers.qtpl:138
|
||||
func WriteHypha(qq422016 qtio422016.Writer, meta Meta, h hyphae.Hypha, contents string) {
|
||||
//line views/readers.qtpl:138
|
||||
//line views/readers.qtpl:140
|
||||
func WriteHypha(qq422016 qtio422016.Writer, meta viewutil.Meta, h hyphae.Hypha, contents string) {
|
||||
//line views/readers.qtpl:140
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/readers.qtpl:138
|
||||
//line views/readers.qtpl:140
|
||||
StreamHypha(qw422016, meta, h, contents)
|
||||
//line views/readers.qtpl:138
|
||||
//line views/readers.qtpl:140
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/readers.qtpl:138
|
||||
//line views/readers.qtpl:140
|
||||
}
|
||||
|
||||
//line views/readers.qtpl:138
|
||||
func Hypha(meta Meta, h hyphae.Hypha, contents string) string {
|
||||
//line views/readers.qtpl:138
|
||||
//line views/readers.qtpl:140
|
||||
func Hypha(meta viewutil.Meta, h hyphae.Hypha, contents string) string {
|
||||
//line views/readers.qtpl:140
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/readers.qtpl:138
|
||||
//line views/readers.qtpl:140
|
||||
WriteHypha(qb422016, meta, h, contents)
|
||||
//line views/readers.qtpl:138
|
||||
//line views/readers.qtpl:140
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/readers.qtpl:138
|
||||
//line views/readers.qtpl:140
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/readers.qtpl:138
|
||||
//line views/readers.qtpl:140
|
||||
return qs422016
|
||||
//line views/readers.qtpl:138
|
||||
//line views/readers.qtpl:140
|
||||
}
|
||||
|
||||
//line views/readers.qtpl:140
|
||||
//line views/readers.qtpl:142
|
||||
func StreamRevision(qw422016 *qt422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents, revHash string) {
|
||||
//line views/readers.qtpl:140
|
||||
//line views/readers.qtpl:142
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
<section>
|
||||
<p>`)
|
||||
//line views/readers.qtpl:144
|
||||
//line views/readers.qtpl:146
|
||||
qw422016.E().S(lc.Get("ui.revision_warning"))
|
||||
//line views/readers.qtpl:144
|
||||
//line views/readers.qtpl:146
|
||||
qw422016.N().S(` <a href="/rev-text/`)
|
||||
//line views/readers.qtpl:144
|
||||
//line views/readers.qtpl:146
|
||||
qw422016.E().S(revHash)
|
||||
//line views/readers.qtpl:144
|
||||
//line views/readers.qtpl:146
|
||||
qw422016.N().S(`/`)
|
||||
//line views/readers.qtpl:144
|
||||
//line views/readers.qtpl:146
|
||||
qw422016.E().S(h.CanonicalName())
|
||||
//line views/readers.qtpl:144
|
||||
//line views/readers.qtpl:146
|
||||
qw422016.N().S(`">`)
|
||||
//line views/readers.qtpl:144
|
||||
//line views/readers.qtpl:146
|
||||
qw422016.E().S(lc.Get("ui.revision_link"))
|
||||
//line views/readers.qtpl:144
|
||||
//line views/readers.qtpl:146
|
||||
qw422016.N().S(`</a></p>
|
||||
`)
|
||||
//line views/readers.qtpl:145
|
||||
//line views/readers.qtpl:147
|
||||
qw422016.N().S(NaviTitle(h))
|
||||
//line views/readers.qtpl:145
|
||||
//line views/readers.qtpl:147
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:146
|
||||
//line views/readers.qtpl:148
|
||||
qw422016.N().S(contents)
|
||||
//line views/readers.qtpl:146
|
||||
//line views/readers.qtpl:148
|
||||
qw422016.N().S(`
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/readers.qtpl:150
|
||||
//line views/readers.qtpl:152
|
||||
streamviewScripts(qw422016)
|
||||
//line views/readers.qtpl:150
|
||||
//line views/readers.qtpl:152
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:151
|
||||
//line views/readers.qtpl:153
|
||||
}
|
||||
|
||||
//line views/readers.qtpl:151
|
||||
//line views/readers.qtpl:153
|
||||
func WriteRevision(qq422016 qtio422016.Writer, rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents, revHash string) {
|
||||
//line views/readers.qtpl:151
|
||||
//line views/readers.qtpl:153
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/readers.qtpl:151
|
||||
//line views/readers.qtpl:153
|
||||
StreamRevision(qw422016, rq, lc, h, contents, revHash)
|
||||
//line views/readers.qtpl:151
|
||||
//line views/readers.qtpl:153
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/readers.qtpl:151
|
||||
//line views/readers.qtpl:153
|
||||
}
|
||||
|
||||
//line views/readers.qtpl:151
|
||||
//line views/readers.qtpl:153
|
||||
func Revision(rq *http.Request, lc *l18n.Localizer, h hyphae.Hypha, contents, revHash string) string {
|
||||
//line views/readers.qtpl:151
|
||||
//line views/readers.qtpl:153
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/readers.qtpl:151
|
||||
//line views/readers.qtpl:153
|
||||
WriteRevision(qb422016, rq, lc, h, contents, revHash)
|
||||
//line views/readers.qtpl:151
|
||||
//line views/readers.qtpl:153
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/readers.qtpl:151
|
||||
//line views/readers.qtpl:153
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/readers.qtpl:151
|
||||
//line views/readers.qtpl:153
|
||||
return qs422016
|
||||
//line views/readers.qtpl:151
|
||||
//line views/readers.qtpl:153
|
||||
}
|
||||
|
||||
//line views/readers.qtpl:153
|
||||
//line views/readers.qtpl:155
|
||||
func streamviewScripts(qw422016 *qt422016.Writer) {
|
||||
//line views/readers.qtpl:153
|
||||
//line views/readers.qtpl:155
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:154
|
||||
//line views/readers.qtpl:156
|
||||
for _, scriptPath := range cfg.ViewScripts {
|
||||
//line views/readers.qtpl:154
|
||||
//line views/readers.qtpl:156
|
||||
qw422016.N().S(`
|
||||
<script src="`)
|
||||
//line views/readers.qtpl:155
|
||||
//line views/readers.qtpl:157
|
||||
qw422016.E().S(scriptPath)
|
||||
//line views/readers.qtpl:155
|
||||
//line views/readers.qtpl:157
|
||||
qw422016.N().S(`"></script>
|
||||
`)
|
||||
//line views/readers.qtpl:156
|
||||
//line views/readers.qtpl:158
|
||||
}
|
||||
//line views/readers.qtpl:156
|
||||
//line views/readers.qtpl:158
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/readers.qtpl:157
|
||||
//line views/readers.qtpl:159
|
||||
}
|
||||
|
||||
//line views/readers.qtpl:157
|
||||
//line views/readers.qtpl:159
|
||||
func writeviewScripts(qq422016 qtio422016.Writer) {
|
||||
//line views/readers.qtpl:157
|
||||
//line views/readers.qtpl:159
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/readers.qtpl:157
|
||||
//line views/readers.qtpl:159
|
||||
streamviewScripts(qw422016)
|
||||
//line views/readers.qtpl:157
|
||||
//line views/readers.qtpl:159
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/readers.qtpl:157
|
||||
//line views/readers.qtpl:159
|
||||
}
|
||||
|
||||
//line views/readers.qtpl:157
|
||||
//line views/readers.qtpl:159
|
||||
func viewScripts() string {
|
||||
//line views/readers.qtpl:157
|
||||
//line views/readers.qtpl:159
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/readers.qtpl:157
|
||||
//line views/readers.qtpl:159
|
||||
writeviewScripts(qb422016)
|
||||
//line views/readers.qtpl:157
|
||||
//line views/readers.qtpl:159
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/readers.qtpl:157
|
||||
//line views/readers.qtpl:159
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/readers.qtpl:157
|
||||
//line views/readers.qtpl:159
|
||||
return qs422016
|
||||
//line views/readers.qtpl:157
|
||||
//line views/readers.qtpl:159
|
||||
}
|
||||
|
180
views/stuff.qtpl
180
views/stuff.qtpl
@ -1,180 +0,0 @@
|
||||
{% import "fmt" %}
|
||||
{% import "path/filepath" %}
|
||||
|
||||
{% import "github.com/bouncepaw/mycorrhiza/cfg" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/hyphae" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/user" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/util" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/l18n" %}
|
||||
|
||||
{% func Base(title, body string, lc *l18n.Localizer, u *user.User, headElements ...string) %}
|
||||
<!doctype html>
|
||||
<html lang="{%s lc.Locale %}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{%s title %}</title>
|
||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
<script src="/static/shortcuts.js"></script>
|
||||
{% for _, el := range headElements %}{%s= el %}{% endfor %}
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav class="main-width top-bar">
|
||||
<ul class="top-bar__wrapper">
|
||||
<li class="top-bar__section top-bar__section_home">
|
||||
<div class="top-bar__home-link-wrapper">
|
||||
<a class="top-bar__home-link" href="/">{%s cfg.WikiName %}</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="top-bar__section top-bar__section_search">
|
||||
<form class="top-bar__search" method="GET" action="/title-search">
|
||||
<input type="text" name="q" placeholder="{%s lc.Get("ui.title_search") %}" class="top-bar__search-bar">
|
||||
</form>
|
||||
</li>
|
||||
<li class="top-bar__section top-bar__section_auth">
|
||||
{% if cfg.UseAuth %}
|
||||
<ul class="top-bar__auth auth-links">
|
||||
<li class="auth-links__box auth-links__user-box">
|
||||
{% if u.Group == "anon" %}
|
||||
<a href="/login" class="auth-links__link auth-links__login-link">{%s lc.Get("ui.login") %}</a>
|
||||
{% else %}
|
||||
<a href="/hypha/{%s cfg.UserHypha %}/{%s u.Name %}" class="auth-links__link auth-links__user-link">{%s util.BeautifulName(u.Name) %}</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% if cfg.AllowRegistration && u.Group == "anon" %}
|
||||
<li class="auth-links__box auth-links__register-box">
|
||||
<a href="/register" class="auth-links__link auth-links__register-link">{%s lc.Get("ui.register") %}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% endif %}
|
||||
</li>
|
||||
<li class="top-bar__section top-bar__section_highlights">
|
||||
<ul class="top-bar__highlights">
|
||||
{%- for _, link := range cfg.HeaderLinks -%}
|
||||
{% if link.Href != "/" %}
|
||||
<li class="top-bar__highlight">
|
||||
<a class="top-bar__highlight-link" href="{%s link.Href %}">{%s link.Display %}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{%- endfor -%}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
{%s= body %}
|
||||
<template id="dialog-template">
|
||||
<div class="dialog-backdrop"></div>
|
||||
<div class="dialog" tabindex="0">
|
||||
<div class="dialog__header">
|
||||
<h1 class="dialog__title"></h1>
|
||||
<button class="dialog__close-button" aria-label="{%s lc.Get("ui.close_dialog") %}"></button>
|
||||
</div>
|
||||
|
||||
<div class="dialog__content"></div>
|
||||
</div>
|
||||
</template>
|
||||
{%= commonScripts() %}
|
||||
<script src="/static/view.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
{% endfunc %}
|
||||
|
||||
{% func TitleSearch(query string, generator func(string) <-chan string, lc *l18n.Localizer) %}
|
||||
<div class="layout">
|
||||
<main class="main-width title-search">
|
||||
<h1>{%s lc.Get("ui.search_results_query", &l18n.Replacements{"query": query})%}</h1>
|
||||
<p>{%s lc.Get("ui.search_results_desc")%}</p>
|
||||
<ul class="title-search__results">
|
||||
{% for hyphaName := range generator(query) %}
|
||||
<li class="title-search__entry">
|
||||
<a class="title-search__link wikilink" href="/hypha/{%s hyphaName %}">{%s util.BeautifulName(hyphaName) %}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</main>
|
||||
</div>
|
||||
{% endfunc %}
|
||||
|
||||
{% func Backlinks(hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) %}
|
||||
<div class="layout">
|
||||
<main class="main-width backlinks">
|
||||
<h1>{%s= lc.Get(
|
||||
"ui.backlinks_heading",
|
||||
&l18n.Replacements{
|
||||
"hypha_link": fmt.Sprintf(
|
||||
`<a href="/hypha/%s">%s</a>`,
|
||||
hyphaName,
|
||||
util.BeautifulName(hyphaName),
|
||||
),
|
||||
},
|
||||
)%}</h1>
|
||||
<p>{%s lc.Get("ui.backlinks_desc")%}</p>
|
||||
<ul class="backlinks__list">
|
||||
{% for hyphaName := range generator(hyphaName) %}
|
||||
<li class="backlinks__entry">
|
||||
<a class="backlinks__link wikilink" href="/hypha/{%s hyphaName %}">{%s util.BeautifulName(hyphaName) %}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</main>
|
||||
</div>
|
||||
{% endfunc %}
|
||||
|
||||
{% func Help(content, lang string, lc *l18n.Localizer) %}
|
||||
<div class="layout">
|
||||
<main class="main-width help">
|
||||
<article>
|
||||
{%s= content %}
|
||||
</article>
|
||||
</main>
|
||||
{%s= helpTopics(lang, lc) %}
|
||||
</div>
|
||||
{% endfunc %}
|
||||
|
||||
{% func HelpEmptyError(lc *l18n.Localizer) %}
|
||||
<h1>{%s lc.Get("help.empty_error_title") %}</h1>
|
||||
<p>{%s lc.Get("help.empty_error_line_1") %}</p>
|
||||
<p>{%s lc.Get("help.empty_error_line_2a") %} <a class="wikilink wikilink_external wikilink_https" href="https://github.com/bouncepaw/mycorrhiza">{%s lc.Get("help.empty_error_link") %}</a> {%s lc.Get("help.empty_error_line_2b") %}</p>
|
||||
{% endfunc %}
|
||||
|
||||
{% func HyphaList(lc *l18n.Localizer) %}
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
<h1>{%s lc.Get("ui.list_heading") %}</h1>
|
||||
<p>{%s lc.GetPlural("ui.list_desc", hyphae.Count()) %}</p>
|
||||
<ul class="hypha-list">
|
||||
{% code
|
||||
hyphaNames := make(chan string)
|
||||
sortedHypha := hyphae.PathographicSort(hyphaNames)
|
||||
for hypha := range hyphae.YieldExistingHyphae() {
|
||||
hyphaNames <- hypha.CanonicalName()
|
||||
}
|
||||
close(hyphaNames)
|
||||
%}
|
||||
{% for hyphaName := range sortedHypha %}
|
||||
{% code h := hyphae.ByName(hyphaName) %}
|
||||
<li class="hypha-list__entry">
|
||||
<a class="hypha-list__link" href="/hypha/{%s h.CanonicalName() %}">
|
||||
{%s util.BeautifulName(h.CanonicalName()) %}
|
||||
</a>
|
||||
{% switch h := h.(type) %}
|
||||
{% case *hyphae.MediaHypha %}
|
||||
<span class="hypha-list__amnt-type">
|
||||
{%s filepath.Ext(h.MediaFilePath())[1:] %}
|
||||
</span>
|
||||
{% endswitch %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</main>
|
||||
</div>
|
||||
{% endfunc %}
|
||||
|
||||
{% func commonScripts() %}
|
||||
{% for _, scriptPath := range cfg.CommonScripts %}
|
||||
<script src="{%s scriptPath %}"></script>
|
||||
{% endfor %}
|
||||
{% endfunc %}
|
@ -1,667 +0,0 @@
|
||||
// Code generated by qtc from "stuff.qtpl". DO NOT EDIT.
|
||||
// See https://github.com/valyala/quicktemplate for details.
|
||||
|
||||
//line views/stuff.qtpl:1
|
||||
package views
|
||||
|
||||
//line views/stuff.qtpl:1
|
||||
import "fmt"
|
||||
|
||||
//line views/stuff.qtpl:2
|
||||
import "path/filepath"
|
||||
|
||||
//line views/stuff.qtpl:4
|
||||
import "github.com/bouncepaw/mycorrhiza/cfg"
|
||||
|
||||
//line views/stuff.qtpl:5
|
||||
import "github.com/bouncepaw/mycorrhiza/hyphae"
|
||||
|
||||
//line views/stuff.qtpl:6
|
||||
import "github.com/bouncepaw/mycorrhiza/user"
|
||||
|
||||
//line views/stuff.qtpl:7
|
||||
import "github.com/bouncepaw/mycorrhiza/util"
|
||||
|
||||
//line views/stuff.qtpl:8
|
||||
import "github.com/bouncepaw/mycorrhiza/l18n"
|
||||
|
||||
//line views/stuff.qtpl:10
|
||||
import (
|
||||
qtio422016 "io"
|
||||
|
||||
qt422016 "github.com/valyala/quicktemplate"
|
||||
)
|
||||
|
||||
//line views/stuff.qtpl:10
|
||||
var (
|
||||
_ = qtio422016.Copy
|
||||
_ = qt422016.AcquireByteBuffer
|
||||
)
|
||||
|
||||
//line views/stuff.qtpl:10
|
||||
func StreamBase(qw422016 *qt422016.Writer, title, body string, lc *l18n.Localizer, u *user.User, headElements ...string) {
|
||||
//line views/stuff.qtpl:10
|
||||
qw422016.N().S(`
|
||||
<!doctype html>
|
||||
<html lang="`)
|
||||
//line views/stuff.qtpl:12
|
||||
qw422016.E().S(lc.Locale)
|
||||
//line views/stuff.qtpl:12
|
||||
qw422016.N().S(`">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>`)
|
||||
//line views/stuff.qtpl:16
|
||||
qw422016.E().S(title)
|
||||
//line views/stuff.qtpl:16
|
||||
qw422016.N().S(`</title>
|
||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
<script src="/static/shortcuts.js"></script>
|
||||
`)
|
||||
//line views/stuff.qtpl:20
|
||||
for _, el := range headElements {
|
||||
//line views/stuff.qtpl:20
|
||||
qw422016.N().S(el)
|
||||
//line views/stuff.qtpl:20
|
||||
}
|
||||
//line views/stuff.qtpl:20
|
||||
qw422016.N().S(`
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav class="main-width top-bar">
|
||||
<ul class="top-bar__wrapper">
|
||||
<li class="top-bar__section top-bar__section_home">
|
||||
<div class="top-bar__home-link-wrapper">
|
||||
<a class="top-bar__home-link" href="/">`)
|
||||
//line views/stuff.qtpl:28
|
||||
qw422016.E().S(cfg.WikiName)
|
||||
//line views/stuff.qtpl:28
|
||||
qw422016.N().S(`</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="top-bar__section top-bar__section_search">
|
||||
<form class="top-bar__search" method="GET" action="/title-search">
|
||||
<input type="text" name="q" placeholder="`)
|
||||
//line views/stuff.qtpl:33
|
||||
qw422016.E().S(lc.Get("ui.title_search"))
|
||||
//line views/stuff.qtpl:33
|
||||
qw422016.N().S(`" class="top-bar__search-bar">
|
||||
</form>
|
||||
</li>
|
||||
<li class="top-bar__section top-bar__section_auth">
|
||||
`)
|
||||
//line views/stuff.qtpl:37
|
||||
if cfg.UseAuth {
|
||||
//line views/stuff.qtpl:37
|
||||
qw422016.N().S(`
|
||||
<ul class="top-bar__auth auth-links">
|
||||
<li class="auth-links__box auth-links__user-box">
|
||||
`)
|
||||
//line views/stuff.qtpl:40
|
||||
if u.Group == "anon" {
|
||||
//line views/stuff.qtpl:40
|
||||
qw422016.N().S(`
|
||||
<a href="/login" class="auth-links__link auth-links__login-link">`)
|
||||
//line views/stuff.qtpl:41
|
||||
qw422016.E().S(lc.Get("ui.login"))
|
||||
//line views/stuff.qtpl:41
|
||||
qw422016.N().S(`</a>
|
||||
`)
|
||||
//line views/stuff.qtpl:42
|
||||
} else {
|
||||
//line views/stuff.qtpl:42
|
||||
qw422016.N().S(`
|
||||
<a href="/hypha/`)
|
||||
//line views/stuff.qtpl:43
|
||||
qw422016.E().S(cfg.UserHypha)
|
||||
//line views/stuff.qtpl:43
|
||||
qw422016.N().S(`/`)
|
||||
//line views/stuff.qtpl:43
|
||||
qw422016.E().S(u.Name)
|
||||
//line views/stuff.qtpl:43
|
||||
qw422016.N().S(`" class="auth-links__link auth-links__user-link">`)
|
||||
//line views/stuff.qtpl:43
|
||||
qw422016.E().S(util.BeautifulName(u.Name))
|
||||
//line views/stuff.qtpl:43
|
||||
qw422016.N().S(`</a>
|
||||
`)
|
||||
//line views/stuff.qtpl:44
|
||||
}
|
||||
//line views/stuff.qtpl:44
|
||||
qw422016.N().S(`
|
||||
</li>
|
||||
`)
|
||||
//line views/stuff.qtpl:46
|
||||
if cfg.AllowRegistration && u.Group == "anon" {
|
||||
//line views/stuff.qtpl:46
|
||||
qw422016.N().S(`
|
||||
<li class="auth-links__box auth-links__register-box">
|
||||
<a href="/register" class="auth-links__link auth-links__register-link">`)
|
||||
//line views/stuff.qtpl:48
|
||||
qw422016.E().S(lc.Get("ui.register"))
|
||||
//line views/stuff.qtpl:48
|
||||
qw422016.N().S(`</a>
|
||||
</li>
|
||||
`)
|
||||
//line views/stuff.qtpl:50
|
||||
}
|
||||
//line views/stuff.qtpl:50
|
||||
qw422016.N().S(`
|
||||
</ul>
|
||||
`)
|
||||
//line views/stuff.qtpl:52
|
||||
}
|
||||
//line views/stuff.qtpl:52
|
||||
qw422016.N().S(`
|
||||
</li>
|
||||
<li class="top-bar__section top-bar__section_highlights">
|
||||
<ul class="top-bar__highlights">
|
||||
`)
|
||||
//line views/stuff.qtpl:56
|
||||
for _, link := range cfg.HeaderLinks {
|
||||
//line views/stuff.qtpl:56
|
||||
qw422016.N().S(` `)
|
||||
//line views/stuff.qtpl:57
|
||||
if link.Href != "/" {
|
||||
//line views/stuff.qtpl:57
|
||||
qw422016.N().S(`
|
||||
<li class="top-bar__highlight">
|
||||
<a class="top-bar__highlight-link" href="`)
|
||||
//line views/stuff.qtpl:59
|
||||
qw422016.E().S(link.Href)
|
||||
//line views/stuff.qtpl:59
|
||||
qw422016.N().S(`">`)
|
||||
//line views/stuff.qtpl:59
|
||||
qw422016.E().S(link.Display)
|
||||
//line views/stuff.qtpl:59
|
||||
qw422016.N().S(`</a>
|
||||
</li>
|
||||
`)
|
||||
//line views/stuff.qtpl:61
|
||||
}
|
||||
//line views/stuff.qtpl:61
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/stuff.qtpl:62
|
||||
}
|
||||
//line views/stuff.qtpl:62
|
||||
qw422016.N().S(` </ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
`)
|
||||
//line views/stuff.qtpl:68
|
||||
qw422016.N().S(body)
|
||||
//line views/stuff.qtpl:68
|
||||
qw422016.N().S(`
|
||||
<template id="dialog-template">
|
||||
<div class="dialog-backdrop"></div>
|
||||
<div class="dialog" tabindex="0">
|
||||
<div class="dialog__header">
|
||||
<h1 class="dialog__title"></h1>
|
||||
<button class="dialog__close-button" aria-label="`)
|
||||
//line views/stuff.qtpl:74
|
||||
qw422016.E().S(lc.Get("ui.close_dialog"))
|
||||
//line views/stuff.qtpl:74
|
||||
qw422016.N().S(`"></button>
|
||||
</div>
|
||||
|
||||
<div class="dialog__content"></div>
|
||||
</div>
|
||||
</template>
|
||||
`)
|
||||
//line views/stuff.qtpl:80
|
||||
streamcommonScripts(qw422016)
|
||||
//line views/stuff.qtpl:80
|
||||
qw422016.N().S(`
|
||||
<script src="/static/view.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
`)
|
||||
//line views/stuff.qtpl:84
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:84
|
||||
func WriteBase(qq422016 qtio422016.Writer, title, body string, lc *l18n.Localizer, u *user.User, headElements ...string) {
|
||||
//line views/stuff.qtpl:84
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/stuff.qtpl:84
|
||||
StreamBase(qw422016, title, body, lc, u, headElements...)
|
||||
//line views/stuff.qtpl:84
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/stuff.qtpl:84
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:84
|
||||
func Base(title, body string, lc *l18n.Localizer, u *user.User, headElements ...string) string {
|
||||
//line views/stuff.qtpl:84
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/stuff.qtpl:84
|
||||
WriteBase(qb422016, title, body, lc, u, headElements...)
|
||||
//line views/stuff.qtpl:84
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/stuff.qtpl:84
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/stuff.qtpl:84
|
||||
return qs422016
|
||||
//line views/stuff.qtpl:84
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:86
|
||||
func StreamTitleSearch(qw422016 *qt422016.Writer, query string, generator func(string) <-chan string, lc *l18n.Localizer) {
|
||||
//line views/stuff.qtpl:86
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width title-search">
|
||||
<h1>`)
|
||||
//line views/stuff.qtpl:89
|
||||
qw422016.E().S(lc.Get("ui.search_results_query", &l18n.Replacements{"query": query}))
|
||||
//line views/stuff.qtpl:89
|
||||
qw422016.N().S(`</h1>
|
||||
<p>`)
|
||||
//line views/stuff.qtpl:90
|
||||
qw422016.E().S(lc.Get("ui.search_results_desc"))
|
||||
//line views/stuff.qtpl:90
|
||||
qw422016.N().S(`</p>
|
||||
<ul class="title-search__results">
|
||||
`)
|
||||
//line views/stuff.qtpl:92
|
||||
for hyphaName := range generator(query) {
|
||||
//line views/stuff.qtpl:92
|
||||
qw422016.N().S(`
|
||||
<li class="title-search__entry">
|
||||
<a class="title-search__link wikilink" href="/hypha/`)
|
||||
//line views/stuff.qtpl:94
|
||||
qw422016.E().S(hyphaName)
|
||||
//line views/stuff.qtpl:94
|
||||
qw422016.N().S(`">`)
|
||||
//line views/stuff.qtpl:94
|
||||
qw422016.E().S(util.BeautifulName(hyphaName))
|
||||
//line views/stuff.qtpl:94
|
||||
qw422016.N().S(`</a>
|
||||
</li>
|
||||
`)
|
||||
//line views/stuff.qtpl:96
|
||||
}
|
||||
//line views/stuff.qtpl:96
|
||||
qw422016.N().S(`
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/stuff.qtpl:99
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:99
|
||||
func WriteTitleSearch(qq422016 qtio422016.Writer, query string, generator func(string) <-chan string, lc *l18n.Localizer) {
|
||||
//line views/stuff.qtpl:99
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/stuff.qtpl:99
|
||||
StreamTitleSearch(qw422016, query, generator, lc)
|
||||
//line views/stuff.qtpl:99
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/stuff.qtpl:99
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:99
|
||||
func TitleSearch(query string, generator func(string) <-chan string, lc *l18n.Localizer) string {
|
||||
//line views/stuff.qtpl:99
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/stuff.qtpl:99
|
||||
WriteTitleSearch(qb422016, query, generator, lc)
|
||||
//line views/stuff.qtpl:99
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/stuff.qtpl:99
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/stuff.qtpl:99
|
||||
return qs422016
|
||||
//line views/stuff.qtpl:99
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:101
|
||||
func StreamBacklinks(qw422016 *qt422016.Writer, hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) {
|
||||
//line views/stuff.qtpl:101
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width backlinks">
|
||||
<h1>`)
|
||||
//line views/stuff.qtpl:104
|
||||
qw422016.N().S(lc.Get(
|
||||
"ui.backlinks_heading",
|
||||
&l18n.Replacements{
|
||||
"hypha_link": fmt.Sprintf(
|
||||
`<a href="/hypha/%s">%s</a>`,
|
||||
hyphaName,
|
||||
util.BeautifulName(hyphaName),
|
||||
),
|
||||
},
|
||||
))
|
||||
//line views/stuff.qtpl:113
|
||||
qw422016.N().S(`</h1>
|
||||
<p>`)
|
||||
//line views/stuff.qtpl:114
|
||||
qw422016.E().S(lc.Get("ui.backlinks_desc"))
|
||||
//line views/stuff.qtpl:114
|
||||
qw422016.N().S(`</p>
|
||||
<ul class="backlinks__list">
|
||||
`)
|
||||
//line views/stuff.qtpl:116
|
||||
for hyphaName := range generator(hyphaName) {
|
||||
//line views/stuff.qtpl:116
|
||||
qw422016.N().S(`
|
||||
<li class="backlinks__entry">
|
||||
<a class="backlinks__link wikilink" href="/hypha/`)
|
||||
//line views/stuff.qtpl:118
|
||||
qw422016.E().S(hyphaName)
|
||||
//line views/stuff.qtpl:118
|
||||
qw422016.N().S(`">`)
|
||||
//line views/stuff.qtpl:118
|
||||
qw422016.E().S(util.BeautifulName(hyphaName))
|
||||
//line views/stuff.qtpl:118
|
||||
qw422016.N().S(`</a>
|
||||
</li>
|
||||
`)
|
||||
//line views/stuff.qtpl:120
|
||||
}
|
||||
//line views/stuff.qtpl:120
|
||||
qw422016.N().S(`
|
||||
</ul>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/stuff.qtpl:124
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:124
|
||||
func WriteBacklinks(qq422016 qtio422016.Writer, hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) {
|
||||
//line views/stuff.qtpl:124
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/stuff.qtpl:124
|
||||
StreamBacklinks(qw422016, hyphaName, generator, lc)
|
||||
//line views/stuff.qtpl:124
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/stuff.qtpl:124
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:124
|
||||
func Backlinks(hyphaName string, generator func(string) <-chan string, lc *l18n.Localizer) string {
|
||||
//line views/stuff.qtpl:124
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/stuff.qtpl:124
|
||||
WriteBacklinks(qb422016, hyphaName, generator, lc)
|
||||
//line views/stuff.qtpl:124
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/stuff.qtpl:124
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/stuff.qtpl:124
|
||||
return qs422016
|
||||
//line views/stuff.qtpl:124
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:126
|
||||
func StreamHelp(qw422016 *qt422016.Writer, content, lang string, lc *l18n.Localizer) {
|
||||
//line views/stuff.qtpl:126
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width help">
|
||||
<article>
|
||||
`)
|
||||
//line views/stuff.qtpl:130
|
||||
qw422016.N().S(content)
|
||||
//line views/stuff.qtpl:130
|
||||
qw422016.N().S(`
|
||||
</article>
|
||||
</main>
|
||||
`)
|
||||
//line views/stuff.qtpl:133
|
||||
qw422016.N().S(helpTopics(lang, lc))
|
||||
//line views/stuff.qtpl:133
|
||||
qw422016.N().S(`
|
||||
</div>
|
||||
`)
|
||||
//line views/stuff.qtpl:135
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:135
|
||||
func WriteHelp(qq422016 qtio422016.Writer, content, lang string, lc *l18n.Localizer) {
|
||||
//line views/stuff.qtpl:135
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/stuff.qtpl:135
|
||||
StreamHelp(qw422016, content, lang, lc)
|
||||
//line views/stuff.qtpl:135
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/stuff.qtpl:135
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:135
|
||||
func Help(content, lang string, lc *l18n.Localizer) string {
|
||||
//line views/stuff.qtpl:135
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/stuff.qtpl:135
|
||||
WriteHelp(qb422016, content, lang, lc)
|
||||
//line views/stuff.qtpl:135
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/stuff.qtpl:135
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/stuff.qtpl:135
|
||||
return qs422016
|
||||
//line views/stuff.qtpl:135
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:137
|
||||
func StreamHelpEmptyError(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
|
||||
//line views/stuff.qtpl:137
|
||||
qw422016.N().S(`
|
||||
<h1>`)
|
||||
//line views/stuff.qtpl:138
|
||||
qw422016.E().S(lc.Get("help.empty_error_title"))
|
||||
//line views/stuff.qtpl:138
|
||||
qw422016.N().S(`</h1>
|
||||
<p>`)
|
||||
//line views/stuff.qtpl:139
|
||||
qw422016.E().S(lc.Get("help.empty_error_line_1"))
|
||||
//line views/stuff.qtpl:139
|
||||
qw422016.N().S(`</p>
|
||||
<p>`)
|
||||
//line views/stuff.qtpl:140
|
||||
qw422016.E().S(lc.Get("help.empty_error_line_2a"))
|
||||
//line views/stuff.qtpl:140
|
||||
qw422016.N().S(` <a class="wikilink wikilink_external wikilink_https" href="https://github.com/bouncepaw/mycorrhiza">`)
|
||||
//line views/stuff.qtpl:140
|
||||
qw422016.E().S(lc.Get("help.empty_error_link"))
|
||||
//line views/stuff.qtpl:140
|
||||
qw422016.N().S(`</a> `)
|
||||
//line views/stuff.qtpl:140
|
||||
qw422016.E().S(lc.Get("help.empty_error_line_2b"))
|
||||
//line views/stuff.qtpl:140
|
||||
qw422016.N().S(`</p>
|
||||
`)
|
||||
//line views/stuff.qtpl:141
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:141
|
||||
func WriteHelpEmptyError(qq422016 qtio422016.Writer, lc *l18n.Localizer) {
|
||||
//line views/stuff.qtpl:141
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/stuff.qtpl:141
|
||||
StreamHelpEmptyError(qw422016, lc)
|
||||
//line views/stuff.qtpl:141
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/stuff.qtpl:141
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:141
|
||||
func HelpEmptyError(lc *l18n.Localizer) string {
|
||||
//line views/stuff.qtpl:141
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/stuff.qtpl:141
|
||||
WriteHelpEmptyError(qb422016, lc)
|
||||
//line views/stuff.qtpl:141
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/stuff.qtpl:141
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/stuff.qtpl:141
|
||||
return qs422016
|
||||
//line views/stuff.qtpl:141
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:143
|
||||
func StreamHyphaList(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
|
||||
//line views/stuff.qtpl:143
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width">
|
||||
<h1>`)
|
||||
//line views/stuff.qtpl:146
|
||||
qw422016.E().S(lc.Get("ui.list_heading"))
|
||||
//line views/stuff.qtpl:146
|
||||
qw422016.N().S(`</h1>
|
||||
<p>`)
|
||||
//line views/stuff.qtpl:147
|
||||
qw422016.E().S(lc.GetPlural("ui.list_desc", hyphae.Count()))
|
||||
//line views/stuff.qtpl:147
|
||||
qw422016.N().S(`</p>
|
||||
<ul class="hypha-list">
|
||||
`)
|
||||
//line views/stuff.qtpl:150
|
||||
hyphaNames := make(chan string)
|
||||
sortedHypha := hyphae.PathographicSort(hyphaNames)
|
||||
for hypha := range hyphae.YieldExistingHyphae() {
|
||||
hyphaNames <- hypha.CanonicalName()
|
||||
}
|
||||
close(hyphaNames)
|
||||
|
||||
//line views/stuff.qtpl:156
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/stuff.qtpl:157
|
||||
for hyphaName := range sortedHypha {
|
||||
//line views/stuff.qtpl:157
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/stuff.qtpl:158
|
||||
h := hyphae.ByName(hyphaName)
|
||||
|
||||
//line views/stuff.qtpl:158
|
||||
qw422016.N().S(`
|
||||
<li class="hypha-list__entry">
|
||||
<a class="hypha-list__link" href="/hypha/`)
|
||||
//line views/stuff.qtpl:160
|
||||
qw422016.E().S(h.CanonicalName())
|
||||
//line views/stuff.qtpl:160
|
||||
qw422016.N().S(`">
|
||||
`)
|
||||
//line views/stuff.qtpl:161
|
||||
qw422016.E().S(util.BeautifulName(h.CanonicalName()))
|
||||
//line views/stuff.qtpl:161
|
||||
qw422016.N().S(`
|
||||
</a>
|
||||
`)
|
||||
//line views/stuff.qtpl:163
|
||||
switch h := h.(type) {
|
||||
//line views/stuff.qtpl:164
|
||||
case *hyphae.MediaHypha:
|
||||
//line views/stuff.qtpl:164
|
||||
qw422016.N().S(`
|
||||
<span class="hypha-list__amnt-type">
|
||||
`)
|
||||
//line views/stuff.qtpl:166
|
||||
qw422016.E().S(filepath.Ext(h.MediaFilePath())[1:])
|
||||
//line views/stuff.qtpl:166
|
||||
qw422016.N().S(`
|
||||
</span>
|
||||
`)
|
||||
//line views/stuff.qtpl:168
|
||||
}
|
||||
//line views/stuff.qtpl:168
|
||||
qw422016.N().S(`
|
||||
</li>
|
||||
`)
|
||||
//line views/stuff.qtpl:170
|
||||
}
|
||||
//line views/stuff.qtpl:170
|
||||
qw422016.N().S(`
|
||||
</ul>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/stuff.qtpl:174
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:174
|
||||
func WriteHyphaList(qq422016 qtio422016.Writer, lc *l18n.Localizer) {
|
||||
//line views/stuff.qtpl:174
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/stuff.qtpl:174
|
||||
StreamHyphaList(qw422016, lc)
|
||||
//line views/stuff.qtpl:174
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/stuff.qtpl:174
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:174
|
||||
func HyphaList(lc *l18n.Localizer) string {
|
||||
//line views/stuff.qtpl:174
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/stuff.qtpl:174
|
||||
WriteHyphaList(qb422016, lc)
|
||||
//line views/stuff.qtpl:174
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/stuff.qtpl:174
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/stuff.qtpl:174
|
||||
return qs422016
|
||||
//line views/stuff.qtpl:174
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:176
|
||||
func streamcommonScripts(qw422016 *qt422016.Writer) {
|
||||
//line views/stuff.qtpl:176
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/stuff.qtpl:177
|
||||
for _, scriptPath := range cfg.CommonScripts {
|
||||
//line views/stuff.qtpl:177
|
||||
qw422016.N().S(`
|
||||
<script src="`)
|
||||
//line views/stuff.qtpl:178
|
||||
qw422016.E().S(scriptPath)
|
||||
//line views/stuff.qtpl:178
|
||||
qw422016.N().S(`"></script>
|
||||
`)
|
||||
//line views/stuff.qtpl:179
|
||||
}
|
||||
//line views/stuff.qtpl:179
|
||||
qw422016.N().S(`
|
||||
`)
|
||||
//line views/stuff.qtpl:180
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:180
|
||||
func writecommonScripts(qq422016 qtio422016.Writer) {
|
||||
//line views/stuff.qtpl:180
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/stuff.qtpl:180
|
||||
streamcommonScripts(qw422016)
|
||||
//line views/stuff.qtpl:180
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/stuff.qtpl:180
|
||||
}
|
||||
|
||||
//line views/stuff.qtpl:180
|
||||
func commonScripts() string {
|
||||
//line views/stuff.qtpl:180
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/stuff.qtpl:180
|
||||
writecommonScripts(qb422016)
|
||||
//line views/stuff.qtpl:180
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/stuff.qtpl:180
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/stuff.qtpl:180
|
||||
return qs422016
|
||||
//line views/stuff.qtpl:180
|
||||
}
|
@ -1,64 +0,0 @@
|
||||
{% import "github.com/bouncepaw/mycorrhiza/cfg" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/l18n" %}
|
||||
{% import "github.com/bouncepaw/mycorrhiza/user" %}
|
||||
{% import "sort" %}
|
||||
|
||||
{% code
|
||||
var hyphaListL10n = map[string]l10nEntry{
|
||||
"heading": en("List of users").ru("Список пользователей"),
|
||||
"administrators": en("Administrators").ru("Администраторы"),
|
||||
"moderators": en("Moderators").ru("Модераторы"),
|
||||
"editors": en("Editors").ru("Редакторы"),
|
||||
}
|
||||
%}
|
||||
|
||||
{% func UserList(lc *l18n.Localizer) %}
|
||||
<div class="layout">
|
||||
<main class="main-width user-list">
|
||||
{% code
|
||||
var get = func(key string) string {
|
||||
return hyphaListL10n[key].get(lc.Locale)
|
||||
}
|
||||
|
||||
var (
|
||||
admins = make([]string, 0)
|
||||
moderators = make([]string, 0)
|
||||
editors = make([]string, 0)
|
||||
)
|
||||
for u := range user.YieldUsers() {
|
||||
switch u.Group {
|
||||
// What if we place the users into sorted slices?
|
||||
case "admin":
|
||||
admins = append(admins, u.Name)
|
||||
case "moderator":
|
||||
moderators = append(moderators, u.Name)
|
||||
case "editor", "trusted":
|
||||
editors = append(editors, u.Name)
|
||||
}
|
||||
}
|
||||
sort.Strings(admins)
|
||||
sort.Strings(moderators)
|
||||
sort.Strings(editors)
|
||||
%}
|
||||
<h1>{%s get("heading") %}</h1>
|
||||
<section>
|
||||
<h2>{%s get("administrators") %}</h2>
|
||||
<ol>{% for _, name := range admins %}
|
||||
<li><a href="/hypha/{%s cfg.UserHypha %}/{%s name %}">{%s name %}</a></li>
|
||||
{% endfor %}</ol>
|
||||
</section>
|
||||
<section>
|
||||
<h2>{%s get("moderators") %}</h2>
|
||||
<ol>{% for _, name := range moderators %}
|
||||
<li><a href="/hypha/{%s cfg.UserHypha %}/{%s name %}">{%s name %}</a></li>
|
||||
{% endfor %}</ol>
|
||||
</section>
|
||||
<section>
|
||||
<h2>{%s get("editors") %}</h2>
|
||||
<ol>{% for _, name := range editors %}
|
||||
<li><a href="/hypha/{%s cfg.UserHypha %}/{%s name %}">{%s name %}</a></li>
|
||||
{% endfor %}</ol>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
{% endfunc %}
|
@ -1,199 +0,0 @@
|
||||
// Code generated by qtc from "user_list.qtpl". DO NOT EDIT.
|
||||
// See https://github.com/valyala/quicktemplate for details.
|
||||
|
||||
//line views/user_list.qtpl:1
|
||||
package views
|
||||
|
||||
//line views/user_list.qtpl:1
|
||||
import "github.com/bouncepaw/mycorrhiza/cfg"
|
||||
|
||||
//line views/user_list.qtpl:2
|
||||
import "github.com/bouncepaw/mycorrhiza/l18n"
|
||||
|
||||
//line views/user_list.qtpl:3
|
||||
import "github.com/bouncepaw/mycorrhiza/user"
|
||||
|
||||
//line views/user_list.qtpl:4
|
||||
import "sort"
|
||||
|
||||
//line views/user_list.qtpl:6
|
||||
import (
|
||||
qtio422016 "io"
|
||||
|
||||
qt422016 "github.com/valyala/quicktemplate"
|
||||
)
|
||||
|
||||
//line views/user_list.qtpl:6
|
||||
var (
|
||||
_ = qtio422016.Copy
|
||||
_ = qt422016.AcquireByteBuffer
|
||||
)
|
||||
|
||||
//line views/user_list.qtpl:7
|
||||
var hyphaListL10n = map[string]l10nEntry{
|
||||
"heading": en("List of users").ru("Список пользователей"),
|
||||
"administrators": en("Administrators").ru("Администраторы"),
|
||||
"moderators": en("Moderators").ru("Модераторы"),
|
||||
"editors": en("Editors").ru("Редакторы"),
|
||||
}
|
||||
|
||||
//line views/user_list.qtpl:15
|
||||
func StreamUserList(qw422016 *qt422016.Writer, lc *l18n.Localizer) {
|
||||
//line views/user_list.qtpl:15
|
||||
qw422016.N().S(`
|
||||
<div class="layout">
|
||||
<main class="main-width user-list">
|
||||
`)
|
||||
//line views/user_list.qtpl:19
|
||||
var get = func(key string) string {
|
||||
return hyphaListL10n[key].get(lc.Locale)
|
||||
}
|
||||
|
||||
var (
|
||||
admins = make([]string, 0)
|
||||
moderators = make([]string, 0)
|
||||
editors = make([]string, 0)
|
||||
)
|
||||
for u := range user.YieldUsers() {
|
||||
switch u.Group {
|
||||
// What if we place the users into sorted slices?
|
||||
case "admin":
|
||||
admins = append(admins, u.Name)
|
||||
case "moderator":
|
||||
moderators = append(moderators, u.Name)
|
||||
case "editor", "trusted":
|
||||
editors = append(editors, u.Name)
|
||||
}
|
||||
}
|
||||
sort.Strings(admins)
|
||||
sort.Strings(moderators)
|
||||
sort.Strings(editors)
|
||||
|
||||
//line views/user_list.qtpl:42
|
||||
qw422016.N().S(`
|
||||
<h1>`)
|
||||
//line views/user_list.qtpl:43
|
||||
qw422016.E().S(get("heading"))
|
||||
//line views/user_list.qtpl:43
|
||||
qw422016.N().S(`</h1>
|
||||
<section>
|
||||
<h2>`)
|
||||
//line views/user_list.qtpl:45
|
||||
qw422016.E().S(get("administrators"))
|
||||
//line views/user_list.qtpl:45
|
||||
qw422016.N().S(`</h2>
|
||||
<ol>`)
|
||||
//line views/user_list.qtpl:46
|
||||
for _, name := range admins {
|
||||
//line views/user_list.qtpl:46
|
||||
qw422016.N().S(`
|
||||
<li><a href="/hypha/`)
|
||||
//line views/user_list.qtpl:47
|
||||
qw422016.E().S(cfg.UserHypha)
|
||||
//line views/user_list.qtpl:47
|
||||
qw422016.N().S(`/`)
|
||||
//line views/user_list.qtpl:47
|
||||
qw422016.E().S(name)
|
||||
//line views/user_list.qtpl:47
|
||||
qw422016.N().S(`">`)
|
||||
//line views/user_list.qtpl:47
|
||||
qw422016.E().S(name)
|
||||
//line views/user_list.qtpl:47
|
||||
qw422016.N().S(`</a></li>
|
||||
`)
|
||||
//line views/user_list.qtpl:48
|
||||
}
|
||||
//line views/user_list.qtpl:48
|
||||
qw422016.N().S(`</ol>
|
||||
</section>
|
||||
<section>
|
||||
<h2>`)
|
||||
//line views/user_list.qtpl:51
|
||||
qw422016.E().S(get("moderators"))
|
||||
//line views/user_list.qtpl:51
|
||||
qw422016.N().S(`</h2>
|
||||
<ol>`)
|
||||
//line views/user_list.qtpl:52
|
||||
for _, name := range moderators {
|
||||
//line views/user_list.qtpl:52
|
||||
qw422016.N().S(`
|
||||
<li><a href="/hypha/`)
|
||||
//line views/user_list.qtpl:53
|
||||
qw422016.E().S(cfg.UserHypha)
|
||||
//line views/user_list.qtpl:53
|
||||
qw422016.N().S(`/`)
|
||||
//line views/user_list.qtpl:53
|
||||
qw422016.E().S(name)
|
||||
//line views/user_list.qtpl:53
|
||||
qw422016.N().S(`">`)
|
||||
//line views/user_list.qtpl:53
|
||||
qw422016.E().S(name)
|
||||
//line views/user_list.qtpl:53
|
||||
qw422016.N().S(`</a></li>
|
||||
`)
|
||||
//line views/user_list.qtpl:54
|
||||
}
|
||||
//line views/user_list.qtpl:54
|
||||
qw422016.N().S(`</ol>
|
||||
</section>
|
||||
<section>
|
||||
<h2>`)
|
||||
//line views/user_list.qtpl:57
|
||||
qw422016.E().S(get("editors"))
|
||||
//line views/user_list.qtpl:57
|
||||
qw422016.N().S(`</h2>
|
||||
<ol>`)
|
||||
//line views/user_list.qtpl:58
|
||||
for _, name := range editors {
|
||||
//line views/user_list.qtpl:58
|
||||
qw422016.N().S(`
|
||||
<li><a href="/hypha/`)
|
||||
//line views/user_list.qtpl:59
|
||||
qw422016.E().S(cfg.UserHypha)
|
||||
//line views/user_list.qtpl:59
|
||||
qw422016.N().S(`/`)
|
||||
//line views/user_list.qtpl:59
|
||||
qw422016.E().S(name)
|
||||
//line views/user_list.qtpl:59
|
||||
qw422016.N().S(`">`)
|
||||
//line views/user_list.qtpl:59
|
||||
qw422016.E().S(name)
|
||||
//line views/user_list.qtpl:59
|
||||
qw422016.N().S(`</a></li>
|
||||
`)
|
||||
//line views/user_list.qtpl:60
|
||||
}
|
||||
//line views/user_list.qtpl:60
|
||||
qw422016.N().S(`</ol>
|
||||
</section>
|
||||
</main>
|
||||
</div>
|
||||
`)
|
||||
//line views/user_list.qtpl:64
|
||||
}
|
||||
|
||||
//line views/user_list.qtpl:64
|
||||
func WriteUserList(qq422016 qtio422016.Writer, lc *l18n.Localizer) {
|
||||
//line views/user_list.qtpl:64
|
||||
qw422016 := qt422016.AcquireWriter(qq422016)
|
||||
//line views/user_list.qtpl:64
|
||||
StreamUserList(qw422016, lc)
|
||||
//line views/user_list.qtpl:64
|
||||
qt422016.ReleaseWriter(qw422016)
|
||||
//line views/user_list.qtpl:64
|
||||
}
|
||||
|
||||
//line views/user_list.qtpl:64
|
||||
func UserList(lc *l18n.Localizer) string {
|
||||
//line views/user_list.qtpl:64
|
||||
qb422016 := qt422016.AcquireByteBuffer()
|
||||
//line views/user_list.qtpl:64
|
||||
WriteUserList(qb422016, lc)
|
||||
//line views/user_list.qtpl:64
|
||||
qs422016 := string(qb422016.B)
|
||||
//line views/user_list.qtpl:64
|
||||
qt422016.ReleaseByteBuffer(qb422016)
|
||||
//line views/user_list.qtpl:64
|
||||
return qs422016
|
||||
//line views/user_list.qtpl:64
|
||||
}
|
82
viewutil/base.html
Normal file
82
viewutil/base.html
Normal file
@ -0,0 +1,82 @@
|
||||
{{define "page"}}
|
||||
<!doctype html>
|
||||
<html lang="{{.Meta.Locale}}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{block "title" .}}{{end}}</title>
|
||||
<link rel="shortcut icon" href="/static/favicon.ico">
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
<script src="/static/shortcuts.js"></script>
|
||||
{{range .HeadElements}}{{.}}{{end}}
|
||||
</head>
|
||||
<body>
|
||||
<header>
|
||||
<nav class="main-width top-bar">
|
||||
<ul class="top-bar__wrapper">
|
||||
<li class="top-bar__section top-bar__section_home">
|
||||
<div class="top-bar__home-link-wrapper">
|
||||
<a class="top-bar__home-link" href="/">{{block "wiki name" .}}{{end}}</a>
|
||||
</div>
|
||||
</li>
|
||||
<li class="top-bar__section top-bar__section_search">
|
||||
<form class="top-bar__search" method="GET" action="/title-search">
|
||||
<input type="text" name="q" class="top-bar__search-bar"
|
||||
placeholder="{{block `search by title` .}}Search by title{{end}}">
|
||||
</form>
|
||||
</li>
|
||||
<li class="top-bar__section top-bar__section_auth">
|
||||
{{block "auth" .}}
|
||||
<ul class="top-bar__auth auth-links">
|
||||
<li class="auth-links__box auth-links__user-box">
|
||||
{{if .Meta.U.Group | eq "anon" }}
|
||||
<a href="/login" class="auth-links__link auth-links__login-link">
|
||||
{{block "login" .}}Login{{end}}
|
||||
</a>
|
||||
{{else}}
|
||||
<a href="/hypha/{%s cfg.UserHypha %}/{%s u.Name %}" class="auth-links__link auth-links__user-link">
|
||||
{{beautifulName .Meta.U.Name}}
|
||||
</a>
|
||||
{{end}}
|
||||
</li>
|
||||
{{block "registration" .}}
|
||||
{{if .Meta.U.Group | eq "anon"}}
|
||||
<li class="auth-links__box auth-links__register-box">
|
||||
<a href="/register" class="auth-links__link auth-links__register-link">
|
||||
{{block "register" .}}Register{{end}}
|
||||
</a>
|
||||
</li>
|
||||
{{end}}
|
||||
{{end}}
|
||||
</ul>
|
||||
{{end}}
|
||||
</li>
|
||||
<li class="top-bar__section top-bar__section_highlights">
|
||||
<ul class="top-bar__highlights">
|
||||
{{range .HeaderLinks}}
|
||||
<li class="top-bar__highlight">
|
||||
<a class="top-bar__highlight-link" href="{{.Href}}">{{.Display}}</a>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</header>
|
||||
{{block "body" .}}{{end}}
|
||||
<template id="dialog-template">
|
||||
<div class="dialog-backdrop"></div>
|
||||
<div class="dialog" tabindex="0">
|
||||
<div class="dialog__header">
|
||||
<h1 class="dialog__title"></h1>
|
||||
<button class="dialog__close-button" aria-label="{{block `close this dialog` .}}{{end}}"></button>
|
||||
</div>
|
||||
|
||||
<div class="dialog__content"></div>
|
||||
</div>
|
||||
</template>
|
||||
{{range .CommonScripts}}{{.}}{{end}}
|
||||
<script src="/static/view.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}
|
33
viewutil/chain.go
Normal file
33
viewutil/chain.go
Normal file
@ -0,0 +1,33 @@
|
||||
package viewutil
|
||||
|
||||
import "text/template"
|
||||
|
||||
// Chain represents a chain of different language versions of the same template.
|
||||
type Chain struct {
|
||||
en *template.Template
|
||||
ru *template.Template
|
||||
}
|
||||
|
||||
// En returns a new Chain. This is the only constructor of the type, so every view is forced to have an English representation.
|
||||
func En(en *template.Template) Chain {
|
||||
return Chain{
|
||||
en: en,
|
||||
}
|
||||
}
|
||||
|
||||
// Ru adds a Russian translation to the Chain.
|
||||
func (c Chain) Ru(ru *template.Template) Chain {
|
||||
c.ru = ru
|
||||
return c
|
||||
}
|
||||
|
||||
// Get returns an appropriate language representation for the given locale in meta.
|
||||
func (c Chain) Get(meta Meta) *template.Template {
|
||||
switch meta.Locale() {
|
||||
case "en":
|
||||
return c.en
|
||||
case "ru":
|
||||
return c.ru
|
||||
}
|
||||
panic("unknown language " + meta.Locale())
|
||||
}
|
27
viewutil/err.go
Normal file
27
viewutil/err.go
Normal file
@ -0,0 +1,27 @@
|
||||
package viewutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"mime"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// HttpErr is used by many handlers to signal errors in a compact way.
|
||||
// TODO: get rid of this abomination
|
||||
func HttpErr(meta Meta, status int, name, errMsg string) {
|
||||
meta.W.(http.ResponseWriter).Header().Set("Content-Type", mime.TypeByExtension(".html"))
|
||||
meta.W.(http.ResponseWriter).WriteHeader(status)
|
||||
fmt.Fprint(
|
||||
meta.W,
|
||||
Base(
|
||||
meta,
|
||||
"Error",
|
||||
fmt.Sprintf(
|
||||
`<main class="main-width"><p>%s. <a href="/hypha/%s">%s<a></p></main>`,
|
||||
errMsg,
|
||||
name,
|
||||
meta.Lc.Get("ui.error_go_back"),
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
28
viewutil/meta.go
Normal file
28
viewutil/meta.go
Normal file
@ -0,0 +1,28 @@
|
||||
package viewutil
|
||||
|
||||
import (
|
||||
"github.com/bouncepaw/mycorrhiza/l18n"
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
"io"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// Meta is a bundle of common stuffs used by views, templates.
|
||||
type Meta struct {
|
||||
Lc *l18n.Localizer
|
||||
U *user.User
|
||||
W io.Writer
|
||||
}
|
||||
|
||||
// MetaFrom makes a Meta from the given data. You are meant to further modify it.
|
||||
func MetaFrom(w http.ResponseWriter, rq *http.Request) Meta {
|
||||
return Meta{
|
||||
Lc: l18n.FromRequest(rq),
|
||||
U: user.FromRequest(rq),
|
||||
W: w,
|
||||
}
|
||||
}
|
||||
|
||||
func (m Meta) Locale() string {
|
||||
return m.Lc.Locale
|
||||
}
|
96
viewutil/viewutil.go
Normal file
96
viewutil/viewutil.go
Normal file
@ -0,0 +1,96 @@
|
||||
// Package viewutil provides utilities and common templates for views across all packages.
|
||||
package viewutil
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
"io/fs"
|
||||
"log"
|
||||
"strings"
|
||||
"text/template" // TODO: save the world
|
||||
)
|
||||
|
||||
var (
|
||||
//go:embed *.html
|
||||
fsys embed.FS
|
||||
BaseEn *template.Template
|
||||
BaseRu *template.Template
|
||||
m = template.Must
|
||||
)
|
||||
|
||||
const ruText = `
|
||||
{{define "search by title"}}Поиск по названию{{end}}
|
||||
{{define "close this dialog"}}Закрыть этот диалог{{end}}
|
||||
{{define "login"}}Войти{{end}}
|
||||
{{define "Register"}}Регистрация{{end}}
|
||||
`
|
||||
|
||||
func Init() {
|
||||
dataText := fmt.Sprintf(`
|
||||
{{define "wiki name"}}%s{{end}}
|
||||
`, cfg.WikiName)
|
||||
BaseEn = m(m(template.New("").
|
||||
Funcs(template.FuncMap{
|
||||
"beautifulName": util.BeautifulName,
|
||||
}).ParseFS(fsys, "base.html")).
|
||||
Parse(dataText))
|
||||
if !cfg.UseAuth {
|
||||
m(BaseEn.Parse(`{{define "auth"}}{{end}}`))
|
||||
}
|
||||
if !cfg.AllowRegistration {
|
||||
m(BaseEn.Parse(`{{define "registration"}}{{end}}`))
|
||||
}
|
||||
BaseRu = m(m(BaseEn.Clone()).Parse(ruText))
|
||||
}
|
||||
|
||||
// TODO: get rid of this
|
||||
func localizedBaseWithWeirdBody(meta Meta) *template.Template {
|
||||
t := func() *template.Template {
|
||||
if meta.Locale() == "ru" {
|
||||
return BaseRu
|
||||
}
|
||||
return BaseEn
|
||||
}()
|
||||
return m(m(t.Clone()).Parse(`
|
||||
{{define "body"}}{{.Body}}{{end}}
|
||||
{{define "title"}}{{.Title}}{{end}}
|
||||
`))
|
||||
}
|
||||
|
||||
type BaseData struct {
|
||||
Meta Meta
|
||||
HeadElements []string
|
||||
HeaderLinks []cfg.HeaderLink
|
||||
CommonScripts []string
|
||||
Title string // TODO: remove
|
||||
Body string // TODO: remove
|
||||
}
|
||||
|
||||
// Base is a temporary wrapper around BaseEn and BaseRu, meant to facilitate the migration from qtpl.
|
||||
func Base(meta Meta, title, body string, headElements ...string) string {
|
||||
var w strings.Builder
|
||||
meta.W = &w
|
||||
t := localizedBaseWithWeirdBody(meta)
|
||||
err := t.ExecuteTemplate(&w, "page", BaseData{
|
||||
Meta: meta,
|
||||
Title: title,
|
||||
HeadElements: headElements,
|
||||
HeaderLinks: cfg.HeaderLinks,
|
||||
CommonScripts: cfg.CommonScripts,
|
||||
Body: body,
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
return w.String()
|
||||
}
|
||||
|
||||
func CopyEnWith(fsys fs.FS, f string) *template.Template {
|
||||
return m(m(BaseEn.Clone()).ParseFS(fsys, f))
|
||||
}
|
||||
|
||||
func CopyRuWith(fsys fs.FS, f string) *template.Template {
|
||||
return m(m(BaseRu.Clone()).ParseFS(fsys, f))
|
||||
}
|
13
web/admin.go
13
web/admin.go
@ -2,6 +2,7 @@ package web
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
"io"
|
||||
"log"
|
||||
"mime"
|
||||
@ -35,7 +36,7 @@ func initAdmin(r *mux.Router) {
|
||||
func handlerAdmin(w http.ResponseWriter, rq *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/html;charset=utf-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
views.AdminPanel(views.MetaFrom(w, rq))
|
||||
views.AdminPanel(viewutil.MetaFrom(w, rq))
|
||||
}
|
||||
|
||||
// handlerAdminShutdown kills the wiki.
|
||||
@ -70,7 +71,7 @@ func handlerAdminUsers(w http.ResponseWriter, rq *http.Request) {
|
||||
|
||||
var lc = l18n.FromRequest(rq)
|
||||
html := views.AdminUsersPanel(userList, lc)
|
||||
html = views.Base(lc.Get("admin.users_title"), html, lc, user.FromRequest(rq))
|
||||
html = views.Base(viewutil.MetaFrom(w, rq), lc.Get("admin.users_title"), html)
|
||||
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
|
||||
io.WriteString(w, html)
|
||||
@ -109,7 +110,7 @@ func handlerAdminUserEdit(w http.ResponseWriter, rq *http.Request) {
|
||||
|
||||
var lc = l18n.FromRequest(rq)
|
||||
html := views.AdminUserEdit(u, f, lc)
|
||||
html = views.Base(fmt.Sprintf(lc.Get("admin.user_title"), u.Name), html, lc, user.FromRequest(rq))
|
||||
html = views.Base(viewutil.MetaFrom(w, rq), fmt.Sprintf(lc.Get("admin.user_title"), u.Name), html)
|
||||
|
||||
if f.HasError() {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
@ -139,7 +140,7 @@ func handlerAdminUserDelete(w http.ResponseWriter, rq *http.Request) {
|
||||
|
||||
var lc = l18n.FromRequest(rq)
|
||||
html := views.AdminUserDelete(u, util.NewFormData(), lc)
|
||||
html = views.Base(fmt.Sprintf(lc.Get("admin.user_title"), u.Name), html, l18n.FromRequest(rq), user.FromRequest(rq))
|
||||
html = views.Base(viewutil.MetaFrom(w, rq), fmt.Sprintf(lc.Get("admin.user_title"), u.Name), html)
|
||||
|
||||
if f.HasError() {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
@ -153,7 +154,7 @@ func handlerAdminUserNew(w http.ResponseWriter, rq *http.Request) {
|
||||
if rq.Method == http.MethodGet {
|
||||
// New user form
|
||||
html := views.AdminUserNew(util.NewFormData(), lc)
|
||||
html = views.Base(lc.Get("admin.newuser_title"), html, lc, user.FromRequest(rq))
|
||||
html = views.Base(viewutil.MetaFrom(w, rq), lc.Get("admin.newuser_title"), html)
|
||||
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
|
||||
io.WriteString(w, html)
|
||||
@ -165,7 +166,7 @@ func handlerAdminUserNew(w http.ResponseWriter, rq *http.Request) {
|
||||
|
||||
if err != nil {
|
||||
html := views.AdminUserNew(f.WithError(err), lc)
|
||||
html = views.Base(lc.Get("admin.newuser_title"), html, lc, user.FromRequest(rq))
|
||||
html = views.Base(viewutil.MetaFrom(w, rq), lc.Get("admin.newuser_title"), html)
|
||||
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
|
||||
|
28
web/auth.go
28
web/auth.go
@ -3,6 +3,7 @@ package web
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
"io"
|
||||
"log"
|
||||
"mime"
|
||||
@ -19,6 +20,7 @@ import (
|
||||
)
|
||||
|
||||
func initAuth(r *mux.Router) {
|
||||
r.HandleFunc("/user-list", handlerUserList)
|
||||
r.HandleFunc("/lock", handlerLock)
|
||||
// The check below saves a lot of extra checks and lines of codes in other places in this file.
|
||||
if !cfg.UseAuth {
|
||||
@ -34,6 +36,13 @@ func initAuth(r *mux.Router) {
|
||||
r.HandleFunc("/logout", handlerLogout)
|
||||
}
|
||||
|
||||
func handlerUserList(w http.ResponseWriter, rq *http.Request) {
|
||||
lc := l18n.FromRequest(rq)
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(views.Base(viewutil.MetaFrom(w, rq), lc.Get("ui.users_title"), views.UserList(lc))))
|
||||
}
|
||||
|
||||
func handlerLock(w http.ResponseWriter, rq *http.Request) {
|
||||
_, _ = io.WriteString(w, views.Lock(l18n.FromRequest(rq)))
|
||||
}
|
||||
@ -46,10 +55,9 @@ func handlerRegister(w http.ResponseWriter, rq *http.Request) {
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
views.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
lc.Get("auth.register_title"),
|
||||
views.Register(rq),
|
||||
lc,
|
||||
user.FromRequest(rq),
|
||||
),
|
||||
)
|
||||
} else if rq.Method == http.MethodPost {
|
||||
@ -65,14 +73,13 @@ func handlerRegister(w http.ResponseWriter, rq *http.Request) {
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
views.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
lc.Get("auth.register_title"),
|
||||
fmt.Sprintf(
|
||||
`<main class="main-width"><p>%s</p><p><a href="/register">%s<a></p></main>`,
|
||||
err.Error(),
|
||||
lc.Get("auth.try_again"),
|
||||
),
|
||||
lc,
|
||||
user.FromRequest(rq),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
@ -101,7 +108,7 @@ func handlerLogout(w http.ResponseWriter, rq *http.Request) {
|
||||
}
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
views.Base(lc.Get("auth.logout_title"), views.Logout(can, lc), lc, u),
|
||||
views.Base(viewutil.MetaFrom(w, rq), lc.Get("auth.logout_title"), views.Logout(can, lc)),
|
||||
)
|
||||
} else if rq.Method == http.MethodPost {
|
||||
user.LogoutFromRequest(w, rq)
|
||||
@ -118,10 +125,9 @@ func handlerLogin(w http.ResponseWriter, rq *http.Request) {
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
views.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
lc.Get("auth.login_title"),
|
||||
views.Login(lc),
|
||||
lc,
|
||||
user.EmptyUser(),
|
||||
),
|
||||
)
|
||||
} else if rq.Method == http.MethodPost {
|
||||
@ -133,7 +139,7 @@ func handlerLogin(w http.ResponseWriter, rq *http.Request) {
|
||||
if err != "" {
|
||||
w.Header().Set("Content-Type", "text/html;charset=utf-8")
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
_, _ = io.WriteString(w, views.Base(err, views.LoginError(err, lc), lc, user.EmptyUser()))
|
||||
_, _ = io.WriteString(w, views.Base(viewutil.MetaFrom(w, rq), err, views.LoginError(err, lc)))
|
||||
return
|
||||
}
|
||||
http.Redirect(w, rq, "/", http.StatusSeeOther)
|
||||
@ -172,6 +178,7 @@ func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) {
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
views.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
lc.Get("ui.error"),
|
||||
fmt.Sprintf(
|
||||
`<main class="main-width"><p>%s</p><p>%s</p><p><a href="/login">%s<a></p></main>`,
|
||||
@ -179,8 +186,6 @@ func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) {
|
||||
err.Error(),
|
||||
lc.Get("auth.go_login"),
|
||||
),
|
||||
lc,
|
||||
user.FromRequest(rq),
|
||||
),
|
||||
)
|
||||
return
|
||||
@ -193,6 +198,7 @@ func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) {
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
views.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
"Error",
|
||||
fmt.Sprintf(
|
||||
`<main class="main-width"><p>%s</p><p>%s</p><p><a href="/login">%s<a></p></main>`,
|
||||
@ -200,8 +206,6 @@ func handlerTelegramLogin(w http.ResponseWriter, rq *http.Request) {
|
||||
err.Error(),
|
||||
lc.Get("auth.go_login"),
|
||||
),
|
||||
lc,
|
||||
user.FromRequest(rq),
|
||||
),
|
||||
)
|
||||
return
|
||||
|
@ -1,30 +0,0 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae/backlinks"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/l18n"
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
"github.com/bouncepaw/mycorrhiza/views"
|
||||
)
|
||||
|
||||
func initBacklinks(r *mux.Router) {
|
||||
r.PathPrefix("/backlinks/").HandlerFunc(handlerBacklinks)
|
||||
}
|
||||
|
||||
// handlerBacklinks lists all backlinks to a hypha.
|
||||
func handlerBacklinks(w http.ResponseWriter, rq *http.Request) {
|
||||
var (
|
||||
hyphaName = util.HyphaNameFromRq(rq, "backlinks")
|
||||
lc = l18n.FromRequest(rq)
|
||||
)
|
||||
util.HTTP200Page(w, views.Base(
|
||||
lc.Get("ui.backlinks_title", &l18n.Replacements{"query": util.BeautifulName(hyphaName)}),
|
||||
views.Backlinks(hyphaName, backlinks.YieldHyphaBacklinks, lc),
|
||||
lc,
|
||||
user.FromRequest(rq)))
|
||||
}
|
@ -2,6 +2,7 @@ package web
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
@ -10,7 +11,6 @@ import (
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/history"
|
||||
"github.com/bouncepaw/mycorrhiza/l18n"
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
"github.com/bouncepaw/mycorrhiza/views"
|
||||
)
|
||||
@ -42,10 +42,10 @@ func handlerHistory(w http.ResponseWriter, rq *http.Request) {
|
||||
|
||||
var lc = l18n.FromRequest(rq)
|
||||
util.HTTP200Page(w, views.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
fmt.Sprintf(lc.Get("ui.history_title"), util.BeautifulName(hyphaName)),
|
||||
views.History(rq, hyphaName, list, lc),
|
||||
lc,
|
||||
user.FromRequest(rq)))
|
||||
))
|
||||
}
|
||||
|
||||
// handlerRecentChanges displays the /recent-changes/ page.
|
||||
@ -57,10 +57,10 @@ func handlerRecentChanges(w http.ResponseWriter, rq *http.Request) {
|
||||
}
|
||||
var lc = l18n.FromRequest(rq)
|
||||
util.HTTP200Page(w, views.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
lc.GetPlural("ui.recent_title", n),
|
||||
views.RecentChanges(n, lc),
|
||||
lc,
|
||||
user.FromRequest(rq)))
|
||||
))
|
||||
}
|
||||
|
||||
// genericHandlerOfFeeds is a helper function for the web feed handlers.
|
||||
|
@ -2,11 +2,12 @@ package web
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/bouncepaw/mycomarkup/v4"
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/bouncepaw/mycomarkup/v3"
|
||||
"github.com/bouncepaw/mycomarkup/v3/mycocontext"
|
||||
"github.com/bouncepaw/mycomarkup/v4/mycocontext"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
@ -32,31 +33,31 @@ func initMutators(r *mux.Router) {
|
||||
func handlerRemoveMedia(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
var (
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
h = hyphae.ByName(util.HyphaNameFromRq(rq, "delete"))
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
h = hyphae.ByName(util.HyphaNameFromRq(rq, "delete"))
|
||||
meta = viewutil.MetaFrom(w, rq)
|
||||
)
|
||||
if !u.CanProceed("remove-media") {
|
||||
httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "no rights")
|
||||
viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "no rights")
|
||||
return
|
||||
}
|
||||
if rq.Method == "GET" {
|
||||
util.HTTP200Page(
|
||||
w,
|
||||
views.Base(
|
||||
meta,
|
||||
fmt.Sprintf(lc.Get("ui.ask_remove_media"), util.BeautifulName(h.CanonicalName())),
|
||||
views.RemoveMediaAsk(rq, h.CanonicalName()),
|
||||
lc,
|
||||
u))
|
||||
views.RemoveMediaAsk(rq, h.CanonicalName())))
|
||||
return
|
||||
}
|
||||
switch h := h.(type) {
|
||||
case *hyphae.EmptyHypha, *hyphae.TextualHypha:
|
||||
httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "no media to remove")
|
||||
viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "no media to remove")
|
||||
return
|
||||
case *hyphae.MediaHypha:
|
||||
if err := shroom.RemoveMedia(u, h); err != nil {
|
||||
httpErr(w, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error())
|
||||
viewutil.HttpErr(meta, http.StatusInternalServerError, h.CanonicalName(), err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -65,14 +66,15 @@ func handlerRemoveMedia(w http.ResponseWriter, rq *http.Request) {
|
||||
func handlerDelete(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
var (
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
h = hyphae.ByName(util.HyphaNameFromRq(rq, "delete"))
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
h = hyphae.ByName(util.HyphaNameFromRq(rq, "delete"))
|
||||
meta = viewutil.MetaFrom(w, rq)
|
||||
)
|
||||
|
||||
if !u.CanProceed("delete") {
|
||||
log.Printf("%s has no rights to delete ‘%s’\n", u.Name, h.CanonicalName())
|
||||
httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "No rights")
|
||||
viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "No rights")
|
||||
return
|
||||
}
|
||||
|
||||
@ -80,7 +82,7 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) {
|
||||
case *hyphae.EmptyHypha:
|
||||
log.Printf("%s tries to delete empty hypha ‘%s’\n", u.Name, h.CanonicalName())
|
||||
// TODO: localize
|
||||
httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "Cannot delete an empty hypha")
|
||||
viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "Cannot delete an empty hypha")
|
||||
return
|
||||
}
|
||||
|
||||
@ -88,16 +90,15 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) {
|
||||
util.HTTP200Page(
|
||||
w,
|
||||
views.Base(
|
||||
meta,
|
||||
fmt.Sprintf(lc.Get("ui.ask_delete"), util.BeautifulName(h.CanonicalName())),
|
||||
views.DeleteAsk(rq, h.CanonicalName()),
|
||||
lc,
|
||||
u))
|
||||
views.DeleteAsk(rq, h.CanonicalName())))
|
||||
return
|
||||
}
|
||||
|
||||
if err := shroom.Delete(u, h.(hyphae.ExistingHypha)); err != nil {
|
||||
log.Println(err)
|
||||
httpErr(w, lc, http.StatusInternalServerError, h.CanonicalName(), err.Error())
|
||||
viewutil.HttpErr(meta, http.StatusInternalServerError, h.CanonicalName(), err.Error())
|
||||
return
|
||||
}
|
||||
http.Redirect(w, rq, "/hypha/"+h.CanonicalName(), http.StatusSeeOther)
|
||||
@ -106,21 +107,22 @@ func handlerDelete(w http.ResponseWriter, rq *http.Request) {
|
||||
func handlerRename(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
var (
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
h = hyphae.ByName(util.HyphaNameFromRq(rq, "rename"))
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
h = hyphae.ByName(util.HyphaNameFromRq(rq, "rename"))
|
||||
meta = viewutil.MetaFrom(w, rq)
|
||||
)
|
||||
|
||||
switch h.(type) {
|
||||
case *hyphae.EmptyHypha:
|
||||
log.Printf("%s tries to rename empty hypha ‘%s’", u.Name, h.CanonicalName())
|
||||
httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "Cannot rename an empty hypha") // TODO: localize
|
||||
viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "Cannot rename an empty hypha") // TODO: localize
|
||||
return
|
||||
}
|
||||
|
||||
if !u.CanProceed("rename") {
|
||||
log.Printf("%s has no rights to rename ‘%s’\n", u.Name, h.CanonicalName())
|
||||
httpErr(w, lc, http.StatusForbidden, h.CanonicalName(), "No rights")
|
||||
viewutil.HttpErr(meta, http.StatusForbidden, h.CanonicalName(), "No rights")
|
||||
return
|
||||
}
|
||||
|
||||
@ -134,16 +136,15 @@ func handlerRename(w http.ResponseWriter, rq *http.Request) {
|
||||
util.HTTP200Page(
|
||||
w,
|
||||
views.Base(
|
||||
meta,
|
||||
fmt.Sprintf(lc.Get("ui.ask_rename"), util.BeautifulName(oldHypha.CanonicalName())),
|
||||
views.RenameAsk(rq, oldHypha.CanonicalName()),
|
||||
lc,
|
||||
u))
|
||||
views.RenameAsk(rq, oldHypha.CanonicalName())))
|
||||
return
|
||||
}
|
||||
|
||||
if err := shroom.Rename(oldHypha, newName, recursive, u); err != nil {
|
||||
log.Printf("%s tries to rename ‘%s’: %s", u.Name, oldHypha.CanonicalName(), err.Error())
|
||||
httpErr(w, lc, http.StatusForbidden, oldHypha.CanonicalName(), lc.Get(err.Error())) // TODO: localize
|
||||
viewutil.HttpErr(meta, http.StatusForbidden, oldHypha.CanonicalName(), lc.Get(err.Error())) // TODO: localize
|
||||
return
|
||||
}
|
||||
http.Redirect(w, rq, "/hypha/"+newName, http.StatusSeeOther)
|
||||
@ -160,10 +161,10 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) {
|
||||
err error
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
meta = viewutil.MetaFrom(w, rq)
|
||||
)
|
||||
if err := shroom.CanEdit(u, h, lc); err != nil {
|
||||
httpErr(w, lc, http.StatusInternalServerError, hyphaName,
|
||||
err.Error())
|
||||
viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, err.Error())
|
||||
return
|
||||
}
|
||||
switch h.(type) {
|
||||
@ -173,18 +174,16 @@ func handlerEdit(w http.ResponseWriter, rq *http.Request) {
|
||||
textAreaFill, err = shroom.FetchTextFile(h)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
httpErr(w, lc, http.StatusInternalServerError, hyphaName,
|
||||
lc.Get("ui.error_text_fetch"))
|
||||
viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, lc.Get("ui.error_text_fetch"))
|
||||
return
|
||||
}
|
||||
}
|
||||
util.HTTP200Page(
|
||||
w,
|
||||
views.Base(
|
||||
meta,
|
||||
fmt.Sprintf(lc.Get("edit.title"), util.BeautifulName(hyphaName)),
|
||||
views.Editor(rq, hyphaName, textAreaFill, warning),
|
||||
lc,
|
||||
u))
|
||||
views.Editor(rq, hyphaName, textAreaFill, warning)))
|
||||
}
|
||||
|
||||
// handlerUploadText uploads a new text part for the hypha.
|
||||
@ -198,21 +197,23 @@ func handlerUploadText(w http.ResponseWriter, rq *http.Request) {
|
||||
message = rq.PostFormValue("message")
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
meta = viewutil.MetaFrom(w, rq)
|
||||
)
|
||||
|
||||
if action != "Preview" {
|
||||
if err := shroom.UploadText(h, []byte(textData), message, u); err != nil {
|
||||
httpErr(w, lc, http.StatusForbidden, hyphaName, err.Error())
|
||||
viewutil.HttpErr(meta, http.StatusForbidden, hyphaName, err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if action == "Preview" {
|
||||
ctx, _ := mycocontext.ContextFromStringInput(hyphaName, textData)
|
||||
ctx, _ := mycocontext.ContextFromStringInput(textData, shroom.MarkupOptions(hyphaName))
|
||||
|
||||
util.HTTP200Page(
|
||||
w,
|
||||
views.Base(
|
||||
meta,
|
||||
fmt.Sprintf(lc.Get("edit.preview_title"), util.BeautifulName(hyphaName)),
|
||||
views.Preview(
|
||||
rq,
|
||||
@ -220,9 +221,7 @@ func handlerUploadText(w http.ResponseWriter, rq *http.Request) {
|
||||
textData,
|
||||
message,
|
||||
"",
|
||||
mycomarkup.BlocksToHTML(ctx, mycomarkup.BlockTree(ctx))),
|
||||
lc,
|
||||
u))
|
||||
mycomarkup.BlocksToHTML(ctx, mycomarkup.BlockTree(ctx)))))
|
||||
} else {
|
||||
http.Redirect(w, rq, "/hypha/"+hyphaName, http.StatusSeeOther)
|
||||
}
|
||||
@ -238,14 +237,13 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) {
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
file, handler, err = rq.FormFile("binary")
|
||||
meta = viewutil.MetaFrom(w, rq)
|
||||
)
|
||||
if err != nil {
|
||||
httpErr(w, lc, http.StatusInternalServerError, hyphaName,
|
||||
err.Error())
|
||||
viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, err.Error())
|
||||
}
|
||||
if err := shroom.CanAttach(u, h, lc); err != nil {
|
||||
httpErr(w, lc, http.StatusInternalServerError, hyphaName,
|
||||
err.Error())
|
||||
viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, err.Error())
|
||||
}
|
||||
|
||||
// If file is not passed:
|
||||
@ -263,7 +261,7 @@ func handlerUploadBinary(w http.ResponseWriter, rq *http.Request) {
|
||||
)
|
||||
|
||||
if err := shroom.UploadBinary(h, mime, file, u); err != nil {
|
||||
httpErr(w, lc, http.StatusInternalServerError, hyphaName, err.Error())
|
||||
viewutil.HttpErr(meta, http.StatusInternalServerError, hyphaName, err.Error())
|
||||
return
|
||||
}
|
||||
http.Redirect(w, rq, "/hypha/"+hyphaName, http.StatusSeeOther)
|
||||
|
@ -3,6 +3,9 @@ package web
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/bouncepaw/mycomarkup/v4"
|
||||
"github.com/bouncepaw/mycorrhiza/shroom"
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
"io"
|
||||
"log"
|
||||
"net/http"
|
||||
@ -12,7 +15,6 @@ import (
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/history"
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae"
|
||||
"github.com/bouncepaw/mycorrhiza/l18n"
|
||||
@ -21,9 +23,8 @@ import (
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
"github.com/bouncepaw/mycorrhiza/views"
|
||||
|
||||
"github.com/bouncepaw/mycomarkup/v3"
|
||||
"github.com/bouncepaw/mycomarkup/v3/mycocontext"
|
||||
"github.com/bouncepaw/mycomarkup/v3/tools"
|
||||
"github.com/bouncepaw/mycomarkup/v4/mycocontext"
|
||||
"github.com/bouncepaw/mycomarkup/v4/tools"
|
||||
)
|
||||
|
||||
func initReaders(r *mux.Router) {
|
||||
@ -47,10 +48,9 @@ func handlerMedia(w http.ResponseWriter, rq *http.Request) {
|
||||
)
|
||||
util.HTTP200Page(w,
|
||||
views.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
lc.Get("ui.media_title", &l18n.Replacements{"name": util.BeautifulName(hyphaName)}),
|
||||
views.MediaMenu(rq, h, u),
|
||||
lc,
|
||||
u))
|
||||
views.MediaMenu(rq, h, u)))
|
||||
}
|
||||
|
||||
func handlerPrimitiveDiff(w http.ResponseWriter, rq *http.Request) {
|
||||
@ -73,7 +73,7 @@ func handlerPrimitiveDiff(w http.ResponseWriter, rq *http.Request) {
|
||||
hyphaName = util.CanonicalName(slug)
|
||||
h = hyphae.ByName(hyphaName)
|
||||
user = user.FromRequest(rq)
|
||||
locale = l18n.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
)
|
||||
switch h := h.(type) {
|
||||
case *hyphae.EmptyHypha:
|
||||
@ -81,8 +81,9 @@ func handlerPrimitiveDiff(w http.ResponseWriter, rq *http.Request) {
|
||||
io.WriteString(w, "404 not found")
|
||||
case hyphae.ExistingHypha:
|
||||
util.HTTP200Page(w, views.Base(
|
||||
locale.Get("ui.diff_title", &l18n.Replacements{"name": util.BeautifulName(hyphaName), "rev": revHash}),
|
||||
views.PrimitiveDiff(rq, h, user, revHash), locale, user))
|
||||
viewutil.MetaFrom(w, rq),
|
||||
lc.Get("ui.diff_title", &l18n.Replacements{"name": util.BeautifulName(hyphaName), "rev": revHash}),
|
||||
views.PrimitiveDiff(rq, h, user, revHash)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -133,14 +134,13 @@ func handlerRevision(w http.ResponseWriter, rq *http.Request) {
|
||||
hyphaName = util.CanonicalName(shorterURL[firstSlashIndex+1:])
|
||||
h = hyphae.ByName(hyphaName)
|
||||
contents = fmt.Sprintf(`<p>%s</p>`, lc.Get("ui.revision_no_text"))
|
||||
u = user.FromRequest(rq)
|
||||
)
|
||||
switch h := h.(type) {
|
||||
case hyphae.ExistingHypha:
|
||||
var textContents, err = history.FileAtRevision(h.TextFilePath(), revHash)
|
||||
|
||||
if err == nil {
|
||||
ctx, _ := mycocontext.ContextFromStringInput(hyphaName, textContents)
|
||||
ctx, _ := mycocontext.ContextFromStringInput(textContents, shroom.MarkupOptions(hyphaName))
|
||||
contents = mycomarkup.BlocksToHTML(ctx, mycomarkup.BlockTree(ctx))
|
||||
}
|
||||
}
|
||||
@ -156,10 +156,9 @@ func handlerRevision(w http.ResponseWriter, rq *http.Request) {
|
||||
_, _ = fmt.Fprint(
|
||||
w,
|
||||
views.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
lc.Get("ui.revision_title", &l18n.Replacements{"name": util.BeautifulName(hyphaName), "rev": revHash}),
|
||||
page,
|
||||
lc,
|
||||
u,
|
||||
),
|
||||
)
|
||||
}
|
||||
@ -200,7 +199,6 @@ func handlerHypha(w http.ResponseWriter, rq *http.Request) {
|
||||
h = hyphae.ByName(hyphaName)
|
||||
contents string
|
||||
openGraph string
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
)
|
||||
|
||||
@ -208,16 +206,14 @@ func handlerHypha(w http.ResponseWriter, rq *http.Request) {
|
||||
case *hyphae.EmptyHypha:
|
||||
util.HTTP404Page(w,
|
||||
views.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
util.BeautifulName(hyphaName),
|
||||
views.Hypha(views.MetaFrom(w, rq), h, contents),
|
||||
lc,
|
||||
u,
|
||||
views.Hypha(viewutil.MetaFrom(w, rq), h, contents),
|
||||
openGraph))
|
||||
case hyphae.ExistingHypha:
|
||||
fileContentsT, errT := os.ReadFile(h.TextFilePath())
|
||||
if errT == nil {
|
||||
ctx, _ := mycocontext.ContextFromStringInput(hyphaName, string(fileContentsT))
|
||||
ctx = mycocontext.WithWebSiteURL(ctx, cfg.URL)
|
||||
ctx, _ := mycocontext.ContextFromStringInput(string(fileContentsT), shroom.MarkupOptions(hyphaName))
|
||||
getOpenGraph, descVisitor, imgVisitor := tools.OpenGraphVisitors(ctx)
|
||||
ast := mycomarkup.BlockTree(ctx, descVisitor, imgVisitor)
|
||||
contents = mycomarkup.BlocksToHTML(ctx, ast)
|
||||
@ -230,10 +226,9 @@ func handlerHypha(w http.ResponseWriter, rq *http.Request) {
|
||||
|
||||
util.HTTP200Page(w,
|
||||
views.Base(
|
||||
viewutil.MetaFrom(w, rq),
|
||||
util.BeautifulName(hyphaName),
|
||||
views.Hypha(views.MetaFrom(w, rq), h, contents),
|
||||
lc,
|
||||
u,
|
||||
views.Hypha(viewutil.MetaFrom(w, rq), h, contents),
|
||||
openGraph))
|
||||
}
|
||||
}
|
||||
|
@ -1,38 +0,0 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/l18n"
|
||||
"github.com/bouncepaw/mycorrhiza/shroom"
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
"github.com/bouncepaw/mycorrhiza/views"
|
||||
)
|
||||
|
||||
func initSearch(r *mux.Router) {
|
||||
r.HandleFunc("/title-search/", handlerTitleSearch)
|
||||
}
|
||||
|
||||
func handlerTitleSearch(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
_ = rq.ParseForm()
|
||||
var (
|
||||
query = rq.FormValue("q")
|
||||
u = user.FromRequest(rq)
|
||||
lc = l18n.FromRequest(rq)
|
||||
)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
views.Base(
|
||||
lc.Get("ui.title_search_title", &l18n.Replacements{"query": query}),
|
||||
views.TitleSearch(query, shroom.YieldHyphaNamesContainingString, lc),
|
||||
lc,
|
||||
u,
|
||||
),
|
||||
)
|
||||
}
|
167
web/stuff.go
167
web/stuff.go
@ -1,167 +0,0 @@
|
||||
package web
|
||||
|
||||
// stuff.go is used for meta stuff about the wiki or all hyphae at once.
|
||||
import (
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae/backlinks"
|
||||
"io"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/files"
|
||||
"github.com/bouncepaw/mycorrhiza/help"
|
||||
"github.com/bouncepaw/mycorrhiza/hyphae"
|
||||
"github.com/bouncepaw/mycorrhiza/l18n"
|
||||
"github.com/bouncepaw/mycorrhiza/shroom"
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
"github.com/bouncepaw/mycorrhiza/views"
|
||||
|
||||
"github.com/bouncepaw/mycomarkup/v3"
|
||||
"github.com/bouncepaw/mycomarkup/v3/mycocontext"
|
||||
)
|
||||
|
||||
func initStuff(r *mux.Router) {
|
||||
r.PathPrefix("/help").HandlerFunc(handlerHelp)
|
||||
r.HandleFunc("/list", handlerList)
|
||||
r.HandleFunc("/reindex", handlerReindex)
|
||||
r.HandleFunc("/update-header-links", handlerUpdateHeaderLinks)
|
||||
r.HandleFunc("/random", handlerRandom)
|
||||
r.HandleFunc("/about", handlerAbout)
|
||||
r.HandleFunc("/favicon.ico", func(w http.ResponseWriter, rq *http.Request) {
|
||||
http.Redirect(w, rq, "/static/favicon.ico", http.StatusSeeOther)
|
||||
})
|
||||
}
|
||||
|
||||
// handlerHelp gets the appropriate documentation or tells you where you (personally) have failed.
|
||||
func handlerHelp(w http.ResponseWriter, rq *http.Request) {
|
||||
lc := l18n.FromRequest(rq)
|
||||
articlePath := strings.TrimPrefix(strings.TrimPrefix(rq.URL.Path, "/help/"), "/help")
|
||||
// See the history of this file to resurrect the old algorithm that supported multiple languages
|
||||
lang := "en"
|
||||
if articlePath == "" {
|
||||
articlePath = "en"
|
||||
}
|
||||
|
||||
if !strings.HasPrefix(articlePath, "en") {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
_, _ = io.WriteString(w, "404 Not found")
|
||||
return
|
||||
}
|
||||
|
||||
content, err := help.Get(articlePath)
|
||||
if err != nil && strings.HasPrefix(err.Error(), "open") {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
views.Base(lc.Get("help.entry_not_found"),
|
||||
views.Help(views.HelpEmptyError(lc), lang, lc),
|
||||
lc,
|
||||
user.FromRequest(rq)),
|
||||
)
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
views.Base(err.Error(),
|
||||
views.Help(err.Error(), lang, lc),
|
||||
lc,
|
||||
user.FromRequest(rq)),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// TODO: change for the function that uses byte array when there is such function in mycomarkup.
|
||||
ctx, _ := mycocontext.ContextFromStringInput(articlePath, string(content))
|
||||
ast := mycomarkup.BlockTree(ctx)
|
||||
result := mycomarkup.BlocksToHTML(ctx, ast)
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = io.WriteString(
|
||||
w,
|
||||
views.Base(lc.Get("help.title"),
|
||||
views.Help(result, lang, lc),
|
||||
lc,
|
||||
user.FromRequest(rq)),
|
||||
)
|
||||
}
|
||||
|
||||
// handlerList shows a list of all hyphae in the wiki in random order.
|
||||
func handlerList(w http.ResponseWriter, rq *http.Request) {
|
||||
u := user.FromRequest(rq)
|
||||
var lc = l18n.FromRequest(rq)
|
||||
util.PrepareRq(rq)
|
||||
util.HTTP200Page(w, views.Base(lc.Get("ui.list_title"), views.HyphaList(lc), lc, u))
|
||||
}
|
||||
|
||||
// handlerReindex reindexes all hyphae by checking the wiki storage directory anew.
|
||||
func handlerReindex(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
if ok := user.CanProceed(rq, "reindex"); !ok {
|
||||
var lc = l18n.FromRequest(rq)
|
||||
httpErr(w, lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.reindex_no_rights"))
|
||||
log.Println("Rejected", rq.URL)
|
||||
return
|
||||
}
|
||||
hyphae.ResetCount()
|
||||
log.Println("Reindexing hyphae in", files.HyphaeDir())
|
||||
hyphae.Index(files.HyphaeDir())
|
||||
backlinks.IndexBacklinks()
|
||||
http.Redirect(w, rq, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// handlerUpdateHeaderLinks updates header links by reading the configured hypha, if there is any, or resorting to default values.
|
||||
//
|
||||
// See https://mycorrhiza.wiki/hypha/configuration/header
|
||||
func handlerUpdateHeaderLinks(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
if ok := user.CanProceed(rq, "update-header-links"); !ok {
|
||||
var lc = l18n.FromRequest(rq)
|
||||
httpErr(w, lc, http.StatusForbidden, cfg.HomeHypha, lc.Get("ui.header_no_rights"))
|
||||
log.Println("Rejected", rq.URL)
|
||||
return
|
||||
}
|
||||
shroom.SetHeaderLinks()
|
||||
http.Redirect(w, rq, "/", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// handlerRandom redirects to a random hypha.
|
||||
func handlerRandom(w http.ResponseWriter, rq *http.Request) {
|
||||
util.PrepareRq(rq)
|
||||
var (
|
||||
randomHyphaName string
|
||||
amountOfHyphae = hyphae.Count()
|
||||
)
|
||||
if amountOfHyphae == 0 {
|
||||
var lc = l18n.FromRequest(rq)
|
||||
httpErr(w, lc, http.StatusNotFound, cfg.HomeHypha, lc.Get("ui.random_no_hyphae_tip"))
|
||||
return
|
||||
}
|
||||
i := rand.Intn(amountOfHyphae)
|
||||
for h := range hyphae.YieldExistingHyphae() {
|
||||
if i == 0 {
|
||||
randomHyphaName = h.CanonicalName()
|
||||
}
|
||||
i--
|
||||
}
|
||||
http.Redirect(w, rq, "/hypha/"+randomHyphaName, http.StatusSeeOther)
|
||||
}
|
||||
|
||||
// handlerAbout shows a summary of wiki's software.
|
||||
func handlerAbout(w http.ResponseWriter, rq *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/html;charset=utf-8")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
var (
|
||||
lc = l18n.FromRequest(rq)
|
||||
title = lc.Get("ui.about_title", &l18n.Replacements{"name": cfg.WikiName})
|
||||
)
|
||||
_, err := io.WriteString(w, views.Base(title, views.AboutHTML(lc), lc, user.FromRequest(rq)))
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
}
|
76
web/web.go
76
web/web.go
@ -2,74 +2,21 @@
|
||||
package web
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/bouncepaw/mycorrhiza/backlinks"
|
||||
"github.com/bouncepaw/mycorrhiza/categories"
|
||||
"github.com/bouncepaw/mycorrhiza/help"
|
||||
"github.com/bouncepaw/mycorrhiza/misc"
|
||||
"io"
|
||||
"mime"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"github.com/bouncepaw/mycorrhiza/cfg"
|
||||
"github.com/bouncepaw/mycorrhiza/l18n"
|
||||
"github.com/bouncepaw/mycorrhiza/static"
|
||||
"github.com/bouncepaw/mycorrhiza/user"
|
||||
"github.com/bouncepaw/mycorrhiza/util"
|
||||
"github.com/bouncepaw/mycorrhiza/views"
|
||||
)
|
||||
|
||||
var stylesheets = []string{"default.css", "custom.css"}
|
||||
|
||||
// httpErr is used by many handlers to signal errors in a compact way.
|
||||
func httpErr(w http.ResponseWriter, lc *l18n.Localizer, status int, name, errMsg string) {
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
|
||||
w.WriteHeader(status)
|
||||
fmt.Fprint(
|
||||
w,
|
||||
views.Base(
|
||||
"Error",
|
||||
fmt.Sprintf(
|
||||
`<main class="main-width"><p>%s. <a href="/hypha/%s">%s<a></p></main>`,
|
||||
errMsg,
|
||||
name,
|
||||
lc.Get("ui.error_go_back"),
|
||||
),
|
||||
lc,
|
||||
user.EmptyUser(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func handlerStyle(w http.ResponseWriter, rq *http.Request) {
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(".css"))
|
||||
for _, name := range stylesheets {
|
||||
file, err := static.FS.Open(name)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
io.Copy(w, file)
|
||||
file.Close()
|
||||
}
|
||||
}
|
||||
|
||||
func handlerUserList(w http.ResponseWriter, rq *http.Request) {
|
||||
lc := l18n.FromRequest(rq)
|
||||
w.Header().Set("Content-Type", mime.TypeByExtension(".html"))
|
||||
w.WriteHeader(http.StatusOK)
|
||||
w.Write([]byte(views.Base(lc.Get("ui.users_title"), views.UserList(lc), lc, user.FromRequest(rq))))
|
||||
}
|
||||
|
||||
func handlerRobotsTxt(w http.ResponseWriter, rq *http.Request) {
|
||||
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
|
||||
|
||||
file, err := static.FS.Open("robots.txt")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
io.Copy(w, file)
|
||||
file.Close()
|
||||
}
|
||||
|
||||
// Handler initializes and returns the HTTP router based on the configuration.
|
||||
func Handler() http.Handler {
|
||||
router := mux.NewRouter()
|
||||
@ -86,10 +33,6 @@ func Handler() http.Handler {
|
||||
|
||||
// Public routes. They're always accessible regardless of the user status.
|
||||
initAuth(router)
|
||||
router.HandleFunc("/robots.txt", handlerRobotsTxt)
|
||||
router.HandleFunc("/static/style.css", handlerStyle)
|
||||
router.PathPrefix("/static/").
|
||||
Handler(http.StripPrefix("/static/", http.FileServer(http.FS(static.FS))))
|
||||
|
||||
// Wiki routes. They may be locked or restricted.
|
||||
wikiRouter := router.PathPrefix("").Subrouter()
|
||||
@ -105,10 +48,10 @@ func Handler() http.Handler {
|
||||
initReaders(wikiRouter)
|
||||
initMutators(wikiRouter)
|
||||
initHistory(wikiRouter)
|
||||
initStuff(wikiRouter)
|
||||
initSearch(wikiRouter)
|
||||
initBacklinks(wikiRouter)
|
||||
initCategories(wikiRouter)
|
||||
help.InitHandlers(wikiRouter)
|
||||
backlinks.InitHandlers(wikiRouter)
|
||||
categories.InitHandlers(wikiRouter)
|
||||
misc.InitHandlers(wikiRouter)
|
||||
|
||||
// Admin routes.
|
||||
if cfg.UseAuth {
|
||||
@ -117,9 +60,6 @@ func Handler() http.Handler {
|
||||
initAdmin(adminRouter)
|
||||
}
|
||||
|
||||
// Miscellaneous
|
||||
wikiRouter.HandleFunc("/user-list", handlerUserList)
|
||||
|
||||
// Index page
|
||||
wikiRouter.HandleFunc("/", func(w http.ResponseWriter, rq *http.Request) {
|
||||
// Let's pray it never fails
|
||||
|
Loading…
Reference in New Issue
Block a user