diff options
-rw-r--r-- | CHANGES | 4 | ||||
-rw-r--r-- | README.md | 11 | ||||
-rw-r--r-- | main.go | 17 | ||||
-rw-r--r-- | static/base.css | 8 | ||||
-rw-r--r-- | templates/archive.html | 3 | ||||
-rw-r--r-- | templates/base-foot.html | 5 | ||||
-rw-r--r-- | templates/directory.html | 3 | ||||
-rw-r--r-- | templates/index.html | 10 |
8 files changed, 46 insertions, 15 deletions
diff --git a/CHANGES b/CHANGES new file mode 100644 index 0000000..f83c2bc --- /dev/null +++ b/CHANGES @@ -0,0 +1,4 @@ +Tag: 0.1.0 +Date: 2022-06-28 + + Initial release diff --git a/README.md b/README.md index bf38a86..dac8e3f 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,16 @@ Phylactery is a web server rendering comic books directly from ZIP archives. +## Installation + + go build -o $prefix/bin/phylactery main.go + +## Usage + +Set environment variables `PHYLACTERY_LIBRARY` to where +the [comic book archives] are stored and `PHYLACTERY_ADDRESS` +to the listening address and run `phylactery`. + ## Hacking PHYLACTERY_LIBRARY=/path/to/library PHYLACTERY_ADDRESS=:42069 go run main.go @@ -15,4 +25,5 @@ under the terms of the GNU [Affero General Public License][agplv3] as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. +[comic book archives]: https://en.wikipedia.org/wiki/Comic_book_archive [agplv3]: https://www.gnu.org/licenses/agpl-3.0.html diff --git a/main.go b/main.go index 42db6d2..b364d20 100644 --- a/main.go +++ b/main.go @@ -37,11 +37,13 @@ var static embed.FS //go:embed templates/*.html var templates embed.FS +// Type Page represents a comic page. type Page struct { Index int Name string } +// Type Archive represents a comic book zip archive. type Archive struct { Title string Prev string @@ -49,15 +51,19 @@ type Archive struct { Entries []Page } +// Type Directory represents a library directory in file system. type Directory struct { Title string Entries []string } +// Function escape ensures that question marks in path +// are not recognized as URL parameters. func escape(name string) template.URL { return template.URL(strings.Replace(name, "?", "%3f", -1)) } +// Function find searches for the directory entry of given name. func find(entries []os.DirEntry, name string) int { for i, entry := range entries { if entry.Name() == name { @@ -67,6 +73,8 @@ func find(entries []os.DirEntry, name string) int { return -1 } +// Function main starts Phylactery serving comics from PHYLACTERY_LIBRARY +// and listening on PHYLACTERY_ADDRESS. func main() { http.Handle("/static/", http.FileServer(http.FS(static))) t, err := template.New("").Funcs(template.FuncMap{ @@ -85,12 +93,15 @@ func main() { } if stat.IsDir() { + // Redirect URL without a trailing slash + // pointing to a non-directory page if !strings.HasSuffix(r.URL.Path, "/") { http.Redirect(w, r, r.URL.Path+"/", http.StatusMovedPermanently) return } + // Render directory page entries, _ := os.ReadDir(p) var names []string for _, entry := range entries { @@ -104,12 +115,14 @@ func main() { t.ExecuteTemplate(w, "directory.html", dir) return } else if strings.HasSuffix(r.URL.Path, "/") { + // Redirect URL with a trailing slash + // pointing to a non-directory page http.Redirect(w, r, r.URL.Path[:len(r.URL.Path)-1], http.StatusMovedPermanently) return } - // TODO: LRU caching + // Check if file is a valid ZIP archive cbz, err := zip.OpenReader(p) if err != nil { http.Error(w, "invalid cbz", http.StatusNotAcceptable) @@ -117,6 +130,7 @@ func main() { } defer cbz.Close() + // Respond with an image inside the CBZ r.ParseForm() if entry, isImage := r.Form["entry"]; isImage { i, err := strconv.Atoi(entry[0]) @@ -130,6 +144,7 @@ func main() { return } + // Render archive page entries, _ := os.ReadDir(path.Join(p, "..")) index := find(entries, stat.Name()) var pages []Page diff --git a/static/base.css b/static/base.css index 549ac8f..5f63e67 100644 --- a/static/base.css +++ b/static/base.css @@ -10,3 +10,11 @@ a { color: white; text-decoration: none; } + +footer { + color: white; + margin: auto; + padding: 1ex; + text-align: center; +} +footer a { text-decoration: underline } diff --git a/templates/archive.html b/templates/archive.html index ee5d2b3..619a5bc 100644 --- a/templates/archive.html +++ b/templates/archive.html @@ -12,5 +12,4 @@ <main>{{range .Entries}} <img src="?entry={{.Index}}" alt="{{.Name}}">{{end}} </main> -</body> -</html> +{{template "base-foot.html" -}} diff --git a/templates/base-foot.html b/templates/base-foot.html new file mode 100644 index 0000000..caf7fff --- /dev/null +++ b/templates/base-foot.html @@ -0,0 +1,5 @@ + <footer> + Powered by <a href=https://git.sr.ht/~cnx/phylactery>Phylactery</a> + </footer> +</body> +</html> diff --git a/templates/directory.html b/templates/directory.html index a04637e..570e526 100644 --- a/templates/directory.html +++ b/templates/directory.html @@ -6,5 +6,4 @@ <a href=../><p>../</p></a>{{range .Entries}} <a href="./{{. | escape}}"><p>{{.}}</p></a>{{end}} </main> -</body> -</html> +{{template "base-foot.html" -}} diff --git a/templates/index.html b/templates/index.html deleted file mode 100644 index 67f96fb..0000000 --- a/templates/index.html +++ /dev/null @@ -1,10 +0,0 @@ -<!DOCTYPE html> -<html lang=en> -<meta charset=utf-8> -<meta name=viewport content='width=device-width, initial-scale=1'> -<link rel=stylesheet href=/static/style.css> -<link rel=icon href=/static/favicon.svg> -<title>{{.}}</title> -<body> -</body> -</html> |