diff options
| -rw-r--r-- | Makefile | 14 | ||||
| -rw-r--r-- | go.mod | 3 | ||||
| -rw-r--r-- | htdocs/base.html | 29 | ||||
| -rw-r--r-- | htdocs/index.html | 3 | ||||
| -rw-r--r-- | htdocs/software/index.html | 7 | ||||
| -rw-r--r-- | htdocs/style.css | 29 | ||||
| -rw-r--r-- | index.html | 6 | ||||
| -rw-r--r-- | server.go | 106 |
8 files changed, 191 insertions, 6 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..5add856 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +build: tidy format + go build + +serve: tidy format + go run . + +live: + rsync -rtvzP ./htdocs/ sam@samanthony.xyz:/var/www/htdocs/samanthony.xyz/ + +format: + gofmt -s -w . + +tidy: + go mod tidy @@ -0,0 +1,3 @@ +module git.samanthony.xyz/samanthony.xyz + +go 1.18 diff --git a/htdocs/base.html b/htdocs/base.html new file mode 100644 index 0000000..5c02174 --- /dev/null +++ b/htdocs/base.html @@ -0,0 +1,29 @@ +<!doctype html> +<html> + <head> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + + <!-- Child templates can choose to overwrite the default title --> + {{ define "title" }}<title>samanthony.xyz</title>{{ end }} + {{ template "title" }} + + <!-- Child templates can apply their own styles --> + {{ define "style" }}{{ end }} + {{ template "style" }} + <link rel="stylesheet" href="/style.css"> + </head> + <body> + <nav> + {{ $this_section := .Nav.ThisSection }} + {{ range .Nav.Links }} + {{ if eq .Href $this_section }} + <p>/</p><a class="this-section" href="{{ .Href }}">{{ .Label }}</a> + {{else }} + <p>|</p><a href="{{ .Href }}">{{ .Label }}</a> + {{ end }} + {{ end }} + <hr> + </nav> + {{ template "body_content" }} + </body> +</html> diff --git a/htdocs/index.html b/htdocs/index.html new file mode 100644 index 0000000..ac2f7a6 --- /dev/null +++ b/htdocs/index.html @@ -0,0 +1,3 @@ +{{ define "body_content" }} + <p>Hello, world!</p> +{{ end }} diff --git a/htdocs/software/index.html b/htdocs/software/index.html new file mode 100644 index 0000000..4b1092d --- /dev/null +++ b/htdocs/software/index.html @@ -0,0 +1,7 @@ +{{ define "title" }} + <title>software | samanthony.xyz</title> +{{ end }} + +{{ define "body_content" }} + <p>This is the software page</p> +{{ end }} diff --git a/htdocs/style.css b/htdocs/style.css new file mode 100644 index 0000000..ae0ac35 --- /dev/null +++ b/htdocs/style.css @@ -0,0 +1,29 @@ +body { + margin-left: 0px; + margin-right: 0px; + margin-top: 0px; + + background-color: black; + color: white; + + font-family: sans-serif; +} + +/* Navbar */ +nav { + background-color: #4acaa4; + font-size: 1.6em; +} +nav a { + font-size: 0.7em; + color: white; + text-decoration: none; +} +nav p:first-child + a { font-weight: bold; } +nav a.this-section { font-style: italic; } +nav p { display: inline; } +nav p:first-child { margin-left: 0.1em; } +nav hr { + margin: 0px; + color: white; +} diff --git a/index.html b/index.html deleted file mode 100644 index 39a00d6..0000000 --- a/index.html +++ /dev/null @@ -1,6 +0,0 @@ -<!doctype html> -<html> - <body> - <p>Hello, world!</p> - </body> -</html> diff --git a/server.go b/server.go new file mode 100644 index 0000000..d40c86c --- /dev/null +++ b/server.go @@ -0,0 +1,106 @@ +package main + +import ( + "fmt" + tmpl "html/template" + "io/fs" + "log" + "net/http" + "os" + "path" + fp "path/filepath" + "strings" +) + +const ( + host = "" + port = "6969" + root = "htdocs/" +) + +var tmpls = make(map[string]*tmpl.Template) + +func init() { + err := fp.WalkDir(root, func(path string, d fs.DirEntry, err error) error { + if fp.Clean(path) == fp.Clean(root) || + fp.Ext(path) != ".html" || + path == fp.Join(root, "base.html") { + return nil + } + label := path[len(fp.Clean(root)):] + tmpls[label] = tmpl.Must(tmpl.ParseFiles(fp.Join(root, "base.html"), path)) + return nil + }) + if err != nil { + log.Fatal(err) + } +} + +type Page struct { + Nav Nav +} + +type Nav struct { + ThisSection string + Links []NavLink +} + +type NavLink struct { + Href string + Label string +} + +var nav = Nav{ + Links: []NavLink{ + {"/", "samanthony.xyz"}, + {"/software/", "software"}, + }, +} + +func rootHandler(w http.ResponseWriter, r *http.Request) { + reqPath := r.URL.Path + + // If request directory, serve index.html. + // ie. /software -> /software/index.html + if info, err := os.Stat(fp.Join(root, reqPath)); err == nil { + if info.IsDir() { + reqPath = path.Join(reqPath, "index.html") + } + } else if os.IsNotExist(err) { + http.NotFound(w, r) + return + } else { + fmt.Println(err) + code := http.StatusInternalServerError + http.Error(w, http.StatusText(code), code) + return + } + + if t, ok := tmpls[reqPath]; ok { + thisSection := "" + for _, link := range nav.Links { + if strings.HasPrefix(reqPath, link.Href) { + thisSection = link.Href + } + } + nav := nav + nav.ThisSection = thisSection + page := Page{nav} + + err := t.Execute(w, page) + if err != nil { + fmt.Println(err) + code := http.StatusInternalServerError + http.Error(w, http.StatusText(code), code) + return + } + } else { + http.ServeFile(w, r, fp.Join(root, reqPath)) + } +} + +func main() { + http.HandleFunc("/", rootHandler) + fmt.Printf("Listening on %s:%s\n", host, port) + log.Fatal(http.ListenAndServe(fmt.Sprintf("%s:%s", host, port), nil)) +} |