oliverpool: 1 tasks: add tasks.feeds support 6 files changed, 126 insertions(+), 18 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~adnano/kiln-devel/patches/24903/mbox | git am -3Learn more about email & git
Every task can now have a [[tasks.feeds]] entry to generate one or more feeds. It must have the following arguments: [[tasks.feeds]] input_dir = "" title = "Example feed" template = "atom.xml" output = "atom.xml" --- I think having [[tasks.feeds]] is fine. Yes it can generate arbitrary files, but since they will be provided with the .Pages variable, they will be some kind of feed or index. If you have another naming suggestion, I can adjust this patch.
Sure, I don't have any suggestions right now.
I have added a Dir.path field, to cleanup the Trim stuff. What do you think about this? I can revert to Permalink (but I can't find a suitable name for the input_dir configuration - so I would appreciate your help here).
Looks good to me! Note that one thing I might change is requiring a leading forward slash for paths. So input_dir will need to be "/" instead of "". I feel like that is clearer.
I have added some comments regarding the position of the feeds processing. I have also added some logging regarding the deprecated [feeds] configuration, as well as some hints to ease the transition. The docs has been updated as well.
Nice, thanks!
config.toml | 9 +++-- dir.go | 71 +++++++++++++++++++++++++++++++++---- docs/kiln.1.scd | 25 +++++++++---- main.go | 2 +- site.go | 35 ++++++++++++++++++ templates/_default/atom.xml | 2 +- 6 files changed, 126 insertions(+), 18 deletions(-) diff --git a/config.toml b/config.toml index 7fd55af..9aeb85d 100644 --- a/config.toml +++ b/config.toml @@ -1,9 +1,6 @@ title = "Example website" urls = ["gemini://example.com"] -[feeds] -"/" = "Example feed" - [permalinks] "/" = "/{{ .Date.Format `2006/01/02` }}/{{ path.Base .Permalink }}/" @@ -13,3 +10,9 @@ output = ".gmi" template = ".gmi" static_dir = "static" output_dir = "public" + +[[tasks.feeds]] +input_dir = "" +title = "Example feed" +template = "atom.xml" +output = "atom.xml" diff --git a/dir.go b/dir.go index e0a2505..24f63bb 100644 --- a/dir.go +++ b/dir.go @@ -18,11 +18,13 @@ import ( // Dir represents a directory. type Dir struct { - Permalink string - Pages []*Page - Dirs []*Dir - index *Page // The index page. - feed []byte // Atom feed. + Permalink string + Pages []*Page + Dirs []*Dir + index *Page // The index page. + feed []byte // Atom feed (deprecated) + extraFiles map[string][]byte // Atom/RSS feeds + path string // relative to the content dir } // Page represents a page. @@ -57,7 +59,7 @@ func (d *Dir) _read(srcDir, path string, task *Task, cfg *Site) error { continue } // Gather directory data - dir := &Dir{Permalink: "/" + path + "/"} + dir := &Dir{Permalink: "/" + path + "/", path: path} if err := dir._read(srcDir, path, task, cfg); err != nil { return err } @@ -151,6 +153,21 @@ 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 { + // build feeds + // this must happen before the page processing + // to have an unprocessed Page.Content + // 192: d.Pages[i].Content = b.String() + for _, feed := range task.Feeds { + if d.path != feed.InputDir { + continue + } + b, err := d.buildFeed(cfg, feed) + if err != nil { + return err + } + d.addExtraFile(feed.Output, b) + } + if task.TemplateExt != "" { // Create index if d.index != nil { @@ -214,6 +231,39 @@ func (d *Dir) process(cfg *Site, task *Task) error { return nil } +// buildFeed build the feed of the directory +func (d Dir) buildFeed(cfg *Site, feed Feed) ([]byte, error) { + tmpl, ok := cfg.templates.FindTemplate(d.Permalink, feed.Template) + if !ok { + return nil, fmt.Errorf("missing feed template %q to generate %q", feed.Template, feed.Title) + } + + var b bytes.Buffer + data := struct { + Title string // Feed title. + Permalink string // Feed permalink. + Updated time.Time // Last updated time. + Pages []*Page // Feed pages. + }{ + Title: feed.Title, + Permalink: d.Permalink, + Updated: time.Now(), + Pages: d.Pages, + } + if err := tmpl.Execute(&b, data); err != nil { + return nil, err + } + return b.Bytes(), nil +} + +func (d *Dir) addExtraFile(name string, content []byte) { + if d.extraFiles == nil { + d.extraFiles = map[string][]byte{name: content} + } else { + d.extraFiles[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) @@ -255,6 +305,15 @@ func (d *Dir) write(dstDir string, task *Task) error { } } + // Write feeds + for name, content := range d.extraFiles { + dstPath := pathpkg.Join(dstDir, name) + os.MkdirAll(dirPath, 0755) + if err := os.WriteFile(dstPath, content, 0644); err != nil { + return err + } + } + // Write subdirectories for _, dir := range d.Dirs { dir.write(dstDir, task) diff --git a/docs/kiln.1.scd b/docs/kiln.1.scd index dbb4c8a..1923995 100644 --- a/docs/kiln.1.scd +++ b/docs/kiln.1.scd @@ -187,20 +187,31 @@ site URLs may be specified for sites that are available at multiple locations. ## FEEDS -Feeds can be specified in the [feeds] table of the configuration file. Keys -denote the path to the feed directory and values denote the title of the feed. - -Feeds are written to the output directory plus the feed directory plus -"atom.xml". +Feeds can be specified in [[tasks.feeds]] for every task needing them. Example feed configuration: ``` # This will generate a feed which will be written to public/blog/atom.xml - [feeds] - "/blog/" = "My blog" + [[tasks.feeds]] + input_dir = "blog" + title = "My Blog" + template = "atom.xml" + output = "blog/atom.xml" ``` +*input_dir* + the content folder for which the feed will be generated + +*title* + the title of the feed, accessible via {{ .Title }} in the template + +*template* + the template to use for the feed + +*output* + the absolute path for the rendered feed + ## PERMALINKS Permalinks can be used to rewrite page paths. Permalinks are specified in the diff --git a/main.go b/main.go index b081099..30e5c26 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: "/"} + s.root = &Dir{Permalink: "/", path: ""} if err := s.root.read("content", task, s); err != nil { return err } diff --git a/site.go b/site.go index 925ece7..189a9f7 100644 --- a/site.go +++ b/site.go @@ -2,7 +2,10 @@ package main import ( "fmt" + "log" "os" + "path" + "strings" "text/template" "github.com/pelletier/go-toml" @@ -31,6 +34,14 @@ type Task struct { StaticDir string `toml:"static_dir"` // static file directory OutputDir string `toml:"output_dir"` // output directory UglyURLs bool `toml:"ugly_urls"` // whether to use ugly URLs + Feeds []Feed `toml:"feeds"` +} + +type Feed struct { + InputDir string `toml:"input_dir"` + Title string `toml:"title"` + Template string `toml:"template"` + Output string `toml:"output"` } func (t *Task) Match(ext string) bool { @@ -80,6 +91,30 @@ func LoadSite(config string) (*Site, error) { return nil, err } + // deprecate [feeds] + if len(site.Feeds) > 0 { + log.Println("The [feeds] configuration is deprecated") + for _, task := range site.Tasks { + if len(task.Feeds) > 0 { + log.Println("and can't be used along [[tasks.feeds]]") + return nil, fmt.Errorf("please remove (or rename) the [feeds] category") + } + } + log.Println("Please replace it with [[tasks.feeds]] in every task needing feeds:") + for permalink, title := range site.Feeds { + dir := strings.Trim(permalink, "/") + output := path.Join(dir, "atom.xml") + fmt.Fprintf(log.Writer(), `[[tasks.feeds]] +input_dir = %q +title = %q +template = "atom.xml" +output = %q + +`, dir, title, output) + } + log.Println("You will also need to change .Entries to .Pages in \"atom.xml\"") + } + return site, nil } diff --git a/templates/_default/atom.xml b/templates/_default/atom.xml index 89cdd2a..553da4b 100644 --- a/templates/_default/atom.xml +++ b/templates/_default/atom.xml @@ -4,7 +4,7 @@ <title>{{ .Title }}</title> <updated>{{ .Updated.Format "2006-01-02T15:04:05Z07:00" }}</updated> <link href="{{ index site.URLs 0 | safeURL }}{{ .Permalink }}" rel="alternate"/> -{{ range .Entries }}<entry> +{{ range .Pages }}<entry> <id>{{ index site.URLs 0 }}{{ .Permalink }}</id> <title>{{ .Title }}</title> <updated>{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}</updated> -- 2.33.0
Thanks! To git@git.sr.ht:~adnano/kiln 508e0c2..66f25b0 master -> master