diff --git a/hyphae/backlinks/backlinks.go b/backlinks/backlinks.go
similarity index 95%
rename from hyphae/backlinks/backlinks.go
rename to backlinks/backlinks.go
index 6ed43b0..605d8bd 100644
--- a/hyphae/backlinks/backlinks.go
+++ b/backlinks/backlinks.go
@@ -9,8 +9,8 @@ import (
"github.com/bouncepaw/mycorrhiza/util"
)
-// YieldHyphaBacklinks gets backlinks for the desired hypha, sorts and yields them one by one.
-func YieldHyphaBacklinks(hyphaName string) <-chan string {
+// yieldHyphaBacklinks gets backlinks for the desired hypha, sorts and yields them one by one.
+func yieldHyphaBacklinks(hyphaName string) <-chan string {
hyphaName = util.CanonicalName(hyphaName)
out := make(chan string)
sorted := hyphae.PathographicSort(out)
@@ -147,7 +147,7 @@ type backlinkIndexRenaming struct {
links []string
}
-// Apply changes backlink index respective to the operation data
+// apply changes backlink index respective to the operation data
func (op backlinkIndexRenaming) apply() {
for _, link := range op.links {
if lSet, exists := backlinkIndex[link]; exists {
diff --git a/hyphae/backlinks/hooks.go b/backlinks/hooks.go
similarity index 83%
rename from hyphae/backlinks/hooks.go
rename to backlinks/hooks.go
index 9cc5237..1ad7ebe 100644
--- a/hyphae/backlinks/hooks.go
+++ b/backlinks/hooks.go
@@ -1,10 +1,11 @@
package backlinks
import (
- "github.com/bouncepaw/mycomarkup/v3"
- "github.com/bouncepaw/mycomarkup/v3/links"
- "github.com/bouncepaw/mycomarkup/v3/mycocontext"
- "github.com/bouncepaw/mycomarkup/v3/tools"
+ "github.com/bouncepaw/mycomarkup/v4"
+ "github.com/bouncepaw/mycomarkup/v4/links"
+ "github.com/bouncepaw/mycomarkup/v4/mycocontext"
+ "github.com/bouncepaw/mycomarkup/v4/options"
+ "github.com/bouncepaw/mycomarkup/v4/tools"
"github.com/bouncepaw/mycorrhiza/hyphae"
)
@@ -34,7 +35,7 @@ func extractHyphaLinks(h hyphae.Hypha) []string {
// extractHyphaLinksFromContent extracts local hypha links from the provided text.
func extractHyphaLinksFromContent(hyphaName string, contents string) []string {
- ctx, _ := mycocontext.ContextFromStringInput(hyphaName, contents)
+ ctx, _ := mycocontext.ContextFromStringInput(contents, options.Options{HyphaName: hyphaName}.FillTheRest())
linkVisitor, getLinks := tools.LinkVisitor(ctx)
// Ignore the result of BlockTree because we call it for linkVisitor.
_ = mycomarkup.BlockTree(ctx, linkVisitor)
diff --git a/backlinks/view_backlinks.html b/backlinks/view_backlinks.html
new file mode 100644
index 0000000..597fe32
--- /dev/null
+++ b/backlinks/view_backlinks.html
@@ -0,0 +1,17 @@
+{{define "backlinks to text"}}Backlinks to {{.}}{{end}}
+{{define "title"}}{{template "backlinks to text" .HyphaName}}{{end}}
+{{define "body"}}
+
+
+ {{block "backlinks to link" .HyphaName}}Backlinks to {{beautifulName .}} {{end}}
+ {{block "description" .}}Hyphae which have a link to this hypha, embed it as an image or transclude it are listed below.{{end}}
+
+
+
+{{end}}
\ No newline at end of file
diff --git a/backlinks/web.go b/backlinks/web.go
new file mode 100644
index 0000000..278b936
--- /dev/null
+++ b/backlinks/web.go
@@ -0,0 +1,62 @@
+package backlinks
+
+import (
+ "embed"
+ "github.com/bouncepaw/mycorrhiza/cfg"
+ "github.com/bouncepaw/mycorrhiza/util"
+ "github.com/bouncepaw/mycorrhiza/viewutil"
+ "github.com/gorilla/mux"
+ "log"
+ "net/http"
+ "text/template"
+)
+
+func InitHandlers(rtr *mux.Router) {
+ rtr.PathPrefix("/backlinks/").HandlerFunc(handlerBacklinks)
+ chain = viewutil.
+ En(viewutil.CopyEnWith(fs, "view_backlinks.html")).
+ Ru(template.Must(viewutil.CopyRuWith(fs, "view_backlinks.html").Parse(ruTranslation)))
+}
+
+// handlerBacklinks lists all backlinks to a hypha.
+func handlerBacklinks(w http.ResponseWriter, rq *http.Request) {
+ var (
+ hyphaName = util.HyphaNameFromRq(rq, "backlinks")
+ backlinks []string
+ )
+ for b := range yieldHyphaBacklinks(hyphaName) {
+ backlinks = append(backlinks, b)
+ }
+ viewBacklinks(viewutil.MetaFrom(w, rq), hyphaName, backlinks)
+}
+
+var (
+ //go:embed *.html
+ fs embed.FS
+ ruTranslation = `
+{{define "backlinks to text"}}Обратные ссылки на {{.}}{{end}}
+{{define "backlinks to link"}}Обратные ссылки на {{beautifulName .}} {{end}}
+{{define "description"}}Ниже перечислены гифы, на которых есть ссылка на эту гифу, трансклюзия этой гифы или эта гифа вставлена как изображение.{{end}}
+`
+ chain viewutil.Chain
+)
+
+type backlinksData struct {
+ viewutil.BaseData
+ HyphaName string
+ Backlinks []string
+}
+
+func viewBacklinks(meta viewutil.Meta, hyphaName string, backlinks []string) {
+ if err := chain.Get(meta).ExecuteTemplate(meta.W, "page", backlinksData{
+ BaseData: viewutil.BaseData{
+ Meta: meta,
+ HeaderLinks: cfg.HeaderLinks,
+ CommonScripts: cfg.CommonScripts,
+ },
+ HyphaName: hyphaName,
+ Backlinks: backlinks,
+ }); err != nil {
+ log.Println(err)
+ }
+}
diff --git a/hyphae/categories/categories.go b/categories/categories.go
similarity index 69%
rename from hyphae/categories/categories.go
rename to categories/categories.go
index 4e26fa5..50ab12b 100644
--- a/hyphae/categories/categories.go
+++ b/categories/categories.go
@@ -1,4 +1,4 @@
-// Package categories provides category management. All operations in this package are mutexed.
+// Package categories provides category management.
//
// As per the long pondering, this is how categories (cats for short)
// work in Mycorrhiza:
@@ -12,12 +12,19 @@
// cat operations are not mentioned on the recent changes page.
// - For cat A, if there are 0 hyphae in the cat, cat A does not
// exist. If there are 1 or more hyphae in the cat, cat A exists.
+//
+// List of things to do with categories later:
+//
+// - Forbid / in cat names.
+// - Rename categories.
+// - Delete categories.
+// - Bind hyphae.
package categories
import "sync"
-// List returns names of all categories.
-func List() (categoryList []string) {
+// listOfCategories returns names of all categories.
+func listOfCategories() (categoryList []string) {
mutex.RLock()
for cat, _ := range categoryToHyphae {
categoryList = append(categoryList, cat)
@@ -26,8 +33,8 @@ func List() (categoryList []string) {
return categoryList
}
-// WithHypha returns what categories have the given hypha. The hypha name must be canonical.
-func WithHypha(hyphaName string) (categoryList []string) {
+// categoriesWithHypha returns what categories have the given hypha. The hypha name must be canonical.
+func categoriesWithHypha(hyphaName string) (categoryList []string) {
mutex.RLock()
defer mutex.RUnlock()
if node, ok := hyphaToCategories[hyphaName]; ok {
@@ -37,8 +44,8 @@ func WithHypha(hyphaName string) (categoryList []string) {
}
}
-// Contents returns what hyphae are in the category. If the returned slice is empty, the category does not exist, and vice versa. The category name must be canonical.
-func Contents(catName string) (hyphaList []string) {
+// hyphaeInCategory returns what hyphae are in the category. If the returned slice is empty, the category does not exist, and vice versa. The category name must be canonical.
+func hyphaeInCategory(catName string) (hyphaList []string) {
mutex.RLock()
defer mutex.RUnlock()
if node, ok := categoryToHyphae[catName]; ok {
@@ -50,8 +57,8 @@ func Contents(catName string) (hyphaList []string) {
var mutex sync.RWMutex
-// AddHyphaToCategory adds the hypha to the category and updates the records on the disk. If the hypha is already in the category, nothing happens. Pass canonical names.
-func AddHyphaToCategory(hyphaName, catName string) {
+// addHyphaToCategory adds the hypha to the category and updates the records on the disk. If the hypha is already in the category, nothing happens. Pass canonical names.
+func addHyphaToCategory(hyphaName, catName string) {
mutex.Lock()
if node, ok := hyphaToCategories[hyphaName]; ok {
node.storeCategory(catName)
@@ -68,8 +75,8 @@ func AddHyphaToCategory(hyphaName, catName string) {
go saveToDisk()
}
-// RemoveHyphaFromCategory removes the hypha from the category and updates the records on the disk. If the hypha is not in the category, nothing happens. Pass canonical names.
-func RemoveHyphaFromCategory(hyphaName, catName string) {
+// removeHyphaFromCategory removes the hypha from the category and updates the records on the disk. If the hypha is not in the category, nothing happens. Pass canonical names.
+func removeHyphaFromCategory(hyphaName, catName string) {
mutex.Lock()
if node, ok := hyphaToCategories[hyphaName]; ok {
node.removeCategory(catName)
diff --git a/hyphae/categories/files.go b/categories/files.go
similarity index 93%
rename from hyphae/categories/files.go
rename to categories/files.go
index fd5c3df..7c51322 100644
--- a/hyphae/categories/files.go
+++ b/categories/files.go
@@ -12,8 +12,8 @@ import (
var categoryToHyphae = map[string]*categoryNode{}
var hyphaToCategories = map[string]*hyphaNode{}
-// InitCategories initializes the category system. Call it after the Structure is initialized. This function might terminate the program in case of a bad mood or filesystem faults.
-func InitCategories() {
+// Init initializes the category system. Call it after the Structure is initialized. This function might terminate the program in case of a bad mood or filesystem faults.
+func Init() {
var (
record, err = readCategoriesFromDisk()
)
diff --git a/web/categories.go b/categories/handlers.go
similarity index 79%
rename from web/categories.go
rename to categories/handlers.go
index fc42444..3c30319 100644
--- a/web/categories.go
+++ b/categories/handlers.go
@@ -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)
}
diff --git a/categories/view_card.html b/categories/view_card.html
new file mode 100644
index 0000000..1f145c2
--- /dev/null
+++ b/categories/view_card.html
@@ -0,0 +1,35 @@
+{{define "category card"}}
+ {{$hyphaName := .HyphaName}}
+ {{$givenPermission := .GivenPermissionToModify}}
+
+ {{block `categories` .}}Categories{{end}}
+
+ {{range .Categories}}
+
+ {{beautifulName .}}
+
+
+ {{end}}
+ {{if .GivenPermissionToModify}}
+
+
+
+ {{end}}
+
+
+{{end}}
\ No newline at end of file
diff --git a/categories/view_list.html b/categories/view_list.html
new file mode 100644
index 0000000..53754b3
--- /dev/null
+++ b/categories/view_list.html
@@ -0,0 +1,18 @@
+{{define "category list"}}Category list{{end}}
+{{define "title"}}{{template "category list"}}{{end}}
+{{define "body"}}
+
+ {{template "title"}}
+ {{if len .Categories}}
+
+ {{else}}
+ {{block `no categories` .}}This wiki has no categories.{{end}}
+ {{end}}
+
+{{end}}
\ No newline at end of file
diff --git a/categories/view_page.html b/categories/view_page.html
new file mode 100644
index 0000000..a250d38
--- /dev/null
+++ b/categories/view_page.html
@@ -0,0 +1,29 @@
+{{define "category x"}}Category {{. | beautifulName}}{{end}}
+{{define "title"}}{{template "category x" .CatName}}{{end}}
+{{define "body"}}
+ {{$catName := .CatName}}
+
+ {{block "cat" .}}Category{{end}} {{beautifulName $catName}}
+ {{if len .Hyphae | not}}
+ {{block "empty cat" .}}This category is empty{{end}}
+ {{end}}
+
+ {{range .Hyphae}}
+
+ {{beautifulName .}}
+
+ {{end}}
+ {{if .GivenPermissionToModify}}
+
+
+
+ {{end}}
+
+
+{{end}}
\ No newline at end of file
diff --git a/categories/views.go b/categories/views.go
new file mode 100644
index 0000000..3401f2d
--- /dev/null
+++ b/categories/views.go
@@ -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)
+ }
+}
diff --git a/cfg/config.go b/cfg/config.go
index c13f00c..4267068 100644
--- a/cfg/config.go
+++ b/cfg/config.go
@@ -193,7 +193,7 @@ func ReadConfigFile(path string) error {
TelegramEnabled = (TelegramBotToken != "") && (TelegramBotName != "")
// This URL makes much more sense. If no URL is set or the protocol is forgotten, assume HTTP.
- if (URL == "") || (strings.Index(URL, ":") == -1) {
+ if (URL == "") || !strings.Contains(URL, ":") {
URL = "http://" + ListenAddr
}
diff --git a/cfg/header_links.go b/cfg/header_links.go
index 3d284aa..fcb51c8 100644
--- a/cfg/header_links.go
+++ b/cfg/header_links.go
@@ -1,10 +1,10 @@
package cfg
-// See https://mycorrhiza.wiki/hypha/configuration/header
import (
- "github.com/bouncepaw/mycomarkup/v3"
- "github.com/bouncepaw/mycomarkup/v3/blocks"
- "github.com/bouncepaw/mycomarkup/v3/mycocontext"
+ "github.com/bouncepaw/mycomarkup/v4"
+ "github.com/bouncepaw/mycomarkup/v4/blocks"
+ "github.com/bouncepaw/mycomarkup/v4/mycocontext"
+ "github.com/bouncepaw/mycomarkup/v4/options"
)
// HeaderLinks is a list off current header links. Feel free to iterate it directly but do not modify it by yourself. Call ParseHeaderLinks if you need to set new header links.
@@ -24,7 +24,7 @@ func SetDefaultHeaderLinks() {
// ParseHeaderLinks extracts all rocketlinks from the given text and saves them as header links.
func ParseHeaderLinks(text string) {
HeaderLinks = []HeaderLink{}
- ctx, _ := mycocontext.ContextFromStringInput("", text)
+ ctx, _ := mycocontext.ContextFromStringInput(text, options.Options{}.FillTheRest())
// We call for side-effects
_ = mycomarkup.BlockTree(ctx, func(block blocks.Block) {
switch launchpad := block.(type) {
diff --git a/go.mod b/go.mod
index a57cbd3..6d1974e 100644
--- a/go.mod
+++ b/go.mod
@@ -3,7 +3,7 @@ module github.com/bouncepaw/mycorrhiza
go 1.18
require (
- github.com/bouncepaw/mycomarkup/v3 v3.6.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
diff --git a/go.sum b/go.sum
index 85d030c..8896013 100644
--- a/go.sum
+++ b/go.sum
@@ -1,7 +1,9 @@
github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
-github.com/bouncepaw/mycomarkup/v3 v3.6.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=
diff --git a/help/en/top_bar.myco b/help/en/top_bar.myco
index 523f684..65214c0 100644
--- a/help/en/top_bar.myco
+++ b/help/en/top_bar.myco
@@ -15,6 +15,7 @@ On big screens, the top bar is spread onto two lines.
** All hyphae
** Random
** Help
+** Categories
On small screens, the authorization section and the most-used-links section are hidden behind a menu. Click the button to see them. If your browser does not support JavaScript, they are always shown.
@@ -40,9 +41,11 @@ Reload the wiki.
----
-Edit the hypha. You can put any markup there. Rocket links will be used for generating the top bar:
+Edit the hypha. You can put any markup there. Only rocket links will be used for generating the top bar:
```myco
+This paragraph is unused.
+
=> /recent-changes | Recent changes
=> Highlights
=> Philosophy | Our views on life
diff --git a/help/help.go b/help/help.go
index bc12477..057d3c1 100644
--- a/help/help.go
+++ b/help/help.go
@@ -5,7 +5,7 @@ import (
"embed"
)
-//go:embed en en.myco
+//go:embed en en.myco *.html
var fs embed.FS
// Get determines what help text you need and returns it. The path is a substring from URL, it follows this form:
diff --git a/help/view_help.html b/help/view_help.html
new file mode 100644
index 0000000..ed426b7
--- /dev/null
+++ b/help/view_help.html
@@ -0,0 +1,50 @@
+{{define "title"}}Help{{end}}
+{{define "body"}}
+
+
+
+ {{if .ContentsHTML}}
+ {{.ContentsHTML}}
+ {{else}}
+ {{block "entry not found" .}}Entry not found{{end}}
+ {{block "entry not found invitation" .}}If you want to write this entry by yourself, consider contributing it directly.{{end}}
+ {{end}}
+
+
+
+ {{block "topics" .}}Help topics{{end}}
+
+
+
+{{end}}
+
diff --git a/help/web.go b/help/web.go
new file mode 100644
index 0000000..a717435
--- /dev/null
+++ b/help/web.go
@@ -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"}}Если вы хотите написать эту статью сами, то будем рады вашим правкам в репозитории Миокризы .{{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)
+ }
+}
diff --git a/history/revision.go b/history/revision.go
index fd9293a..4817aa1 100644
--- a/history/revision.go
+++ b/history/revision.go
@@ -175,7 +175,7 @@ func (rev *Revision) hyphaeAffected() (hyphae []string) {
filesAffected = rev.filesAffected()
)
for _, filename := range filesAffected {
- if strings.IndexRune(filename, '.') >= 0 {
+ if strings.ContainsRune(filename, '.') {
dotPos := strings.LastIndexByte(filename, '.')
hyphaName := string([]byte(filename)[0:dotPos]) // is it safe?
if isNewName(hyphaName) {
diff --git a/l18n/en/ui.json b/l18n/en/ui.json
index 28a1de6..485429a 100644
--- a/l18n/en/ui.json
+++ b/l18n/en/ui.json
@@ -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",
diff --git a/l18n/l18n.go b/l18n/l18n.go
index 67b347b..b557de0 100644
--- a/l18n/l18n.go
+++ b/l18n/l18n.go
@@ -118,7 +118,7 @@ func (t Localizer) GetWithLocale(locale, key string, replacements ...*Replacemen
// If the str doesn't have any substitutions, no need to
// template.Execute.
- if strings.Index(str, "}}") == -1 {
+ if !strings.Contains(str, "}}") {
return str
}
@@ -145,7 +145,7 @@ func (t Localizer) GetPlural(key string, n int, replacements ...*Replacements) s
// As in the original, we skip templating if have nothing to replace
// (however, it's strange case for plurals)
- if strings.Index(str, "}}") == -1 {
+ if !strings.Contains(str, "}}") {
return str
}
@@ -164,7 +164,7 @@ func (t Localizer) GetPlural64(key string, n int64, replacements ...*Replacement
// As in the original, we skip templating if have nothing to replace
// (however, it's strange case for plurals)
- if strings.Index(str, "}}") == -1 {
+ if !strings.Contains(str, "}}") {
return str
}
diff --git a/l18n/ru/ui.json b/l18n/ru/ui.json
index 43285ac..83ae6ae 100644
--- a/l18n/ru/ui.json
+++ b/l18n/ru/ui.json
@@ -3,21 +3,10 @@
"register": "Регистрация",
"title_search": "Поиск по названию",
"admin_panel": "Администрирование",
-
- "search_results_title": "Поиск: {{.query}}",
- "search_results_query": "Результаты поиска для «{{.query}}»",
- "search_results_desc": "Название каждой из существующих гиф сопоставлено с запросом. Подходящие гифы приведены ниже.",
-
+
"backlinks_title": "Обратные ссылки на {{.hypha_name}}",
"backlinks_heading": "Обратные ссылки на {{.hypha_link}}",
"backlinks_desc": "Ниже перечислены гифы, на которых есть ссылка на эту гифу, трансклюзия этой гифы или эта гифа вставлена как изображение.",
-
- "list_title": "Список страниц",
- "list_heading": "Список гиф",
- "list_desc": "В этой вики {{.n}} %s.",
- "list_desc+one": "гифа",
- "list_desc+few": "гифы",
- "list_desc+many": "гиф",
"edit_link": "Редактировать",
"logout_link": "Выйти",
diff --git a/main.go b/main.go
index bfa549c..a67ac4c 100644
--- a/main.go
+++ b/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())
diff --git a/migration/rockets.go b/migration/rockets.go
index f68ce97..3895aec 100644
--- a/migration/rockets.go
+++ b/migration/rockets.go
@@ -4,7 +4,7 @@
package migration
import (
- "github.com/bouncepaw/mycomarkup/v3/tools"
+ "github.com/bouncepaw/mycomarkup/v4/tools"
"io"
"io/ioutil"
"log"
diff --git a/misc/handlers.go b/misc/handlers.go
new file mode 100644
index 0000000..f15a129
--- /dev/null
+++ b/misc/handlers.go
@@ -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)
+}
diff --git a/misc/view_list.html b/misc/view_list.html
new file mode 100644
index 0000000..0b99b5b
--- /dev/null
+++ b/misc/view_list.html
@@ -0,0 +1,21 @@
+{{define "list of hyphae"}}List of hyphae{{end}}
+{{define "title"}}{{template "list of hyphae"}}{{end}}
+{{define "body"}}
+
+
+ {{template "list of hyphae"}}
+
+ {{range .Entries}}
+
+
+ {{beautifulName .Name}}
+
+ {{if .Ext}}
+ {{.Ext}}
+ {{end}}
+
+ {{end}}
+
+
+
+{{end}}
\ No newline at end of file
diff --git a/misc/view_title_search.html b/misc/view_title_search.html
new file mode 100644
index 0000000..0ce4872
--- /dev/null
+++ b/misc/view_title_search.html
@@ -0,0 +1,16 @@
+{{define "search:"}}Search: {{.}}{{end}}
+{{define "title"}}{{template "search:" .Query}}{{end}}
+{{define "body"}}
+
+ {{block "search results for" .Query}}Search results for ‘{{.}}’{{end}}
+ {{block "search desc" .}}Every hypha name has been compared with the query. Hyphae that have matched the query are listed below.{{end}}
+
+
+
+{{end}}
\ No newline at end of file
diff --git a/misc/views.go b/misc/views.go
new file mode 100644
index 0000000..e288067
--- /dev/null
+++ b/misc/views.go
@@ -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)
+ }
+}
diff --git a/shroom/delete.go b/shroom/delete.go
index 1227dcb..958262e 100644
--- a/shroom/delete.go
+++ b/shroom/delete.go
@@ -2,8 +2,7 @@ package shroom
import (
"fmt"
- "github.com/bouncepaw/mycorrhiza/hyphae/backlinks"
-
+ "github.com/bouncepaw/mycorrhiza/backlinks"
"github.com/bouncepaw/mycorrhiza/history"
"github.com/bouncepaw/mycorrhiza/hyphae"
"github.com/bouncepaw/mycorrhiza/user"
diff --git a/shroom/log.go b/shroom/log.go
index ecda380..2be9a70 100644
--- a/shroom/log.go
+++ b/shroom/log.go
@@ -7,9 +7,6 @@ import (
"github.com/bouncepaw/mycorrhiza/user"
)
-func rejectDeleteLog(h hyphae.Hypha, u *user.User, errmsg string) {
- log.Printf("Reject delete ‘%s’ by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
-}
func rejectRenameLog(h hyphae.Hypha, u *user.User, errmsg string) {
log.Printf("Reject rename ‘%s’ by @%s: %s\n", h.CanonicalName(), u.Name, errmsg)
}
diff --git a/shroom/mycomarkup_options.go b/shroom/mycomarkup_options.go
new file mode 100644
index 0000000..05595e0
--- /dev/null
+++ b/shroom/mycomarkup_options.go
@@ -0,0 +1,46 @@
+package shroom
+
+import (
+ "errors"
+ "github.com/bouncepaw/mycomarkup/v4/options"
+ "github.com/bouncepaw/mycorrhiza/cfg"
+ "github.com/bouncepaw/mycorrhiza/hyphae"
+ "github.com/bouncepaw/mycorrhiza/views"
+)
+
+func MarkupOptions(hyphaName string) options.Options {
+ return fillMycomarkupOptions(options.Options{
+ HyphaName: hyphaName,
+ WebSiteURL: cfg.URL,
+ TransclusionSupported: true,
+ })
+}
+
+func fillMycomarkupOptions(opts options.Options) options.Options {
+ opts.HyphaExists = func(hyphaName string) bool {
+ switch hyphae.ByName(hyphaName).(type) {
+ case *hyphae.EmptyHypha:
+ return false
+ default:
+ return true
+ }
+ }
+ opts.HyphaHTMLData = func(hyphaName string) (rawText, binaryBlock string, err error) {
+ switch h := hyphae.ByName(hyphaName).(type) {
+ case *hyphae.EmptyHypha:
+ err = errors.New("Hypha " + hyphaName + " does not exist")
+ case *hyphae.TextualHypha:
+ rawText, err = FetchTextFile(h)
+ case *hyphae.MediaHypha:
+ rawText, err = FetchTextFile(h)
+ binaryBlock = views.MediaRaw(h)
+ }
+ return
+ }
+ opts.IterateHyphaNamesWith = func(λ func(string)) {
+ for h := range hyphae.YieldExistingHyphae() {
+ λ(h.CanonicalName())
+ }
+ }
+ return opts.FillTheRest()
+}
diff --git a/shroom/rename.go b/shroom/rename.go
index b232b63..71b4e9c 100644
--- a/shroom/rename.go
+++ b/shroom/rename.go
@@ -3,7 +3,7 @@ package shroom
import (
"errors"
"fmt"
- "github.com/bouncepaw/mycorrhiza/hyphae/backlinks"
+ "github.com/bouncepaw/mycorrhiza/backlinks"
"regexp"
"github.com/bouncepaw/mycorrhiza/history"
diff --git a/shroom/search.go b/shroom/search.go
index 6f6e902..4387abf 100644
--- a/shroom/search.go
+++ b/shroom/search.go
@@ -7,7 +7,7 @@ import (
"github.com/bouncepaw/mycorrhiza/util"
)
-// YieldHyphaNamesContainingString picks hyphae with have a string in their title, sorts and iterates over them.
+// YieldHyphaNamesContainingString picks hyphae with have a string in their title, sorts and iterates over them in alphabetical order.
func YieldHyphaNamesContainingString(query string) <-chan string {
query = util.CanonicalName(strings.TrimSpace(query))
out := make(chan string)
diff --git a/shroom/shroom.go b/shroom/shroom.go
index 6269694..469307c 100644
--- a/shroom/shroom.go
+++ b/shroom/shroom.go
@@ -2,41 +2,3 @@
//
// Some of them are wrappers around functions provided by package hyphae. They manage history for you.
package shroom
-
-import (
- "errors"
-
- "github.com/bouncepaw/mycorrhiza/hyphae"
- "github.com/bouncepaw/mycorrhiza/views"
-
- "github.com/bouncepaw/mycomarkup/v3/globals"
-)
-
-func init() {
- // TODO: clean this complete and utter mess
- globals.HyphaExists = func(hyphaName string) bool {
- switch hyphae.ByName(hyphaName).(type) {
- case *hyphae.EmptyHypha:
- return false
- default:
- return true
- }
- }
- globals.HyphaAccess = func(hyphaName string) (rawText, binaryBlock string, err error) {
- switch h := hyphae.ByName(hyphaName).(type) {
- case *hyphae.EmptyHypha:
- err = errors.New("Hypha " + hyphaName + " does not exist")
- case *hyphae.TextualHypha:
- rawText, err = FetchTextFile(h)
- case *hyphae.MediaHypha:
- rawText, err = FetchTextFile(h)
- binaryBlock = views.MediaRaw(h)
- }
- return
- }
- globals.HyphaIterate = func(λ func(string)) {
- for h := range hyphae.YieldExistingHyphae() {
- λ(h.CanonicalName())
- }
- }
-}
diff --git a/shroom/upload.go b/shroom/upload.go
index 74e2ba5..54d34cf 100644
--- a/shroom/upload.go
+++ b/shroom/upload.go
@@ -4,10 +4,10 @@ import (
"bytes"
"errors"
"fmt"
+ "github.com/bouncepaw/mycorrhiza/backlinks"
"github.com/bouncepaw/mycorrhiza/files"
"github.com/bouncepaw/mycorrhiza/history"
"github.com/bouncepaw/mycorrhiza/hyphae"
- "github.com/bouncepaw/mycorrhiza/hyphae/backlinks"
"github.com/bouncepaw/mycorrhiza/mimetype"
"github.com/bouncepaw/mycorrhiza/user"
"io"
@@ -97,7 +97,7 @@ func UploadText(h hyphae.Hypha, data []byte, userMessage string, u *user.User) e
}
// TODO: that []byte(...) part should be removed
- if bytes.Compare(data, []byte(oldText)) == 0 {
+ if bytes.Equal(data, []byte(oldText)) {
// No changes! Just like cancel button
hop.Abort()
return nil
@@ -118,7 +118,7 @@ func UploadText(h hyphae.Hypha, data []byte, userMessage string, u *user.User) e
}
// TODO: that []byte(...) part should be removed
- if bytes.Compare(data, []byte(oldText)) == 0 {
+ if bytes.Equal(data, []byte(oldText)) {
// No changes! Just like cancel button
hop.Abort()
return nil
diff --git a/util/util.go b/util/util.go
index 66fedd0..9af0361 100644
--- a/util/util.go
+++ b/util/util.go
@@ -8,7 +8,7 @@ import (
"net/http"
"strings"
- "github.com/bouncepaw/mycomarkup/v3/util"
+ "github.com/bouncepaw/mycomarkup/v4/util"
"github.com/bouncepaw/mycorrhiza/cfg"
)
diff --git a/views/about.go b/views/about.go
index e5c2793..7aa29ce 100644
--- a/views/about.go
+++ b/views/about.go
@@ -47,7 +47,7 @@ const aboutTemplateString = `
{{ get .L.Version }} 1.9.0
{{ if .Cfg.UseAuth }}
{{ get .L.UserCount }} {{ .UserCount }}
-
{{ get .L.HomePage }} {{ .Cfg.HomeHypha }}
+
{{ get .L.HomeHypha }} {{ .Cfg.HomeHypha }}
{{ get .L.Admins }} {{$cfg := .Cfg}}{{ range $i, $username := .Admins }}
{{ if gt $i 0 }}, {{ end }}
{{ $username }}
@@ -71,7 +71,7 @@ var aboutData = struct {
"Title": e().en("About %s").ru("О %s"),
"Version": e().en("Mycorrhiza Wiki version:").ru("Версия Микоризы :"),
"UserCount": e().en("User count:").ru("Число пользователей:"),
- "HomePage": e().en("Home page:").ru("Домашняя гифа:"),
+ "HomeHypha": e().en("Home hypha:").ru("Домашняя гифа:"),
"Admins": e().en("Administrators:").ru("Администраторы:"),
"NoAuth": e().en("This wiki does not use authorization").ru("На этой вики не используется авторизация"),
"AboutHyphae": e().en("See /list for information about hyphae on this wiki.").ru("См. /list , чтобы узнать о гифах в этой вики."),
diff --git a/views/admin.go b/views/admin.go
index dd89e2b..f0d9993 100644
--- a/views/admin.go
+++ b/views/admin.go
@@ -2,6 +2,7 @@ package views
import (
"github.com/bouncepaw/mycorrhiza/util"
+ "github.com/bouncepaw/mycorrhiza/viewutil"
"html/template"
"io"
"log"
@@ -25,7 +26,7 @@ var (
adminTemplatesRu *template.Template
)
-func localizedAdminTemplates(meta Meta) *template.Template {
+func localizedAdminTemplates(meta viewutil.Meta) *template.Template {
if meta.Lc.Locale == "ru" {
return adminTemplatesRu
}
@@ -59,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)
+ }
}
diff --git a/views/auth.qtpl b/views/auth.qtpl
index 619d2fd..fc94ec5 100644
--- a/views/auth.qtpl
+++ b/views/auth.qtpl
@@ -1,6 +1,8 @@
{% import "net/http" %}
+{% import "sort" %}
{% import "github.com/bouncepaw/mycorrhiza/cfg" %}
{% import "github.com/bouncepaw/mycorrhiza/l18n" %}
+{% import "github.com/bouncepaw/mycorrhiza/user" %}
{% func Register(rq *http.Request) %}
{% code
@@ -148,3 +150,63 @@ Telegram auth widget was requested by Yogurt. As you can see, we don't offer use