--- /dev/null
+const std = @import("std");
+
+const rss = @import("./rss_formatter.zig");
+const md = @import("./markdown_parser.zig");
+
+const HEADER =
+ \\<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+ \\<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
+ \\<channel>
+ \\<title>Posts on Alexander Goussas</title>
+ \\<link>https://frustrated-functor.dev</link>
+ \\<description></description>
+ \\<generator></generator>
+ \\<language>en-us</language>
+ \\<lastBuildDate></lastBuildDate>
+ \\<atom:link href="https://frustrated-functor.dev/rss.xml" rel="self" type="application/rss+xml"/>
+ ;
+
+const FOOTER =
+ \\</channel>
+ \\</rss>
+ ;
+
+// TODO: Create a MarkdownMetaDoc that includes the post URL.
+
+pub const RssDocument = struct {
+ buffer: std.ArrayList(u8) = .empty,
+
+ pub fn md2rss(self: *@This(), alloc: std.mem.Allocator, docs: std.ArrayList(md.MarkdownDoc)) ![]const u8 {
+ try self.buffer.appendSlice(alloc, HEADER);
+
+ for (docs.items) |doc| {
+ // TODO: Thread URL here.
+ // TODO: Add an API to RSS formatter to be able to reset the buffer.
+ var rssFormatter = rss.RssFormatter.init(alloc, "");
+ defer rssFormatter.deinit();
+
+ const formattedEntry = try rssFormatter.format(doc);
+ try self.buffer.appendSlice(alloc, formattedEntry);
+ }
+
+ try self.buffer.appendSlice(alloc, FOOTER);
+
+ return self.buffer.toOwnedSlice(alloc);
+ }
+};
+
+test "rss document can format an empty document" {
+ const alloc = std.testing.allocator;
+
+ var rssDoc: RssDocument = .{};
+
+ const docs: std.ArrayList(md.MarkdownDoc) = .empty;
+ const result = try rssDoc.md2rss(alloc, docs);
+ defer alloc.free(result);
+
+ try std.testing.expectEqualStrings(HEADER ++ FOOTER, result);
+}