about summary refs log tree commit diff stats
path: root/internal/builder
diff options
context:
space:
mode:
authorAlan Pearce2024-06-18 20:13:26 +0200
committerAlan Pearce2024-06-18 20:13:26 +0200
commitb27c96688785372787eb5c3c71a32767fab71ac4 (patch)
tree2e39bc6cd94724953cf917c509fb141d39690cf1 /internal/builder
parent1d247493e05cdc659e46cd3d8a01d5da1e893867 (diff)
downloadwebsite-b27c96688785372787eb5c3c71a32767fab71ac4.tar.lz
website-b27c96688785372787eb5c3c71a32767fab71ac4.tar.zst
website-b27c96688785372787eb5c3c71a32767fab71ac4.zip
split content and sitemap code from builder
Diffstat (limited to 'internal/builder')
-rw-r--r--internal/builder/builder.go35
-rw-r--r--internal/builder/homepage.templ5
-rw-r--r--internal/builder/list.templ11
-rw-r--r--internal/builder/post.templ3
-rw-r--r--internal/builder/posts.go129
-rw-r--r--internal/builder/sitemap.go29
-rw-r--r--internal/builder/template.go3
7 files changed, 25 insertions, 190 deletions
diff --git a/internal/builder/builder.go b/internal/builder/builder.go
index 7b6af0b..141bd6f 100644
--- a/internal/builder/builder.go
+++ b/internal/builder/builder.go
@@ -11,13 +11,14 @@ import (
 	"time"
 
 	"website/internal/config"
+	"website/internal/content"
 	"website/internal/log"
+	"website/internal/sitemap"
 
 	"github.com/a-h/templ"
 	mapset "github.com/deckarep/golang-set/v2"
 	cp "github.com/otiai10/copy"
 	"github.com/pkg/errors"
-	"github.com/snabb/sitemap"
 )
 
 type IOConfig struct {
@@ -108,12 +109,12 @@ func build(outDir string, config config.Config) (*Result, error) {
 		return nil, errors.WithMessage(err, "could not create post output directory")
 	}
 	log.Debug("reading posts")
-	posts, tags, err := readPosts("content", "post", publicDir)
+	posts, tags, err := content.ReadPosts("content", "post", publicDir)
 	if err != nil {
 		return nil, err
 	}
 
-	sm := NewSitemap(config)
+	sitemap := sitemap.New(config)
 	lastMod := time.Now()
 	if len(posts) > 0 {
 		lastMod = posts[0].Date
@@ -124,10 +125,7 @@ func build(outDir string, config config.Config) (*Result, error) {
 			return nil, errors.WithMessage(err, "could not create directory for post")
 		}
 		log.Debug("rendering post", "post", post.Basename)
-		sm.Add(&sitemap.URL{
-			Loc:     post.URL,
-			LastMod: &post.Date,
-		})
+		sitemap.AddPath(post.URL, post.Date)
 		if err := renderToFile(postPage(config, post), post.Output); err != nil {
 			return nil, err
 		}
@@ -140,13 +138,10 @@ func build(outDir string, config config.Config) (*Result, error) {
 	if err := renderToFile(tagsPage(config, "tags", mapset.Sorted(tags), "/tags"), publicDir, "tags", "index.html"); err != nil {
 		return nil, err
 	}
-	sm.Add(&sitemap.URL{
-		Loc:     "/tags/",
-		LastMod: &lastMod,
-	})
+	sitemap.AddPath("/tags/", lastMod)
 
 	for _, tag := range tags.ToSlice() {
-		matchingPosts := []Post{}
+		matchingPosts := []content.Post{}
 		for _, post := range posts {
 			if slices.Contains(post.Taxonomies.Tags, tag) {
 				matchingPosts = append(matchingPosts, post)
@@ -160,10 +155,7 @@ func build(outDir string, config config.Config) (*Result, error) {
 		if err := renderToFile(tagPage(config, tag, matchingPosts, url), publicDir, "tags", tag, "index.html"); err != nil {
 			return nil, err
 		}
-		sm.Add(&sitemap.URL{
-			Loc:     url,
-			LastMod: &matchingPosts[0].Date,
-		})
+		sitemap.AddPath(url, matchingPosts[0].Date)
 
 		log.Debug("rendering tags feed", "tag", tag)
 		feed, err := renderFeed(
@@ -184,10 +176,7 @@ func build(outDir string, config config.Config) (*Result, error) {
 	if err := renderToFile(listPage(config, posts, "/post"), publicDir, "post", "index.html"); err != nil {
 		return nil, err
 	}
-	sm.Add(&sitemap.URL{
-		Loc:     "/post/",
-		LastMod: &lastMod,
-	})
+	sitemap.AddPath("/post/", lastMod)
 
 	log.Debug("rendering feed")
 	feed, err := renderFeed(config.Title, config, posts, "feed")
@@ -223,9 +212,7 @@ func build(outDir string, config config.Config) (*Result, error) {
 	// it would be nice to set LastMod here, but using the latest post
 	// date would be wrong as the homepage has its own content file
 	// without a date, which could be newer
-	sm.Add(&sitemap.URL{
-		Loc: "/",
-	})
+	sitemap.AddPath("/", time.Time{})
 	h, _ = getHTMLStyleHash(publicDir, "index.html")
 	r.Hashes = append(r.Hashes, h)
 
@@ -235,7 +222,7 @@ func build(outDir string, config config.Config) (*Result, error) {
 	}
 
 	log.Debug("rendering sitemap")
-	if err := writerToFile(sm, publicDir, "sitemap.xml"); err != nil {
+	if err := writerToFile(sitemap, publicDir, "sitemap.xml"); err != nil {
 		return nil, err
 	}
 
diff --git a/internal/builder/homepage.templ b/internal/builder/homepage.templ
index 9897b5d..1df401b 100644
--- a/internal/builder/homepage.templ
+++ b/internal/builder/homepage.templ
@@ -3,11 +3,12 @@ package builder
 import (
 	"website/internal/config"
 	"path"
+	"website/internal/content"
 )
 
 func getContent(filename string) templ.Component {
 	return templ.ComponentFunc(func(ctx context.Context, w io.Writer) error {
-		_, index, err := getPost(path.Join("content", filename))
+		_, index, err := content.GetPost(path.Join("content", filename))
 		if err != nil {
 			return err
 		}
@@ -17,7 +18,7 @@ func getContent(filename string) templ.Component {
 	})
 }
 
-templ homepage(config config.Config, posts []Post) {
+templ homepage(config config.Config, posts []content.Post) {
 	@page(config, PageSettings{
 		Title: config.Title,
 		TitleAttrs: templ.Attributes{
diff --git a/internal/builder/list.templ b/internal/builder/list.templ
index 48563ed..24cafe8 100644
--- a/internal/builder/list.templ
+++ b/internal/builder/list.templ
@@ -1,8 +1,11 @@
 package builder
 
-import "website/internal/config"
+import (
+	"website/internal/config"
+	"website/internal/content"
+)
 
-templ tagPage(config config.Config, tag string, posts []Post, path string) {
+templ tagPage(config config.Config, tag string, posts []content.Post, path string) {
 	@page(config, PageSettings{
 		Title: tag,
 		Path:  path,
@@ -21,7 +24,7 @@ templ tagPage(config config.Config, tag string, posts []Post, path string) {
 	}
 }
 
-templ listPage(config config.Config, posts []Post, path string) {
+templ listPage(config config.Config, posts []content.Post, path string) {
 	@page(config, PageSettings{
 		Title: config.Title,
 		TitleAttrs: templ.Attributes{
@@ -34,7 +37,7 @@ templ listPage(config config.Config, posts []Post, path string) {
 	}
 }
 
-templ list(posts []Post) {
+templ list(posts []content.Post) {
 	<ul class="h-feed">
 		for _, post := range posts {
 			<li class="h-entry">
diff --git a/internal/builder/post.templ b/internal/builder/post.templ
index 740c5aa..6f12e5c 100644
--- a/internal/builder/post.templ
+++ b/internal/builder/post.templ
@@ -3,6 +3,7 @@ package builder
 import (
 	"time"
 	"website/internal/config"
+	"website/internal/content"
 )
 
 func Unsafe(html string) templ.Component {
@@ -18,7 +19,7 @@ templ postDate(d time.Time) {
 	</time>
 }
 
-templ postPage(config config.Config, post Post) {
+templ postPage(config config.Config, post content.Post) {
 	@page(config, PageSettings{
 		Title: post.Title,
 		TitleAttrs: templ.Attributes{
diff --git a/internal/builder/posts.go b/internal/builder/posts.go
deleted file mode 100644
index deae3e8..0000000
--- a/internal/builder/posts.go
+++ /dev/null
@@ -1,129 +0,0 @@
-package builder
-
-import (
-	"bytes"
-	"os"
-	"path"
-	"path/filepath"
-	"slices"
-	"strings"
-	"time"
-	"website/internal/log"
-
-	"github.com/adrg/frontmatter"
-	mapset "github.com/deckarep/golang-set/v2"
-	"github.com/pkg/errors"
-	fences "github.com/stefanfritsch/goldmark-fences"
-	"github.com/yuin/goldmark"
-	"github.com/yuin/goldmark/extension"
-	htmlrenderer "github.com/yuin/goldmark/renderer/html"
-)
-
-type PostMatter struct {
-	Date        time.Time `toml:"date"`
-	Description string    `toml:"description"`
-	Title       string    `toml:"title"`
-	Taxonomies  struct {
-		Tags []string `toml:"tags"`
-	} `toml:"taxonomies"`
-}
-
-type Post struct {
-	Input    string
-	Output   string
-	Basename string
-	URL      string
-	Content  string
-	PostMatter
-}
-
-type Tags mapset.Set[string]
-
-var markdown = goldmark.New(
-	goldmark.WithRendererOptions(
-		htmlrenderer.WithUnsafe(),
-	),
-	goldmark.WithExtensions(
-		extension.GFM,
-		extension.Footnote,
-		extension.Typographer,
-		&fences.Extender{},
-	),
-)
-
-func getPost(filename string) (*PostMatter, []byte, error) {
-	matter := PostMatter{}
-	content, err := os.Open(filename)
-	if err != nil {
-		return nil, nil, errors.WithMessagef(err, "could not open post %s", filename)
-	}
-	defer content.Close()
-	rest, err := frontmatter.MustParse(content, &matter)
-	if err != nil {
-		return nil, nil, errors.WithMessagef(
-			err,
-			"could not parse front matter of post %s",
-			filename,
-		)
-	}
-
-	return &matter, rest, nil
-}
-
-func renderMarkdown(content []byte) (string, error) {
-	var buf bytes.Buffer
-	if err := markdown.Convert(content, &buf); err != nil {
-		return "", errors.WithMessage(err, "could not convert markdown content")
-	}
-
-	return buf.String(), nil
-}
-
-func readPosts(root string, inputDir string, outputDir string) ([]Post, Tags, error) {
-	tags := mapset.NewSet[string]()
-	posts := []Post{}
-	subdir := filepath.Join(root, inputDir)
-	files, err := os.ReadDir(subdir)
-	if err != nil {
-		return nil, nil, errors.WithMessagef(err, "could not read post directory %s", subdir)
-	}
-	outputReplacer := strings.NewReplacer(root, outputDir, ".md", "/index.html")
-	urlReplacer := strings.NewReplacer(root, "", ".md", "/")
-	for _, f := range files {
-		pathFromRoot := filepath.Join(subdir, f.Name())
-		if !f.IsDir() && path.Ext(pathFromRoot) == ".md" {
-			output := outputReplacer.Replace(pathFromRoot)
-			url := urlReplacer.Replace(pathFromRoot)
-			log.Debug("reading post", "post", pathFromRoot)
-			matter, content, err := getPost(pathFromRoot)
-			if err != nil {
-				return nil, nil, err
-			}
-
-			for _, tag := range matter.Taxonomies.Tags {
-				tags.Add(strings.ToLower(tag))
-			}
-
-			log.Debug("rendering markdown in post", "post", pathFromRoot)
-			html, err := renderMarkdown(content)
-			if err != nil {
-				return nil, nil, err
-			}
-			post := Post{
-				Input:      pathFromRoot,
-				Output:     output,
-				Basename:   filepath.Base(url),
-				URL:        url,
-				PostMatter: *matter,
-				Content:    html,
-			}
-
-			posts = append(posts, post)
-		}
-	}
-	slices.SortFunc(posts, func(a, b Post) int {
-		return b.Date.Compare(a.Date)
-	})
-
-	return posts, tags, nil
-}
diff --git a/internal/builder/sitemap.go b/internal/builder/sitemap.go
deleted file mode 100644
index 81e3a31..0000000
--- a/internal/builder/sitemap.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package builder
-
-import (
-	"io"
-	"website/internal/config"
-
-	"github.com/snabb/sitemap"
-)
-
-type Sitemap struct {
-	config  *config.Config
-	Sitemap *sitemap.Sitemap
-}
-
-func NewSitemap(cfg config.Config) *Sitemap {
-	return &Sitemap{
-		config:  &cfg,
-		Sitemap: sitemap.New(),
-	}
-}
-
-func (s *Sitemap) Add(u *sitemap.URL) {
-	u.Loc = s.config.BaseURL.JoinPath(u.Loc).String()
-	s.Sitemap.Add(u)
-}
-
-func (s *Sitemap) WriteTo(w io.Writer) (int64, error) {
-	return s.Sitemap.WriteTo(w)
-}
diff --git a/internal/builder/template.go b/internal/builder/template.go
index 376e48a..9b1d9bd 100644
--- a/internal/builder/template.go
+++ b/internal/builder/template.go
@@ -9,6 +9,7 @@ import (
 	"text/template"
 	"website/internal/atom"
 	"website/internal/config"
+	"website/internal/content"
 	"website/internal/log"
 
 	"github.com/PuerkitoBio/goquery"
@@ -89,7 +90,7 @@ func renderRobotsTXT(config config.Config) (io.Reader, error) {
 func renderFeed(
 	title string,
 	config config.Config,
-	posts []Post,
+	posts []content.Post,
 	specific string,
 ) (io.Reader, error) {
 	reader, err := loadTemplate("templates/feed.xml")