Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | 1x 1x 1x 1x 1x 1x 1x 1x 6x 1x 50x 50x 79x 50x 1x 1x | /**
* @module Infrastructure/Rss/Render/Feed
* @category Intelligence Operations / Supporting Infrastructure
* @name RSS 2.0 feed builder
*
* @description
* Pure string builder for the full `rss.xml` document — channel header,
* categories, image, atom:link self-reference, and one `<item>` per
* article (with hreflang `atom:link` extensions for every alternate
* language). The lastBuildDate / pubDate / copyright year are derived
* from the most recent article so output is deterministic.
*
* Round-6 split: extracted from `scripts/generate-rss.ts`.
*
* @author Hack23 AB (Infrastructure Team)
* @license Apache-2.0
*/
import { getRssArticles } from '../scanner.js';
import { escapeXml } from '../escape.js';
import { hreflangCode } from '../hreflang.js';
const BASE_URL = 'https://riksdagsmonitor.com';
/**
* Generate RSS 2.0 XML feed.
*/
export function generateRss(): string {
console.log('🔨 Generating RSS feed...');
const articles = getRssArticles();
const now = new Date().toUTCString();
// Use most recent article date for lastBuildDate
const lastBuildDate = articles.length > 0
? new Date(articles[0]!.pubDate).toUTCString()
: now;
let xml = `<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:content="http://purl.org/rss/1.0/modules/content/">
<channel>
<title>Riksdagsmonitor - Swedish Parliament Intelligence</title>
<link>${BASE_URL}</link>
<description>Real-time monitoring, analysis, and intelligence from the Swedish Parliament (Riksdag) and Government. Covering legislative activity, voting patterns, coalition dynamics, and election forecasts.</description>
<language>en</language>
<lastBuildDate>${lastBuildDate}</lastBuildDate>
<pubDate>${lastBuildDate}</pubDate>
<ttl>60</ttl>
<copyright>Copyright ${articles.length > 0 ? new Date(articles[0]!.pubDate).getUTCFullYear() : new Date(lastBuildDate).getUTCFullYear()} Hack23 AB. Licensed under Apache-2.0.</copyright>
<managingEditor>info@hack23.com (Hack23 AB)</managingEditor>
<webMaster>info@hack23.com (Hack23 AB)</webMaster>
<generator>Riksdagsmonitor RSS Generator v1.0</generator>
<docs>https://www.rssboard.org/rss-specification</docs>
<image>
<url>https://riksdagsmonitor.com/images/android-chrome-512x512.png</url>
<title>Riksdagsmonitor</title>
<link>${BASE_URL}</link>
<width>144</width>
<height>144</height>
<description>Riksdagsmonitor - Swedish Parliament Intelligence Platform</description>
</image>
<atom:link href="${BASE_URL}/rss.xml" rel="self" type="application/rss+xml"/>`;
// Add category tags for the channel
const channelCategories = [
'Swedish Politics', 'Parliament', 'Riksdag', 'Political Intelligence',
'Election Analysis', 'Legislative Monitoring',
];
for (const cat of channelCategories) {
xml += `
<category>${escapeXml(cat)}</category>`;
}
// Add items
for (const article of articles) {
xml += `
<item>
<title>${escapeXml(article.title)}</title>
<link>${escapeXml(article.link)}</link>
<description>${escapeXml(article.description)}</description>
<pubDate>${new Date(article.pubDate).toUTCString()}</pubDate>
<guid isPermaLink="true">${escapeXml(article.link)}</guid>
<dc:creator>${escapeXml(article.author)}</dc:creator>
<category>${escapeXml(article.category)}</category>
<atom:link href="${escapeXml(article.link)}" rel="alternate" type="text/html" hreflang="en"/>`;
// Add multi-language alternate links
for (const alt of article.alternateLanguages) {
xml += `
<atom:link href="${escapeXml(alt.href)}" rel="alternate" type="text/html" hreflang="${hreflangCode(alt.lang)}"/>`;
}
xml += `
</item>`;
}
xml += `
</channel>
</rss>`;
return xml;
}
|