Merge branch 'feature/theme' into develop

This commit is contained in:
Maxim Lebedev 2023-11-08 08:55:55 +06:00
commit 76a65f0e3a
Signed by: toby3d
GPG Key ID: 1F14E25B7C119FC5
6 changed files with 121 additions and 15 deletions

View File

@ -7,8 +7,9 @@ import (
)
type Config struct {
Host string `env:"HOST" envDefault:"0.0.0.0"`
ContentDir string `env:"CONTENT_DIR" envDefault:"content/"`
Host string `env:"HOST" envDefault:"0.0.0.0"`
ThemeDir string `env:"THEME_DIR" envDefault:"theme/"`
Port uint16 `env:"PORT" envDefault:"3000"`
}

View File

@ -0,0 +1,11 @@
package theme
import (
"context"
"html/template"
)
type Repository interface {
// TODO(toby3d): use Page context to find it's specific template.
Get(ctx context.Context) (*template.Template, error)
}

View File

@ -0,0 +1,29 @@
package fs
import (
"context"
"fmt"
"html/template"
"io/fs"
"source.toby3d.me/toby3d/home/internal/theme"
)
type fileSystemThemeRepository struct {
dir fs.FS
}
func NewFileSystemThemeRepository(dir fs.FS) theme.Repository {
return &fileSystemThemeRepository{
dir: dir,
}
}
func (repo *fileSystemThemeRepository) Get(ctx context.Context) (*template.Template, error) {
tpl, err := template.New("").ParseFS(repo.dir, "baseof.html", "single.html")
if err != nil {
return nil, fmt.Errorf("cannot find baseof.html: %w", err)
}
return tpl, nil
}

10
internal/theme/usecase.go Normal file
View File

@ -0,0 +1,10 @@
package theme
import (
"context"
"html/template"
)
type UseCase interface {
Do(ctx context.Context) (*template.Template, error)
}

View File

@ -0,0 +1,28 @@
package usecase
import (
"context"
"fmt"
"html/template"
"source.toby3d.me/toby3d/home/internal/theme"
)
type themeUseCase struct {
themes theme.Repository
}
func NewThemeUseCase(themes theme.Repository) theme.UseCase {
return &themeUseCase{
themes: themes,
}
}
func (ucase *themeUseCase) Do(ctx context.Context) (*template.Template, error) {
out, err := ucase.themes.Get(ctx)
if err != nil {
return nil, fmt.Errorf("cannot find theme: %w", err)
}
return out.Lookup("baseof"), nil
}

55
main.go
View File

@ -29,9 +29,15 @@ import (
pageucase "source.toby3d.me/toby3d/home/internal/page/usecase"
sitefsrepo "source.toby3d.me/toby3d/home/internal/site/repository/fs"
siteucase "source.toby3d.me/toby3d/home/internal/site/usecase"
"source.toby3d.me/toby3d/home/web/template"
themefsrepo "source.toby3d.me/toby3d/home/internal/theme/repository/fs"
themeucase "source.toby3d.me/toby3d/home/internal/theme/usecase"
)
type Context struct {
Site *domain.Site
Page *domain.Page
}
var (
config = new(domain.Config)
logger = log.New(os.Stdout, "home\t", log.Lmsgprefix|log.LstdFlags|log.LUTC)
@ -49,21 +55,26 @@ func init() {
logger.Fatalln("cannot unmarshal configuration into domain:", err)
}
if config.ContentDir, err = filepath.Abs(filepath.Clean(config.ContentDir)); err != nil {
logger.Fatalf("cannot format '%s' content dir path into absolute path: %s", config.ContentDir, err)
}
if _, err = os.Stat(config.ContentDir); err != nil {
if errors.Is(err, os.ErrExist) {
return
for _, dir := range []*string{
&config.ContentDir,
&config.ThemeDir,
} {
if *dir, err = filepath.Abs(filepath.Clean(*dir)); err != nil {
logger.Fatalf("cannot format '%s' into absolute path: %s", *dir, err)
}
if !errors.Is(err, os.ErrNotExist) {
logger.Fatalln("cannot check directory path for content:", err)
}
if _, err = os.Stat(*dir); err != nil {
if errors.Is(err, os.ErrExist) {
return
}
if err = os.MkdirAll(config.ContentDir, os.ModePerm); err != nil {
logger.Fatalln("cannot create directory for content:", err)
if !errors.Is(err, os.ErrNotExist) {
logger.Fatalf("cannot check '%s' path: %v", *dir, err)
}
if err = os.MkdirAll(*dir, os.ModePerm); err != nil {
logger.Fatalf("cannot create directory on '%s': %v", *dir, err)
}
}
}
}
@ -73,6 +84,10 @@ func main() {
matcher := language.NewMatcher(message.DefaultCatalog.Languages())
contentDir := os.DirFS(config.ContentDir)
themeDir := os.DirFS(config.ThemeDir)
themes := themefsrepo.NewFileSystemThemeRepository(themeDir)
themer := themeucase.NewThemeUseCase(themes)
sites := sitefsrepo.NewFileSystemSiteRepository(contentDir)
siter := siteucase.NewSiteUseCase(sites)
@ -104,8 +119,20 @@ func main() {
return
}
tpl, err := themer.Do(r.Context())
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Header().Set(common.HeaderContentType, common.MIMETextHTMLCharsetUTF8)
template.WriteTemplate(w, template.NewPage(template.NewBaseOf(site), page))
if err = tpl.Execute(w, &Context{
Site: site,
Page: page,
}); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
}),
ErrorLog: logger,
BaseContext: func(ln net.Listener) context.Context { return ctx },