blog/post/post.go

90 lines
1.8 KiB
Go

package post
import (
"os"
"path/filepath"
"sort"
"strings"
"time"
"go.jolheiser.com/blog/markdown"
"github.com/rs/zerolog/log"
)
func NewBlog(basePath string) (*Blog, error) {
posts, err := Scan(basePath)
if err != nil {
return nil, err
}
return &Blog{
Path: basePath,
Posts: posts,
}, nil
}
func Scan(basePath string) (map[string]*Post, error) {
posts := make(map[string]*Post)
ents, err := os.ReadDir(basePath)
if err != nil {
return nil, err
}
for _, ent := range ents {
var apn string
if ent.IsDir() {
apn = filepath.Join(basePath, ent.Name(), "index.md")
if _, err := os.Stat(apn); err != nil {
log.Error().Err(err).Msgf("could not parse %s", ent.Name())
continue
}
} else {
if !strings.HasSuffix(ent.Name(), ".md") {
continue
}
apn = filepath.Join(basePath, ent.Name())
}
fi, err := os.Open(apn)
if err != nil {
log.Error().Err(err).Msg("could not open file")
continue
}
post := &Post{Path: apn, Slug: strings.TrimSuffix(ent.Name(), ".md")}
if err := markdown.Meta(fi, &post); err != nil {
log.Error().Err(err).Msg("could not extract meta")
continue
}
posts[post.Slug] = post
if err := fi.Close(); err != nil {
log.Error().Err(err).Msg("could not close file")
continue
}
}
return posts, nil
}
type Blog struct {
Path string
Posts map[string]*Post
}
func (b *Blog) SortedPosts() []*Post {
posts := make([]*Post, 0, len(b.Posts))
for _, post := range b.Posts {
posts = append(posts, post)
}
sort.Slice(posts, func(i, j int) bool {
return posts[i].Date.After(posts[j].Date)
})
return posts
}
type Post struct {
Path string `toml:"-"`
Slug string `toml:"-"`
Title string `toml:"title"`
Author string `toml:"author"`
Date time.Time `toml:"date"`
Tags []string `toml:"tags"`
}