From 250ff9131fb99d4c7a943ad56f790dddd33b7d98 Mon Sep 17 00:00:00 2001 From: adnano Date: Sat, 2 Oct 2021 17:50:23 -0400 Subject: [PATCH] Merge Page and Dir structs --- funcs.go | 1 - main.go | 2 +- dir.go => page.go | 228 +++++++++++++++++++++------------------------- site.go | 6 +- 4 files changed, 105 insertions(+), 132 deletions(-) rename dir.go => page.go (58%) diff --git a/funcs.go b/funcs.go index 989f068..cff26eb 100644 --- a/funcs.go +++ b/funcs.go @@ -10,7 +10,6 @@ import ( // funcs returns functions for use in templates. func (s *Site) funcs() map[string]interface{} { return map[string]interface{}{ - "dir": s.dir, "exec": executeString, "page": s.page, "path": func() _path { return _path{} }, diff --git a/main.go b/main.go index 24a86e1..e224115 100644 --- a/main.go +++ b/main.go @@ -71,7 +71,7 @@ func (site *Site) run() error { func (s *Site) runTask(task *Task) error { // Read content - s.root = &Dir{Permalink: "/", path: ""} + s.root = &Page{Permalink: "/", FilePath: ""} if err := s.root.read("content", task, s); err != nil { return err } diff --git a/dir.go b/page.go similarity index 58% rename from dir.go rename to page.go index 8738697..5c88185 100644 --- a/dir.go +++ b/page.go @@ -16,35 +16,29 @@ import ( "gopkg.in/yaml.v3" ) -// Dir represents a directory. -type Dir struct { - Permalink string - Pages []*Page - Dirs []*Dir - index *Page // The index page. - feeds map[string][]byte // Atom/RSS/Custom feeds. - path string // relative to the content dir -} - // Page represents a page. type Page struct { Title string Date time.Time Weight int - Permalink string `yaml:"-"` - FilePath string `yaml:"-"` - Content string `yaml:"-"` Params map[string]interface{} - Prev *Page `yaml:"-"` - Next *Page `yaml:"-"` + FilePath string `yaml:"-"` + Permalink string `yaml:"-"` + Content string `yaml:"-"` + Prev *Page `yaml:"-"` + Next *Page `yaml:"-"` + Pages []*Page `yaml:"-"` + Dirs []*Page `yaml:"-"` + feeds map[string][]byte + index bool } // read reads from a directory and indexes the files and directories within it. -func (d *Dir) read(srcDir string, task *Task, cfg *Site) error { - return d._read(srcDir, "", task, cfg) +func (p *Page) read(srcDir string, task *Task, cfg *Site) error { + return p._read(srcDir, "", task, cfg) } -func (d *Dir) _read(srcDir, path string, task *Task, cfg *Site) error { +func (p *Page) _read(srcDir, path string, task *Task, cfg *Site) error { entries, err := ioutil.ReadDir(pathpkg.Join(srcDir, path)) if err != nil { return err @@ -58,11 +52,11 @@ func (d *Dir) _read(srcDir, path string, task *Task, cfg *Site) error { continue } // Gather directory data - dir := &Dir{Permalink: "/" + path + "/", path: path} + dir := &Page{Permalink: "/" + path + "/", FilePath: path} if err := dir._read(srcDir, path, task, cfg); err != nil { return err } - d.Dirs = append(d.Dirs, dir) + p.Dirs = append(p.Dirs, dir) } else if ext := pathpkg.Ext(name); task.Match(ext) { // Ignore pages beginning with "_" with the exception of _index pages namePrefix := strings.TrimSuffix(name, ext) @@ -76,7 +70,13 @@ func (d *Dir) _read(srcDir, path string, task *Task, cfg *Site) error { return err } - page := &Page{} + page := &Page{ + FilePath: path, + } + if namePrefix == "_index" { + p.index = true + page = p + } // Try to parse the date from the page filename const layout = "2006-01-02" @@ -123,12 +123,7 @@ func (d *Dir) _read(srcDir, path string, task *Task, cfg *Site) error { } page.Content = string(content) - page.FilePath = path - - if namePrefix == "_index" { - page.Permalink = d.Permalink - d.index = page - } else { + if !page.index { if namePrefix == "index" { path = "/" + strings.TrimSuffix(path, name) } else { @@ -140,12 +135,12 @@ func (d *Dir) _read(srcDir, path string, task *Task, cfg *Site) error { } } page.Permalink = path - if permalink, ok := cfg.permalinks[d.Permalink]; ok { + if permalink, ok := cfg.permalinks[p.Permalink]; ok { var b strings.Builder permalink.Execute(&b, page) page.Permalink = b.String() } - d.Pages = append(d.Pages, page) + p.Pages = append(p.Pages, page) } } } @@ -153,44 +148,44 @@ func (d *Dir) _read(srcDir, path string, task *Task, cfg *Site) error { } // process processes the directory's contents. -func (d *Dir) process(cfg *Site, task *Task) error { +func (p *Page) process(cfg *Site, task *Task) error { // Build feeds before templates are applied to the page contents - for _, feed := range task.feeds[d.path] { - b, err := d.buildFeed(cfg, feed) + for _, feed := range task.feeds[p.FilePath] { + b, err := p.buildFeed(cfg, feed) if err != nil { return err } - d.addFeed(feed.Output, b) + p.addFeed(feed.Output, b) } if task.TemplateExt != "" { // Create index - if d.index != nil { - tmpl, ok := cfg.templates.FindTemplate(d.Permalink, "index"+task.TemplateExt) + if p.index { + tmpl, ok := cfg.templates.FindTemplate(p.Permalink, "index"+task.TemplateExt) if ok { var b strings.Builder - if err := tmpl.Execute(&b, d); err != nil { + if err := tmpl.Execute(&b, p); err != nil { return err } - d.index.Content = b.String() + p.Content = b.String() } } // Process pages - for i := range d.Pages { + for i := range p.Pages { var b strings.Builder - tmpl, ok := cfg.templates.FindTemplate(d.Permalink, "page"+task.TemplateExt) + tmpl, ok := cfg.templates.FindTemplate(p.Permalink, "page"+task.TemplateExt) if ok { - if err := tmpl.Execute(&b, d.Pages[i]); err != nil { + if err := tmpl.Execute(&b, p.Pages[i]); err != nil { return err } - d.Pages[i].Content = b.String() + p.Pages[i].Content = b.String() } } } // Process subdirectories - for _, d := range d.Dirs { + for _, d := range p.Dirs { if err := d.process(cfg, task); err != nil { return err } @@ -199,7 +194,7 @@ func (d *Dir) process(cfg *Site, task *Task) error { } // buildFeed build the feed of the directory -func (d Dir) buildFeed(cfg *Site, feed Feed) ([]byte, error) { +func (p *Page) buildFeed(cfg *Site, feed Feed) ([]byte, error) { // Feed represents a feed. type Feed struct { Title string @@ -207,7 +202,7 @@ func (d Dir) buildFeed(cfg *Site, feed Feed) ([]byte, error) { Pages []*Page } - tmpl, ok := cfg.templates.FindTemplate(d.Permalink, feed.Template) + tmpl, ok := cfg.templates.FindTemplate(p.Permalink, feed.Template) if !ok { return nil, fmt.Errorf("failed to generate feed %q: missing feed template %q", feed.Title, feed.Template) } @@ -215,8 +210,8 @@ func (d Dir) buildFeed(cfg *Site, feed Feed) ([]byte, error) { var b bytes.Buffer data := Feed{ Title: feed.Title, - Permalink: d.Permalink, - Pages: d.Pages, + Permalink: p.Permalink, + Pages: p.Pages, } if err := tmpl.Execute(&b, data); err != nil { return nil, err @@ -224,48 +219,37 @@ func (d Dir) buildFeed(cfg *Site, feed Feed) ([]byte, error) { return b.Bytes(), nil } -func (d *Dir) addFeed(name string, content []byte) { - if d.feeds == nil { - d.feeds = map[string][]byte{} +func (p *Page) addFeed(name string, content []byte) { + if p.feeds == nil { + p.feeds = map[string][]byte{} } - d.feeds[name] = content + p.feeds[name] = content } // write writes the directory's contents to the provided destination path. -func (d *Dir) write(dstDir string, task *Task) error { - dirPath := pathpkg.Join(dstDir, d.Permalink) +func (p *Page) write(dstDir string, task *Task) error { + dirPath := pathpkg.Join(dstDir, p.Permalink) // Write pages - pages := d.Pages - if d.index != nil { - pages = append(pages, d.index) + for _, page := range p.Pages { + dstPath := pathpkg.Join(dstDir, page.Permalink) + if !task.UglyURLs { + dstPath = pathpkg.Join(dstPath, "index"+task.OutputExt) + } + if err := page.writeTo(dstPath, task); err != nil { + return err + } } - for _, page := range pages { - path := page.Permalink - if !task.UglyURLs || page == d.index { - path = pathpkg.Join(path, "index"+task.OutputExt) - } - var content []byte - if cmd := task.Postprocess; cmd != "" { - var buf bytes.Buffer - if err := execute(cmd, strings.NewReader(page.Content), &buf); err != nil { - return err - } - content = buf.Bytes() - } else { - content = []byte(page.Content) - } - - dstPath := pathpkg.Join(dstDir, path) - dir := pathpkg.Dir(dstPath) - os.MkdirAll(dir, 0755) - if err := os.WriteFile(dstPath, content, 0644); err != nil { + // Write index page + if p.index { + dstPath := pathpkg.Join(dirPath, p.Permalink, "index"+task.OutputExt) + if err := p.writeTo(dstPath, task); err != nil { return err } } // Write feeds - for name, content := range d.feeds { + for name, content := range p.feeds { dstPath := pathpkg.Join(dstDir, name) os.MkdirAll(dirPath, 0755) if err := os.WriteFile(dstPath, content, 0644); err != nil { @@ -274,40 +258,60 @@ func (d *Dir) write(dstDir string, task *Task) error { } // Write subdirectories - for _, dir := range d.Dirs { + for _, dir := range p.Dirs { dir.write(dstDir, task) } return nil } +func (p *Page) writeTo(dstPath string, task *Task) error { + var content []byte + if cmd := task.Postprocess; cmd != "" { + var buf bytes.Buffer + if err := execute(cmd, strings.NewReader(p.Content), &buf); err != nil { + return err + } + content = buf.Bytes() + } else { + content = []byte(p.Content) + } + + dir := pathpkg.Dir(dstPath) + os.MkdirAll(dir, 0755) + if err := os.WriteFile(dstPath, content, 0644); err != nil { + return err + } + return nil +} + // sort sorts the directory's pages by weight, then date, then filepath. -func (d *Dir) sort() { - sort.Slice(d.Pages, func(i, j int) bool { - pi, pj := d.Pages[i], d.Pages[j] +func (p *Page) sort() { + sort.Slice(p.Pages, func(i, j int) bool { + pi, pj := p.Pages[i], p.Pages[j] return pi.FilePath < pj.FilePath }) - sort.SliceStable(d.Pages, func(i, j int) bool { - pi, pj := d.Pages[i], d.Pages[j] + sort.SliceStable(p.Pages, func(i, j int) bool { + pi, pj := p.Pages[i], p.Pages[j] return pi.Date.After(pj.Date) }) - sort.SliceStable(d.Pages, func(i, j int) bool { - pi, pj := d.Pages[i], d.Pages[j] + sort.SliceStable(p.Pages, func(i, j int) bool { + pi, pj := p.Pages[i], p.Pages[j] return pi.Weight < pj.Weight }) - for i := range d.Pages { + for i := range p.Pages { if i-1 >= 0 { - d.Pages[i].Prev = d.Pages[i-1] + p.Pages[i].Prev = p.Pages[i-1] } - if i+1 < len(d.Pages) { - d.Pages[i].Next = d.Pages[i+1] + if i+1 < len(p.Pages) { + p.Pages[i].Next = p.Pages[i+1] } } // Sort subdirectories - for _, d := range d.Dirs { + for _, d := range p.Dirs { d.sort() } } @@ -326,48 +330,22 @@ func execute(command string, input io.Reader, output io.Writer) error { return nil } -func (d *Dir) Title() string { - return d.index.Title -} - -func (d *Dir) Date() time.Time { - return d.index.Date -} - -func (d *Dir) Content() string { - return d.index.Content -} - -func (d *Dir) Params() map[string]interface{} { - return d.index.Params -} - -func (d *Dir) getDir(path string) *Dir { +func (p *Page) getPage(path string) *Page { // XXX: This is inefficient - if d.Permalink == path { - return d + if p.Permalink == path { + return p } - for _, dir := range d.Dirs { - if dir.Permalink == path { - return dir - } - } - for i := range d.Dirs { - if dir := d.Dirs[i].getDir(path); dir != nil { - return dir - } - } - return nil -} - -func (d *Dir) getPage(path string) *Page { - // XXX: This is inefficient - for _, page := range d.Pages { + for _, page := range p.Pages { if page.FilePath == path { return page } } - for _, dir := range d.Dirs { + for _, dir := range p.Dirs { + if dir.Permalink == path { + return dir + } + } + for _, dir := range p.Dirs { if page := dir.getPage(path); page != nil { return page } diff --git a/site.go b/site.go index 708f393..a1568f2 100644 --- a/site.go +++ b/site.go @@ -18,7 +18,7 @@ type Site struct { Generated time.Time `toml:"-"` permalinks map[string]*template.Template templates Templates - root *Dir + root *Page } // Task represents a site build task. @@ -103,10 +103,6 @@ func LoadSite(config string) (*Site, error) { return site, nil } -func (s *Site) dir(path string) *Dir { - return s.root.getDir(path) -} - func (s *Site) page(path string) *Page { return s.root.getPage(path) }