From 4b58544300847e5faf19be5baa4eb177a86b2b0f Mon Sep 17 00:00:00 2001 From: Leonardo Bishop Date: Thu, 17 Jul 2025 21:52:26 +0100 Subject: Add automatic index --- pkg/site/fs.go | 84 ++++++++++++++++++++++++++++++++++++++++++++------------ pkg/site/site.go | 2 +- 2 files changed, 68 insertions(+), 18 deletions(-) (limited to 'pkg/site') diff --git a/pkg/site/fs.go b/pkg/site/fs.go index e8ee7fc..c9bbe21 100644 --- a/pkg/site/fs.go +++ b/pkg/site/fs.go @@ -1,45 +1,95 @@ package site import ( + "log/slog" "net/http" + "os" "path/filepath" "strings" + + "github.com/LMBishop/scrapbook/pkg/config" + "github.com/LMBishop/scrapbook/pkg/html" ) -type siteFS struct { - fs http.FileSystem +type SiteFileServer struct { + root http.FileSystem + siteConfig *config.SiteConfig +} + +func NewSiteFileServer(root http.FileSystem, siteConfig *config.SiteConfig) *SiteFileServer { + return &SiteFileServer{root: root, siteConfig: siteConfig} } -func (sfs siteFS) Open(path string) (http.File, error) { - f, err := sfs.fs.Open(path) +func (fs *SiteFileServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { + path := filepath.Clean(r.URL.Path) + + file, err := fs.root.Open(path) if err != nil { if strings.HasSuffix(path, ".html") { - return nil, err + html.NotFoundUrlPage(path, fs.siteConfig.Host).Render(w) + return } htmlPath := path + ".html" - f, err = sfs.fs.Open(htmlPath) + file, err = fs.root.Open(htmlPath) if err != nil { - return nil, err + html.NotFoundUrlPage(path, fs.siteConfig.Host).Render(w) + return } } + defer file.Close() - s, err := f.Stat() + info, err := file.Stat() if err != nil { - return nil, err + html.NotFoundUrlPage(path, fs.siteConfig.Host).Render(w) + return } - if s.IsDir() { - index := filepath.Join(path, "index.html") - if _, err := sfs.fs.Open(index); err != nil { - closeErr := f.Close() - if closeErr != nil { - return nil, closeErr + if info.IsDir() { + indexPath := filepath.Join(path, "index.html") + if _, err := fs.root.Open(indexPath); os.IsNotExist(err) { + if fs.siteConfig.Flags&config.FlagIndex == 0 { + html.NotFoundUrlPage(path, fs.siteConfig.Host).Render(w) + return } + files, err := fs.listFiles(path) + if path != "/" { + files = append([]html.File{{Name: "..", IsDir: true, Size: 0}}, files...) + } + if err != nil { + html.IndexPage(path, true, files).Render(w) + slog.Error("could not list directory for index page generation", "host", fs.siteConfig.Host, "path", path, "error", err) + } else { + html.IndexPage(path, false, files).Render(w) + } + return + } + http.ServeFile(w, r, indexPath) + } else { + http.ServeFile(w, r, path) + } +} + +func (fs *SiteFileServer) listFiles(dir string) ([]html.File, error) { + file, err := fs.root.Open(dir) + if err != nil { + return nil, err + } + defer file.Close() + + entries, err := file.Readdir(-1) + if err != nil { + return nil, err + } - return nil, err + var files []html.File + for _, entry := range entries { + if !entry.IsDir() { + files = append(files, html.File{Name: entry.Name(), IsDir: false, Size: entry.Size()}) + } else { + files = append(files, html.File{Name: entry.Name(), IsDir: true, Size: 0}) } } - return f, nil + return files, nil } diff --git a/pkg/site/site.go b/pkg/site/site.go index 82f25ad..8b7af41 100644 --- a/pkg/site/site.go +++ b/pkg/site/site.go @@ -30,7 +30,7 @@ func NewSite(name string, dir string, config *config.SiteConfig) *Site { site.Name = name site.Path = dir site.SiteConfig = config - site.Handler = http.FileServer(siteFS{http.Dir(path.Join(dir, "default"))}) + site.Handler = NewSiteFileServer(http.Dir(path.Join(dir, "default")), config) return &site } -- cgit v1.2.3-70-g09d2