From 1b496432df1dc28b25eaeadec5fa537aaf014f98 Mon Sep 17 00:00:00 2001 From: a73x Date: Sun, 25 Aug 2024 15:14:42 +0100 Subject: feat(post): templating add templating for posts and first post --- cmd/generate/main.go | 44 ----------------- cmd/home/main.go | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 130 insertions(+), 46 deletions(-) delete mode 100644 cmd/generate/main.go (limited to 'cmd') diff --git a/cmd/generate/main.go b/cmd/generate/main.go deleted file mode 100644 index a739fea..0000000 --- a/cmd/generate/main.go +++ /dev/null @@ -1,44 +0,0 @@ -package main - -import ( - "fmt" - "log" - "os" - "path/filepath" - "text/template" -) - -func Run() error { - t, err := template.ParseGlob("./templates/layouts/*.html") - // t, err := template.ParseFiles("index.html", "header.html") - if err != nil { - return fmt.Errorf("Failed to parse layouts: %v", err) - } - - for _, page := range []string{"index.html", "posts.html"} { - file, err := os.Create(filepath.Join("public", page)) - if err != nil { - return fmt.Errorf("Failed to create file: %v", err) - } - - defer file.Close() - - foo, err := t.ParseFiles("./templates/" + page) - if err != nil { - return fmt.Errorf("Parse template file: %v", err) - } - - err = foo.ExecuteTemplate(file, "index.html", nil) - if err != nil { - return fmt.Errorf("Failed to generate file: %v", err) - } - } - - return nil - -} -func main() { - if err := Run(); err != nil { - log.Fatal(err) - } -} diff --git a/cmd/home/main.go b/cmd/home/main.go index f284c30..01bddee 100644 --- a/cmd/home/main.go +++ b/cmd/home/main.go @@ -1,15 +1,131 @@ package main import ( + "bytes" + "fmt" + "io" "io/fs" "log" "net/http" + "path/filepath" + "strings" + "text/template" "time" "git.sr.ht/~a73x/home" + "github.com/yuin/goldmark" + "github.com/yuin/goldmark/parser" + "go.abhg.dev/goldmark/frontmatter" "go.uber.org/zap" ) +type CommonData struct { + Posts []PostData +} + +type PostData struct { + Title string + Path string +} + +func GeneratePosts(mux *http.ServeMux) ([]PostData, error) { + converter := goldmark.New( + goldmark.WithExtensions( + &frontmatter.Extender{}, + )) + + t, err := template.ParseFS(home.Content, "templates/layouts/*.html") + if err != nil { + return nil, fmt.Errorf("failed to parse layouts: %v", err) + } + + final := []PostData{} + posts, err := fs.Glob(home.Content, "posts/*.md") + if err != nil { + return nil, fmt.Errorf("failed to glob posts: %v", err) + } + + for _, post := range posts { + postName := filepath.Base(post) + postName = strings.Split(postName, ".")[0] + ".html" + + // parse markdown + input, err := fs.ReadFile(home.Content, post) + if err != nil { + return nil, fmt.Errorf("failed to read post: %v", err) + } + + var b bytes.Buffer + ctx := parser.NewContext() + if err := converter.Convert(input, &b, parser.WithContext(ctx)); err != nil { + return nil, err + } + + d := frontmatter.Get(ctx) + var meta map[string]string + if err := d.Decode(&meta); err != nil { + return nil, err + } + + foo, err := t.ParseFS(home.Content, "templates/post.html") + if err != nil { + return nil, fmt.Errorf("failed to parse post template: %v", err) + } + + content, err := io.ReadAll(&b) + if err != nil { + return nil, fmt.Errorf("failed to read post template: %v", err) + } + + mux.HandleFunc("/posts/"+postName, func(w http.ResponseWriter, r *http.Request) { + if err := foo.ExecuteTemplate(w, "post.html", string(content)); err != nil { + fmt.Println(err) + } + }) + + final = append(final, PostData{ + Title: meta["title"], + Path: "posts/" + postName, + }) + } + + return final, nil +} + +func loadTemplates(mux *http.ServeMux, data any) error { + tmplFiles, err := fs.ReadDir(home.Content, "templates") + if err != nil { + return fmt.Errorf("failed to parse template layouts") + } + + for _, tmpl := range tmplFiles { + if tmpl.IsDir() { + continue + } + + pt, err := template.ParseFS(home.Content, "templates/"+tmpl.Name(), "templates/layouts/*.html") + if err != nil { + return fmt.Errorf("failed to parse template "+tmpl.Name(), err) + } + + if tmpl.Name() == "index.html" { + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + pt.ExecuteTemplate(w, tmpl.Name(), data) + }) + } else if tmpl.Name() == "page.html" { + continue + } else { + mux.HandleFunc("/"+tmpl.Name(), func(w http.ResponseWriter, r *http.Request) { + pt, err := template.ParseFS(home.Content, "templates/"+tmpl.Name(), "templates/layouts/*.html") + if err != nil { + fmt.Printf("failed to parse template "+tmpl.Name(), err) + } + pt.ExecuteTemplate(w, tmpl.Name(), data) + }) + } + } + return nil +} func main() { logger, _ := zap.NewProduction() loggingMiddleware := func(next http.Handler) http.Handler { @@ -26,13 +142,25 @@ func main() { } mux := http.NewServeMux() + postData, err := GeneratePosts(mux) + data := CommonData{ + Posts: postData, + } + + if err != nil { + log.Fatal("failed to generate posts", err) + } + + if err := loadTemplates(mux, data); err != nil { + log.Fatal("failed to parse templates", err) + } - staticFs, err := fs.Sub(home.Content, "public") + staticFs, err := fs.Sub(home.Content, "public/static") if err != nil { log.Fatal(err) } - mux.Handle("GET /", http.FileServer(http.FS(staticFs))) + mux.Handle("GET /static", http.FileServer(http.FS(staticFs))) server := http.Server{ Addr: ":8080", -- cgit v1.2.3