1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-12-13 05:50:27 +00:00

Make it render all hyphae

This commit is contained in:
Timur Ismagilov 2020-06-13 16:18:11 +05:00
parent 14fe4acf6b
commit de7b7faca2
6 changed files with 170 additions and 37 deletions

1
go.mod
View File

@ -3,6 +3,7 @@ module github.com/bouncepaw/mycorrhiza
go 1.14
require (
github.com/gomarkdown/markdown v0.0.0-20200609195525-3f9352745725 // indirect
github.com/gorilla/mux v1.7.4
github.com/sirupsen/logrus v1.6.0 // indirect
gopkg.in/ini.v1 v1.57.0

3
go.sum
View File

@ -1,4 +1,6 @@
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/gomarkdown/markdown v0.0.0-20200609195525-3f9352745725 h1:X6sZdr+t2E2jwajTy/FfXbmAKPFTYxEq9hiFgzMiuPQ=
github.com/gomarkdown/markdown v0.0.0-20200609195525-3f9352745725/go.mod h1:aii0r/K0ZnHv7G0KF7xy1v0A7s2Ljrb5byB7MO5p6TU=
github.com/gorilla/mux v1.7.4 h1:VuZ8uybHlWmqV03+zRzdwKL4tUnIp1MAQtp1mIFE1bc=
github.com/gorilla/mux v1.7.4/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@ -6,6 +8,7 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/dl v0.0.0-20190829154251-82a15e2f2ead/go.mod h1:IUMfjQLJQd4UTqG1Z90tenwKoCX93Gn3MAQJMOSBsDQ=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
gopkg.in/ini.v1 v1.57.0 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww=

View File

@ -1,7 +1,9 @@
package main
import (
"errors"
"fmt"
"strconv"
)
type Hypha struct {
@ -36,39 +38,29 @@ func (h Hypha) String() string {
revbuf)
}
type Revision struct {
// Revision is hypha's state at some point in time. Future revisions are not really supported. Most data here is stored in m.ini.
Id int
// Name used at this revision
Name string `json:"name"`
// Present in every hypha. Stored in t.txt.
TextPath string
// In at least one markup. Supported ones are "myco", "html", "md", "plain"
Markup string `json:"markup"`
// Some hyphæ have binary contents such as images. Their presence change hypha's behavior in a lot of ways (see methods' implementations). If stored, it is stored in b (filename "b")
BinaryPath string
// To tell what is meaning of binary content, mimeType for them is stored. If the hypha has no binary content, this field must be "application/x-hypha"
MimeType string `json:"mimeType"`
// Every revision was created at some point. This field stores the creation time of the latest revision
RevisionTime int `json:"createdAt"`
// Every hypha has any number of tags
Tags []string `json:"tags"`
// Current revision is authored by someone
RevisionAuthor string `json:"author"`
// and has a comment in plain text
RevisionComment string `json:"comment"`
// Rest of fields are ignored
func GetRevision(hyphae map[string]*Hypha, hyphaName string, rev string) (Revision, error) {
for name, _ := range hyphae {
if name == hyphaName {
for _, r := range hyphae[name].Revisions {
id, err := strconv.Atoi(rev)
if err != nil {
return Revision{}, err
}
if r.Id == id {
return r, nil
}
}
}
}
return Revision{}, errors.New("Some error idk")
}
func (h Revision) String() string {
return fmt.Sprintf(`Revision %v created at %v {
name: %v
textPath: %v
markup: %v
binaryPath: %v
mimeType: %v
tags: %v
revisionAuthor: %v
revisionComment: %v
}`, h.Id, h.RevisionTime, h.Name, h.TextPath, h.Markup, h.BinaryPath, h.MimeType, h.Tags, h.RevisionAuthor, h.RevisionComment)
// `rev` is the id of revision to render. If it = 0, the last one is rendered. If the revision is not found, an error is returned.
func (h Hypha) Render(hyphae map[string]*Hypha, rev int) (ret string, err error) {
for _, r := range h.Revisions {
if r.Id == rev {
return r.Render(hyphae)
}
}
return "", errors.New("Revision was not found")
}

59
main.go
View File

@ -2,8 +2,14 @@ package main
import (
"fmt"
"github.com/gorilla/mux"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
// "strconv"
"time"
)
var rootWikiDir string
@ -30,5 +36,56 @@ func main() {
hyphae := hyphaeAsMap(recurFindHyphae(rootWikiDir))
setRelations(hyphae)
fmt.Println(hyphae)
// Start server code
r := mux.NewRouter()
r.HandleFunc("/showHyphae", func(w http.ResponseWriter, r *http.Request) {
for _, h := range hyphae {
fmt.Fprintln(w, h)
}
})
r.Queries(
"action", "getBinary",
"rev", "{rev:[\\d]+}",
).Path("/{hypha:" + hyphaPattern + "}").
HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
rev, err := GetRevision(hyphae, vars["hypha"], vars["rev"])
if err != nil {
log.Println("Failed to show image of", rev.FullName)
}
fileContents, err := ioutil.ReadFile(rev.BinaryPath)
if err != nil {
log.Println("Failed to show image of", rev.FullName)
}
log.Println("Contents:", fileContents[:10], "...")
w.Header().Set("Content-Type", rev.MimeType)
// w.Header().Set("Content-Length", strconv.Itoa(len(fileContents)))
w.WriteHeader(http.StatusOK)
w.Write(fileContents)
log.Println("Showing image of", rev.FullName)
})
r.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(http.StatusOK)
for _, v := range hyphae {
log.Println("Rendering latest revision of hypha", v.Name)
html, err := v.Render(hyphae, 0)
if err != nil {
fmt.Fprintln(w, err)
}
fmt.Fprintln(w, html)
}
})
http.Handle("/", r)
srv := &http.Server{
Handler: r,
Addr: "127.0.0.1:8000",
// Good practice: enforce timeouts for servers you create!
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
log.Fatal(srv.ListenAndServe())
}

