From 10bf59e4d2c5aca34d3344ad7a74f70d9e3bc8fb Mon Sep 17 00:00:00 2001
From: johnnyreilly
Date: Mon, 31 Jul 2023 07:06:58 +0100
Subject: [PATCH 1/3] feat: limit option for blog feedOptions
---
.../__tests__/__snapshots__/feed.test.ts.snap | 97 +++++++++++++++++++
.../src/__tests__/feed.test.ts | 43 ++++++++
.../src/__tests__/options.test.ts | 14 ++-
.../src/feed.ts | 9 +-
.../src/options.ts | 5 +-
.../src/plugin-content-blog.d.ts | 2 +
.../docs/api/plugins/plugin-content-blog.mdx | 3 +-
website/docs/blog.mdx | 1 +
8 files changed, 165 insertions(+), 9 deletions(-)
diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/feed.test.ts.snap b/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/feed.test.ts.snap
index ae568922d131..3cfe3b572485 100644
--- a/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/feed.test.ts.snap
+++ b/packages/docusaurus-plugin-content-blog/src/__tests__/__snapshots__/feed.test.ts.snap
@@ -32,6 +32,38 @@ exports[`atom filters to the first two entries 1`] = `
]
`;
+exports[`atom filters to the first two entries using limit 1`] = `
+[
+ "
+
+ https://docusaurus.io/myBaseUrl/blog
+ Hello Blog
+ 2021-03-06T00:00:00.000Z
+ https://github.com/jpmonette/feed
+
+ Hello Blog
+ https://docusaurus.io/myBaseUrl/image/favicon.ico
+ Copyright
+
+
+ https://docusaurus.io/myBaseUrl/blog/mdx-require-blog-post
+
+ 2021-03-06T00:00:00.000Z
+
+ Test MDX with require calls


]]>
+
+
+
+ https://docusaurus.io/myBaseUrl/blog/mdx-blog-post
+
+ 2021-03-05T00:00:00.000Z
+
+ HTML Heading 1HTML Heading 2
HTML Paragraph
Import DOM
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Normal Text Italics Text Bold Text
link
]]>
+
+",
+]
+`;
+
exports[`atom has feed item for each post 1`] = `
[
"
@@ -147,6 +179,37 @@ exports[`json filters to the first two entries 1`] = `
]
`;
+exports[`json filters to the first two entries using limit 1`] = `
+[
+ "{
+ "version": "https://jsonfeed.org/version/1",
+ "title": "Hello Blog",
+ "home_page_url": "https://docusaurus.io/myBaseUrl/blog",
+ "description": "Hello Blog",
+ "items": [
+ {
+ "id": "https://docusaurus.io/myBaseUrl/blog/mdx-require-blog-post",
+ "content_html": "Test MDX with require calls


",
+ "url": "https://docusaurus.io/myBaseUrl/blog/mdx-require-blog-post",
+ "title": "MDX Blog Sample with require calls",
+ "summary": "Test MDX with require calls",
+ "date_modified": "2021-03-06T00:00:00.000Z",
+ "tags": []
+ },
+ {
+ "id": "https://docusaurus.io/myBaseUrl/blog/mdx-blog-post",
+ "content_html": "HTML Heading 1
HTML Heading 2
HTML Paragraph
Import DOM
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Normal Text Italics Text Bold Text
link
",
+ "url": "https://docusaurus.io/myBaseUrl/blog/mdx-blog-post",
+ "title": "Full Blog Sample",
+ "summary": "HTML Heading 1",
+ "date_modified": "2021-03-05T00:00:00.000Z",
+ "tags": []
+ }
+ ]
+}",
+]
+`;
+
exports[`json has feed item for each post 1`] = `
[
"{
@@ -268,6 +331,40 @@ exports[`rss filters to the first two entries 1`] = `
]
`;
+exports[`rss filters to the first two entries using limit 1`] = `
+[
+ "
+
+
+ Hello Blog
+ https://docusaurus.io/myBaseUrl/blog
+ Hello Blog
+ Sat, 06 Mar 2021 00:00:00 GMT
+ https://validator.w3.org/feed/docs/rss2.html
+ https://github.com/jpmonette/feed
+ en
+ Copyright
+ -
+
+ https://docusaurus.io/myBaseUrl/blog/mdx-require-blog-post
+ https://docusaurus.io/myBaseUrl/blog/mdx-require-blog-post
+ Sat, 06 Mar 2021 00:00:00 GMT
+
+ Test MDX with require calls


]]>
+
+ -
+
+ https://docusaurus.io/myBaseUrl/blog/mdx-blog-post
+ https://docusaurus.io/myBaseUrl/blog/mdx-blog-post
+ Fri, 05 Mar 2021 00:00:00 GMT
+
+ HTML Heading 1
HTML Heading 2
HTML Paragraph
Import DOM
Heading 1
Heading 2
Heading 3
Heading 4
Heading 5
Normal Text Italics Text Bold Text
link
]]>
+
+
+",
+]
+`;
+
exports[`rss has feed item for each post 1`] = `
[
"
diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts
index 6592c09d7aa5..f928296bf9df 100644
--- a/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts
+++ b/packages/docusaurus-plugin-content-blog/src/__tests__/feed.test.ts
@@ -195,4 +195,47 @@ describe.each(['atom', 'rss', 'json'])('%s', (feedType) => {
).toMatchSnapshot();
fsMock.mockClear();
});
+
+ it('filters to the first two entries using limit', async () => {
+ const siteDir = path.join(__dirname, '__fixtures__', 'website');
+ const outDir = path.join(siteDir, 'build-snap');
+ const siteConfig = {
+ title: 'Hello',
+ baseUrl: '/myBaseUrl/',
+ url: 'https://docusaurus.io',
+ favicon: 'image/favicon.ico',
+ };
+
+ // Build is quite difficult to mock, so we built the blog beforehand and
+ // copied the output to the fixture...
+ await testGenerateFeeds(
+ {
+ siteDir,
+ siteConfig,
+ i18n: DefaultI18N,
+ outDir,
+ } as LoadContext,
+ {
+ path: 'blog',
+ routeBasePath: 'blog',
+ tagsBasePath: 'tags',
+ authorsMapPath: 'authors.yml',
+ include: DEFAULT_OPTIONS.include,
+ exclude: DEFAULT_OPTIONS.exclude,
+ feedOptions: {
+ type: [feedType],
+ copyright: 'Copyright',
+ limit: 2,
+ },
+ readingTime: ({content, defaultReadingTime}) =>
+ defaultReadingTime({content}),
+ truncateMarker: //,
+ } as PluginOptions,
+ );
+
+ expect(
+ fsMock.mock.calls.map((call) => call[1] as string),
+ ).toMatchSnapshot();
+ fsMock.mockClear();
+ });
});
diff --git a/packages/docusaurus-plugin-content-blog/src/__tests__/options.test.ts b/packages/docusaurus-plugin-content-blog/src/__tests__/options.test.ts
index bb0f53c5f338..8133d10df1fb 100644
--- a/packages/docusaurus-plugin-content-blog/src/__tests__/options.test.ts
+++ b/packages/docusaurus-plugin-content-blog/src/__tests__/options.test.ts
@@ -46,7 +46,7 @@ describe('validateOptions', () => {
};
expect(testValidate(userOptions)).toEqual({
...userOptions,
- feedOptions: {type: ['rss'], title: 'myTitle', copyright: ''},
+ feedOptions: {type: ['rss'], title: 'myTitle', copyright: '', limit: 20},
});
});
@@ -58,7 +58,6 @@ describe('validateOptions', () => {
beforeDefaultRehypePlugins: [markdownPluginsFunctionStub],
remarkPlugins: [[markdownPluginsFunctionStub, {option1: '42'}]],
rehypePlugins: [
- // @ts-expect-error: it seems to work in practice
markdownPluginsObjectStub,
[markdownPluginsFunctionStub, {option1: '42'}],
],
@@ -95,7 +94,7 @@ describe('validateOptions', () => {
}),
).toEqual({
...defaultOptions,
- feedOptions: {type: ['rss', 'atom', 'json'], copyright: ''},
+ feedOptions: {type: ['rss', 'atom', 'json'], copyright: '', limit: 20},
});
});
@@ -106,7 +105,7 @@ describe('validateOptions', () => {
}),
).toEqual({
...defaultOptions,
- feedOptions: {type: null},
+ feedOptions: {type: null, limit: 20},
});
});
@@ -125,7 +124,12 @@ describe('validateOptions', () => {
}),
).toEqual({
...defaultOptions,
- feedOptions: {type: ['rss', 'atom'], title: 'title', copyright: ''},
+ feedOptions: {
+ type: ['rss', 'atom'],
+ title: 'title',
+ copyright: '',
+ limit: 20,
+ },
});
});
diff --git a/packages/docusaurus-plugin-content-blog/src/feed.ts b/packages/docusaurus-plugin-content-blog/src/feed.ts
index dc9a7b85f84c..3cfa0f929716 100644
--- a/packages/docusaurus-plugin-content-blog/src/feed.ts
+++ b/packages/docusaurus-plugin-content-blog/src/feed.ts
@@ -42,7 +42,12 @@ async function generateBlogFeed({
const {url: siteUrl, baseUrl, title, favicon} = siteConfig;
const blogBaseUrl = normalizeUrl([siteUrl, baseUrl, routeBasePath]);
- const updated = blogPosts[0]?.metadata.date;
+ const blogPostsForFeed =
+ feedOptions.limit === false || feedOptions.limit === null
+ ? blogPosts
+ : blogPosts.slice(0, feedOptions.limit);
+
+ const updated = blogPostsForFeed[0]?.metadata.date;
const feed = new Feed({
id: blogBaseUrl,
@@ -59,7 +64,7 @@ async function generateBlogFeed({
options.feedOptions.createFeedItems ?? defaultCreateFeedItems;
const feedItems = await createFeedItems({
- blogPosts,
+ blogPosts: blogPostsForFeed,
siteConfig,
outDir,
defaultCreateFeedItems,
diff --git a/packages/docusaurus-plugin-content-blog/src/options.ts b/packages/docusaurus-plugin-content-blog/src/options.ts
index 5d136d43993e..5b9889399a10 100644
--- a/packages/docusaurus-plugin-content-blog/src/options.ts
+++ b/packages/docusaurus-plugin-content-blog/src/options.ts
@@ -22,7 +22,7 @@ import type {
import type {OptionValidationContext} from '@docusaurus/types';
export const DEFAULT_OPTIONS: PluginOptions = {
- feedOptions: {type: ['rss', 'atom'], copyright: ''},
+ feedOptions: {type: ['rss', 'atom'], copyright: '', limit: 20},
beforeDefaultRehypePlugins: [],
beforeDefaultRemarkPlugins: [],
admonitions: true,
@@ -123,6 +123,9 @@ const PluginOptionSchema = Joi.object({
}),
language: Joi.string(),
createFeedItems: Joi.function(),
+ limit: Joi.alternatives()
+ .try(Joi.number(), Joi.valid(null), Joi.valid(false))
+ .default(DEFAULT_OPTIONS.feedOptions.limit),
}).default(DEFAULT_OPTIONS.feedOptions),
authorsMapPath: Joi.string().default(DEFAULT_OPTIONS.authorsMapPath),
readingTime: Joi.function().default(() => DEFAULT_OPTIONS.readingTime),
diff --git a/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts b/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts
index bcce2e7c70ec..1ade5e8cbac9 100644
--- a/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts
+++ b/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts
@@ -272,6 +272,8 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the
language?: string;
/** Allow control over the construction of BlogFeedItems */
createFeedItems?: CreateFeedItemsFn;
+ /** Limits the feed to the specified number of posts, false|null for all */
+ limit?: number | false | null = 20;
};
type DefaultCreateFeedItemsParams = {
diff --git a/website/docs/api/plugins/plugin-content-blog.mdx b/website/docs/api/plugins/plugin-content-blog.mdx
index 52212f8b56c1..1cdacb794889 100644
--- a/website/docs/api/plugins/plugin-content-blog.mdx
+++ b/website/docs/api/plugins/plugin-content-blog.mdx
@@ -38,7 +38,7 @@ Accepted fields:
```
| Name | Type | Default | Description |
-| --- | --- | --- | --- |
+| --- | --- | --- | --- | --- | --- | --- |
| `path` | `string` | `'blog'` | Path to the blog content directory on the file system, relative to site dir. |
| `editUrl` | string \| EditUrlFn
| `undefined` | Base URL to edit your site. The final URL is computed by `editUrl + relativePostPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. |
| `editLocalizedFiles` | `boolean` | `false` | The edit URL will target the localized file, instead of the original unlocalized file. Ignored when `editUrl` is a function. |
@@ -68,6 +68,7 @@ Accepted fields:
| `feedOptions` | _See below_ | `{type: ['rss', 'atom']}` | Blog feed. |
| `feedOptions.type` | FeedType \| FeedType[] \| 'all' \| null
| **Required** | Type of feed to be generated. Use `null` to disable generation. |
| `feedOptions.createFeedItems` | CreateFeedItemsFn \| undefined
| `undefined` | An optional function which can be used to transform and / or filter the items in the feed. |
+| `feedOptions.limit` | `number | null | false` | `undefined` | Limits the feed to the specified number of posts, `false` | `null` for all. Defaults to `20`. |
| `feedOptions.title` | `string` | `siteConfig.title` | Title of the feed. |
| `feedOptions.description` | `string` | \`$\{siteConfig.title} Blog\`
| Description of the feed. |
| `feedOptions.copyright` | `string` | `undefined` | Copyright message. |
diff --git a/website/docs/blog.mdx b/website/docs/blog.mdx
index 742692f55570..2b8d8651121a 100644
--- a/website/docs/blog.mdx
+++ b/website/docs/blog.mdx
@@ -520,6 +520,7 @@ type BlogOptions = {
description?: string;
copyright: string;
language?: string; // possible values: http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
+ limit?: number; // defaults to 20
/** Allow control over the construction of BlogFeedItems */
createFeedItems?: (params: {
blogPosts: BlogPost[];
From fe5f308b7da2db90fc812ca4eaef5409957946cc Mon Sep 17 00:00:00 2001
From: johnnyreilly
Date: Mon, 31 Jul 2023 07:29:00 +0100
Subject: [PATCH 2/3] fix: type literal initialiser
---
.../docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts b/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts
index 1ade5e8cbac9..b1915f75196f 100644
--- a/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts
+++ b/packages/docusaurus-plugin-content-blog/src/plugin-content-blog.d.ts
@@ -273,7 +273,7 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the
/** Allow control over the construction of BlogFeedItems */
createFeedItems?: CreateFeedItemsFn;
/** Limits the feed to the specified number of posts, false|null for all */
- limit?: number | false | null = 20;
+ limit?: number | false | null;
};
type DefaultCreateFeedItemsParams = {
From 9b75dbf44efbdf2219e2add9dc50d05a8d6d74c1 Mon Sep 17 00:00:00 2001
From: johnnyreilly
Date: Mon, 31 Jul 2023 07:32:30 +0100
Subject: [PATCH 3/3] fix: docs
---
website/docs/api/plugins/plugin-content-blog.mdx | 4 ++--
website/docs/blog.mdx | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/website/docs/api/plugins/plugin-content-blog.mdx b/website/docs/api/plugins/plugin-content-blog.mdx
index 1cdacb794889..b640dcae105e 100644
--- a/website/docs/api/plugins/plugin-content-blog.mdx
+++ b/website/docs/api/plugins/plugin-content-blog.mdx
@@ -38,7 +38,7 @@ Accepted fields:
```
| Name | Type | Default | Description |
-| --- | --- | --- | --- | --- | --- | --- |
+| --- | --- | --- | --- |
| `path` | `string` | `'blog'` | Path to the blog content directory on the file system, relative to site dir. |
| `editUrl` | string \| EditUrlFn
| `undefined` | Base URL to edit your site. The final URL is computed by `editUrl + relativePostPath`. Using a function allows more nuanced control for each file. Omitting this variable entirely will disable edit links. |
| `editLocalizedFiles` | `boolean` | `false` | The edit URL will target the localized file, instead of the original unlocalized file. Ignored when `editUrl` is a function. |
@@ -68,7 +68,7 @@ Accepted fields:
| `feedOptions` | _See below_ | `{type: ['rss', 'atom']}` | Blog feed. |
| `feedOptions.type` | FeedType \| FeedType[] \| 'all' \| null
| **Required** | Type of feed to be generated. Use `null` to disable generation. |
| `feedOptions.createFeedItems` | CreateFeedItemsFn \| undefined
| `undefined` | An optional function which can be used to transform and / or filter the items in the feed. |
-| `feedOptions.limit` | `number | null | false` | `undefined` | Limits the feed to the specified number of posts, `false` | `null` for all. Defaults to `20`. |
+| `feedOptions.limit` | `number \| null \| false` | `20` | Limits the feed to the specified number of posts, `false` or `null` for all entries. Defaults to `20`. |
| `feedOptions.title` | `string` | `siteConfig.title` | Title of the feed. |
| `feedOptions.description` | `string` | \`$\{siteConfig.title} Blog\`
| Description of the feed. |
| `feedOptions.copyright` | `string` | `undefined` | Copyright message. |
diff --git a/website/docs/blog.mdx b/website/docs/blog.mdx
index 2b8d8651121a..3bd2e65875bb 100644
--- a/website/docs/blog.mdx
+++ b/website/docs/blog.mdx
@@ -520,7 +520,7 @@ type BlogOptions = {
description?: string;
copyright: string;
language?: string; // possible values: http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes
- limit?: number; // defaults to 20
+ limit?: number | false | null; // defaults to 20
/** Allow control over the construction of BlogFeedItems */
createFeedItems?: (params: {
blogPosts: BlogPost[];