diff options
Diffstat (limited to 'feed.typ')
| -rw-r--r-- | feed.typ | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/feed.typ b/feed.typ new file mode 100644 index 0000000..75639e0 --- /dev/null +++ b/feed.typ @@ -0,0 +1,54 @@ +// RSS 2.0 feed for the blog posts, emitted as feed.xml by main.typ. +// Items are built from the metadata in site-info.pages (newest first). + +#import "/global/common.typ": baseurl + +#let xml-escape(s) = s.replace("&", "&").replace("<", "<").replace(">", ">") + +// ISO date ("2026-07-28") to RFC 822 ("Tue, 28 Jul 2026 00:00:00 GMT"). +#let rfc822(iso) = { + let (y, m, d) = iso.split("-").map(int) + datetime(year: y, month: m, day: d).display( + "[weekday repr:short], [day] [month repr:short] [year] 00:00:00 GMT" + ) +} + +#let feed-xml(site-info) = { + let pages = site-info.pages + let ids = pages.keys().filter(k => k.starts-with("post/")) + + let items = () + for id in ids { + let p = pages.at(id) + let title = if "long-title" in p { p.long-title } else { p.title } + let url = baseurl + "/" + id + ".html" + + let lines = ( + " <item>", + " <title>" + xml-escape(title) + "</title>", + " <link>" + url + "</link>", + " <guid>" + url + "</guid>", + ) + if "date" in p { + lines.push(" <pubDate>" + rfc822(p.date) + "</pubDate>") + } + if "description" in p { + lines.push(" <description>" + xml-escape(p.description) + "</description>") + } + lines.push(" </item>") + items.push(lines.join("\n")) + } + + ( + "<?xml version=\"1.0\" encoding=\"UTF-8\"?>", + "<rss version=\"2.0\">", + "<channel>", + " <title>" + xml-escape(site-info.title) + "</title>", + " <link>" + baseurl + "/</link>", + " <description>Posts from " + xml-escape(site-info.title) + " (" + baseurl + ")</description>", + items.join("\n"), + "</channel>", + "</rss>", + "", + ).join("\n") +} |
