weiro/providers/sitereader/provider.go
2026-02-19 22:29:44 +11:00

95 lines
1.7 KiB
Go

package sitereader
import (
"bytes"
"io"
"io/fs"
"time"
"gopkg.in/yaml.v3"
"lmika.dev/lmika/weiro/models"
)
type Provider struct {
fs fs.FS
}
func New(fs fs.FS) *Provider {
return &Provider{
fs: fs,
}
}
func (p *Provider) ReadSite() (ReadSiteModels, error) {
posts, err := p.ListPosts()
if err != nil {
return ReadSiteModels{}, err
}
meta := siteMeta{}
metaBytes, err := fs.ReadFile(p.fs, "site.yaml")
if err != nil {
return ReadSiteModels{}, err
}
if err := yaml.Unmarshal(metaBytes, &meta); err != nil {
return ReadSiteModels{}, err
}
site := models.Site{
Title: meta.Title,
Tagline: meta.Tagline,
}
return ReadSiteModels{
Site: site,
Posts: posts,
}, nil
}
func (p *Provider) ListPosts() (posts []*models.Post, err error) {
err = fs.WalkDir(p.fs, "posts", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
} else if d.IsDir() {
return nil
}
post, err := p.ReadPost(path)
if err != nil {
return err
}
posts = append(posts, post)
return nil
})
return posts, err
}
func (p *Provider) ReadPost(path string) (*models.Post, error) {
data, err := fs.ReadFile(p.fs, path)
if err != nil {
return nil, err
}
// Split front matter and content
parts := bytes.SplitN(data, []byte("---"), 3)
if len(parts) < 3 {
return nil, io.ErrUnexpectedEOF
}
var meta postMeta
if err := yaml.Unmarshal(parts[1], &meta); err != nil {
return nil, err
}
post := models.Post{
Slug: meta.Slug,
Title: meta.Title,
GUID: meta.ID,
PublishedAt: meta.Date,
CreatedAt: time.Now(),
}
post.Body = string(bytes.TrimPrefix(parts[2], []byte("\n")))
return &post, nil
}