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, } publishTarget := models.SitePublishTarget{ BaseURL: meta.BaseURL, } return ReadSiteModels{ Site: site, Target: publishTarget, 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 }