diff --git a/legit/routes/template.go b/legit/routes/file.go similarity index 58% rename from legit/routes/template.go rename to legit/routes/file.go index d7c96ae..03a5eb1 100644 --- a/legit/routes/template.go +++ b/legit/routes/file.go @@ -2,12 +2,10 @@ package routes import ( "bytes" - "fmt" "html/template" "io" "log" "net/http" - "path/filepath" "strings" "github.com/alecthomas/chroma/v2/formatters/html" @@ -16,36 +14,11 @@ import ( "github.com/icyphox/bild/legit/git" ) -func (h *Handle) Write404(w http.ResponseWriter) { - w.WriteHeader(404) - if err := h.t.ExecuteTemplate(w, "404", nil); err != nil { - log.Printf("404 template: %s", err) - } -} - -func (h *Handle) Write500(w http.ResponseWriter) { - w.WriteHeader(500) - if err := h.t.ExecuteTemplate(w, "500", nil); err != nil { - log.Printf("500 template: %s", err) - } -} - -func (h *Handle) WriteOOBNotice(w http.ResponseWriter, id, msg string) { - html := fmt.Sprintf(`%s`, id, msg) - - w.Header().Set("Content-Type", "text/html") - w.WriteHeader(http.StatusOK) - w.Write([]byte(html)) -} - func (h *Handle) listFiles(files []git.NiceTree, data map[string]any, w http.ResponseWriter) { - tpath := filepath.Join(h.c.Dirs.Templates, "*") - t := template.Must(template.ParseGlob(tpath)) - data["files"] = files data["meta"] = h.c.Meta - if err := t.ExecuteTemplate(w, "tree", data); err != nil { + if err := h.t.ExecuteTemplate(w, "repo/tree", data); err != nil { log.Println(err) return } @@ -77,16 +50,13 @@ func countLines(r io.Reader) (int, error) { } } -func (d *Handle) showFileWithHighlight(name, content string, data map[string]any, w http.ResponseWriter) { - tpath := filepath.Join(d.c.Dirs.Templates, "*") - t := template.Must(template.ParseGlob(tpath)) - +func (h *Handle) showFileWithHighlight(name, content string, data map[string]any, w http.ResponseWriter) { lexer := lexers.Get(name) if lexer == nil { lexer = lexers.Get(".txt") } - style := styles.Get(d.c.Meta.SyntaxHighlight) + style := styles.Get(h.c.Meta.SyntaxHighlight) if style == nil { style = styles.Get("monokailight") } @@ -98,31 +68,28 @@ func (d *Handle) showFileWithHighlight(name, content string, data map[string]any iterator, err := lexer.Tokenise(nil, content) if err != nil { - d.Write500(w) + h.Write500(w) return } var code bytes.Buffer err = formatter.Format(&code, style, iterator) if err != nil { - d.Write500(w) + h.Write500(w) return } data["content"] = template.HTML(code.String()) - data["meta"] = d.c.Meta + data["meta"] = h.c.Meta data["chroma"] = true - if err := t.ExecuteTemplate(w, "file", data); err != nil { + if err := h.t.ExecuteTemplate(w, "repo/file", data); err != nil { log.Println(err) return } } -func (d *Handle) showFile(content string, data map[string]any, w http.ResponseWriter) { - tpath := filepath.Join(d.c.Dirs.Templates, "*") - t := template.Must(template.ParseGlob(tpath)) - +func (h *Handle) showFile(content string, data map[string]any, w http.ResponseWriter) { lc, err := countLines(strings.NewReader(content)) if err != nil { // Non-fatal, we'll just skip showing line numbers in the template. @@ -138,16 +105,16 @@ func (d *Handle) showFile(content string, data map[string]any, w http.ResponseWr data["linecount"] = lines data["content"] = content - data["meta"] = d.c.Meta + data["meta"] = h.c.Meta data["chroma"] = false - if err := t.ExecuteTemplate(w, "file", data); err != nil { + if err := h.t.ExecuteTemplate(w, "repo/file", data); err != nil { log.Println(err) return } } -func (d *Handle) showRaw(content string, w http.ResponseWriter) { +func (h *Handle) showRaw(content string, w http.ResponseWriter) { w.WriteHeader(http.StatusOK) w.Header().Set("Content-Type", "text/plain") w.Write([]byte(content)) diff --git a/legit/routes/handler.go b/legit/routes/handler.go index 8288b90..d290984 100644 --- a/legit/routes/handler.go +++ b/legit/routes/handler.go @@ -2,9 +2,7 @@ package routes import ( "fmt" - "html/template" "net/http" - "path/filepath" _ "github.com/bluesky-social/indigo/atproto/identity" _ "github.com/bluesky-social/indigo/atproto/syntax" @@ -13,6 +11,7 @@ import ( "github.com/gorilla/sessions" "github.com/icyphox/bild/legit/config" "github.com/icyphox/bild/legit/db" + "github.com/icyphox/bild/legit/routes/tmpl" ) // Checks for gitprotocol-http(5) specific smells; if found, passes @@ -39,10 +38,13 @@ func (h *Handle) Multiplex(w http.ResponseWriter, r *http.Request) { func Setup(c *config.Config) (http.Handler, error) { r := chi.NewRouter() - t := template.Must(template.ParseGlob(filepath.Join(c.Dirs.Templates, "*"))) s := sessions.NewCookieStore([]byte("TODO_CHANGE_ME")) - db, err := db.Setup(c.Server.DBPath) + t, err := tmpl.Load(c.Dirs.Templates) + if err != nil { + return nil, fmt.Errorf("failed to load templates: %w", err) + } + db, err := db.Setup(c.Server.DBPath) if err != nil { return nil, fmt.Errorf("failed to setup db: %w", err) } diff --git a/legit/routes/html_util.go b/legit/routes/html_util.go new file mode 100644 index 0000000..991ce57 --- /dev/null +++ b/legit/routes/html_util.go @@ -0,0 +1,29 @@ +package routes + +import ( + "fmt" + "log" + "net/http" +) + +func (h *Handle) Write404(w http.ResponseWriter) { + w.WriteHeader(404) + if err := h.t.ExecuteTemplate(w, "errors/404", nil); err != nil { + log.Printf("404 template: %s", err) + } +} + +func (h *Handle) Write500(w http.ResponseWriter) { + w.WriteHeader(500) + if err := h.t.ExecuteTemplate(w, "errors/500", nil); err != nil { + log.Printf("500 template: %s", err) + } +} + +func (h *Handle) WriteOOBNotice(w http.ResponseWriter, id, msg string) { + html := fmt.Sprintf(`%s`, id, msg) + + w.Header().Set("Content-Type", "text/html") + w.WriteHeader(http.StatusOK) + w.Write([]byte(html)) +} diff --git a/legit/routes/routes.go b/legit/routes/routes.go index 958da3e..9a1107e 100644 --- a/legit/routes/routes.go +++ b/legit/routes/routes.go @@ -106,11 +106,10 @@ func (h *Handle) RepoIndex(w http.ResponseWriter, r *http.Request) { name = filepath.Clean(name) path := filepath.Join(h.c.Repo.ScanPath, name) - fmt.Println(path) gr, err := git.Open(path, "") if err != nil { if errors.Is(err, plumbing.ErrReferenceNotFound) { - h.t.ExecuteTemplate(w, "empty", nil) + h.t.ExecuteTemplate(w, "repo/empty", nil) return } else { h.Write404(w) @@ -173,7 +172,7 @@ func (h *Handle) RepoIndex(w http.ResponseWriter, r *http.Request) { data["meta"] = h.c.Meta data["gomod"] = isGoModule(gr) - if err := h.t.ExecuteTemplate(w, "repo", data); err != nil { + if err := h.t.ExecuteTemplate(w, "repo/repo", data); err != nil { log.Println(err) return } @@ -192,7 +191,6 @@ func (h *Handle) RepoTree(w http.ResponseWriter, r *http.Request) { name = filepath.Clean(name) path := filepath.Join(h.c.Repo.ScanPath, name) - fmt.Println(path) gr, err := git.Open(path, ref) if err != nil { h.Write404(w) @@ -348,7 +346,7 @@ func (h *Handle) Log(w http.ResponseWriter, r *http.Request) { data["desc"] = getDescription(path) data["log"] = true - if err := h.t.ExecuteTemplate(w, "log", data); err != nil { + if err := h.t.ExecuteTemplate(w, "repo/log", data); err != nil { log.Println(err) return } @@ -387,7 +385,7 @@ func (h *Handle) Diff(w http.ResponseWriter, r *http.Request) { data["ref"] = ref data["desc"] = getDescription(path) - if err := h.t.ExecuteTemplate(w, "commit", data); err != nil { + if err := h.t.ExecuteTemplate(w, "repo/commit", data); err != nil { log.Println(err) return } @@ -429,7 +427,7 @@ func (h *Handle) Refs(w http.ResponseWriter, r *http.Request) { data["tags"] = tags data["desc"] = getDescription(path) - if err := h.t.ExecuteTemplate(w, "refs", data); err != nil { + if err := h.t.ExecuteTemplate(w, "repo/refs", data); err != nil { log.Println(err) return } @@ -509,7 +507,7 @@ func (h *Handle) Keys(w http.ResponseWriter, r *http.Request) { data := make(map[string]interface{}) data["keys"] = keys - if err := h.t.ExecuteTemplate(w, "keys", data); err != nil { + if err := h.t.ExecuteTemplate(w, "settings/keys", data); err != nil { log.Println(err) return } @@ -541,7 +539,7 @@ func (h *Handle) NewRepo(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: - if err := h.t.ExecuteTemplate(w, "new", nil); err != nil { + if err := h.t.ExecuteTemplate(w, "repo/new", nil); err != nil { log.Println(err) return } diff --git a/legit/routes/tmpl/tmpl.go b/legit/routes/tmpl/tmpl.go new file mode 100644 index 0000000..2f8d757 --- /dev/null +++ b/legit/routes/tmpl/tmpl.go @@ -0,0 +1,54 @@ +package tmpl + +import ( + "html/template" + "log" + "os" + "path/filepath" + "strings" +) + +func Load(tpath string) (*template.Template, error) { + tmpl := template.New("") + loadedTemplates := make(map[string]bool) + + err := filepath.Walk(tpath, func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + + if !info.IsDir() && strings.HasSuffix(path, ".html") { + content, err := os.ReadFile(path) + if err != nil { + return err + } + + relPath, err := filepath.Rel(tpath, path) + if err != nil { + return err + } + + name := strings.TrimSuffix(relPath, ".html") + name = strings.ReplaceAll(name, string(filepath.Separator), "/") + + _, err = tmpl.New(name).Parse(string(content)) + if err != nil { + log.Printf("error parsing template %s: %v", name, err) + return err + } + + loadedTemplates[name] = true + log.Printf("loaded template: %s", name) + return err + } + return nil + }) + + if err != nil { + return nil, err + } + + log.Printf("total templates loaded: %d", len(loadedTemplates)) + return tmpl, nil + +} diff --git a/legit/templates/404.html b/legit/templates/404.html deleted file mode 100644 index 8c40cd1..0000000 --- a/legit/templates/404.html +++ /dev/null @@ -1,13 +0,0 @@ -{{ define "404" }} - -
- {{- .commit.Message -}}
-
+ {{- .commit.Message -}}
{{ .path }} (view raw)
{{if .chroma }} @@ -33,4 +32,3 @@