diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 5154f76..304a7ba 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -2,5 +2,9 @@
+
+
+
+
\ No newline at end of file
diff --git a/cfg/config.go b/cfg/config.go
index 09f4088..e1671be 100644
--- a/cfg/config.go
+++ b/cfg/config.go
@@ -1,3 +1,4 @@
+// Package cfg contains global variables that represent the current wiki configuration, including CLI options, configuration file values and header links.
package cfg
import (
@@ -8,6 +9,9 @@ import (
"github.com/go-ini/ini"
)
+// These variables represent the configuration. You are not meant to modify them after they were set.
+//
+// See https://mycorrhiza.lesarbr.es/hypha/configuration/fields for their docs.
var (
WikiName string
NaviTitleIcon string
@@ -20,9 +24,6 @@ var (
URL string
GeminiCertificatePath string
- WikiDir string
- ConfigFilePath string
-
UseFixedAuth bool
FixedAuthCredentialsPath string
UseRegistration bool
@@ -30,9 +31,15 @@ var (
LimitRegistration int
)
-// Config represents a Mycorrhiza wiki configuration file.
-//
-// See https://mycorrhiza.lesarbr.es/hypha/configuration/fields for fields' docs.
+// These variables are set before reading the config file, they are set in main.parseCliArgs.
+var (
+ // WikiDir is a full path to the wiki storage directory, which also must be a git repo.
+ WikiDir string
+ // ConfigFilePath is a path to the config file. Its value is used when calling ReadConfigFile.
+ ConfigFilePath string
+)
+
+// Config represents a Mycorrhiza wiki configuration file. This type is used only when reading configs.
type Config struct {
WikiName string
NaviTitleIcon string
@@ -65,8 +72,10 @@ type Authorization struct {
LimitRegistration uint64
}
-// ReadConfigFile reads a config on the given path and stores the configuration.
-func ReadConfigFile(path string) {
+// ReadConfigFile reads a config on the given path and stores the configuration. Call it sometime during the initialization.
+//
+// Note that it may log.Fatal.
+func ReadConfigFile() {
cfg := &Config{
WikiName: "MycorrhizaWiki",
NaviTitleIcon: "馃崉",
@@ -90,8 +99,8 @@ func ReadConfigFile(path string) {
},
}
- if path != "" {
- path, err := filepath.Abs(path)
+ if ConfigFilePath != "" {
+ path, err := filepath.Abs(ConfigFilePath)
if err != nil {
log.Fatalf("cannot expand config file path: %s", err)
}
@@ -117,4 +126,9 @@ func ReadConfigFile(path string) {
UseRegistration = cfg.UseRegistration
RegistrationCredentialsPath = cfg.RegistrationCredentialsPath
LimitRegistration = int(cfg.LimitRegistration)
+
+ // This URL makes much more sense.
+ if URL == "" {
+ URL = "http://0.0.0.0:" + HTTPPort
+ }
}
diff --git a/cfg/header_links.go b/cfg/header_links.go
new file mode 100644
index 0000000..7afb3f6
--- /dev/null
+++ b/cfg/header_links.go
@@ -0,0 +1,48 @@
+package cfg
+
+// See https://mycorrhiza.lesarbr.es/hypha/configuration/header
+import (
+ "strings"
+)
+
+// 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.
+var HeaderLinks []HeaderLink
+
+// SetDefaultHeaderLinks sets the header links to the default list of: home hypha, recent changes, hyphae list, random hypha.
+func SetDefaultHeaderLinks() {
+ HeaderLinks = []HeaderLink{
+ {"/", WikiName},
+ {"/recent-changes", "Recent changes"},
+ {"/list", "All hyphae"},
+ {"/random", "Random"},
+ }
+}
+
+// ParseHeaderLinks extracts all rocketlinks from the given text and saves them as header links. rocketlink位 must be set to markup.Rocketlink. You have to pass it like that to avoid cyclical dependency.
+func ParseHeaderLinks(text string, rocketlink位 func(string, string) (string, string, string)) {
+ HeaderLinks = []HeaderLink{}
+ for _, line := range strings.Split(text, "\n") {
+ // There is a false positive when parsing markup like that:
+ //
+ // ```
+ // => this is not a link, it is part of the preformatted block
+ // ```
+ //
+ // I do not really care.
+ if strings.HasPrefix(line, "=>") {
+ href, display, _ := rocketlink位(line, HeaderLinksHypha)
+ HeaderLinks = append(HeaderLinks, HeaderLink{
+ Href: href,
+ Display: display,
+ })
+ }
+ }
+}
+
+// HeaderLink represents a header link. Header links are the links shown in the top gray bar.
+type HeaderLink struct {
+ // Href is the URL of the link. It goes ....
+ Href string
+ // Display is what is shown when the link is rendered. It goes here.
+ Display string
+}
diff --git a/files/files.go b/files/files.go
index 634cc16..740041b 100644
--- a/files/files.go
+++ b/files/files.go
@@ -1,3 +1,4 @@
+// Package files is used to get paths to different files Mycorrhiza uses. Also see cfg.
package files
import (
@@ -17,9 +18,20 @@ var paths struct {
fixedCredentialsJSON string
}
-func TokensJSON() string { return paths.tokensJSON }
+// TokensJSON returns a path to the JSON file where users' tokens are stored.
+//
+// Default path: $XDG_DATA_HOME/mycorrhiza/tokens.json
+func TokensJSON() string { return paths.tokensJSON }
+
+// RegistrationCredentialsJSON returns a path to the JSON file where registration credentials are stored.
+//
+// Default path: $XDG_DATA_HOME/mycorrhiza/registration.json
func RegistrationCredentialsJSON() string { return paths.registrationCredentialsJSON }
-func FixedCredentialsJSON() string { return paths.fixedCredentialsJSON }
+
+// FixedCredentialsJSON returns a path to the JSON file where fixed credentials are stored.
+//
+// There is no default path.
+func FixedCredentialsJSON() string { return paths.fixedCredentialsJSON }
// CalculatePaths looks for all external paths and stores them. Tries its best to find any errors. It is safe it to call it multiple times in order to save new paths.
func CalculatePaths() error {
diff --git a/flag.go b/flag.go
index d801d3d..19c69d6 100644
--- a/flag.go
+++ b/flag.go
@@ -9,25 +9,32 @@ import (
"path/filepath"
"github.com/bouncepaw/mycorrhiza/assets"
- "github.com/bouncepaw/mycorrhiza/util"
)
+// CLI options are read and parsed here.
+
var printExampleConfig bool
func init() {
flag.StringVar(&cfg.ConfigFilePath, "config-path", "", "Path to a configuration file. Leave empty if you don't want to use it.")
flag.BoolVar(&printExampleConfig, "print-example-config", false, "If true, print an example configuration file contents and exit. You can save the output to a file and base your own configuration on it.")
- flag.Usage = func() {
- fmt.Fprintf(
- flag.CommandLine.Output(),
- assets.HelpMessage(),
- os.Args[0],
- )
- flag.PrintDefaults()
- }
+ flag.Usage = printHelp
}
-// Do the things related to cli args and die maybe
+// printHelp prints the help message. The help message is stored in assets.
+func printHelp() {
+ _, err := fmt.Fprintf(
+ flag.CommandLine.Output(),
+ assets.HelpMessage(),
+ os.Args[0],
+ )
+ if err != nil {
+ log.Fatal(err)
+ }
+ flag.PrintDefaults()
+}
+
+// parseCliArgs parses CLI options and sets several important global variables. Call it early.
func parseCliArgs() {
flag.Parse()
@@ -46,12 +53,4 @@ func parseCliArgs() {
if err != nil {
log.Fatal(err)
}
-
- if cfg.URL == "" {
- cfg.URL = "http://0.0.0.0:" + cfg.HTTPPort
- }
-
- cfg.HomeHypha = util.CanonicalName(cfg.HomeHypha)
- cfg.UserHypha = util.CanonicalName(cfg.UserHypha)
- cfg.HeaderLinksHypha = util.CanonicalName(cfg.HeaderLinksHypha)
}
diff --git a/gemini.go b/gemini.go
index 050edc1..8cbd6df 100644
--- a/gemini.go
+++ b/gemini.go
@@ -1,29 +1,37 @@
package main
+// Gemini-related stuff. This is currently a proof-of-concept implementation, no one really uses it.
+// Maybe we should deprecate it until we find power to do it properly?
+//
+// When this stuff gets more serious, a separate module will be needed.
+
import (
"crypto/tls"
"crypto/x509/pkix"
- "github.com/bouncepaw/mycorrhiza/cfg"
+ "io"
"io/ioutil"
"log"
"path/filepath"
+ "strings"
"time"
"git.sr.ht/~adnano/go-gemini"
"git.sr.ht/~adnano/go-gemini/certificate"
+ "github.com/bouncepaw/mycorrhiza/cfg"
"github.com/bouncepaw/mycorrhiza/hyphae"
"github.com/bouncepaw/mycorrhiza/markup"
+ "github.com/bouncepaw/mycorrhiza/util"
)
func geminiHomeHypha(w *gemini.ResponseWriter, rq *gemini.Request) {
log.Println(rq.URL)
- w.Write([]byte(`# MycorrhizaWiki
+ _, _ = io.WriteString(w, `# MycorrhizaWiki
You have successfully served the wiki through Gemini. Currently, support is really work-in-progress; you should resort to using Mycorrhiza through the web protocols.
Visit home hypha:
-=> /hypha/` + cfg.HomeHypha))
+=> /hypha/`+cfg.HomeHypha)
}
func geminiHypha(w *gemini.ResponseWriter, rq *gemini.Request) {
@@ -42,9 +50,9 @@ func geminiHypha(w *gemini.ResponseWriter, rq *gemini.Request) {
}
}
if hasAmnt {
- w.Write([]byte("This hypha has an attachment\n"))
+ _, _ = io.WriteString(w, "This hypha has an attachment\n")
}
- w.Write([]byte(contents))
+ _, _ = io.WriteString(w, contents)
}
func handleGemini() {
@@ -82,3 +90,15 @@ func handleGemini() {
log.Fatal(err)
}
}
+
+// geminiHyphaNameFromRq extracts hypha name from gemini request. You have to also pass the action which is embedded in the url or several actions. For url /hypha/hypha, the action would be "hypha".
+func geminiHyphaNameFromRq(rq *gemini.Request, actions ...string) string {
+ p := rq.URL.Path
+ for _, action := range actions {
+ if strings.HasPrefix(p, "/"+action+"/") {
+ return util.CanonicalName(strings.TrimPrefix(p, "/"+action+"/"))
+ }
+ }
+ log.Fatal("HyphaNameFromRq: no matching action passed")
+ return ""
+}
diff --git a/main.go b/main.go
index 8f08ee6..c6352cf 100644
--- a/main.go
+++ b/main.go
@@ -2,6 +2,7 @@
//go:generate qtc -dir=assets
//go:generate qtc -dir=views
//go:generate qtc -dir=tree
+// Command mycorrhiza is a program that runs a mycorrhiza wiki.
package main
import (
@@ -21,7 +22,7 @@ func main() {
parseCliArgs()
// It is ok if the path is ""
- cfg.ReadConfigFile(cfg.ConfigFilePath)
+ cfg.ReadConfigFile()
if err := files.CalculatePaths(); err != nil {
log.Fatal(err)
diff --git a/name.go b/name.go
deleted file mode 100644
index f05a44f..0000000
--- a/name.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package main
-
-import (
- "log"
- "strings"
-
- "git.sr.ht/~adnano/go-gemini"
-
- "github.com/bouncepaw/mycorrhiza/util"
-)
-
-// geminiHyphaNameFromRq extracts hypha name from gemini request. You have to also pass the action which is embedded in the url or several actions. For url /hypha/hypha, the action would be "hypha".
-func geminiHyphaNameFromRq(rq *gemini.Request, actions ...string) string {
- p := rq.URL.Path
- for _, action := range actions {
- if strings.HasPrefix(p, "/"+action+"/") {
- return util.CanonicalName(strings.TrimPrefix(p, "/"+action+"/"))
- }
- }
- log.Fatal("HyphaNameFromRq: no matching action passed")
- return ""
-}
diff --git a/shroom/view.go b/shroom/view.go
index b00bf75..52879c6 100644
--- a/shroom/view.go
+++ b/shroom/view.go
@@ -7,7 +7,6 @@ import (
"github.com/bouncepaw/mycorrhiza/hyphae"
"github.com/bouncepaw/mycorrhiza/markup"
- "github.com/bouncepaw/mycorrhiza/util"
)
// FetchTextPart tries to read text file of the given hypha. If there is no file, empty string is returned.
@@ -26,14 +25,14 @@ func FetchTextPart(h *hyphae.Hypha) (string, error) {
func SetHeaderLinks() {
if userLinksHypha := hyphae.ByName(cfg.HeaderLinksHypha); !userLinksHypha.Exists {
- util.SetDefaultHeaderLinks()
+ cfg.SetDefaultHeaderLinks()
} else {
contents, err := ioutil.ReadFile(userLinksHypha.TextPath)
if err != nil || len(contents) == 0 {
- util.SetDefaultHeaderLinks()
+ cfg.SetDefaultHeaderLinks()
} else {
text := string(contents)
- util.ParseHeaderLinks(text, markup.Rocketlink)
+ cfg.ParseHeaderLinks(text, markup.Rocketlink)
}
}
}
diff --git a/util/header_links.go b/util/header_links.go
deleted file mode 100644
index bc942c7..0000000
--- a/util/header_links.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package util
-
-import (
- "github.com/bouncepaw/mycorrhiza/cfg"
- "strings"
-)
-
-func SetDefaultHeaderLinks() {
- HeaderLinks = []HeaderLink{
- {"/", cfg.WikiName},
- {"/recent-changes", "Recent changes"},
- {"/list", "All hyphae"},
- {"/random", "Random"},
- }
-}
-
-// rocketlink位 is markup.Rocketlink. You have to pass it like that to avoid cyclical dependency.
-func ParseHeaderLinks(text string, rocketlink位 func(string, string) (string, string, string)) {
- HeaderLinks = []HeaderLink{}
- for _, line := range strings.Split(text, "\n") {
- if strings.HasPrefix(line, "=>") {
- href, text, _ := rocketlink位(line, cfg.HeaderLinksHypha)
- HeaderLinks = append(HeaderLinks, HeaderLink{
- Href: href,
- Display: text,
- })
- }
- }
-}
-
-type HeaderLink struct {
- Href string
- Display string
-}
-
-var HeaderLinks []HeaderLink
diff --git a/util/util.go b/util/util.go
index 1f3aced..0cd0ca0 100644
--- a/util/util.go
+++ b/util/util.go
@@ -3,12 +3,13 @@ package util
import (
"crypto/rand"
"encoding/hex"
- "github.com/bouncepaw/mycorrhiza/cfg"
"log"
"net/http"
"regexp"
"strings"
"unicode"
+
+ "github.com/bouncepaw/mycorrhiza/cfg"
)
func PrepareRq(rq *http.Request) {
diff --git a/views/stuff.qtpl.go b/views/stuff.qtpl.go
index a2d3de6..9344f8e 100644
--- a/views/stuff.qtpl.go
+++ b/views/stuff.qtpl.go
@@ -63,7 +63,7 @@ func StreamBaseHTML(qw422016 *qt422016.Writer, title, body string, u *user.User,
`)
//line views/stuff.qtpl:21
- for _, link := range util.HeaderLinks {
+ for _, link := range cfg.HeaderLinks {
//line views/stuff.qtpl:21
qw422016.N().S(`