mirror of
https://github.com/osmarks/mycorrhiza.git
synced 2025-05-17 04:54:05 +00:00
Merge pull request #6 from DanInSpace104/features/templates-from-html
Features/templates from html
This commit is contained in:
commit
550bcbd444
16
config.go
16
config.go
@ -1,14 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
const (
|
const (
|
||||||
FooterText = `
|
TitleTemplate = `%s at MycorrhizaWiki`
|
||||||
This website runs <a href="https://github.com/bouncepaw/mycorrhiza">MycorrhizaWiki</a>.
|
DefaultTitle = "MycorrhizaWiki"
|
||||||
`
|
DefaultHeaderText = `MycorrhizaWiki 🍄`
|
||||||
TitleTemplate = `%s at MycorrhizaWiki`
|
DefaultFooterText = `This website runs <a href="https://github.com/bouncepaw/mycorrhiza">MycorrhizaWiki</a>.`
|
||||||
DefaultStyles = `
|
DefaultSidebar = ""
|
||||||
|
DefaultBodyBottom = ""
|
||||||
|
DefaultContent = "It is empty here"
|
||||||
|
DefaultStyles = `
|
||||||
<link rel="stylesheet" href="/sys/main.css?action=raw">
|
<link rel="stylesheet" href="/sys/main.css?action=raw">
|
||||||
`
|
`
|
||||||
DefaultHeader = `
|
|
||||||
<h1 class="site-title">MycorrhizaWiki 🍄</h1>
|
|
||||||
` // TODO: Search input
|
|
||||||
)
|
)
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -9,6 +8,8 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Boilerplate code present in many handlers. Good to have it.
|
// Boilerplate code present in many handlers. Good to have it.
|
||||||
|
4
main.go
4
main.go
@ -2,13 +2,13 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
// "strconv"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetRevision(hyphae map[string]*Hypha, hyphaName string, rev string, w http.ResponseWriter) (Revision, bool) {
|
func GetRevision(hyphae map[string]*Hypha, hyphaName string, rev string, w http.ResponseWriter) (Revision, bool) {
|
||||||
|
187
render.go
187
render.go
@ -1,126 +1,85 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"path"
|
||||||
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Layout(f map[string]string) string {
|
func EditHyphaPage(name, textMime, content, tags string) string {
|
||||||
template := `
|
keys := map[string]string{
|
||||||
<!doctype html>
|
"Title": fmt.Sprintf(TitleTemplate, "Edit "+name),
|
||||||
<html>
|
"Header": renderFromString(name, "Hypha/edit/header.html"),
|
||||||
<head>
|
|
||||||
<title>%s</title>
|
|
||||||
%s
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="shroom">
|
|
||||||
<button class="shroom__button" id="shroomBtn"><span>🍄</span> Open mycelium</button>
|
|
||||||
</div>
|
|
||||||
<main class="main">%s</main>
|
|
||||||
<div class="left-panel" id="shroomburgerMenu">
|
|
||||||
<div class="left-panel__in">
|
|
||||||
<div class="shroom mushroom">
|
|
||||||
<button class="shroom__button" id="mushroomBtn"><span>🍄</span> Close mycelium</button>
|
|
||||||
</div>
|
|
||||||
<div class="left-panel__contents">
|
|
||||||
<header class="header">%s</header>
|
|
||||||
<aside class="sidebar">%s</aside>
|
|
||||||
<footer class="footer">%s</footer>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
%s
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
`
|
|
||||||
return fmt.Sprintf(template, f["title"], f["head"], f["main"], f["header"], f["sidebar"], FooterText, f["bodyBottom"])
|
|
||||||
}
|
|
||||||
|
|
||||||
func EditHyphaPage(name, text_mime, content, tags string) string {
|
|
||||||
template := `
|
|
||||||
<div class="naviwrapper">
|
|
||||||
<form class="naviwrapper__edit edit-box"
|
|
||||||
method="POST"
|
|
||||||
enctype="multipart/form-data"
|
|
||||||
action="?action=update">
|
|
||||||
<div class="naviwrapper__buttons">
|
|
||||||
<input type="submit" value="update"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="edit-box__left">
|
|
||||||
<h4>Edit box</h4>
|
|
||||||
<textarea class="edit-box__text" name="text" cols="80" rows="25">
|
|
||||||
%s
|
|
||||||
</textarea>
|
|
||||||
|
|
||||||
<h4>Upload file</h4>
|
|
||||||
<p>If this hypha has a file like that, the text above is meant to be a description of it</p>
|
|
||||||
<input type="file" name="binary"/>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="edit-box__right">
|
|
||||||
<h4>Text MIME-type</h4>
|
|
||||||
<p>Good types are <code>text/markdown</code> and <code>text/plain</code></p>
|
|
||||||
<input type="text" name="text_mime" value="%s"/>
|
|
||||||
|
|
||||||
<h4>Revision comment</h4>
|
|
||||||
<p>Please make your comment helpful</p>
|
|
||||||
<input type="text" name="comment" value="%s"/>
|
|
||||||
|
|
||||||
<h4>Edit tags</h4>
|
|
||||||
<p>Tags are separated by commas, whitespace is ignored</p>
|
|
||||||
<input type="text" name="tags" value="%s"/>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
args := map[string]string{
|
|
||||||
"title": fmt.Sprintf(TitleTemplate, "Edit "+name),
|
|
||||||
"head": DefaultStyles,
|
|
||||||
"header": `<h1 class="header__edit-title">Edit ` + name + `</h1>`,
|
|
||||||
"main": fmt.Sprintf(template, content, text_mime, "Update "+name, tags),
|
|
||||||
"sidebar": "",
|
|
||||||
"footer": FooterText,
|
|
||||||
}
|
}
|
||||||
|
page := map[string]string{
|
||||||
return Layout(args)
|
"Text": content,
|
||||||
|
"TextMime": textMime,
|
||||||
|
"Name": name,
|
||||||
|
"Tags": tags,
|
||||||
|
}
|
||||||
|
return renderBase(renderFromMap(page, "Hypha/edit/index.html"), keys)
|
||||||
}
|
}
|
||||||
|
|
||||||
func HyphaPage(hyphae map[string]*Hypha, rev Revision, content string) string {
|
func HyphaPage(hyphae map[string]*Hypha, rev Revision, content string) string {
|
||||||
sidebar := `
|
sidebar := DefaultSidebar
|
||||||
<div class="naviwrapper">
|
bside, err := ioutil.ReadFile("Hypha/view/sidebar.html")
|
||||||
<div class="hypha-actions">
|
if err == nil {
|
||||||
<ul>
|
sidebar = string(bside)
|
||||||
<li><a href="?action=edit">Edit</a>
|
|
||||||
<li><a href="?action=getBinary">Download</a>
|
|
||||||
<li><a href="?action=zen">Zen mode</a>
|
|
||||||
<li><a href="?action=raw">View raw</a>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`
|
|
||||||
|
|
||||||
bodyBottom := `
|
|
||||||
<script type="text/javascript">
|
|
||||||
var menu = document.getElementById('shroomburgerMenu');
|
|
||||||
document.getElementById('shroomBtn').addEventListener('click', function() {
|
|
||||||
menu.classList.add('active');
|
|
||||||
});
|
|
||||||
document.getElementById('mushroomBtn').addEventListener('click', function() {
|
|
||||||
menu.classList.remove('active');
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
`
|
|
||||||
|
|
||||||
args := map[string]string{
|
|
||||||
"title": fmt.Sprintf(TitleTemplate, rev.FullName),
|
|
||||||
"head": DefaultStyles,
|
|
||||||
"header": DefaultHeader,
|
|
||||||
"main": content,
|
|
||||||
"sidebar": sidebar,
|
|
||||||
"footer": FooterText,
|
|
||||||
"bodyBottom": bodyBottom,
|
|
||||||
}
|
}
|
||||||
|
keys := map[string]string{
|
||||||
return Layout(args)
|
"Title": fmt.Sprintf(TitleTemplate, rev.FullName),
|
||||||
|
"Sidebar": sidebar,
|
||||||
|
}
|
||||||
|
return renderBase(renderFromString(content, "Hypha/view/index.html"), keys)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Collect and render page from base template
|
||||||
|
Args:
|
||||||
|
content: string or pre-rendered template
|
||||||
|
keys: map with replaced standart fields
|
||||||
|
*/
|
||||||
|
func renderBase(content string, keys map[string]string) string {
|
||||||
|
page := map[string]string{
|
||||||
|
"Title": DefaultTitle,
|
||||||
|
"Head": DefaultStyles,
|
||||||
|
"Sidebar": DefaultSidebar,
|
||||||
|
"Main": DefaultContent,
|
||||||
|
"BodyBottom": DefaultBodyBottom,
|
||||||
|
"Header": renderFromString(DefaultHeaderText, "header.html"),
|
||||||
|
"Footer": renderFromString(DefaultFooterText, "footer.html"),
|
||||||
|
}
|
||||||
|
for key, val := range keys {
|
||||||
|
page[key] = val
|
||||||
|
}
|
||||||
|
page["Main"] = content
|
||||||
|
return renderFromMap(page, "base.html")
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderFromMap(data map[string]string, templatePath string) string {
|
||||||
|
filePath := path.Join("templates", templatePath)
|
||||||
|
tmpl, err := template.ParseFiles(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
if err := tmpl.Execute(buf, data); err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderFromString(data string, templatePath string) string {
|
||||||
|
filePath := path.Join("templates", templatePath)
|
||||||
|
tmpl, err := template.ParseFiles(filePath)
|
||||||
|
if err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
buf := new(bytes.Buffer)
|
||||||
|
if err := tmpl.Execute(buf, data); err != nil {
|
||||||
|
return err.Error()
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
10
revision.go
10
revision.go
@ -2,11 +2,13 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/gomarkdown/markdown"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/gomarkdown/markdown"
|
||||||
)
|
)
|
||||||
|
|
||||||
// In different places, revision variable is called `r`. But when there is an http.Request as well, the revision becomes `rev`. TODO: name them consistently.
|
// In different places, revision variable is called `r`. But when there is an http.Request as well, the revision becomes `rev`. TODO: name them consistently.
|
||||||
@ -112,12 +114,10 @@ func (r *Revision) ActionView(w http.ResponseWriter, layoutFun func(map[string]*
|
|||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
w.Header().Set("Content-Type", "text/html; charset=utf-8")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
|
|
||||||
fmt.Fprint(w, layoutFun(hyphae, *r, html))
|
fmt.Fprint(w, layoutFun(hyphae, *r, html))
|
||||||
log.Println("Rendering", r.FullName)
|
log.Println("Rendering", r.FullName)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Revision) Name() string {
|
|
||||||
return r.FullName
|
|
||||||
}
|
|
||||||
|
1
templates/Hypha/edit/header.html
Normal file
1
templates/Hypha/edit/header.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<h1 class="header__edit-title">Edit {{ . }}</h1>
|
35
templates/Hypha/edit/index.html
Normal file
35
templates/Hypha/edit/index.html
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<div class="naviwrapper">
|
||||||
|
<form class="naviwrapper__edit edit-box"
|
||||||
|
method="POST"
|
||||||
|
enctype="multipart/form-data"
|
||||||
|
action="?action=update">
|
||||||
|
<div class="naviwrapper__buttons">
|
||||||
|
<input type="submit" value="update"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="edit-box__left">
|
||||||
|
<h4>Edit box</h4>
|
||||||
|
<textarea class="edit-box__text" name="text" cols="80" rows="25">
|
||||||
|
{{ .Text }}
|
||||||
|
</textarea>
|
||||||
|
|
||||||
|
<h4>Upload file</h4>
|
||||||
|
<p>If this hypha has a file like that, the text above is meant to be a description of it</p>
|
||||||
|
<input type="file" name="binary"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="edit-box__right">
|
||||||
|
<h4>Text MIME-type</h4>
|
||||||
|
<p>Good types are <code>text/markdown</code> and <code>text/plain</code></p>
|
||||||
|
<input type="text" name="text_mime" value="{{ .TextMime }}"/>
|
||||||
|
|
||||||
|
<h4>Revision comment</h4>
|
||||||
|
<p>Please make your comment helpful</p>
|
||||||
|
<input type="text" name="comment" value="Update {{ .Name }}"/>
|
||||||
|
|
||||||
|
<h4>Edit tags</h4>
|
||||||
|
<p>Tags are separated by commas, whitespace is ignored</p>
|
||||||
|
<input type="text" name="tags" value="{{ .Tags }}"/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
9
templates/Hypha/view/bodybottom.html
Normal file
9
templates/Hypha/view/bodybottom.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<script type="text/javascript">
|
||||||
|
var menu = document.getElementById('shroomburgerMenu');
|
||||||
|
document.getElementById('shroomBtn').addEventListener('click', function() {
|
||||||
|
menu.classList.add('active');
|
||||||
|
});
|
||||||
|
document.getElementById('mushroomBtn').addEventListener('click', function() {
|
||||||
|
menu.classList.remove('active');
|
||||||
|
});
|
||||||
|
</script>
|
9
templates/Hypha/view/index.html
Normal file
9
templates/Hypha/view/index.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<div class="naviwrapper">
|
||||||
|
<form class="naviwrapper__buttons">
|
||||||
|
<input type="submit" name="action" value="edit"/>
|
||||||
|
<input type="submit" name="action" value="getBinary"/>
|
||||||
|
<input type="submit" name="action" value="zen"/>
|
||||||
|
<input type="submit" name="action" value="raw"/>
|
||||||
|
</form>
|
||||||
|
{{ . }}
|
||||||
|
</div>
|
10
templates/Hypha/view/sidebar.html
Normal file
10
templates/Hypha/view/sidebar.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<div class="naviwrapper">
|
||||||
|
<div class="hypha-actions">
|
||||||
|
<ul>
|
||||||
|
<li><a href="?action=edit">Edit</a>
|
||||||
|
<li><a href="?action=getBinary">Download</a>
|
||||||
|
<li><a href="?action=zen">Zen mode</a>
|
||||||
|
<li><a href="?action=raw">View raw</a>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
25
templates/base.html
Normal file
25
templates/base.html
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{{ .Title }}</title>
|
||||||
|
{{ .Head }}
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="shroom">
|
||||||
|
<button class="shroom__button" id="shroomBtn"><span>🍄</span> Open mycelium</button>
|
||||||
|
</div>
|
||||||
|
<main class="main">{{ .Main }}</main>
|
||||||
|
<div class="left-panel" id="shroomburgerMenu">
|
||||||
|
<div class="left-panel__in">
|
||||||
|
<div class="shroom mushroom">
|
||||||
|
<button class="shroom__button" id="mushroomBtn"><span>🍄</span> Close mycelium</button>
|
||||||
|
</div>
|
||||||
|
<div class="left-panel__contents">
|
||||||
|
<header class="header">{{ .Header }}</header>
|
||||||
|
<aside class="sidebar">{{ .Sidebar }}</aside>
|
||||||
|
<footer class="footer">{{ .Footer }}</footer>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{ .BodyBottom }}
|
||||||
|
</body>
|
||||||
|
</html>
|
1
templates/footer.html
Normal file
1
templates/footer.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<h1 class="header__site-title">{{ . }}</h1>
|
1
templates/header.html
Normal file
1
templates/header.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<h1 class="header__site-title">{{ . }}</h1>
|
Loading…
x
Reference in New Issue
Block a user