Add frontmatter, markdown, path, xml, rss, and web packages

Sync local packages into the registry repo and update index.json
and README.md to include all 9 packages.
This commit is contained in:
2026-02-24 21:04:20 -05:00
parent c5a2276f6e
commit cbb66fbb73
42 changed files with 3844 additions and 0 deletions

101
packages/rss/lib.lux Normal file
View File

@@ -0,0 +1,101 @@
// rss - RSS 2.0 feed generator for Lux
//
// Generates valid RSS 2.0 XML feeds from structured data.
import xml
// An RSS feed item
type Item =
| Item(String, String, String, String, String)
// Item(title, link, description, pubDate, guid)
// An RSS channel/feed
type Feed =
| Feed(String, String, String, String, List<Item>)
// Feed(title, link, description, language, items)
// Create a feed item
pub fn item(title: String, link: String, description: String, pubDate: String): Item =
Item(title, link, description, pubDate, link)
// Create a feed item with custom GUID
pub fn itemWithGuid(title: String, link: String, description: String, pubDate: String, guid: String): Item =
Item(title, link, description, pubDate, guid)
// Create an RSS feed
pub fn feed(title: String, link: String, description: String, items: List<Item>): Feed =
Feed(title, link, description, "en", items)
// Create an RSS feed with language
pub fn feedWithLang(title: String, link: String, description: String, language: String, items: List<Item>): Feed =
Feed(title, link, description, language, items)
// Access item fields
pub fn itemTitle(i: Item): String = match i { Item(t, _, _, _, _) => t, }
pub fn itemLink(i: Item): String = match i { Item(_, l, _, _, _) => l, }
pub fn itemDescription(i: Item): String = match i { Item(_, _, d, _, _) => d, }
pub fn itemPubDate(i: Item): String = match i { Item(_, _, _, p, _) => p, }
pub fn itemGuid(i: Item): String = match i { Item(_, _, _, _, g) => g, }
// Convert ISO date (2025-01-29) to RFC 822 format (29 Jan 2025 00:00:00 GMT)
pub fn isoToRfc822(isoDate: String): String =
if String.length(isoDate) < 10 then isoDate
else {
let year = String.substring(isoDate, 0, 4)
let month = String.substring(isoDate, 5, 7)
let day = String.substring(isoDate, 8, 10)
let monthName = if month == "01" then "Jan"
else if month == "02" then "Feb"
else if month == "03" then "Mar"
else if month == "04" then "Apr"
else if month == "05" then "May"
else if month == "06" then "Jun"
else if month == "07" then "Jul"
else if month == "08" then "Aug"
else if month == "09" then "Sep"
else if month == "10" then "Oct"
else if month == "11" then "Nov"
else "Dec"
day + " " + monthName + " " + year + " 00:00:00 GMT"
}
// Render a single item to XML string
fn renderItemXml(i: Item): String =
match i {
Item(title, link, desc, pubDate, guid) =>
xml.render(xml.el("item", [
xml.textEl("title", title),
xml.textEl("link", link),
xml.textEl("description", desc),
xml.textEl("pubDate", isoToRfc822(pubDate)),
xml.textElAttr("guid", [xml.attr("isPermaLink", "true")], guid)
])),
}
// Render items to concatenated XML string
fn renderItemsXml(items: List<Item>): String =
match List.head(items) {
None => "",
Some(i) => renderItemXml(i) + match List.tail(items) {
Some(rest) => renderItemsXml(rest),
None => "",
},
}
// Render an RSS feed to XML string
pub fn render(f: Feed): String =
match f {
Feed(title, link, desc, lang, items) => {
let itemsXml = renderItemsXml(items)
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">" +
"<channel>" +
"<title>" + xml.escape(title) + "</title>" +
"<link>" + xml.escape(link) + "</link>" +
"<description>" + xml.escape(desc) + "</description>" +
"<language>" + lang + "</language>" +
"<generator>Lux RSS Package</generator>" +
itemsXml +
"</channel></rss>"
},
}