atom/feed.go (view raw)
1package atom
2
3import (
4 "encoding/xml"
5 "fmt"
6 "path/filepath"
7 "time"
8
9 "git.icyphox.sh/vite/config"
10 "git.icyphox.sh/vite/markdown"
11)
12
13type AtomLink struct {
14 XMLName xml.Name `xml:"link"`
15 Href string `xml:"href,attr"`
16 Rel string `xml:"rel,attr,omitempty"`
17}
18
19type AtomSummary struct {
20 XMLName xml.Name `xml:"summary"`
21 Content string `xml:",chardata"`
22 Type string `xml:"type,attr"`
23}
24
25type AtomAuthor struct {
26 XMLName xml.Name `xml:"author"`
27 Name string `xml:"name"`
28 Email string `xml:"email"`
29}
30
31type AtomEntry struct {
32 XMLName xml.Name `xml:"entry"`
33 Title string `xml:"title"`
34 Updated string `xml:"updated"`
35 ID string `xml:"id"`
36 Link *AtomLink
37 Summary *AtomSummary
38}
39
40type AtomFeed struct {
41 XMLName xml.Name `xml:"feed"`
42 Xmlns string `xml:"xmlns,attr"`
43 Title string `xml:"title"`
44 Subtitle string `xml:"subtitle"`
45 ID string `xml:"id"`
46 Updated string `xml:"updated"`
47 Link *AtomLink
48 Author *AtomAuthor `xml:"author"`
49 Entries []AtomEntry
50}
51
52// Creates a new Atom feed.
53func NewAtomFeed(srcDir string, posts []markdown.Output) ([]byte, error) {
54 entries := []AtomEntry{}
55 cfg := config.ConfigYaml{}
56 cfg.ParseConfig()
57 for _, p := range posts {
58 dateStr := p.Meta["date"]
59 date, err := time.Parse("2006-01-02", dateStr)
60 if err != nil {
61 return nil, err
62 }
63 rfc3339 := date.Format(time.RFC3339)
64
65 entry := AtomEntry{
66 Title: p.Meta["title"],
67 Updated: rfc3339,
68 // tag:icyphox.sh,2019-10-23:blog/some-post/
69 ID: fmt.Sprintf(
70 "tag:%s,%s:%s",
71 cfg.URL[8:], // strip https://
72 dateStr,
73 filepath.Join(srcDir, p.Meta["slug"]),
74 ),
75 // filepath.Join strips the second / in http://
76 Link: &AtomLink{Href: cfg.URL + filepath.Join(srcDir, p.Meta["slug"])},
77 Summary: &AtomSummary{
78 Content: fmt.Sprintf("<h2>%s</h2>\n%s",
79 p.Meta["subtitle"],
80 string(p.HTML)),
81 Type: "html",
82 },
83 }
84 entries = append(entries, entry)
85 }
86
87 // 2021-07-14T00:00:00Z
88 now := time.Now().Format(time.RFC3339)
89 feed := &AtomFeed{
90 Xmlns: "http://www.w3.org/2005/Atom",
91 Title: cfg.Title,
92 ID: cfg.URL,
93 Subtitle: cfg.Desc,
94 Link: &AtomLink{Href: cfg.URL},
95 Author: &AtomAuthor{
96 Name: cfg.Author.Name,
97 Email: cfg.Author.Email,
98 },
99 Updated: now,
100 Entries: entries,
101 }
102
103 feedXML, err := xml.MarshalIndent(feed, " ", " ")
104 if err != nil {
105 return nil, err
106 }
107 // Add the <?xml...> header.
108 return []byte(xml.Header + string(feedXML)), nil
109}