79
revision.go Normal file
View File

@ -0,0 +1,79 @@
package main
import (
"errors"
"fmt"
"github.com/gomarkdown/markdown"
"io/ioutil"
)
type Revision struct {
// Revision is hypha's state at some point in time. Future revisions are not really supported. Most data here is stored in m.ini.
Id int
// Name used at this revision
Name string `json:"name"`
// Name of hypha
FullName string
// Present in every hypha. Stored in t.txt.
TextPath string
// In at least one markup. Supported ones are "myco", "html", "md", "plain"
Markup string `json:"markup"`
// Some hyphæ have binary contents such as images. Their presence change hypha's behavior in a lot of ways (see methods' implementations). If stored, it is stored in b (filename "b")
BinaryPath string
BinaryRequest string
// To tell what is meaning of binary content, mimeType for them is stored. If the hypha has no binary content, this field must be "application/x-hypha"
MimeType string `json:"mimeType"`
// Every revision was created at some point. This field stores the creation time of the latest revision
RevisionTime int `json:"createdAt"`
// Every hypha has any number of tags
Tags []string `json:"tags"`
// Current revision is authored by someone
RevisionAuthor string `json:"author"`
// and has a comment in plain text
RevisionComment string `json:"comment"`
}
func (h Revision) String() string {
return fmt.Sprintf(`Revision %v created at %v {
name: %v
textPath: %v
markup: %v
binaryPath: %v
mimeType: %v
tags: %v
revisionAuthor: %v
revisionComment: %v
}`, h.Id, h.RevisionTime, h.Name, h.TextPath, h.Markup, h.BinaryPath, h.MimeType, h.Tags, h.RevisionAuthor, h.RevisionComment)
}
// This method is meant to be called only by Hypha#Render.
func (r Revision) Render(hyphae map[string]*Hypha) (ret string, err error) {
ret += `<article class="page">
`
// If it is a binary hypha (we support only images for now):
// TODO: support things other than images.
if r.MimeType != "application/x-hypha" {
ret += fmt.Sprintf(`<img src="%s" class="page__image"/>`, r.BinaryRequest)
}
contents, err := ioutil.ReadFile(r.TextPath)
if err != nil {
return "", err
}
// TODO: support more markups.
// TODO: support mycorrhiza extensions like transclusion.
switch r.Markup {
case "plain":
ret += fmt.Sprintf(`<pre>%s</pre>`, contents)
case "md":
html := markdown.ToHTML(contents, nil, nil)
ret += string(html)
default:
return "", errors.New("Unsupported markup: " + r.Markup)
}
ret += `
</article>`
return ret, nil
}

View File

@ -96,7 +96,7 @@ func recurFindHyphae(fullPath string) (hyphae []*Hypha) {
// Fill in every revision
for _, possibleRevisionPath := range possibleRevisionPaths {
rev, err := makeRevision(possibleRevisionPath)
rev, err := makeRevision(possibleRevisionPath, h.Name)
if err == nil {
h.Revisions = append(h.Revisions, rev)
}
@ -119,7 +119,7 @@ func recurFindHyphae(fullPath string) (hyphae []*Hypha) {
return hyphae
}
func makeRevision(fullPath string) (r Revision, err error) {
func makeRevision(fullPath string, fullName string) (r Revision, err error) {
// fullPath is expected to be a path to a dir.
// Revision directory must have at least `m.json` and `t.txt` files.
var (
@ -159,7 +159,7 @@ func makeRevision(fullPath string) (r Revision, err error) {
return r, err
}
r = Revision{}
r = Revision{FullName: fullName}
err = json.Unmarshal(mJsonContents, &r)
if err != nil {
fmt.Println(fullPath, ">\tError:", err)
@ -174,6 +174,7 @@ func makeRevision(fullPath string) (r Revision, err error) {
// Do not check for binary file presence, attempt to read it will fail anyway
if bPresent {
r.BinaryPath = filepath.Join(fullPath, "b")
r.BinaryRequest = fmt.Sprintf("%s?rev=%d&action=getBinary", r.FullName, r.Id)
} else {
return r, errors.New("makeRevision: b file not present")
}