♻️ Refactored template context usage
This commit is contained in:
parent
bd2a62b40d
commit
47c88e26f0
|
@ -28,42 +28,32 @@ import (
|
|||
siteucase "source.toby3d.me/toby3d/home/internal/site/usecase"
|
||||
staticfsrepo "source.toby3d.me/toby3d/home/internal/static/repository/fs"
|
||||
staticucase "source.toby3d.me/toby3d/home/internal/static/usecase"
|
||||
"source.toby3d.me/toby3d/home/internal/templateutil"
|
||||
themefsrepo "source.toby3d.me/toby3d/home/internal/theme/repository/fs"
|
||||
themeucase "source.toby3d.me/toby3d/home/internal/theme/usecase"
|
||||
"source.toby3d.me/toby3d/home/internal/urlutil"
|
||||
)
|
||||
|
||||
type (
|
||||
App struct {
|
||||
server *http.Server
|
||||
}
|
||||
|
||||
// TODO(toby3d): move this into separated package.
|
||||
Context struct {
|
||||
Site *domain.Site
|
||||
Page *domain.Page
|
||||
}
|
||||
)
|
||||
type App struct {
|
||||
server *http.Server
|
||||
}
|
||||
|
||||
func NewApp(logger *log.Logger, config *domain.Config) (*App, error) {
|
||||
themeDir := os.DirFS(config.ThemeDir)
|
||||
|
||||
partialsDir, err := fs.Sub(themeDir, "partials")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot substitute into partials subdirectory: %w", err)
|
||||
}
|
||||
contentDir := os.DirFS(config.ContentDir)
|
||||
resources := resourcefsrepo.NewFileServerResourceRepository(contentDir)
|
||||
sites := sitefsrepo.NewFileSystemSiteRepository(contentDir)
|
||||
siter := siteucase.NewSiteUseCase(sites, resources)
|
||||
|
||||
funcMap, err := templateutil.New(themeDir, siter)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot setup template.FuncMap for templates: %w", err)
|
||||
}
|
||||
|
||||
staticDir := os.DirFS(config.StaticDir)
|
||||
statics := staticfsrepo.NewFileServerStaticRepository(staticDir)
|
||||
staticer := staticucase.NewStaticUseCase(statics)
|
||||
resourcer := resourceucase.NewResourceUseCase(resources)
|
||||
themes := themefsrepo.NewFileSystemThemeRepository(themeDir, funcMap)
|
||||
themer := themeucase.NewThemeUseCase(themes)
|
||||
themes := themefsrepo.NewFileSystemThemeRepository(themeDir)
|
||||
themer := themeucase.NewThemeUseCase(partialsDir, themes)
|
||||
pages := pagefsrepo.NewFileSystemPageRepository(contentDir)
|
||||
pager := pageucase.NewPageUseCase(pages, resources)
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -175,7 +165,7 @@ func NewApp(logger *log.Logger, config *domain.Config) (*App, error) {
|
|||
|
||||
w.Header().Set(common.HeaderContentLanguage, strings.Join(contentLanguage, ", "))
|
||||
|
||||
tpl, err := themer.Do(r.Context())
|
||||
pageTemplate, err := themer.Do(r.Context(), s, p)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
|
||||
|
@ -183,10 +173,7 @@ func NewApp(logger *log.Logger, config *domain.Config) (*App, error) {
|
|||
}
|
||||
|
||||
w.Header().Set(common.HeaderContentType, common.MIMETextHTMLCharsetUTF8)
|
||||
if err = tpl.Execute(w, &Context{
|
||||
Site: s,
|
||||
Page: p,
|
||||
}); err != nil {
|
||||
if err = pageTemplate(w); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
package templateutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io/fs"
|
||||
|
||||
"source.toby3d.me/toby3d/home/internal/site"
|
||||
"source.toby3d.me/toby3d/home/internal/domain"
|
||||
"source.toby3d.me/toby3d/home/internal/templateutil/collections"
|
||||
"source.toby3d.me/toby3d/home/internal/templateutil/partials"
|
||||
"source.toby3d.me/toby3d/home/internal/templateutil/safe"
|
||||
|
@ -20,12 +19,7 @@ type Function struct {
|
|||
Name string
|
||||
}
|
||||
|
||||
func New(dir fs.FS, siter site.UseCase) (template.FuncMap, error) {
|
||||
partialDir, err := fs.Sub(dir, "partials")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot substitute into partials subdirectory: %w", err)
|
||||
}
|
||||
|
||||
func New(partialsDir fs.FS, site *domain.Site) template.FuncMap {
|
||||
funcMap := make(template.FuncMap)
|
||||
funcs := make([]Function, 0)
|
||||
stringsNamespace := strings.New()
|
||||
|
@ -45,7 +39,7 @@ func New(dir fs.FS, siter site.UseCase) (template.FuncMap, error) {
|
|||
"safeHTML": safeNamespace.HTML,
|
||||
},
|
||||
})
|
||||
partialsNamespace := partials.New(partialDir, funcMap)
|
||||
partialsNamespace := partials.New(partialsDir, funcMap)
|
||||
funcs = append(funcs, Function{
|
||||
Name: "partials",
|
||||
Handler: func(v ...any) any { return partialsNamespace },
|
||||
|
@ -53,7 +47,7 @@ func New(dir fs.FS, siter site.UseCase) (template.FuncMap, error) {
|
|||
"partial": partialsNamespace.Include,
|
||||
},
|
||||
})
|
||||
urlsNamespace := urls.New(siter)
|
||||
urlsNamespace := urls.New(site)
|
||||
funcs = append(funcs, Function{
|
||||
Name: "urls",
|
||||
Handler: func(v ...any) any { return urlsNamespace },
|
||||
|
@ -89,5 +83,5 @@ func New(dir fs.FS, siter site.UseCase) (template.FuncMap, error) {
|
|||
}
|
||||
}
|
||||
|
||||
return funcMap, nil
|
||||
return funcMap
|
||||
}
|
||||
|
|
|
@ -1,35 +1,24 @@
|
|||
package urls
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
|
||||
"source.toby3d.me/toby3d/home/internal/domain"
|
||||
"source.toby3d.me/toby3d/home/internal/site"
|
||||
)
|
||||
|
||||
type Namespace struct {
|
||||
siter site.UseCase
|
||||
site *domain.Site
|
||||
}
|
||||
|
||||
var ErrAbsURL error = errors.New("unsupported input type for AbsURL")
|
||||
|
||||
func New(siter site.UseCase) *Namespace {
|
||||
func New(site *domain.Site) *Namespace {
|
||||
return &Namespace{
|
||||
siter: siter,
|
||||
site: site,
|
||||
}
|
||||
}
|
||||
|
||||
func (ns *Namespace) AbsURL(p string) (string, error) {
|
||||
site, err := ns.siter.Do(context.Background(), domain.LanguageUnd)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("cannot fetch site root for AbsURL processing: %w", err)
|
||||
}
|
||||
|
||||
return site.BaseURL.JoinPath(p).String(), nil
|
||||
func (ns *Namespace) AbsURL(p string) string {
|
||||
return ns.site.BaseURL.JoinPath(p).String()
|
||||
}
|
||||
|
||||
func (ns *Namespace) RelURL(p string) string {
|
||||
|
|
|
@ -7,5 +7,5 @@ import (
|
|||
|
||||
type Repository interface {
|
||||
// TODO(toby3d): use Page context to find it's specific template.
|
||||
Get(ctx context.Context) (*template.Template, error)
|
||||
Get(ctx context.Context, funcMap template.FuncMap) (*template.Template, error)
|
||||
}
|
||||
|
|
|
@ -10,19 +10,17 @@ import (
|
|||
)
|
||||
|
||||
type fileSystemThemeRepository struct {
|
||||
dir fs.FS
|
||||
funcMap template.FuncMap
|
||||
dir fs.FS
|
||||
}
|
||||
|
||||
func NewFileSystemThemeRepository(dir fs.FS, funcMap template.FuncMap) theme.Repository {
|
||||
func NewFileSystemThemeRepository(dir fs.FS) theme.Repository {
|
||||
return &fileSystemThemeRepository{
|
||||
dir: dir,
|
||||
funcMap: funcMap,
|
||||
dir: dir,
|
||||
}
|
||||
}
|
||||
|
||||
func (repo *fileSystemThemeRepository) Get(ctx context.Context) (*template.Template, error) {
|
||||
tpl, err := template.New("").Funcs(repo.funcMap).ParseFS(repo.dir, "*.html")
|
||||
func (repo *fileSystemThemeRepository) Get(ctx context.Context, funcMap template.FuncMap) (*template.Template, error) {
|
||||
tpl, err := template.New("").Funcs(funcMap).ParseFS(repo.dir, "*.html")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot find baseof template: %w", err)
|
||||
}
|
||||
|
|
|
@ -2,9 +2,15 @@ package theme
|
|||
|
||||
import (
|
||||
"context"
|
||||
"html/template"
|
||||
"io"
|
||||
|
||||
"source.toby3d.me/toby3d/home/internal/domain"
|
||||
)
|
||||
|
||||
type UseCase interface {
|
||||
Do(ctx context.Context) (*template.Template, error)
|
||||
}
|
||||
type (
|
||||
Writer func(w io.Writer) error
|
||||
|
||||
UseCase interface {
|
||||
Do(ctx context.Context, site *domain.Site, page *domain.Page) (Writer, error)
|
||||
}
|
||||
)
|
||||
|
|
|
@ -3,26 +3,36 @@ package usecase
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
"io/fs"
|
||||
|
||||
"source.toby3d.me/toby3d/home/internal/domain"
|
||||
"source.toby3d.me/toby3d/home/internal/templateutil"
|
||||
"source.toby3d.me/toby3d/home/internal/theme"
|
||||
)
|
||||
|
||||
type themeUseCase struct {
|
||||
dir fs.FS
|
||||
themes theme.Repository
|
||||
}
|
||||
|
||||
func NewThemeUseCase(themes theme.Repository) theme.UseCase {
|
||||
func NewThemeUseCase(dir fs.FS, themes theme.Repository) theme.UseCase {
|
||||
return &themeUseCase{
|
||||
dir: dir,
|
||||
themes: themes,
|
||||
}
|
||||
}
|
||||
|
||||
func (ucase *themeUseCase) Do(ctx context.Context) (*template.Template, error) {
|
||||
out, err := ucase.themes.Get(ctx)
|
||||
func (ucase *themeUseCase) Do(ctx context.Context, site *domain.Site, page *domain.Page) (theme.Writer, error) {
|
||||
out, err := ucase.themes.Get(ctx, templateutil.New(ucase.dir, site))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot find theme: %w", err)
|
||||
}
|
||||
|
||||
return out.Lookup("baseof"), nil
|
||||
return func(w io.Writer) error {
|
||||
return out.Lookup("baseof.html").Execute(w, &domain.Context{
|
||||
Site: site,
|
||||
Page: page,
|
||||
})
|
||||
}, nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue