🗃️ Created basic pages FileSystem repository implementation

This commit is contained in:
Maxim Lebedev 2023-11-08 05:09:31 +06:00
parent a9586897b3
commit fe19646f7e
Signed by: toby3d
GPG Key ID: 1F14E25B7C119FC5
2 changed files with 134 additions and 0 deletions

View File

@ -0,0 +1,64 @@
package fs
import (
"context"
"fmt"
"io/fs"
"path/filepath"
"github.com/adrg/frontmatter"
"golang.org/x/text/language"
"gopkg.in/yaml.v3"
"source.toby3d.me/toby3d/home/internal/domain"
"source.toby3d.me/toby3d/home/internal/page"
)
type (
Page struct {
Title string `yaml:"title"`
Params map[string]any `yaml:",inline"`
Content []byte `yaml:"-"`
}
fileSystemPageRepository struct {
dir fs.FS
rootPath string
}
)
var FrontMatterFormats = []*frontmatter.Format{
frontmatter.NewFormat(`---`, `---`, yaml.Unmarshal),
}
func NewFileSystemPageRepository(rootDir fs.FS) page.Repository {
return &fileSystemPageRepository{
dir: rootDir,
}
}
func (repo *fileSystemPageRepository) Get(ctx context.Context, lang language.Tag, path string) (*domain.Page, error) {
target := "index." + lang.String() + ".md"
if lang == language.Und {
target = "index.md"
}
target = filepath.Join(path, target)
f, err := repo.dir.Open(target)
if err != nil {
return nil, fmt.Errorf("cannot open '%s' page file: %w", target, err)
}
defer f.Close()
data := new(Page)
if data.Content, err = frontmatter.Parse(f, data, FrontMatterFormats...); err != nil {
return nil, fmt.Errorf("cannot parse page content as FrontMatter: %w", err)
}
return &domain.Page{
Language: lang,
Title: data.Title,
Content: data.Content,
}, nil
}

View File

@ -0,0 +1,70 @@
package fs_test
import (
"context"
"path"
"path/filepath"
"testing"
"testing/fstest"
"github.com/google/go-cmp/cmp"
"golang.org/x/text/language"
"source.toby3d.me/toby3d/home/internal/domain"
repository "source.toby3d.me/toby3d/home/internal/page/repository/fs"
)
func TestGet(t *testing.T) {
t.Parallel()
testData := fstest.MapFS{
filepath.Join("index.ru.md"): &fstest.MapFile{
Data: []byte("---\ntitle: страница\n---\nпривет, мир!\n"),
},
filepath.Join("dir", "index.en.md"): &fstest.MapFile{
Data: []byte("---\ntitle: page\n---\nhello, world!\n"),
},
}
repo := repository.NewFileSystemPageRepository(testData)
for name, tc := range map[string]struct {
lang language.Tag
expect *domain.Page
path string
}{
"file": {
lang: language.English,
path: path.Join("dir"),
expect: &domain.Page{
Language: language.English,
Title: "page",
Content: []byte("hello, world!\n"),
},
},
"dir": {
lang: language.Russian,
path: path.Join(""),
expect: &domain.Page{
Language: language.Russian,
Title: "страница",
Content: []byte("привет, мир!\n"),
},
},
} {
name, tc := name, tc
t.Run(name, func(t *testing.T) {
t.Parallel()
out, err := repo.Get(context.Background(), tc.lang, tc.path)
if err != nil {
t.Fatal(err)
}
if diff := cmp.Diff(out, tc.expect, cmp.AllowUnexported(language.Und)); diff != "" {
t.Error(diff)
}
})
}
}