@@ 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 pages {
- path := page.Permalink
- if !task.UglyURLs || page == d.index {
- path = pathpkg.Join(path, "index"+task.OutputExt)
+ for _, page := range p.Pages {
+ dstPath := pathpkg.Join(dstDir, page.Permalink)
+ if !task.UglyURLs {
+ dstPath = pathpkg.Join(dstPath, "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)
+ if err := page.writeTo(dstPath, task); err != nil {
+ return err
}
-
- 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 _, page := range p.Pages {
+ if page.FilePath == path {
+ return page
}
}
- for i := range d.Dirs {
- if dir := d.Dirs[i].getDir(path); dir != nil {
+ for _, dir := range p.Dirs {
+ if dir.Permalink == path {
return dir
}
}
- return nil
-}
-
-func (d *Dir) getPage(path string) *Page {
- // XXX: This is inefficient
- for _, page := range d.Pages {
- if page.FilePath == path {
- return page
- }
- }
- for _, dir := range d.Dirs {
+ for _, dir := range p.Dirs {
if page := dir.getPage(path); page != nil {
return page
}