diff --git a/cfg/config.go b/cfg/config.go index fbe0107..d47ca38 100644 --- a/cfg/config.go +++ b/cfg/config.go @@ -6,6 +6,8 @@ import ( "log" "os" "path/filepath" + + "github.com/bouncepaw/mycorrhiza/plugin/lang" ) type MyceliumConfig struct { @@ -23,20 +25,18 @@ const ( ) var ( - DescribeHyphaHerePattern = "Describe %s here" - WikiDir string - configJsonPath string + Locale map[string]string + WikiDir string + configJsonPath string // Default values that can be overriden in config.json - Address = "0.0.0.0:80" - TitleEditTemplate = `Edit %s` - TitleTemplate = `%s` - GenericErrorMsg = `Sorry, something went wrong` - SiteTitle = `MycorrhizaWiki` - Theme = `default-light` - HomePage = `/Home` - BinaryLimit int64 = 10 << 20 - Mycelia = []MyceliumConfig{ + Address = "0.0.0.0:80" + LocaleName = "en" + SiteTitle = `MycorrhizaWiki` + Theme = `default-light` + HomePage = `/Home` + BinaryLimit int64 = 10 << 20 + Mycelia = []MyceliumConfig{ {[]string{"main"}, "main"}, {[]string{"sys", "system"}, "system"}, } @@ -63,16 +63,13 @@ func readConfig() bool { } cfg := struct { - Address string `json:"address"` - Theme string `json:"theme"` - SiteTitle string `json:"site-title"` - HomePage string `json:"home-page"` - BinaryLimitMB int64 `json:"binary-limit-mb"` - Mycelia []MyceliumConfig `json:"mycelia"` - TitleTemplates struct { - EditHypha string `json:"edit-hypha"` - ViewHypha string `json:"view-hypha"` - } `json:"title-templates"` + Address string `json:"address"` + Theme string `json:"theme"` + SiteTitle string `json:"site-title"` + HomePage string `json:"home-page"` + BinaryLimitMB int64 `json:"binary-limit-mb"` + LocaleName string `json:"locale"` + Mycelia []MyceliumConfig `json:"mycelia"` }{} err = json.Unmarshal(configJsonContents, &cfg) @@ -84,11 +81,16 @@ func readConfig() bool { Address = cfg.Address Theme = cfg.Theme SiteTitle = cfg.SiteTitle - TitleEditTemplate = cfg.TitleTemplates.EditHypha - TitleTemplate = cfg.TitleTemplates.ViewHypha HomePage = "/" + cfg.HomePage BinaryLimit = 1024 * cfg.BinaryLimitMB Mycelia = cfg.Mycelia + switch cfg.LocaleName { + case "en": + Locale = lang.EnglishMap + default: + Locale = lang.EnglishMap + } + return true } diff --git a/fs/data.go b/fs/data.go index 58b7264..15599cf 100644 --- a/fs/data.go +++ b/fs/data.go @@ -82,5 +82,5 @@ func (h *Hypha) TextContent() string { } return string(contents) } - return fmt.Sprintf(cfg.DescribeHyphaHerePattern, h.FullName) + return fmt.Sprintf(cfg.Locale["edit/box/help pattern"], h.FullName) } diff --git a/main.go b/main.go index dbd2fe1..d2eb2b1 100644 --- a/main.go +++ b/main.go @@ -60,7 +60,7 @@ func main() { r := mux.NewRouter() r.HandleFunc("/favicon.ico", func(w http.ResponseWriter, rq *http.Request) { - http.ServeFile(w, rq, filepath.Join(filepath.Dir(cfg.WikiDir), "favicon.ico")) + http.ServeFile(w, rq, filepath.Join(cfg.WikiDir, "favicon.ico")) }) IdempotentRouterBoiler(r, "binary", HandlerBinary) diff --git a/plugin/lang/en.go b/plugin/lang/en.go new file mode 100644 index 0000000..049c38b --- /dev/null +++ b/plugin/lang/en.go @@ -0,0 +1,31 @@ +package lang + +var EnglishMap = map[string]string{ + "edit hypha title template": "Edit %s at MycorrhizaWiki", + "view hypha title template": "%s at MycorrhizaWiki", + "this site runs myco wiki": `

This website runs MycorrhizaWiki

`, + "generic error msg": `Sorry, something went wrong`, + + "edit/text mime type": "Text MIME-type", + "edit/text mime type/tip": "We support text/markdown, text/creole and text/gemini", + + "edit/revision comment": "Revision comment", + "edit/revision comment/tip": "Please make your comment helpful", + "edit/revision comment/new": "Create %s", + "edit/revision comment/old": "Update %s", + + "edit/tags": "Edit tags", + "edit/tags/tip": "Tags are separated by commas, whitespace is ignored", + + "edit/upload file": "Upload file", + "edit/upload file/tip": "Only images are fully supported for now", + + "edit/box": "Edit box", + "edit/box/title": "Edit %s", + "edit/box/help pattern": "Describe %s here", + + "edit/cancel": "Cancel", + + "update ok/title": "Saved %s", + "update ok/msg": "Saved successfully. Go back", +} diff --git a/render/render.go b/render/render.go index 095dff5..6ac8a58 100644 --- a/render/render.go +++ b/render/render.go @@ -11,59 +11,59 @@ import ( "github.com/bouncepaw/mycorrhiza/mycelium" ) +func titleTemplateView(name string) string { + return fmt.Sprintf(cfg.Locale["view hypha title template"], name) +} + // HyphaEdit renders hypha editor. func HyphaEdit(h *fs.Hypha) []byte { // - hyphaData := map[string]string{ + hyphaData := map[string]interface{}{ "Name": h.FullName, "Tags": h.TagsJoined(), "TextMime": h.TextMime(), "Text": h.TextContent(), + "Locale": cfg.Locale, } return layout("edit/index"). withMap(hyphaData). wrapInBase(map[string]string{ - "Title": fmt.Sprintf(cfg.TitleEditTemplate, h.FullName), + "Title": fmt.Sprintf(cfg.Locale["edit hypha title template"], h.FullName), }) } // HyphaUpdateOk is used to inform that update was successful. func HyphaUpdateOk(h *fs.Hypha) []byte { // return layout("update_ok"). - withMap(map[string]string{"Name": h.FullName}). + withMap(map[string]interface{}{ + "Name": h.FullName, + "Locale": cfg.Locale, + }). Bytes() } // Hypha404 renders 404 page for nonexistent page. func Hypha404(name, _ string) []byte { return layout("view/404"). - withMap(map[string]string{ + withMap(map[string]interface{}{ "PageTitle": name, "Tree": hyphaTree(name), + "Locale": cfg.Locale, }). wrapInBase(map[string]string{ - "Title": fmt.Sprintf(cfg.TitleTemplate, name), + "Title": titleTemplateView(name), }) } // HyphaPage renders hypha viewer. func HyphaPage(name, content string) []byte { return layout("view/index"). - withMap(map[string]string{ + withMap(map[string]interface{}{ "Content": content, "Tree": hyphaTree(name), + "Locale": cfg.Locale, }). wrapInBase(map[string]string{ - "Title": fmt.Sprintf(cfg.TitleTemplate, name), - }) -} - -// hyphaGeneric is used when building renderers for all types of hypha pages -func hyphaGeneric(name, content, templateName string) []byte { - return layout(templateName). - withString(content). - wrapInBase(map[string]string{ - "Title": fmt.Sprintf(cfg.TitleTemplate, name), - "Sidebar": hyphaTree(name), + "Title": titleTemplateView(name), }) } @@ -72,9 +72,10 @@ func (lyt *Layout) wrapInBase(keys map[string]string) []byte { if lyt.invalid { return lyt.Bytes() } - page := map[string]string{ - "Title": cfg.SiteTitle, + page := map[string]interface{}{ "Content": lyt.String(), + "Locale": cfg.Locale, + "Title": cfg.SiteTitle, "SiteTitle": cfg.SiteTitle, } for key, val := range keys { @@ -122,7 +123,7 @@ func (lyt *Layout) withString(data string) *Layout { return lyt } -func (lyt *Layout) withMap(data map[string]string) *Layout { +func (lyt *Layout) withMap(data map[string]interface{}) *Layout { if lyt.invalid { return lyt } diff --git a/wiki/config.json b/wiki/config.json index 3d41bce..67c2da8 100644 --- a/wiki/config.json +++ b/wiki/config.json @@ -4,10 +4,7 @@ "site-title": "🍄 MycorrhizaWiki", "home-page": "Home", "binary-limit-mb": 10, - "title-templates": { - "edit-hypha": "Edit %s at MycorrhizaWiki", - "view-hypha": "%s at MycorrhizaWiki" - }, + "locale": "en", "mycelia": [ { "names": ["main"], diff --git a/wiki/main/doc/plugin/3.markdown b/wiki/main/doc/plugin/3.markdown new file mode 100644 index 0000000..702f628 --- /dev/null +++ b/wiki/main/doc/plugin/3.markdown @@ -0,0 +1,27 @@ +# Plugin system RFC +MycorrhizaWiki engine does not provide all the functionality a wiki may need and not need. Instead, it relies on the system of plugins. + +This document is up-to-date. + +## Types of plugins +- **Parser.** They add support for displaying different MIME-types. +- **Language.** They provide i18n support. + +## Default plugins +Default MycorrhizaWiki distributive is shipped with several plugins installed. + +- **parser/markdown.** Support for `text/markdown`. This parser is powered by [russross/blackfriday](https://github.com/russross/blackfriday); this parser is ok, I guess. +- **parser/creole.** Support for `text/creole`. *Note:* there is no standard Creole MIME type. This parser is powered by [m4tty/cajun](https://github.com/m4tty/cajun); this library is somewhat outdated. Perhaps we'll reimplement it. +- **parser/gemini.** Support for `text/gemini`. +- **language/en.** Support for English language. + +## Plugin implementation +All plugins are written in Go and are compiled together with MycorrhizaWiki. If a wiki's admin decides to add a plugin, they shall recompile the engine with the plugin. + +> Reminds of [something](http://suckless.org/), right? + +*But compiling the engine just to add a plugin is stupid!!* Not really. Also, it makes the architecture more simple and secure. + +*What if an admin doesn't know how to program?* Plugin installation is basically limited to putting some files into a folder, editing the config and running a shell command. No programming required to install a plugin. + +See `plugin` directory at the root of the repo to get inspired by the present parsers. diff --git a/wiki/main/doc/plugin/4.markdown b/wiki/main/doc/plugin/4.markdown new file mode 100644 index 0000000..961a49b --- /dev/null +++ b/wiki/main/doc/plugin/4.markdown @@ -0,0 +1,27 @@ +# Plugin system RFC +MycorrhizaWiki engine does not provide all the functionality a wiki may need and not need. Instead, it relies on the system of plugins. + +This document is up-to-date. + +## Types of plugins +- **Parser.** They add support for displaying different MIME-types. +- **Language.** They provide i18n support. + +## Default plugins +Default MycorrhizaWiki distributive is shipped with several plugins installed. + +- **parser/markdown.** Support for `text/markdown`. This parser is powered by [russross/blackfriday](https://github.com/russross/blackfriday); this parser is ok, I guess. +- **parser/creole.** Support for `text/creole`. *Note:* there is no standard Creole MIME type. This parser is powered by [m4tty/cajun](https://github.com/m4tty/cajun); this library is somewhat outdated. Perhaps we'll reimplement it. +- **parser/gemini.** Support for `text/gemini`. +- **lang/en.** Support for English language. + +## Plugin implementation +All plugins are written in Go and are compiled together with MycorrhizaWiki. If a wiki's admin decides to add a plugin, they shall recompile the engine with the plugin. + +> Reminds of [something](http://suckless.org/), right? + +*But compiling the engine just to add a plugin is stupid!!* Not really. Also, it makes the architecture more simple and secure. + +*What if an admin doesn't know how to program?* Plugin installation is basically limited to putting some files into a folder, editing the config and running a shell command. No programming required to install a plugin. + +See `plugin` directory at the root of the repo to get inspired by the present parsers. diff --git a/wiki/main/doc/plugin/5.markdown b/wiki/main/doc/plugin/5.markdown new file mode 100644 index 0000000..44b04e4 --- /dev/null +++ b/wiki/main/doc/plugin/5.markdown @@ -0,0 +1,32 @@ +# Plugin system RFC +MycorrhizaWiki engine does not provide all the functionality a wiki may need and not need. Instead, it relies on the system of plugins. + +This document is up-to-date. + +## Types of plugins +- **Parser.** They add support for displaying different MIME-types. +- **Language.** They provide i18n support. + +## Default plugins +Default MycorrhizaWiki distributive is shipped with several plugins installed. + +- **parser/markdown.** Support for `text/markdown`. This parser is powered by [russross/blackfriday](https://github.com/russross/blackfriday); this parser is ok, I guess. +- **parser/creole.** Support for `text/creole`. *Note:* there is no standard Creole MIME type. This parser is powered by [m4tty/cajun](https://github.com/m4tty/cajun); this library is somewhat outdated. Perhaps we'll reimplement it. +- **parser/gemini.** Support for `text/gemini`. +- **lang/en.** Support for English language. + +## Plugin implementation +All plugins are written in Go and are compiled together with MycorrhizaWiki. If a wiki's admin decides to add a plugin, they shall recompile the engine with the plugin. + +> Reminds of [something](http://suckless.org/), right? + +*But compiling the engine just to add a plugin is stupid!!* Not really. Also, it makes the architecture more simple and secure. + +*What if an admin doesn't know how to program?* Plugin installation is basically limited to putting some files into a folder, editing the config and running a shell command. No programming required to install a plugin. + +See `plugin` directory at the root of the repo to get inspired by the present parsers. + +## Possible future plugins +- **Utilites.** Plugins that can do different things and provide their own hypha interface in `:spec` mycelium. +- **Macros.** Dynamic content parts that are generated when page is accessed: TOC, meta information accessors, etc. + diff --git a/wiki/main/doc/plugin/6.markdown b/wiki/main/doc/plugin/6.markdown new file mode 100644 index 0000000..44b04e4 --- /dev/null +++ b/wiki/main/doc/plugin/6.markdown @@ -0,0 +1,32 @@ +# Plugin system RFC +MycorrhizaWiki engine does not provide all the functionality a wiki may need and not need. Instead, it relies on the system of plugins. + +This document is up-to-date. + +## Types of plugins +- **Parser.** They add support for displaying different MIME-types. +- **Language.** They provide i18n support. + +## Default plugins +Default MycorrhizaWiki distributive is shipped with several plugins installed. + +- **parser/markdown.** Support for `text/markdown`. This parser is powered by [russross/blackfriday](https://github.com/russross/blackfriday); this parser is ok, I guess. +- **parser/creole.** Support for `text/creole`. *Note:* there is no standard Creole MIME type. This parser is powered by [m4tty/cajun](https://github.com/m4tty/cajun); this library is somewhat outdated. Perhaps we'll reimplement it. +- **parser/gemini.** Support for `text/gemini`. +- **lang/en.** Support for English language. + +## Plugin implementation +All plugins are written in Go and are compiled together with MycorrhizaWiki. If a wiki's admin decides to add a plugin, they shall recompile the engine with the plugin. + +> Reminds of [something](http://suckless.org/), right? + +*But compiling the engine just to add a plugin is stupid!!* Not really. Also, it makes the architecture more simple and secure. + +*What if an admin doesn't know how to program?* Plugin installation is basically limited to putting some files into a folder, editing the config and running a shell command. No programming required to install a plugin. + +See `plugin` directory at the root of the repo to get inspired by the present parsers. + +## Possible future plugins +- **Utilites.** Plugins that can do different things and provide their own hypha interface in `:spec` mycelium. +- **Macros.** Dynamic content parts that are generated when page is accessed: TOC, meta information accessors, etc. + diff --git a/wiki/main/doc/plugin/meta.json b/wiki/main/doc/plugin/meta.json index e2f04b5..ccfb082 100644 --- a/wiki/main/doc/plugin/meta.json +++ b/wiki/main/doc/plugin/meta.json @@ -27,6 +27,58 @@ "binary_mime": "", "text_name": "2.markdown", "binary_name": "" + }, + "3": { + "tags": [ + "" + ], + "name": "Plugin", + "comment": "Update :Main/Doc/Plugin", + "author": "", + "time": 1594999571, + "text_mime": "text/markdown", + "binary_mime": "", + "text_name": "3.markdown", + "binary_name": "" + }, + "4": { + "tags": [ + "" + ], + "name": "Plugin", + "comment": "Update :Main/Doc/Plugin", + "author": "", + "time": 1595001530, + "text_mime": "text/markdown", + "binary_mime": "", + "text_name": "4.markdown", + "binary_name": "" + }, + "5": { + "tags": [ + "" + ], + "name": "Plugin", + "comment": "Update :Main/Doc/Plugin", + "author": "", + "time": 1595092102, + "text_mime": "text/markdown", + "binary_mime": "", + "text_name": "5.markdown", + "binary_name": "" + }, + "6": { + "tags": [ + "" + ], + "name": "Plugin", + "comment": "Update :Main/Doc/Plugin", + "author": "", + "time": 1595092219, + "text_mime": "text/markdown", + "binary_mime": "", + "text_name": "6.markdown", + "binary_name": "" } } } \ No newline at end of file diff --git a/wiki/main/doc/user/1.txt b/wiki/main/doc/user/1.txt new file mode 100644 index 0000000..472bd33 --- /dev/null +++ b/wiki/main/doc/user/1.txt @@ -0,0 +1,7 @@ +Unlike earliest wiki engines, MycorrhizaWiki supports authorization system and non-authorized edits are disabled by default. Anyone can get an account on a MycorrhizaWiki wiki by signing up. There must be a form for that. + +* Each user is part of one or more user groups. +* Each user has a username. Usernames follow the same naming conventions as hyphae but additionally the forward slash / character is prohibited in usernames. Please note that usernames are case-insensitive, thus //shroom// and //Shroom// mean the same; spaces and underscores are also the same, //amanita muscaria// = //amanita_muscaria//. +* Password chosen by the user is not directly stored on the server. Only its hash is salted so even if a server is hacked, a hacker won't get the passwords. There are no restrictions on passwords. Server administrator doesn't have access to the password as well. +* Each user gets their own hypha in the //:user// mycelium. The hypha has the same name as the user. Subhyphae can also be added. +* If an authenticated user makes an edit, the fact that they have made the edit is stored in the revision history. diff --git a/wiki/main/doc/user/2.txt b/wiki/main/doc/user/2.txt new file mode 100644 index 0000000..98c4781 --- /dev/null +++ b/wiki/main/doc/user/2.txt @@ -0,0 +1,9 @@ +This document is not up-to-date. Information here will be true once we finish its development :) + +Unlike earliest wiki engines, MycorrhizaWiki supports authorization system and non-authorized edits are disabled by default. Anyone can get an account on a MycorrhizaWiki wiki by signing up. There must be a form for that. + +* Each user is part of one or more user groups. +* Each user has a username. Usernames follow the same naming conventions as hyphae but additionally the forward slash / character is prohibited in usernames. Please note that usernames are case-insensitive, thus //shroom// and //Shroom// mean the same; spaces and underscores are also the same, //amanita muscaria// = //amanita_muscaria//. +* Password chosen by the user is not directly stored on the server. Only its hash is salted so even if a server is hacked, a hacker won't get the passwords. There are no restrictions on passwords. Server administrator doesn't have access to the password as well. +* Each user gets their own hypha in the //:user// mycelium. The hypha has the same name as the user. Subhyphae can also be added. +* If an authenticated user makes an edit, the fact that they have made the edit is stored in the revision history. diff --git a/wiki/main/doc/user/meta.json b/wiki/main/doc/user/meta.json new file mode 100644 index 0000000..0ee761d --- /dev/null +++ b/wiki/main/doc/user/meta.json @@ -0,0 +1,32 @@ +{ + "views": 0, + "deleted": false, + "revisions": { + "1": { + "tags": [ + "" + ], + "name": "User", + "comment": "Update :Main/Doc/User", + "author": "", + "time": 1594749111, + "text_mime": "text/creole", + "binary_mime": "", + "text_name": "1.txt", + "binary_name": "" + }, + "2": { + "tags": [ + "" + ], + "name": "User", + "comment": "Update :Main/Doc/User", + "author": "", + "time": 1595092543, + "text_mime": "text/creole", + "binary_mime": "", + "text_name": "2.txt", + "binary_name": "" + } + } +} \ No newline at end of file diff --git a/wiki/main/doc/wikilink/3.markdown b/wiki/main/doc/wikilink/3.markdown new file mode 100644 index 0000000..28598d7 --- /dev/null +++ b/wiki/main/doc/wikilink/3.markdown @@ -0,0 +1,51 @@ +# Wikilink RFC + +*This page is not up-to-date. One day, features defined here shall be implemented.* + +All parsers for MycorrhizaWiki provide hyperlink support. Usually, they follow HTML convention. + +- `http://example.org/absolute-path` +- `/rooted-path` +- `same-folder-path` +- `../parent-folder-path` + +This is not really convenient for wikis where most of links are either rooted or links to children! + +All parsers of MycorrhizaWiki are expected to support these types of links and convert them to rooted paths. + +- `http://example.org/absolute-path` +- `hypha in main mycelium` +- `::hypha in the same mycelium` +- `:mycelium/hypha in an explicit mycelium` +- `/subhypha` +- `./subhypha` +- `../sibling-hypha` + +**TODO:** create a package that implements this thing. NB: to generate a correct link, it is required to know full name of hypha where the link is used. + +## Markdown extension + +> This is an extension to markdown's syntax that is used in MycorrhizaWiki and nowhere else. + +Text wrapped in `[[` and `]]` is a link that has same text and url. *For some reason it's not possible in Markdown without duplicating url* + +``` +[[x]] == [x](x) +``` + +## Examples + +All examples assume that `:example/test` is the current hypha. + +``` +wikilink actual path +foo == /foo +::foo == /:example/foo +:bar/foo == /:bar/foo +/baz == /:example/test/baz +./baz == /:example/test/baz +../qux == /:example/qux +http://example.org == http://example.org +gemini://example.org == gemini://example.org +mailto:me@example.org == mailto:me@example.org +``` diff --git a/wiki/main/doc/wikilink/meta.json b/wiki/main/doc/wikilink/meta.json index 7b2f55e..09c4ea1 100644 --- a/wiki/main/doc/wikilink/meta.json +++ b/wiki/main/doc/wikilink/meta.json @@ -27,6 +27,19 @@ "binary_mime": "", "text_name": "2.markdown", "binary_name": "" + }, + "3": { + "tags": [ + "" + ], + "name": "Wikilink", + "comment": "Update :Main/Doc/Wikilink", + "author": "", + "time": 1595092265, + "text_mime": "text/markdown", + "binary_mime": "", + "text_name": "3.markdown", + "binary_name": "" } } } \ No newline at end of file diff --git a/wiki/sys/theme/default-light/base.html/1.html b/wiki/sys/theme/default-light/base.html/1.html index 07d5cbf..511eed0 100644 --- a/wiki/sys/theme/default-light/base.html/1.html +++ b/wiki/sys/theme/default-light/base.html/1.html @@ -17,7 +17,7 @@ {{ .Content }} diff --git a/wiki/sys/theme/default-light/edit/index.html/1.html b/wiki/sys/theme/default-light/edit/index.html/1.html index 080e1a5..db331e8 100644 --- a/wiki/sys/theme/default-light/edit/index.html/1.html +++ b/wiki/sys/theme/default-light/edit/index.html/1.html @@ -5,38 +5,39 @@ id="edit-form">
-

Edit {{ .Name }}

+

{{printf (index .Locale "edit/box/title") .Name}}

- Edit box + {{index .Locale "edit/box"}}
diff --git a/wiki/sys/theme/default-light/update_ok.html/1.html b/wiki/sys/theme/default-light/update_ok.html/1.html index 4d5854c..4805dac 100644 --- a/wiki/sys/theme/default-light/update_ok.html/1.html +++ b/wiki/sys/theme/default-light/update_ok.html/1.html @@ -1,9 +1,9 @@ - Saved {{ .Name }} + {{printf (index .Locale "update ok/title") .Name}} -

Saved successfully. Go back

+

{{printf (index .Locale "update ok/msg") .Name}}