1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2025-01-18 22:52:50 +00:00

Final touches. Refactoring is done?

This commit is contained in:
Timur Ismagilov 2020-06-27 22:47:53 +05:00
parent d36f86f715
commit 5f79930539
5 changed files with 174 additions and 140 deletions

81
fs/data.go Normal file
View File

@ -0,0 +1,81 @@
// This file contains methods for Hypha that calculate data about the hypha based on known information.
package fs
import (
"fmt"
"io/ioutil"
"log"
"path/filepath"
"strconv"
"strings"
"github.com/bouncepaw/mycorrhiza/cfg"
)
func (h *Hypha) MetaJsonPath() string {
return filepath.Join(h.Path(), "meta.json")
}
func (h *Hypha) Path() string {
return filepath.Join(cfg.WikiDir, h.FullName)
}
func (h *Hypha) TextPath() string {
return h.actual.TextPath
}
func (h *Hypha) parentName() string {
return filepath.Dir(h.FullName)
}
// hasBinaryData returns true if the revision has any binary data associated.
// During initialisation, it is guaranteed that r.BinaryMime is set to "" if the revision has no binary data. (is it?)
func (h *Hypha) hasBinaryData() bool {
return h.actual.BinaryMime != ""
}
func (h *Hypha) TagsJoined() string {
if h.Exists {
return strings.Join(h.actual.Tags, ", ")
}
return ""
}
func (h *Hypha) TextMime() string {
if h.Exists {
return h.actual.TextMime
}
return "text/markdown"
}
func (h *Hypha) mimeTypeForActionRaw() string {
// If text mime type is text/html, it is not good as it will be rendered.
if h.actual.TextMime == "text/html" {
return "text/plain"
}
return h.actual.TextMime
}
// NewestId finds the largest id among all revisions.
func (h *Hypha) NewestId() string {
var largest int
for k, _ := range h.Revisions {
id, _ := strconv.Atoi(k)
if id > largest {
largest = id
}
}
return strconv.Itoa(largest)
}
func (h *Hypha) TextContent() string {
if h.Exists {
contents, err := ioutil.ReadFile(h.TextPath())
if err != nil {
log.Println("Could not read", h.FullName)
return "Error: could not hypha text content file. It is recommended to cancel editing. Please contact the wiki admin. If you are the admin, see the logs."
}
return string(contents)
}
return fmt.Sprintf(cfg.DescribeHyphaHerePattern, h.FullName)
}

View File

