summary refs log tree commit diff homepage
diff options
context:
space:
mode:
-rw-r--r--main.go62
-rw-r--r--static/archive.css24
-rw-r--r--templates/archive.html22
-rw-r--r--templates/directory.html12
4 files changed, 98 insertions, 22 deletions
diff --git a/main.go b/main.go
index 4fa807b..c60be5b 100644
--- a/main.go
+++ b/main.go
@@ -22,8 +22,8 @@ import (
 	"archive/zip"
 	"embed"
 	"html/template"
-	"log"
 	"io"
+	"log"
 	"net/http"
 	"os"
 	"path"
@@ -39,15 +39,30 @@ var templates embed.FS
 
 type Page struct {
 	Index int
-	Name string
+	Name  string
 }
 
 type Archive struct {
-	Path string
-	Title string
+	Title   string
+	Prev    template.URL
+	Next    template.URL
 	Entries []Page
 }
 
+type Directory struct {
+	Title   string
+	Entries []string
+}
+
+func find(entries []os.DirEntry, name string) int {
+	for i, entry := range entries {
+		if entry.Name() == name {
+			return i
+		}
+	}
+	return -1
+}
+
 func main() {
 	http.Handle("/static/", http.FileServer(http.FS(static)))
 	t, err := template.ParseFS(templates, "templates/*.html")
@@ -56,7 +71,7 @@ func main() {
 	}
 	lib := os.Getenv("PHYLACTERY_LIBRARY")
 	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
-		p := path.Clean(lib + r.URL.Path)
+		p := path.Join(lib, path.Clean(r.URL.Path))
 		stat, err := os.Stat(p)
 		if err != nil {
 			http.NotFound(w, r)
@@ -64,13 +79,34 @@ func main() {
 		}
 
 		if stat.IsDir() {
-			// TODO
+			if !strings.HasSuffix(r.URL.Path, "/") {
+				http.Redirect(w, r, r.URL.Path+"/",
+					http.StatusMovedPermanently)
+				return
+			}
+
+			entries, _ := os.ReadDir(p)
+			var names []string
+			for _, entry := range entries {
+				if entry.IsDir() {
+					names = append(names, entry.Name()+"/")
+				} else {
+					names = append(names, entry.Name())
+				}
+			}
+			dir := Directory{stat.Name(), names}
+			t.ExecuteTemplate(w, "directory.html", dir)
+			return
+		} else if strings.HasSuffix(r.URL.Path, "/") {
+			http.Redirect(w, r, r.URL.Path[:len(r.URL.Path)-1],
+				http.StatusMovedPermanently)
+			return
 		}
 
 		// TODO: LRU caching
 		cbz, err := zip.OpenReader(p)
 		if err != nil {
-			http.Error(w, "invalid cbz", 406)
+			http.Error(w, "invalid cbz", http.StatusNotAcceptable)
 			return
 		}
 		defer cbz.Close()
@@ -88,6 +124,8 @@ func main() {
 			return
 		}
 
+		entries, _ := os.ReadDir(path.Join(p, ".."))
+		index := find(entries, stat.Name())
 		var pages []Page
 		for i, f := range cbz.File {
 			image, _ := cbz.File[i].Open()
@@ -96,11 +134,15 @@ func main() {
 			n, _ := image.Read(buf)
 			mime := http.DetectContentType(buf[:n])
 			if strings.HasPrefix(mime, "image/") {
-				pages = append(pages, Page{ i, f.Name })
+				pages = append(pages, Page{i, f.Name})
 			}
 		}
-		archive := Archive{ r.URL.Path, stat.Name(), pages }
-		t.ExecuteTemplate(w, "archive.html", archive)
+		t.ExecuteTemplate(w, "archive.html", Archive{
+			stat.Name(),
+			template.URL(entries[index-1].Name()),
+			template.URL(entries[index+1].Name()),
+			pages,
+		})
 	})
 
 	addr := os.Getenv("PHYLACTERY_ADDRESS")
diff --git a/static/archive.css b/static/archive.css
new file mode 100644
index 0000000..7bd1c47
--- /dev/null
+++ b/static/archive.css
@@ -0,0 +1,24 @@
+body { margin: 0 }
+
+nav {
+    display: flex;
+    justify-content: space-around;
+    position: sticky;
+    top: 0;
+}
+nav > a {
+    color: white;
+    flex: 1;
+    text-align: center;
+    text-decoration: none;
+}
+nav > a:hover { font-weight: bold }
+#prev { background-color: #a40000 }
+#up { background-color: #4e9a06 }
+#next { background-color: #204a87 }
+
+img {
+    display: block;
+    margin: auto;
+    max-width: 100%;
+}
diff --git a/templates/archive.html b/templates/archive.html
index d3d8e0b..c0cc144 100644
--- a/templates/archive.html
+++ b/templates/archive.html
@@ -1,19 +1,17 @@
 <!DOCTYPE html>
 <html lang=en>
 <meta charset=utf-8>
-<link rel=stylesheet href=/static/archive.css>
 <link rel=icon href=/static/favicon.svg>
+<link rel=stylesheet href=/static/archive.css>
 <title>{{.Title}}</title>
-<style>
-body { margin: 0 }
-img {
-    display: block;
-    margin: auto;
-    max-width: 100%;
-}
-</style>
-
-<body>{{range .Entries}}
-<img src="?entry={{.Index}}" alt="{{.Name}}">{{end}}
+<body>
+  <nav>
+    <a id=prev href="{{.Prev}}">PREV</a>
+    <a id=up href=.>UP</a>
+    <a id=next href="{{.Next}}">NEXT</a>
+  </nav>
+  <main>{{range .Entries}}
+    <img src="?entry={{.Index}}" alt="{{.Name}}">{{end}}
+  </main>
 </body>
 </html>
diff --git a/templates/directory.html b/templates/directory.html
new file mode 100644
index 0000000..c89d388
--- /dev/null
+++ b/templates/directory.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html lang=en>
+<meta charset=utf-8>
+<link rel=icon href=/static/favicon.svg>
+<title>{{.Title}}</title>
+<body>
+  <main>
+    <p><a href=../>../</a></p>{{range .Entries}}
+    <p><a href="./{{.}}">{{.}}</a></p>{{end}}
+  </main>
+</body>
+</html>