Repos / s4g / 3e3f45cb6d
commit 3e3f45cb6d296202e1364077f2c40c75e1618ed8
Author: Nhân <hi@imnhan.com>
Date: Wed Aug 23 17:18:06 2023 +0700
implement standard PageTypes
TODO: write actual series-index template
diff --git a/Makefile b/Makefile
index 1f406a3..d9bbd9c 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,8 @@ build:
go build -o dist/
watch:
- fd -E docs -E theme | entr -rc go run . serve -f docs -p 8000
+ fd -E docs -E theme | entr -rc -s \
+ 'go build -o dist/ && ./dist/s4g serve -f docs -p 8000'
watch-theme:
find theme/* | entr -c rsync -av theme/ docs/_s4g/theme/
diff --git a/docs/index.dj b/docs/index.dj
index d75a6e5..ea36263 100644
--- a/docs/index.dj
+++ b/docs/index.dj
@@ -1,4 +1,4 @@
Title: Home
ShowInFeed: false
-Templates: $base.tmpl, $includes.tmpl, $home.tmpl
+PageType: home
---
diff --git a/docs/scale/index.dj b/docs/scale/index.dj
index 1aa7db7..73a7ad2 100644
--- a/docs/scale/index.dj
+++ b/docs/scale/index.dj
@@ -1,5 +1,6 @@
Title: I'm Going To Scale My Foot Up Your Ass
PostedAt: 2008-04-24
+PageType: custom
Templates: $base.tmpl, $includes.tmpl, scale.tmpl
---
diff --git a/main.go b/main.go
index 17c4b12..56a35a1 100644
--- a/main.go
+++ b/main.go
@@ -267,15 +267,16 @@ type Article struct {
}
func (a *Article) ComputeDerivedFields(addr, root string) {
- a.WebPath = computeWebPath(root, a.OutputPath)
- a.TemplatePaths = computeTemplatePaths(a.Path, a.Templates)
+ a.computeWebPath(root)
+ a.computeTemplatePaths()
+
if a.Thumb != "" {
a.OpenGraphImage = addr + root + filepath.Dir(a.Path) + "/" + a.Thumb
}
}
-func computeWebPath(root string, outputPath string) string {
- webPath := root + outputPath
+func (a *Article) computeWebPath(root string) {
+ webPath := root + a.OutputPath
if strings.HasSuffix(webPath, "/index.html") {
webPath = strings.TrimSuffix(webPath, "index.html")
}
@@ -286,20 +287,47 @@ func computeWebPath(root string, outputPath string) string {
escaped[i] = url.PathEscape(parts[i])
}
- return strings.Join(escaped, "/")
+ a.WebPath = strings.Join(escaped, "/")
}
-func computeTemplatePaths(articlePath string, templates []string) []string {
+func (a *Article) computeTemplatePaths() {
+ var templates []string
+ switch a.PageType {
+ case PTPost:
+ templates = []string{
+ "$base.tmpl",
+ "$includes.tmpl",
+ "$post.tmpl",
+ }
+ case PTHome:
+ templates = []string{
+ "$base.tmpl",
+ "$includes.tmpl",
+ "$home.tmpl",
+ }
+ case PTSeriesIndex:
+ templates = []string{
+ "$base.tmpl",
+ "$includes.tmpl",
+ "$series-index.tmpl",
+ }
+ case PTCustom:
+ templates = a.Templates
+ default:
+ panic(fmt.Sprintf("Invalid PageType: %v", a.PageType))
+ }
+
paths := make([]string, len(templates))
for i := 0; i < len(paths); i++ {
p := templates[i]
if strings.HasPrefix(p, "$") {
paths[i] = ThemePath + "/" + strings.TrimPrefix(p, "$")
} else {
- paths[i] = filepath.Join(filepath.Dir(articlePath), p)
+ paths[i] = filepath.Join(filepath.Dir(a.Path), p)
}
}
- return paths
+
+ a.TemplatePaths = paths
}
func (a *Article) WriteHtmlFile(
@@ -314,7 +342,7 @@ func (a *Article) WriteHtmlFile(
// TODO: should probably reuse the template object for common cases
if err != nil {
return fmt.Errorf(
- "Failed to parse templates (%v): %w", a.Templates, err,
+ "Failed to parse templates (%v): %w", a.TemplatePaths, err,
)
}
@@ -343,7 +371,7 @@ func (a *Article) WriteHtmlFile(
ThemePath: site.Root + ThemePath,
})
if err != nil {
- return fmt.Errorf("Failed to execute templates (%v): %w", a.Templates, err)
+ return fmt.Errorf("Failed to execute templates (%v): %w", a.TemplatePaths, err)
}
fullHtml := buf.Bytes()
@@ -377,11 +405,7 @@ func findArticles(fsys writablefs.FS, site *SiteMetadata) (map[string]Article, e
}
meta := ArticleMetadata{
- Templates: []string{
- "$base.tmpl",
- "$includes.tmpl",
- "$post.tmpl",
- },
+ PageType: PTPost,
ShowInFeed: true,
}
userErr := UnmarshalMetadata(metaText, &meta)
@@ -390,6 +414,22 @@ func findArticles(fsys writablefs.FS, site *SiteMetadata) (map[string]Article, e
return fmt.Errorf("findArticles failed to unmarshall metadata: %w", userErr)
}
+ if meta.PageType != PTCustom && len(meta.Templates) > 0 {
+ return &errs.UserErr{
+ File: path,
+ Field: "PageType",
+ Msg: `you must set "PageType: custom" in order to use custom Templates`,
+ }
+ }
+
+ if meta.PageType == PTCustom && len(meta.Templates) == 0 {
+ return &errs.UserErr{
+ File: path,
+ Field: "Templates",
+ Msg: `custom PageType requires a non-empty Templates list`,
+ }
+ }
+
article := Article{
Fs: fsys,
Path: path,
diff --git a/makesite.go b/makesite.go
index 11f0725..259491d 100644
--- a/makesite.go
+++ b/makesite.go
@@ -32,7 +32,7 @@ func makeSite(path string, meta SiteMetadata) error {
// Write default index page
indexData := []byte(`Title: Home
ShowInFeed: false
-Templates: $base.tmpl, $includes.tmpl, $home.tmpl
+PageType: home
---
`)
err = os.WriteFile(filepath.Join(path, "index.dj"), indexData, 0664)
diff --git a/metadata.go b/metadata.go
index bf9e52e..98981dc 100644
--- a/metadata.go
+++ b/metadata.go
@@ -29,11 +29,51 @@ type SiteMetadata struct {
AuthorTwitter string
}
+type PageType int
+
+const (
+ PTPost PageType = iota
+ PTHome
+ PTSeriesIndex
+ PTCustom
+)
+
+func (t PageType) String() string {
+ switch t {
+ case PTPost:
+ return "post"
+ case PTHome:
+ return "home"
+ case PTSeriesIndex:
+ return "series-index"
+ case PTCustom:
+ return "custom"
+ default:
+ panic(fmt.Sprintf("unexpected value: %d", t))
+ }
+}
+
+func ParsePageType(name string) (PageType, error) {
+ switch name {
+ case "post":
+ return PTPost, nil
+ case "home":
+ return PTHome, nil
+ case "series-index":
+ return PTSeriesIndex, nil
+ case "custom":
+ return PTCustom, nil
+ default:
+ return -1, fmt.Errorf(`"%s" is not a valid PageType`, name)
+ }
+}
+
type ArticleMetadata struct {
Title string
Description string
IsDraft bool
PostedAt time.Time
+ PageType PageType
Templates []string
ShowInFeed bool
Thumb string
@@ -149,6 +189,16 @@ func UnmarshalMetadata(data []byte, dest any) *errs.UserErr {
}
s.Field(i).Set(reflect.ValueOf(trimmed))
+ case "main.PageType":
+ pt, err := ParsePageType(val)
+ if err != nil {
+ return &errs.UserErr{
+ Field: fieldName,
+ Msg: err.Error(),
+ }
+ }
+ s.Field(i).Set(reflect.ValueOf(pt))
+
default:
panic(fmt.Sprintf(
`unsupported metadata field type: "%s"`,