feat(astro-rss): generate post content in feed (#5366)

This commit is contained in:
Ben Smith 2022-12-06 15:19:55 -08:00 committed by GitHub
parent a72a131e22
commit 081e0a9d20
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 1 deletions

View file

@ -0,0 +1,6 @@
---
'@astrojs/rss': minor
---
Added the ability for users to include the full content of their posts/items in each RSS feed entry
via the new `content` key on the `RSSFeedItem` model.

View file

@ -95,6 +95,8 @@ type RSSFeedItem = {
pubDate: Date;
/** Item description */
description?: string;
/** Full content of the item, should be valid HTML */
content?: string;
/** Append some other XML-valid data to this item */
customData?: string;
};

View file

@ -39,6 +39,8 @@ type RSSFeedItem = {
pubDate: Date;
/** Item description */
description?: string;
/** Full content of the item, should be valid HTML */
content?: string;
/** Append some other XML-valid data to this item */
customData?: string;
};
@ -103,6 +105,15 @@ export async function generateRSS({ rssOptions, items }: GenerateRSSArgs): Promi
xml += `<?xml-stylesheet href="${rssOptions.stylesheet}" type="text/xsl"?>`;
}
xml += `<rss version="2.0"`;
if (items.find((result) => result.content)) {
// the namespace to be added to the xmlns:content attribute to enable the <content> RSS feature
const XMLContentNamespace = 'http://purl.org/rss/1.0/modules/content/';
xml += ` xmlns:content="${XMLContentNamespace}"`;
// Ensure that the user hasn't tried to manually include the necessary namespace themselves
if (rssOptions.xmlns?.content && rssOptions.xmlns.content === XMLContentNamespace) {
delete rssOptions.xmlns.content;
}
}
// xmlns
if (rssOptions.xmlns) {
@ -139,6 +150,10 @@ export async function generateRSS({ rssOptions, items }: GenerateRSSArgs): Promi
}
xml += `<pubDate>${result.pubDate.toUTCString()}</pubDate>`;
}
// include the full content of the post if the user supplies it
if (typeof result.content === 'string') {
xml += `<content:encoded><![CDATA[${result.content}]]></content:encoded>`;
}
if (typeof result.customData === 'string') xml += result.customData;
xml += `</item>`;
}

View file

@ -15,6 +15,10 @@ const phpFeedItem = {
description:
'PHP is a general-purpose scripting language geared toward web development. It was originally created by Danish-Canadian programmer Rasmus Lerdorf in 1994.',
};
const phpFeedItemWithContent = {
...phpFeedItem,
content: `<h1>${phpFeedItem.title}</h1><p>${phpFeedItem.description}</p>`,
};
const web1FeedItem = {
// Should support empty string as a URL (possible for homepage route)
@ -24,10 +28,17 @@ const web1FeedItem = {
description:
'Web 1.0 is the term used for the earliest version of the Internet as it emerged from its origins with Defense Advanced Research Projects Agency (DARPA) and became, for the first time, a global network representing the future of digital communications.',
};
const web1FeedItemWithContent = {
...web1FeedItem,
content: `<h1>${web1FeedItem.title}</h1><p>${web1FeedItem.description}</p>`,
};
// note: I spent 30 minutes looking for a nice node-based snapshot tool
// ...and I gave up. Enjoy big strings!
const validXmlResult = `<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title><![CDATA[My RSS feed]]></title><description><![CDATA[This sure is a nice RSS feed]]></description><link>https://example.com/</link><item><title><![CDATA[Remember PHP?]]></title><link>https://example.com/php/</link><guid>https://example.com/php/</guid><description><![CDATA[PHP is a general-purpose scripting language geared toward web development. It was originally created by Danish-Canadian programmer Rasmus Lerdorf in 1994.]]></description><pubDate>Tue, 03 May 1994 00:00:00 GMT</pubDate></item><item><title><![CDATA[Web 1.0]]></title><link>https://example.com/</link><guid>https://example.com/</guid><description><![CDATA[Web 1.0 is the term used for the earliest version of the Internet as it emerged from its origins with Defense Advanced Research Projects Agency (DARPA) and became, for the first time, a global network representing the future of digital communications.]]></description><pubDate>Sat, 03 May 1997 00:00:00 GMT</pubDate></item></channel></rss>`;
// prettier-ignore
const validXmlResult = `<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title><![CDATA[${title}]]></title><description><![CDATA[${description}]]></description><link>${site}/</link><item><title><![CDATA[${phpFeedItem.title}]]></title><link>${site}${phpFeedItem.link}/</link><guid>${site}${phpFeedItem.link}/</guid><description><![CDATA[${phpFeedItem.description}]]></description><pubDate>${new Date(phpFeedItem.pubDate).toUTCString()}</pubDate></item><item><title><![CDATA[${web1FeedItem.title}]]></title><link>${site}${web1FeedItem.link}/</link><guid>${site}${web1FeedItem.link}/</guid><description><![CDATA[${web1FeedItem.description}]]></description><pubDate>${new Date(web1FeedItem.pubDate).toUTCString()}</pubDate></item></channel></rss>`;
// prettier-ignore
const validXmlWithContentResult = `<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title><![CDATA[${title}]]></title><description><![CDATA[${description}]]></description><link>${site}/</link><item><title><![CDATA[${phpFeedItemWithContent.title}]]></title><link>${site}${phpFeedItemWithContent.link}/</link><guid>${site}${phpFeedItemWithContent.link}/</guid><description><![CDATA[${phpFeedItemWithContent.description}]]></description><pubDate>${new Date(phpFeedItemWithContent.pubDate).toUTCString()}</pubDate><content:encoded><![CDATA[${phpFeedItemWithContent.content}]]></content:encoded></item><item><title><![CDATA[${web1FeedItemWithContent.title}]]></title><link>${site}${web1FeedItemWithContent.link}/</link><guid>${site}${web1FeedItemWithContent.link}/</guid><description><![CDATA[${web1FeedItemWithContent.description}]]></description><pubDate>${new Date(web1FeedItemWithContent.pubDate).toUTCString()}</pubDate><content:encoded><![CDATA[${web1FeedItemWithContent.content}]]></content:encoded></item></channel></rss>`;
describe('rss', () => {
it('should generate on valid RSSFeedItem array', async () => {
@ -41,6 +52,17 @@ describe('rss', () => {
chai.expect(body).to.equal(validXmlResult);
});
it('should generate on valid RSSFeedItem array with HTML content included', async () => {
const { body } = await rss({
title,
description,
items: [phpFeedItemWithContent, web1FeedItemWithContent],
site,
});
chai.expect(body).to.equal(validXmlWithContentResult);
});
describe('glob result', () => {
it('should generate on valid result', async () => {
const globResult = {