Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement full post/item content included in generated @astrojs/rss feed as opt-in feature #5366

Merged
merged 1 commit into from
Dec 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/purple-knives-tan.md
Original file line number Diff line number Diff line change
@@ -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.
2 changes: 2 additions & 0 deletions packages/astro-rss/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ type RSSFeedItem = {
pubDate: Date;
/** Item description */
description?: string;
/** Full content of the item, should be valid HTML */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On behalf of Astro Docs Maintainers, if nothing else changes in the README except this, we're cool!

I'll look forward to seeing a PR to docs in the future. I know a lot of people will be happy to see full post content in RSS, even if only for Markdown files right now.

content?: string;
/** Append some other XML-valid data to this item */
customData?: string;
};
Expand Down
15 changes: 15 additions & 0 deletions packages/astro-rss/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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>`;
}
Expand Down
24 changes: 23 additions & 1 deletion packages/astro-rss/test/rss.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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 () => {
Expand All @@ -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 = {
Expand Down