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 }