diff --git a/cmd/ssg/main.go b/cmd/ssg/main.go index c2f0a8c..e510a23 100644 --- a/cmd/ssg/main.go +++ b/cmd/ssg/main.go @@ -25,7 +25,11 @@ func main() { } // initialize site - s, err := site.New(*resources) + config, err := site.NewSiteConfig(site.SITE_EWNL) + if err != nil { + log.Fatal(err) + } + s, err := site.New(config, *resources) if err != nil { log.Fatal(err) } diff --git a/cmd/ssg/site/config.go b/cmd/ssg/site/config.go new file mode 100644 index 0000000..2e43653 --- /dev/null +++ b/cmd/ssg/site/config.go @@ -0,0 +1,78 @@ +package site + +import ( + "errors" + "fmt" + "path/filepath" + "text/template" + + "git.sr.ht/~ewintr/shitty-ssg/pkg/adoc" +) + +var ( + ErrUnknownSiteID = errors.New("unknown site id") +) + +type SiteID string + +const ( + SITE_EWNL = SiteID("ewnl") + SITE_VKVNL = SiteID("vkvnl") +) + +type TemplateConfig struct { + Name string + TemplateNames []string + TemplateExt string + Template *template.Template + Render func(targetPath string, tpl *template.Template, posts Posts, staticPages []*StaticPage) error +} + +type SiteConfig struct { + ID SiteID + BaseURL string + TemplateConfigs []*TemplateConfig + RSS bool + StaticPages []*StaticPage + KindMap map[adoc.Kind]Kind +} + +func NewSiteConfig(id SiteID) (*SiteConfig, error) { + var config *SiteConfig + + switch id { + case SITE_EWNL: + config = SITE_CONFIG_EWNL + case SITE_VKVNL: + config = SITE_CONFIG_VKVNL + default: + return &SiteConfig{}, ErrUnknownSiteID + } + + return config, nil +} + +func (sc *SiteConfig) ParseTemplates(tplPath string) error { + for _, tplConf := range sc.TemplateConfigs { + for _, tName := range tplConf.TemplateNames { + var tFiles []string + tFiles = append(tFiles, filepath.Join(tplPath, fmt.Sprintf("%s.%s", tName, tplConf.TemplateExt))) + tpl, err := template.ParseFiles(tFiles...) + if err != nil { + return err + } + tplConf.Template = tpl + } + } + + return nil +} + +func (sc *SiteConfig) MapKind(docKind adoc.Kind) Kind { + siteKind, ok := sc.KindMap[docKind] + if !ok { + return KIND_INVALID + } + + return siteKind +} diff --git a/cmd/ssg/site/meta.go b/cmd/ssg/site/meta.go index 5b6b7f9..a798b1c 100644 --- a/cmd/ssg/site/meta.go +++ b/cmd/ssg/site/meta.go @@ -13,24 +13,6 @@ const ( type Kind string -func NewKind(kind adoc.Kind) Kind { - switch kind { - case adoc.KIND_NOTE: - return KIND_NOTE - case adoc.KIND_VKV: - return KIND_STORY - case adoc.KIND_ESSAY: - fallthrough - case adoc.KIND_ARTICLE: - fallthrough - case adoc.KIND_TUTORIAL: - return KIND_ARTICLE - default: - return KIND_INVALID - } - -} - const ( LANGUAGE_EN = Language("en") LANGUAGE_NL = Language("nl") diff --git a/cmd/ssg/site/meta_test.go b/cmd/ssg/site/meta_test.go index e22cb5e..a455571 100644 --- a/cmd/ssg/site/meta_test.go +++ b/cmd/ssg/site/meta_test.go @@ -8,53 +8,6 @@ import ( "git.sr.ht/~ewintr/shitty-ssg/pkg/adoc" ) -func TestNewKind(t *testing.T) { - for _, tc := range []struct { - name string - input adoc.Kind - exp site.Kind - }{ - { - name: "empty", - exp: site.KIND_INVALID, - }, - { - name: "note", - input: adoc.KIND_NOTE, - exp: site.KIND_NOTE, - }, - { - name: "work", - input: adoc.KIND_WORK, - exp: site.KIND_INVALID, - }, - { - name: "vkv", - input: adoc.KIND_VKV, - exp: site.KIND_STORY, - }, - { - name: "essay", - input: adoc.KIND_ESSAY, - exp: site.KIND_ARTICLE, - }, - { - name: "article", - input: adoc.KIND_ARTICLE, - exp: site.KIND_ARTICLE, - }, - { - name: "tutorial", - input: adoc.KIND_TUTORIAL, - exp: site.KIND_ARTICLE, - }, - } { - t.Run(tc.name, func(t *testing.T) { - test.Equals(t, tc.exp, site.NewKind(tc.input)) - }) - } -} - func TestNewLanguage(t *testing.T) { for _, tc := range []struct { name string diff --git a/cmd/ssg/site/post.go b/cmd/ssg/site/post.go index 4e9fac8..0006c41 100644 --- a/cmd/ssg/site/post.go +++ b/cmd/ssg/site/post.go @@ -31,7 +31,7 @@ type Post struct { Tags []Tag } -func NewPost(doc *adoc.ADoc) *Post { +func NewPost(config *SiteConfig, doc *adoc.ADoc) *Post { var tags []Tag for _, t := range doc.Tags { tags = append(tags, Tag(t)) @@ -39,7 +39,7 @@ func NewPost(doc *adoc.ADoc) *Post { return &Post{ doc: doc, Date: doc.Date, - Kind: NewKind(doc.Kind), + Kind: config.MapKind(doc.Kind), Language: Language(doc.Language), Tags: tags, } diff --git a/cmd/ssg/site/post_test.go b/cmd/ssg/site/post_test.go index 50c6530..1b66c4a 100644 --- a/cmd/ssg/site/post_test.go +++ b/cmd/ssg/site/post_test.go @@ -10,19 +10,25 @@ import ( ) func TestPost(t *testing.T) { + docKind := adoc.KIND_NOTE + siteKind := site.Kind(docKind) + config := &site.SiteConfig{ + KindMap: map[adoc.Kind]site.Kind{ + docKind: siteKind, + }, + } title := "title thing" author := "author" - kind := adoc.KIND_NOTE language := adoc.LANGUAGE_EN path := "/path" date := time.Date(2020, 12, 28, 7, 23, 45, 0, time.UTC) tag1, tag2 := adoc.Tag("tag1"), adoc.Tag("tag2") par1 := adoc.Paragraph{adoc.PlainText("one")} par2 := adoc.Paragraph{adoc.PlainText("two")} - post := site.NewPost(&adoc.ADoc{ + post := site.NewPost(config, &adoc.ADoc{ Title: title, Author: author, - Kind: kind, + Kind: docKind, Language: language, Path: path, Date: date, @@ -32,7 +38,7 @@ func TestPost(t *testing.T) { t.Run("new", func(t *testing.T) { test.Equals(t, date, post.Date) - test.Equals(t, site.Kind(kind), post.Kind) + test.Equals(t, siteKind, post.Kind) test.Equals(t, site.Language(language), post.Language) test.Equals(t, []site.Tag{site.Tag(tag1), site.Tag(tag2)}, post.Tags) }) diff --git a/cmd/ssg/site/posts.go b/cmd/ssg/site/posts.go index d8060a4..8a76ace 100644 --- a/cmd/ssg/site/posts.go +++ b/cmd/ssg/site/posts.go @@ -15,7 +15,7 @@ func (p Posts) Sort() Posts { return p } -func (p Posts) FilterByKind(wanted Kind) Posts { +func (p Posts) SelectKind(wanted Kind) Posts { pList := Posts{} for _, post := range p { if post.Kind == wanted { @@ -26,7 +26,7 @@ func (p Posts) FilterByKind(wanted Kind) Posts { return pList } -func (p Posts) FilterByYear(year string) Posts { +func (p Posts) SelectYear(year string) Posts { pList := Posts{} for _, post := range p { if post.Year() == year { @@ -37,7 +37,7 @@ func (p Posts) FilterByYear(year string) Posts { return pList } -func (p Posts) FilterByTag(wanted Tag) Posts { +func (p Posts) SelectTag(wanted Tag) Posts { pList := Posts{} POSTS: @@ -54,6 +54,18 @@ POSTS: return pList } +func (p Posts) RemoveKind(kind Kind) Posts { + pList := Posts{} + for _, post := range p { + if post.Kind == kind { + continue + } + pList = append(pList, post) + } + + return pList +} + func (p Posts) Limit(limit int) Posts { if len(p) <= limit { return p diff --git a/cmd/ssg/site/posts_test.go b/cmd/ssg/site/posts_test.go index 40d9270..8f9170b 100644 --- a/cmd/ssg/site/posts_test.go +++ b/cmd/ssg/site/posts_test.go @@ -51,16 +51,20 @@ func TestPosts(t *testing.T) { posts := site.Posts{post1, post2, post3} - t.Run("filter kind", func(t *testing.T) { - test.Equals(t, site.Posts{post1, post3}, posts.FilterByKind(kind1)) + t.Run("select kind", func(t *testing.T) { + test.Equals(t, site.Posts{post1, post3}, posts.SelectKind(kind1)) }) - t.Run("filter year", func(t *testing.T) { - test.Equals(t, site.Posts{post2}, posts.FilterByYear("2019")) + t.Run("select year", func(t *testing.T) { + test.Equals(t, site.Posts{post2}, posts.SelectYear("2019")) }) - t.Run("tilter tag", func(t *testing.T) { - test.Equals(t, site.Posts{post2, post3}, posts.FilterByTag(tag2)) + t.Run("select tag", func(t *testing.T) { + test.Equals(t, site.Posts{post2, post3}, posts.SelectTag(tag2)) + }) + + t.Run("remove kind", func(t *testing.T) { + test.Equals(t, site.Posts{post2}, posts.RemoveKind(kind1)) }) t.Run("limit", func(t *testing.T) { diff --git a/cmd/ssg/site/render.go b/cmd/ssg/site/render.go index 52265eb..d2763ba 100644 --- a/cmd/ssg/site/render.go +++ b/cmd/ssg/site/render.go @@ -33,7 +33,7 @@ func moveResources(targetPath, resourcesPath string) error { return nil } -func renderStaticPages(targetPath string, tpl *template.Template, statics []*StaticPage) error { +func renderStaticPages(targetPath string, tpl *template.Template, _ Posts, statics []*StaticPage) error { for _, static := range statics { destPath := filepath.Join(targetPath, static.Name) if err := os.MkdirAll(destPath, dirMode); err != nil { @@ -68,9 +68,9 @@ func renderStaticPages(targetPath string, tpl *template.Template, statics []*Sta return nil } -func renderHome(targetPath string, tpl *template.Template, posts Posts) error { +func renderHome(targetPath string, tpl *template.Template, posts Posts, _ []*StaticPage) error { var summaries []*HTMLSummary - for _, p := range posts { + for _, p := range posts.RemoveKind(KIND_NOTE).Limit(10) { summaries = append(summaries, p.HTMLSummary()) } data := struct { @@ -91,7 +91,7 @@ func renderHome(targetPath string, tpl *template.Template, posts Posts) error { return tpl.Execute(homeFile, data) } -func renderArchive(targetPath string, tpl *template.Template, title string, posts Posts) error { +func renderArchive(targetPath string, tpl *template.Template, posts Posts, _ []*StaticPage) error { archPath := filepath.Join(targetPath, "archive") if err := os.MkdirAll(archPath, dirMode); err != nil { return err @@ -120,7 +120,7 @@ func renderArchive(targetPath string, tpl *template.Template, title string, post KIND_STORY: {}, } for kind := range yearLinks { - for _, year := range posts.FilterByKind(kind).YearList() { + for _, year := range posts.SelectKind(kind).YearList() { yearLinks[kind] = append(yearLinks[kind], link{ Name: year, Link: fmt.Sprintf("%s/", path.Join("/", pluralKind[kind], year)), @@ -135,7 +135,7 @@ func renderArchive(targetPath string, tpl *template.Template, title string, post NoteYears []link StoryYears []link }{ - Title: title, + Title: "Archive", Tags: tags, ArticleYears: yearLinks[KIND_ARTICLE], NoteYears: yearLinks[KIND_NOTE], @@ -145,11 +145,11 @@ func renderArchive(targetPath string, tpl *template.Template, title string, post return tpl.Execute(archFile, data) } -func renderListings(targetPath string, tpl *template.Template, posts Posts) error { +func renderListings(targetPath string, tpl *template.Template, posts Posts, _ []*StaticPage) error { for _, kind := range []Kind{KIND_NOTE, KIND_STORY, KIND_ARTICLE} { - for _, year := range posts.FilterByKind(kind).YearList() { + for _, year := range posts.SelectKind(kind).YearList() { title := fmt.Sprintf("%s in %s", strings.Title(pluralKind[kind]), year) - kyposts := posts.FilterByKind(kind).FilterByYear(year) + kyposts := posts.SelectKind(kind).SelectYear(year) var summaries []*HTMLSummary for _, p := range kyposts { summaries = append(summaries, p.HTMLSummary()) @@ -163,7 +163,7 @@ func renderListings(targetPath string, tpl *template.Template, posts Posts) erro for _, tag := range posts.TagList() { title := fmt.Sprintf("Posts Tagged with \"%s\"", tag) - tposts := posts.FilterByTag(Tag(tag)) + tposts := posts.SelectTag(Tag(tag)) var summaries []*HTMLSummary for _, p := range tposts { summaries = append(summaries, p.HTMLSummary()) @@ -198,7 +198,7 @@ func renderListing(path string, tpl *template.Template, title string, summaries return tpl.Execute(f, data) } -func renderPosts(targetPath string, tpl *template.Template, posts Posts) error { +func renderPosts(targetPath string, tpl *template.Template, posts Posts, _ []*StaticPage) error { for _, post := range posts { data := post.HTMLPost() if data.Slug == "" { @@ -225,7 +225,7 @@ func renderPosts(targetPath string, tpl *template.Template, posts Posts) error { return nil } -func renderRSS(targetPath string, tpl *template.Template, posts Posts) error { +func renderRSS(targetPath string, tpl *template.Template, posts Posts, _ []*StaticPage) error { rssPath := filepath.Join(targetPath, "index.xml") rssFile, err := os.Create(rssPath) if err != nil { diff --git a/cmd/ssg/site/site.go b/cmd/ssg/site/site.go index 387d096..791b9e2 100644 --- a/cmd/ssg/site/site.go +++ b/cmd/ssg/site/site.go @@ -1,10 +1,8 @@ package site import ( - "fmt" "io/ioutil" "path/filepath" - "text/template" "git.sr.ht/~ewintr/shitty-ssg/pkg/adoc" ) @@ -16,20 +14,19 @@ type StaticPage struct { type Site struct { resourcesPath string - templates map[string]*template.Template + config *SiteConfig posts Posts staticPages []*StaticPage } -func New(resourcesPath string) (*Site, error) { - templates, err := parseTemplates(resourcesPath) - if err != nil { +func New(config *SiteConfig, resourcesPath string) (*Site, error) { + if err := config.ParseTemplates(filepath.Join(resourcesPath, "template")); err != nil { return &Site{}, err } return &Site{ resourcesPath: resourcesPath, - templates: templates, + config: config, posts: Posts{}, staticPages: []*StaticPage{}, }, nil @@ -47,7 +44,7 @@ func (s *Site) AddFilePost(fPath string) error { if err != nil { return err } - post := NewPost(adoc.New(string(content))) + post := NewPost(s.config, adoc.New(string(content))) if post.Kind != KIND_INVALID { s.posts = append(s.posts, post) } @@ -64,52 +61,12 @@ func (s *Site) RenderHTML(targetPath string) error { if err := moveResources(targetPath, s.resourcesPath); err != nil { return err } - if err := renderStaticPages(targetPath, s.templates["static"], s.staticPages); err != nil { - return err + + for _, tplConf := range s.config.TemplateConfigs { + if err := tplConf.Render(targetPath, tplConf.Template, posts, s.staticPages); err != nil { + return err + } } - if err := renderArchive(targetPath, s.templates["archive"], "Archive", posts); err != nil { - return err - } - - if err := renderHome(targetPath, s.templates["list"], posts.Limit(10)); err != nil { - return err - } - - if err := renderListings(targetPath, s.templates["list"], posts); err != nil { - return err - } - - if err := renderPosts(targetPath, s.templates["post"], posts); err != nil { - return err - } - - if err := renderRSS(targetPath, s.templates["rss"], posts); err != nil { - return err - } return nil } - -func parseTemplates(resourcesPath string) (map[string]*template.Template, error) { - templates := map[string]*template.Template{} - tPath := filepath.Join(resourcesPath, "template") - for _, tName := range []string{"post", "list", "archive", "static"} { - var tFiles []string - for _, tf := range []string{tName, "head", "menu"} { - tFiles = append(tFiles, filepath.Join(tPath, fmt.Sprintf("%s.gohtml", tf))) - } - tpl, err := template.ParseFiles(tFiles...) - if err != nil { - return map[string]*template.Template{}, err - } - templates[tName] = tpl - } - - rss, err := template.ParseFiles(filepath.Join(tPath, "rss.goxml")) - if err != nil { - return map[string]*template.Template{}, err - } - templates["rss"] = rss - - return templates, nil -} diff --git a/cmd/ssg/site/sites.go b/cmd/ssg/site/sites.go new file mode 100644 index 0000000..de01f5e --- /dev/null +++ b/cmd/ssg/site/sites.go @@ -0,0 +1,56 @@ +package site + +import "git.sr.ht/~ewintr/shitty-ssg/pkg/adoc" + +var ( + SITE_CONFIG_EWNL = &SiteConfig{ + ID: SITE_EWNL, + BaseURL: "https://erikwinter.nl", + TemplateConfigs: []*TemplateConfig{ + { + Name: "home", + TemplateNames: []string{"list", "head", "menu"}, + TemplateExt: "gohtml", + Render: renderHome, + }, + { + Name: "listings", + TemplateNames: []string{"list", "head", "menu"}, + TemplateExt: "gohtml", + Render: renderListings, + }, + { + Name: "archive", + TemplateNames: []string{"archive", "head", "menu"}, + TemplateExt: "gohtml", + Render: renderArchive, + }, + { + Name: "static", + TemplateNames: []string{"static", "head", "menu"}, + TemplateExt: "gohtml", + Render: renderStaticPages, + }, + { + Name: "posts", + TemplateNames: []string{"post", "head", "menu"}, + TemplateExt: "gohtml", + Render: renderPosts, + }, + { + Name: "rss", + TemplateNames: []string{"rss"}, + TemplateExt: "goxml", + Render: renderRSS, + }, + }, + KindMap: map[adoc.Kind]Kind{ + adoc.KIND_NOTE: KIND_NOTE, + adoc.KIND_VKV: KIND_STORY, + adoc.KIND_ESSAY: KIND_ARTICLE, + adoc.KIND_TUTORIAL: KIND_ARTICLE, + adoc.KIND_ARTICLE: KIND_ARTICLE, + }, + } + SITE_CONFIG_VKVNL = &SiteConfig{} +)