@ -3,7 +3,6 @@ package fs
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"log"
"net/http"
@ -33,44 +32,6 @@ func (h *Hypha) Invalidate(err error) *Hypha {
return h
}
func (h *Hypha) MetaJsonPath() string {
return filepath.Join(h.Path(), "meta.json")
}
func (h *Hypha) Path() string {
return filepath.Join(cfg.WikiDir, h.FullName)
}
func (h *Hypha) TextPath() string {
return h.actual.TextPath
}
func (h *Hypha) TagsJoined() string {
if h.Exists {
return strings.Join(h.actual.Tags, ", ")
}
return ""
}
func (h *Hypha) TextMime() string {
if h.Exists {
return h.actual.TextMime
}
return "text/markdown"
}
func (h *Hypha) TextContent() string {
if h.Exists {
contents, err := ioutil.ReadFile(h.TextPath())
if err != nil {
log.Println("Could not read", h.FullName)
return "Error: could not hypha text content file. It is recommended to cancel editing. Please contact the wiki admin. If you are the admin, see the logs."
}
return string(contents)
}
return fmt.Sprintf(cfg.DescribeHyphaHerePattern, h.FullName)
}
func (s *Storage) Open(name string) *Hypha {
h := &Hypha{
Exists: true,
@ -107,14 +68,6 @@ func (s *Storage) Open(name string) *Hypha {
return h
}
func (h *Hypha) parentName() string {
return filepath.Dir(h.FullName)
}
func (h *Hypha) metaJsonPath() string {
return filepath.Join(cfg.WikiDir, h.FullName, "meta.json")
}
// OnRevision tries to change to a revision specified by `id`.
func (h *Hypha) OnRevision(id string) *Hypha {
if h.Invalid || !h.Exists {
@ -133,18 +86,6 @@ func (h *Hypha) OnRevision(id string) *Hypha {
return h
}
// NewestId finds the largest id among all revisions.
func (h *Hypha) NewestId() string {
var largest int
for k, _ := range h.Revisions {
id, _ := strconv.Atoi(k)
if id > largest {
largest = id
}
}
return strconv.Itoa(largest)
}
func (h *Hypha) PlainLog(s string) {
if h.Exists {
log.Println(h.FullName, h.actual.Id, s)
@ -153,74 +94,74 @@ func (h *Hypha) PlainLog(s string) {
}
}
func (h *Hypha) mimeTypeForActionRaw() string {
// If text mime type is text/html, it is not good as it will be rendered.
if h.actual.TextMime == "text/html" {
return "text/plain"
func (h *Hypha) LogSuccMaybe(succMsg string) *Hypha {
if h.Invalid {
h.PlainLog(h.Err.Error())
} else {
h.PlainLog(succMsg)
}
return h.actual.TextMime
}
// hasBinaryData returns true if the revision has any binary data associated.
// During initialisation, it is guaranteed that r.BinaryMime is set to "" if the revision has no binary data. (is it?)
func (h *Hypha) hasBinaryData() bool {
return h.actual.BinaryMime != ""
return h
}
// ActionRaw is used with `?action=raw`.
// It writes text content of the revision without any parsing or rendering.
func (h *Hypha) ActionRaw(w http.ResponseWriter) {
func (h *Hypha) ActionRaw(w http.ResponseWriter) *Hypha {
if h.Invalid {
return h
}
fileContents, err := ioutil.ReadFile(h.actual.TextPath)
if err != nil {
log.Fatal(err)
return
return h.Invalidate(err)
}
w.Header().Set("Content-Type", h.mimeTypeForActionRaw())
w.WriteHeader(http.StatusOK)
w.Write(fileContents)
h.PlainLog("Serving raw text")
return h
}
// ActionBinary is used with `?action=binary`.
// It writes contents of binary content file.
func (h *Hypha) ActionBinary(w http.ResponseWriter) {
func (h *Hypha) ActionBinary(w http.ResponseWriter) *Hypha {
if h.Invalid {
return h
}
fileContents, err := ioutil.ReadFile(h.actual.BinaryPath)
if err != nil {
log.Fatal(err)
return
return h.Invalidate(err)
}
w.Header().Set("Content-Type", h.actual.BinaryMime)
w.WriteHeader(http.StatusOK)
w.Write(fileContents)
h.PlainLog("Serving raw text")
return h
}
// ActionZen is used with `?action=zen`.
// It renders the hypha but without any layout or styles. Pure. Zen.
func (h *Hypha) ActionZen(w http.ResponseWriter) {
func (h *Hypha) ActionZen(w http.ResponseWriter) *Hypha {
if h.Invalid {
return h
}
html, err := h.asHtml()
if err != nil {
log.Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
return h.Invalidate(err)
}
w.Header().Set("Content-Type", "text/html;charset=utf-8")
w.WriteHeader(http.StatusOK)
w.Write([]byte(html))
h.PlainLog("Rendering zen")
return h
}
// ActionView is used with `?action=view` or no action at all.
// It renders the page, the layout and everything else.
func (h *Hypha) ActionView(w http.ResponseWriter, renderExists, renderNotExists func(string, string) string) {
func (h *Hypha) ActionView(w http.ResponseWriter, renderExists, renderNotExists func(string, string) string) *Hypha {
var html string
var err error
if h.Exists {
html, err = h.asHtml()
if err != nil {
log.Println(err)
w.WriteHeader(http.StatusInternalServerError)
return
return h.Invalidate(err)
}
}
w.Header().Set("Content-Type", "text/html;charset=utf-8")
@ -230,7 +171,7 @@ func (h *Hypha) ActionView(w http.ResponseWriter, renderExists, renderNotExists
} else {
w.Write([]byte(renderNotExists(h.FullName, "")))
}
h.PlainLog("Rendering hypha view")
return h
}
// CreateDirIfNeeded creates directory where the hypha must reside if needed.

View File

@ -2,13 +2,7 @@ package main
import (
"log"
// "io/ioutil"
// "log"
"net/http"
// "path/filepath"
// "strconv"
// "strings"
// "time"
"github.com/bouncepaw/mycorrhiza/fs"
"github.com/bouncepaw/mycorrhiza/render"
@ -18,40 +12,31 @@ import (
// There are handlers below. See main() for their usage.
// Boilerplate code present in many handlers. Good to have it.
func HandlerBase(w http.ResponseWriter, rq *http.Request) (*fs.Hypha, bool) {
func HandlerBase(w http.ResponseWriter, rq *http.Request) *fs.Hypha {
vars := mux.Vars(rq)
h := fs.Hs.Open(vars["hypha"]).OnRevision(RevInMap(vars))
if h.Invalid {
log.Println(h.Err)
return h, false
}
return h, true
return fs.Hs.Open(vars["hypha"]).OnRevision(RevInMap(vars))
}
func HandlerRaw(w http.ResponseWriter, rq *http.Request) {
log.Println("?action=raw")
if h, ok := HandlerBase(w, rq); ok {
h.ActionRaw(w)
}
HandlerBase(w, rq).ActionRaw(w).LogSuccMaybe("Serving raw text")
}
func HandlerBinary(w http.ResponseWriter, rq *http.Request) {
log.Println("?action=binary")
if h, ok := HandlerBase(w, rq); ok {
h.ActionBinary(w)
}
HandlerBase(w, rq).ActionBinary(w).LogSuccMaybe("Serving binary data")
}
func HandlerZen(w http.ResponseWriter, rq *http.Request) {
if h, ok := HandlerBase(w, rq); ok {
h.ActionZen(w)
}
log.Println("?action=zen")
HandlerBase(w, rq).ActionZen(w).LogSuccMaybe("Rendering zen")
}
func HandlerView(w http.ResponseWriter, rq *http.Request) {
if h, ok := HandlerBase(w, rq); ok {
h.ActionView(w, render.HyphaPage, render.Hypha404)
}
log.Println("?action=view")
HandlerBase(w, rq).
ActionView(w, render.HyphaPage, render.Hypha404).
LogSuccMaybe("Rendering hypha view")
}
func HandlerEdit(w http.ResponseWriter, rq *http.Request) {
@ -72,14 +57,12 @@ func HandlerUpdate(w http.ResponseWriter, rq *http.Request) {
WriteTextFileFromHttpData(rq).
WriteBinaryFileFromHttpData(rq).
SaveJson().
Store()
Store().
LogSuccMaybe("Saved changes")
if h.Invalid {
log.Println(h.Err)
return
if !h.Invalid {
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Write([]byte(render.HyphaUpdateOk(h)))
}
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Write([]byte(render.HyphaUpdateOk(h)))
}

4
w/m/Fruit/3.markdown Normal file
View File

@ -0,0 +1,4 @@
According to real *scientists*, fruit is a type of fetus. Most of them are tasty and cool, though some of them are really sour and depressing. Be careful when choosing fruit. Best ones are:
* [Apple](Apple)
* [Pear](Pear)

View File

@ -1,22 +1,47 @@
{
"revisions":{
"1":{
"name": "Fruit",
"time": 1591635559,
"author": "bouncepaw",
"comment": "create Fruit",
"tags": ["fetus", "tasty"],
"text_mime": "text/markdown",
"text_name": "1.md"
},
"2":{
"name": "Fruit",
"time": 1591636222,
"author": "fungimaster",
"comment": "update Fruit",
"tags": ["fetus", "tasty"],
"text_mime": "text/markdown",
"text_name": "2.md"
}
}
}
"views": 0,
"deleted": false,
"revisions": {
"1": {
"tags": [
"fetus",
"tasty"
],
"name": "Fruit",
"comment": "create Fruit",
"author": "bouncepaw",
"time": 1591635559,
"text_mime": "text/markdown",
"binary_mime": "",
"text_name": "1.md",
"binary_name": ""
},
"2": {
"tags": [
"fetus",
"tasty"
],
"name": "Fruit",
"comment": "update Fruit",
"author": "fungimaster",
"time": 1591636222,
"text_mime": "text/markdown",
"binary_mime": "",
"text_name": "2.md",
"binary_name": ""
},
"3": {
"tags": null,
"name": "Fruit",
"comment": "Update Fruit",
"author": "",
"time": 1593279957,
"text_mime": "text/markdown",
"binary_mime": "",
"text_name": "3.markdown",
"binary_name": ""
}
},
"Invalid": false,
"Err": null
}