all repos — homestead @ e586c122cf3b8fb845f8836f9361406ad94c844c

Code for my website

make posts a bit more abstract

Alan Pearce
commit

e586c122cf3b8fb845f8836f9361406ad94c844c

parent

143c1d889fb83fe3db5642e2f3ac6e15587929ab

M internal/builder/builder.gointernal/builder/builder.go
@@ -95,7 +95,7 @@ return nil, errors.WithMessage(err, "could not copy static files")
} log.Debug("reading posts", "source", options.Source) - posts, tags, err := content.ReadPosts(&content.Config{ + pc, err := content.NewPostsCollection(&content.Config{ Root: options.Source, InputDir: "post", }, log.Named("content"))
@@ -105,11 +105,11 @@ }
sitemap := sitemap.New(config) lastMod := time.Now() - if len(posts) > 0 { - lastMod = posts[0].Date + if len(pc.Posts) > 0 { + lastMod = pc.Posts[0].Date } - for _, post := range posts { + for _, post := range pc.Posts { log.Debug("rendering post", "post", post.Basename) sitemap.AddPath(post.URL, post.Date) if err := templates.PostPage(config, post).Render(ctx, buf); err != nil {
@@ -123,7 +123,7 @@ }
log.Debug("rendering tags list") buf.Reset() - if err := templates.TagsPage(config, "tags", mapset.Sorted(tags), "/tags").Render(ctx, buf); err != nil { + if err := templates.TagsPage(config, "tags", mapset.Sorted(pc.Tags), "/tags").Render(ctx, buf); err != nil { return nil, err } if err := storage.Write("/tags/", buf); err != nil {
@@ -131,9 +131,9 @@ return nil, err
} sitemap.AddPath("/tags/", lastMod) - for _, tag := range tags.ToSlice() { + for _, tag := range pc.Tags.ToSlice() { matchingPosts := []content.Post{} - for _, post := range posts { + for _, post := range pc.Posts { if slices.Contains(post.Taxonomies.Tags, tag) { matchingPosts = append(matchingPosts, post) }
@@ -170,7 +170,7 @@ }
log.Debug("rendering list page") buf.Reset() - if err := templates.ListPage(config, posts, "/post").Render(ctx, buf); err != nil { + if err := templates.ListPage(config, pc.Posts, "/post").Render(ctx, buf); err != nil { return nil, err } if err := storage.Write("/post/", buf); err != nil {
@@ -179,7 +179,7 @@ }
sitemap.AddPath("/post/", lastMod) log.Debug("rendering feed") - feed, err := renderFeed(config.Title, config, posts, "feed") + feed, err := renderFeed(config.Title, config, pc.Posts, "feed") if err != nil { return nil, errors.WithMessage(err, "could not render feed") }
@@ -214,16 +214,12 @@ }
r.Hashes = append(r.Hashes, h) log.Debug("rendering homepage") - _, text, err := content.GetPost(joinSource("index.md")) - if err != nil { - return nil, err - } - content, err := content.RenderMarkdown(text) + post, err := pc.GetPost("index.md") if err != nil { return nil, err } buf.Reset() - if err := templates.Homepage(config, posts, content).Render(ctx, buf); err != nil { + if err := templates.Homepage(config, pc.Posts, post).Render(ctx, buf); err != nil { return nil, err } if err := storage.Write("/", buf); err != nil {
M internal/builder/template.gointernal/builder/template.go
@@ -86,6 +86,10 @@ Entries: make([]*atom.FeedEntry, len(posts)),
} for i, post := range posts { + html, err := post.RenderString() + if err != nil { + return nil, errors.WithMessage(err, "could not render post") + } feed.Entries[i] = &atom.FeedEntry{ Title: post.Title, Link: atom.MakeLink(config.BaseURL.JoinPath(post.URL)),
@@ -94,7 +98,7 @@ Updated: post.Date.UTC(),
Summary: post.Description, Author: config.Title, Content: atom.FeedContent{ - Content: post.Content, + Content: html, Type: "html", }, }
M internal/content/posts.gointernal/content/posts.go
@@ -2,6 +2,8 @@ package content
import ( "bytes" + "context" + "io" "os" "path" "path/filepath"
@@ -34,11 +36,22 @@ Input string
Output string Basename string URL string - Content string - PostMatter + *PostMatter + + content []byte +} + +type Config struct { + Root string + InputDir string } -type Tags mapset.Set[string] +type PostsCollection struct { + config *Config + + Posts []Post + Tags mapset.Set[string] +} var markdown = goldmark.New( goldmark.WithRendererOptions(
@@ -52,91 +65,90 @@ &fences.Extender{},
), ) -func GetPost(filename string) (*PostMatter, []byte, error) { - matter := PostMatter{} - content, err := os.Open(filename) +var outputReplacer = strings.NewReplacer( + "index.md", "index.html", + ".md", "/index.html", +) +var urlReplacer = strings.NewReplacer( + "index.md", "", + ".md", "/", +) + +func (pc *PostsCollection) GetPost(filename string) (*Post, error) { + fp := filepath.Join(pc.config.Root, filename) + url := path.Join("/", pc.config.InputDir, urlReplacer.Replace(filename)) + "/" + post := &Post{ + Input: fp, + Output: path.Join(pc.config.InputDir, outputReplacer.Replace(filename)), + Basename: filepath.Base(url), + URL: url, + PostMatter: &PostMatter{}, + } + + content, err := os.Open(fp) if err != nil { - return nil, nil, errors.WithMessagef(err, "could not open post %s", filename) + return nil, errors.WithMessagef(err, "could not open post %s", fp) } defer content.Close() - rest, err := frontmatter.MustParse(content, &matter) + + post.content, err = frontmatter.Parse(content, post.PostMatter) if err != nil { - return nil, nil, errors.WithMessagef( + return nil, errors.WithMessagef( err, "could not parse front matter of post %s", - filename, + fp, ) } - return &matter, rest, nil + return post, nil } -func RenderMarkdown(content []byte) (string, error) { +// implements templ.Component +func (p *Post) Render(_ context.Context, w io.Writer) error { + return markdown.Convert(p.content, w) +} + +func (p *Post) RenderString() (string, error) { var buf bytes.Buffer - if err := markdown.Convert(content, &buf); err != nil { + if err := p.Render(context.Background(), &buf); err != nil { return "", errors.WithMessage(err, "could not convert markdown content") } return buf.String(), nil } -type Config struct { - Root string - InputDir string -} +func NewPostsCollection(config *Config, log *log.Logger) (*PostsCollection, error) { + pc := &PostsCollection{ + Posts: []Post{}, + Tags: mapset.NewSet[string](), + config: config, + } -func ReadPosts(config *Config, log *log.Logger) ([]Post, Tags, error) { - tags := mapset.NewSet[string]() - posts := []Post{} log.Debug("reading posts", "root", config.Root, "input_dir", config.InputDir) subdir := filepath.Join(config.Root, config.InputDir) files, err := os.ReadDir(subdir) if err != nil { - return nil, nil, errors.WithMessagef(err, "could not read post directory %s", subdir) + return nil, errors.WithMessagef(err, "could not read post directory %s", subdir) } - outputReplacer := strings.NewReplacer( - "index.md", "index.html", - ".md", "/index.html", - ) - urlReplacer := strings.NewReplacer( - "index.md", "", - ".md", "/", - ) for _, f := range files { fn := f.Name() if !f.IsDir() && path.Ext(fn) == ".md" { - output := path.Join(config.InputDir, outputReplacer.Replace(fn)) - url := path.Join("/", config.InputDir, urlReplacer.Replace(fn)) + "/" - log.Debug("reading post", "post", fn, "url", url) - matter, content, err := GetPost(path.Join(subdir, fn)) + log.Debug("reading post", "post", fn) + post, err := pc.GetPost(filepath.Join(subdir, fn)) if err != nil { - return nil, nil, err + return nil, err } - for _, tag := range matter.Taxonomies.Tags { - tags.Add(strings.ToLower(tag)) + for _, tag := range post.PostMatter.Taxonomies.Tags { + pc.Tags.Add(strings.ToLower(tag)) } - log.Debug("rendering markdown in post", "post", fn) - html, err := RenderMarkdown(content) - if err != nil { - return nil, nil, err - } - post := Post{ - Input: fn, - Output: output, - Basename: filepath.Base(url), - URL: url, - PostMatter: *matter, - Content: html, - } - - posts = append(posts, post) + pc.Posts = append(pc.Posts, *post) } } - slices.SortFunc(posts, func(a, b Post) int { + slices.SortFunc(pc.Posts, func(a, b Post) int { return b.Date.Compare(a.Date) }) - return posts, tags, nil + return pc, nil }
M templates/homepage.templtemplates/homepage.templ
@@ -5,7 +5,7 @@ "go.alanpearce.eu/website/internal/config"
"go.alanpearce.eu/website/internal/content" ) -templ Homepage(config *config.Config, posts []content.Post, content string) { +templ Homepage(config *config.Config, posts []content.Post, content templ.Component) { @Page(config, PageSettings{ Title: config.Title, TitleAttrs: templ.Attributes{
@@ -17,7 +17,7 @@ "class": "h-card",
}, }) { <div id="content"> - @Unsafe(content) + @content </div> <section> <h2>Latest Posts</h2>
M templates/post.templtemplates/post.templ
@@ -42,7 +42,7 @@ @postDate(post.Date)
</a> </p> <div class="e-content"> - @Unsafe(post.Content) + @post </div> <div class="tags"> Tags: