home/internal/entry/repository/fs/fs_page.go

82 lines
1.8 KiB
Go

package fs
import (
"context"
"errors"
"fmt"
"io/fs"
"github.com/adrg/frontmatter"
"gopkg.in/yaml.v3"
"source.toby3d.me/toby3d/home/internal/domain"
"source.toby3d.me/toby3d/home/internal/entry"
)
type (
Page struct {
Title string `yaml:"title"`
Description string `yaml:"description"`
Params map[string]any `yaml:",inline"`
Content []byte `yaml:"-"`
}
fileSystemPageRepository struct {
dir fs.FS
}
)
var FrontMatterFormats = []*frontmatter.Format{
frontmatter.NewFormat(`---`, `---`, yaml.Unmarshal),
}
func NewFileSystemPageRepository(dir fs.FS) entry.Repository {
return &fileSystemPageRepository{
dir: dir,
}
}
func (repo *fileSystemPageRepository) Get(ctx context.Context, lang domain.Language, p string) (*domain.Page, error) {
ext := ".md"
if lang != domain.LanguageUnd {
ext = "." + lang.Lang() + ext
}
target := p + ext
f, err := repo.dir.Open(target)
if err != nil {
return nil, fmt.Errorf("cannot open '%s' entry file: %w", target, err)
}
defer f.Close()
data := &Page{
Params: make(map[string]any),
}
if data.Content, err = frontmatter.Parse(f, data, FrontMatterFormats...); err != nil {
return nil, fmt.Errorf("cannot parse entry content as FrontMatter: %w", err)
}
return &domain.Page{
File: domain.NewPath(target),
Language: lang,
Title: data.Title,
Content: data.Content,
Description: data.Description,
Params: data.Params,
Resources: make([]*domain.Resource, 0),
Translations: make([]*domain.Page, 0),
}, nil
}
func (repo *fileSystemPageRepository) Stat(_ context.Context, l domain.Language, p string) (bool, error) {
ext := ".md"
if l != domain.LanguageUnd {
ext = "." + l.Lang() + ext
}
_, err := fs.Stat(repo.dir, p+ext)
return errors.Is(err, fs.ErrExist), nil
}