package usecase import ( "context" "fmt" "path" "strings" "golang.org/x/text/language" "source.toby3d.me/toby3d/home/internal/domain" "source.toby3d.me/toby3d/home/internal/page" "source.toby3d.me/toby3d/home/internal/static" "source.toby3d.me/toby3d/home/internal/urlutil" ) type pageUseCase struct { pages page.Repository statics static.Repository } func NewPageUseCase(pages page.Repository, statics static.Repository) page.UseCase { return &pageUseCase{ pages: pages, statics: statics, } } func (ucase *pageUseCase) Do(ctx context.Context, lang language.Tag, p string) (*domain.Page, error) { ext := path.Ext(p) if ext == ".html" { p = p[:len(p)-len(ext)] } hasTrailingSlash := p[len(p)-1] == '/' head, tail := urlutil.ShiftPath(p) targets := []string{path.Join(head, tail)} if tail == "/" { if hasTrailingSlash || ext == "" { targets = append([]string{path.Join(head, "index")}, targets...) } targets = append(targets, head) } for i := range targets { out, err := ucase.pages.Get(ctx, lang, targets[i]) if err != nil { continue } if out.Resources, _, err = ucase.statics.Fetch(ctx, out.File.Dir()+"*"); err != nil { return out, nil } for _, res := range out.Resources.GetType(domain.ResourceTypePage) { // TODO(toby3d): simplify this, it's awful resName := path.Base(res.Key()) resExt := path.Ext(resName) resParts := strings.Split(resName[:len(resName)-len(resExt)], ".") translationBaseName := strings.Join(resParts[:len(resParts)-1], ".") if translationBaseName != out.File.TranslationBaseName() { continue } resLang := language.Make(resParts[len(resParts)-1]) if resLang == language.Und { continue } translation, err := ucase.pages.Get(ctx, resLang, targets[i]) if err != nil { continue } out.Translations = append(out.Translations, translation) } translations := make([]string, 0) for i := range out.Translations { translations = append(translations, out.Translations[i].Language.String()) } return out, nil } return nil, fmt.Errorf("cannot find page on path '%s': %w", p, page.ErrNotExist) }