From 081e0a9d2070b23d596b687ad52ed3a68bc3ac24 Mon Sep 17 00:00:00 2001 From: Ben Smith Date: Tue, 6 Dec 2022 15:19:55 -0800 Subject: [PATCH] feat(astro-rss): generate post content in feed (#5366) --- .changeset/purple-knives-tan.md | 6 ++++++ packages/astro-rss/README.md | 2 ++ packages/astro-rss/src/index.ts | 15 +++++++++++++++ packages/astro-rss/test/rss.test.js | 24 +++++++++++++++++++++++- 4 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 .changeset/purple-knives-tan.md diff --git a/.changeset/purple-knives-tan.md b/.changeset/purple-knives-tan.md new file mode 100644 index 000000000..188c49ee6 --- /dev/null +++ b/.changeset/purple-knives-tan.md @@ -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. diff --git a/packages/astro-rss/README.md b/packages/astro-rss/README.md index 931e9200b..767a2bbcc 100644 --- a/packages/astro-rss/README.md +++ b/packages/astro-rss/README.md @@ -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; }; diff --git a/packages/astro-rss/src/index.ts b/packages/astro-rss/src/index.ts index f90f39287..bb6afd562 100644 --- a/packages/astro-rss/src/index.ts +++ b/packages/astro-rss/src/index.ts @@ -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 += ` result.content)) { + // the namespace to be added to the xmlns:content attribute to enable the 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 += `${result.pubDate.toUTCString()}`; } + // include the full content of the post if the user supplies it + if (typeof result.content === 'string') { + xml += ``; + } if (typeof result.customData === 'string') xml += result.customData; xml += ``; } diff --git a/packages/astro-rss/test/rss.test.js b/packages/astro-rss/test/rss.test.js index 42fb0759d..8f4af3272 100644 --- a/packages/astro-rss/test/rss.test.js +++ b/packages/astro-rss/test/rss.test.js @@ -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: `

${phpFeedItem.title}

${phpFeedItem.description}

`, +}; 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: `

${web1FeedItem.title}

${web1FeedItem.description}

`, +}; // note: I spent 30 minutes looking for a nice node-based snapshot tool // ...and I gave up. Enjoy big strings! -const validXmlResult = `<![CDATA[My RSS feed]]>https://example.com/<![CDATA[Remember PHP?]]>https://example.com/php/https://example.com/php/Tue, 03 May 1994 00:00:00 GMT<![CDATA[Web 1.0]]>https://example.com/https://example.com/Sat, 03 May 1997 00:00:00 GMT`; +// prettier-ignore +const validXmlResult = `<![CDATA[${title}]]>${site}/<![CDATA[${phpFeedItem.title}]]>${site}${phpFeedItem.link}/${site}${phpFeedItem.link}/${new Date(phpFeedItem.pubDate).toUTCString()}<![CDATA[${web1FeedItem.title}]]>${site}${web1FeedItem.link}/${site}${web1FeedItem.link}/${new Date(web1FeedItem.pubDate).toUTCString()}`; +// prettier-ignore +const validXmlWithContentResult = `<![CDATA[${title}]]>${site}/<![CDATA[${phpFeedItemWithContent.title}]]>${site}${phpFeedItemWithContent.link}/${site}${phpFeedItemWithContent.link}/${new Date(phpFeedItemWithContent.pubDate).toUTCString()}<![CDATA[${web1FeedItemWithContent.title}]]>${site}${web1FeedItemWithContent.link}/${site}${web1FeedItemWithContent.link}/${new Date(web1FeedItemWithContent.pubDate).toUTCString()}`; 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 = {