95 lines
1.7 KiB
Go
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
|
|
}
|