summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlejandro Sior <aho@sior.be>2022-08-31 20:28:57 +0200
committerAlejandro Sior <aho@sior.be>2022-08-31 20:28:57 +0200
commit1ccd4c87136091e7a71f05c8660849552e0dba36 (patch)
treedd036ea4e5a9ae15dadd513d75895c41d6b68c59
site: add the basis
-rw-r--r--go.mod3
-rw-r--r--localhost:8080/.index57
-rw-r--r--localhost:8080/.view3
-rw-r--r--localhost:8080/about1
-rw-r--r--localhost:8080/docs/.view1
-rw-r--r--localhost:8080/docs/index12
-rw-r--r--localhost:8080/docs/view3
-rw-r--r--site.go149
8 files changed, 229 insertions, 0 deletions
diff --git a/go.mod b/go.mod
new file mode 100644
index 0000000..329e56d
--- /dev/null
+++ b/go.mod
@@ -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>{&zwnj;{ post }}</code> gets replaced by the content of the post resolved by the HTML path</li>
+<li><code>{&zwnj;{ 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
diff --git a/site.go b/site.go
new file mode 100644
index 0000000..46e6cee
--- /dev/null
+++ b/site.go
@@ -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