diff options
| -rw-r--r-- | go.mod | 3 | ||||
| -rw-r--r-- | localhost:8080/.index | 57 | ||||
| -rw-r--r-- | localhost:8080/.view | 3 | ||||
| -rw-r--r-- | localhost:8080/about | 1 | ||||
| -rw-r--r-- | localhost:8080/docs/.view | 1 | ||||
| -rw-r--r-- | localhost:8080/docs/index | 12 | ||||
| -rw-r--r-- | localhost:8080/docs/view | 3 | ||||
| -rw-r--r-- | site.go | 149 |
8 files changed, 229 insertions, 0 deletions
@@ -0,0 +1,3 @@ +module github.com/aosync/site + +go 1.19 diff --git a/localhost:8080/.index b/localhost:8080/.index new file mode 100644 index 0000000..d35e674 --- /dev/null +++ b/localhost:8080/.index @@ -0,0 +1,57 @@ +<html> + <title>aosync</title> + <link href='data:image/gif;base64,R0lGODlhEAAQAPH/AAAAAP8AAP8AN////yH5BAUAAAQALAAAAAAQABAAAAM2SLrc/jA+QBUFM2iqA2bAMHSktwCCWJIYEIyvKLOuJt+wV69ry5cfwu7WCVp2RSPoUpE4n4sEADs=' rel=icon> + <style> + body { + padding: 5px 10px 5px 15px; + + background-color: rgb(235, 233, 253); + color: rgb(44, 42, 58); + + font-size: 17px; + font-family: 'Times New Roman', Times, serif; + } + + nav { + display: inline-flex; + font-family: monospace; + } + nav li { + font-size: 15px; + list-style-type: none; + list-style-position: outside; + } + nav a { + text-decoration: none; + font-weight: bold; + color: inherit; + } + nav > * { + padding-left: 0px; + padding-right: 35px; + } + + .nav-intended { + font-style: oblique; + } + + pre { + border-radius: 6px; + background-color: rgb(201, 199, 219); + padding: 12px; + } + code { + font-family: monospace; + } + + article { + margin-top: 8px; + } + </style> + <body> + <header><nav><a href="/"><h1 id="title">site</h1><h3 id="subtitle"></h3></a>{{ nav }}</nav></header> + <article class="rest"> + {{ post }} + </article> + </body> +</html>
\ No newline at end of file diff --git a/localhost:8080/.view b/localhost:8080/.view new file mode 100644 index 0000000..45d9e3b --- /dev/null +++ b/localhost:8080/.view @@ -0,0 +1,3 @@ +<h2>site is a simple static site generator</h2> + +<p>This sample website serves as a usage reference.</p>
\ No newline at end of file diff --git a/localhost:8080/about b/localhost:8080/about new file mode 100644 index 0000000..c4c593f --- /dev/null +++ b/localhost:8080/about @@ -0,0 +1 @@ +<p><em>site</em> and this template are inspired by <a href="https://werc.cat-v.org/docs/">werc</a> and <a href="https://wiki.xxiivv.com/site/home.html">XXIIVV</a>. I found that these models of personal website organisations are well suited to lay out notes about varieties of subjects.</p>
\ No newline at end of file diff --git a/localhost:8080/docs/.view b/localhost:8080/docs/.view new file mode 100644 index 0000000..d8c8fec --- /dev/null +++ b/localhost:8080/docs/.view @@ -0,0 +1 @@ +<p>This directory holds a few notes about <em>site</em> concepts.</p>
\ No newline at end of file diff --git a/localhost:8080/docs/index b/localhost:8080/docs/index new file mode 100644 index 0000000..30610a5 --- /dev/null +++ b/localhost:8080/docs/index @@ -0,0 +1,12 @@ +<h3><code>.index</code> is the template of children pages in the subtree</h3> + +<p>When a directory contains a file named <code>.index</code>, all files in children directories are going to use it as template.</p> + +<p>An <code>.index</code> file is a normal html file, except that a few templates get replaced by the server generated content: +<ul> +<li><code>{‌{ post }}</code> gets replaced by the content of the post resolved by the HTML path</li> +<li><code>{‌{ nav }}</code> gets replaced by the server generated navbar, which is to be placed anywhere. This template places it next to the title</li> +</ul> +</p> + +<p>The role of <code>.index</code> is thus to structure and composite in a relatively minimalistic manner the componants that make up a page of the site.</p>
\ No newline at end of file diff --git a/localhost:8080/docs/view b/localhost:8080/docs/view new file mode 100644 index 0000000..ced1356 --- /dev/null +++ b/localhost:8080/docs/view @@ -0,0 +1,3 @@ +<h3><code>.view</code> is the default page rendered in a directory</h3> + +<p>It can be used to provide a summary of what to expect in the subdirectories</p>
\ No newline at end of file @@ -0,0 +1,149 @@ +package main + +import ( + "os" + "io/ioutil" + "net/http" + "path" + "path/filepath" + "strings" +) + +const staticPrefix = "/static/" + +type NavTree struct { + name string + path string + children []NavTree + hasIndex bool + selected bool +} + +func stripPath(caminho string) string { + caminho = path.Clean(caminho) + return "/" + path.Join(strings.Split(caminho, "/")[1:]...) +} + +func rootTree(root string, goal string) (NavTree, string) { + nav := NavTree{} + nav.name = path.Base(root) + nav.path = root + nav.selected = false + + index := "" + + if !strings.HasPrefix(goal, root) { + return nav, index + } + + nav.selected = true + + filepath.Walk(root, func(current string, info os.FileInfo, err error) error { + if info.Name() == ".index" { + index = current + } + + if current == root || info.Name()[0] == '.' { + return nil + } + + rec, idx := rootTree(current, goal) + if idx != "" { + index = idx + } + + nav.children = append(nav.children, rec) + + if info.IsDir() { + return filepath.SkipDir + } else { + return nil + } + }) + + return nav, index +} + +func RenderList(children []NavTree) string { + deleg := "" + ul := "<ul>" + for _, s := range children { + u, d := s.Render() + ul += u + deleg += d + } + ul += "</ul>" + ul += deleg + return ul +} + +func (v *NavTree) Render() (string, string) { + li := "<li><a href=\"" + stripPath(v.path) + "\">" + if v.selected { + li += "<span class=\"nav-intended\">" + } else { + li += "<span class=\"nav-not-intended\">" + } + li += v.name + li += "</span></a></li>" + + deleg := "" + + if len(v.children) > 0 { + deleg += RenderList(v.children) + } + + return li, deleg +} + +func build(request *http.Request) (string, int) { + code := 200 + root := request.Host + postLoc := path.Join(root, request.URL.Path) + + if strings.HasPrefix(request.URL.Path, staticPrefix) { + staticLoc := path.Join(root, request.URL.Path[len(staticPrefix):]) + static, err0 := ioutil.ReadFile(staticLoc) + if err0 != nil { + return "Path not found", 404 + } + + return string(static), 200 + } + + tr, idx := rootTree(root, postLoc) + template, err0 := ioutil.ReadFile(idx) + if err0 != nil { + return "No template in tree", 500 + } + + final := string(template) + + post, err1 := ioutil.ReadFile(postLoc) + if err1 != nil { + viewLoc := path.Join(root, request.URL.Path, ".view") + + view, err1_0 := ioutil.ReadFile(viewLoc) + if err1_0 != nil { + return "Path not found", 404 + } + post = view + } + + final = strings.Replace(string(template), "{{ post }}", string(post), -1) + final = strings.Replace(string(final), "{{ nav }}", RenderList(tr.children), -1) + + return final, code +} + +func handler(w http.ResponseWriter, r *http.Request) { + content, code := build(r) + + w.WriteHeader(code) + w.Write([]byte(content)) +} + +func main() { + http.HandleFunc("/", handler) + http.ListenAndServe(":8080", nil) +}
\ No newline at end of file |
