From 65e2c4ad6b7f8d9d1685d26e5c976dd846453252 Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Fri, 10 Apr 2026 09:49:58 +0300 Subject: generator: isolate Atom feed in atom subpackage, document boundaries Move Atom 1.0 XML generation to internal/generator/atom so it depends only on config and post, not on themes or the HTML template pipeline. Add generator/doc.go mapping files (orchestration, registry, themes, shared nav templates) and dependency direction. Made-with: Cursor --- internal/generator/atom.go | 104 --------------------------------------------- 1 file changed, 104 deletions(-) delete mode 100644 internal/generator/atom.go (limited to 'internal/generator/atom.go') diff --git a/internal/generator/atom.go b/internal/generator/atom.go deleted file mode 100644 index 259301c..0000000 --- a/internal/generator/atom.go +++ /dev/null @@ -1,104 +0,0 @@ -package generator - -import ( - "encoding/xml" - "fmt" - "os" - "path/filepath" - "time" - - "codeberg.org/snonux/snonux/internal/config" - "codeberg.org/snonux/snonux/internal/post" -) - -// atomFeed is the root element of an Atom 1.0 feed document. -type atomFeed struct { - XMLName xml.Name `xml:"feed"` - XMLNS string `xml:"xmlns,attr"` - Title string `xml:"title"` - Link atomLink `xml:"link"` - Updated string `xml:"updated"` - ID string `xml:"id"` - Entries []atomEntry `xml:"entry"` -} - -type atomLink struct { - Href string `xml:"href,attr"` - Rel string `xml:"rel,attr,omitempty"` -} - -type atomEntry struct { - Title string `xml:"title"` - Link atomLink `xml:"link"` - ID string `xml:"id"` - Updated string `xml:"updated"` - Content atomContent `xml:"content"` -} - -type atomContent struct { - Type string `xml:"type,attr"` - Value string `xml:",chardata"` -} - -// generateAtom writes atom.xml to cfg.OutputDir containing the most recent -// min(len(posts), config.PostsPerPage) entries. -func generateAtom(posts []*post.Post, cfg *config.Config) error { - limit := config.PostsPerPage - if len(posts) < limit { - limit = len(posts) - } - - recent := posts[:limit] - entries := buildAtomEntries(recent, cfg.BaseURL) - - updated := time.Now().UTC().Format(time.RFC3339) - if len(recent) > 0 { - updated = recent[0].Timestamp.UTC().Format(time.RFC3339) - } - - feed := atomFeed{ - XMLNS: "http://www.w3.org/2005/Atom", - Title: "snonux.foo", - Link: atomLink{Href: cfg.BaseURL + "/"}, - Updated: updated, - ID: cfg.BaseURL + "/", - Entries: entries, - } - - return writeAtomFile(feed, filepath.Join(cfg.OutputDir, "atom.xml")) -} - -// buildAtomEntries converts a slice of posts into Atom entry elements. -func buildAtomEntries(posts []*post.Post, baseURL string) []atomEntry { - entries := make([]atomEntry, 0, len(posts)) - - for _, p := range posts { - entryURL := fmt.Sprintf("%s/posts/%s/", baseURL, p.ID) - entry := atomEntry{ - Title: fmt.Sprintf("Post %s", p.ID), - Link: atomLink{Href: entryURL, Rel: "alternate"}, - ID: entryURL, - Updated: p.Timestamp.UTC().Format(time.RFC3339), - Content: atomContent{Type: "html", Value: p.Content}, - } - entries = append(entries, entry) - } - - return entries -} - -// writeAtomFile marshals feed to XML and writes it to path with XML declaration. -func writeAtomFile(feed atomFeed, path string) error { - data, err := xml.MarshalIndent(feed, "", " ") - if err != nil { - return fmt.Errorf("marshal atom feed: %w", err) - } - - content := append([]byte(xml.Header), data...) - - if err := os.WriteFile(path, content, 0o644); err != nil { - return fmt.Errorf("write atom.xml: %w", err) - } - - return nil -} -- cgit v1.2.3