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

feat(blog): allow processing blog posts through a processBlogPosts function #9886

Merged
merged 18 commits into from
Mar 5, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
linkify,
getSourceToPermalink,
paginateBlogPosts,
applyProcessBlogPosts,
type LinkifyParams,
} from '../blogUtils';
import type {BlogBrokenMarkdownLink, BlogContentPaths} from '../types';
import type {BlogPost} from '@docusaurus/plugin-content-blog';
import type {BlogPost, BlogPostMetadata} from '@docusaurus/plugin-content-blog';

describe('truncate', () => {
it('truncates texts', () => {
Expand Down Expand Up @@ -237,6 +238,7 @@
frontMatter: {},
authors: [],
formattedDate: '',
unlisted: false,
},
content: '',
},
Expand Down Expand Up @@ -295,3 +297,49 @@
} as BlogBrokenMarkdownLink);
});
});

const defaultValuesForOtherKeys: Omit<BlogPostMetadata, 'date'> = {
OzakIOne marked this conversation as resolved.
Show resolved Hide resolved
source: '',
title: '',
formattedDate: '',
permalink: '',
description: '',
hasTruncateMarker: false,
authors: [],
frontMatter: {},
tags: [],
unlisted: false,
};
const createBlogPost = (args: Partial<BlogPost>): BlogPost => ({
id: '',
metadata: {
date: new Date(),
...defaultValuesForOtherKeys,
...args.metadata,
},
content: args.content || '',
});

describe('processBlogPosts', () => {
const blogPost2022 = createBlogPost({
metadata: {date: new Date('2022-01-01'), ...defaultValuesForOtherKeys},
});
const blogPost2023 = createBlogPost({
metadata: {date: new Date('2023-01-01'), ...defaultValuesForOtherKeys},
});
const blogPost2024 = createBlogPost({
metadata: {date: new Date('2024-01-01'), ...defaultValuesForOtherKeys},
});

it('filter blogs', async () => {
OzakIOne marked this conversation as resolved.
Show resolved Hide resolved
const processedBlogPosts = applyProcessBlogPosts({
OzakIOne marked this conversation as resolved.
Show resolved Hide resolved
blogPosts: [blogPost2022, blogPost2023, blogPost2024],
processBlogPosts: ({blogPosts}: {blogPosts: BlogPost[]}) =>
blogPosts.filter(
(blogPost) => blogPost.metadata.date.getFullYear() === 2024,
),
});

expect(processedBlogPosts).toEqual([blogPost2024]);

Check failure on line 343 in packages/docusaurus-plugin-content-blog/src/__tests__/blogUtils.test.ts

View workflow job for this annotation

GitHub Actions / Windows Tests (18.0)

processBlogPosts › filter blogs

expect(received).toEqual(expected) // deep equality Expected: [{"content": "", "id": "", "metadata": {"authors": [], "date": 2024-01-01T00:00:00.000Z, "description": "", "formattedDate": "", "frontMatter": {}, "hasTruncateMarker": false, "permalink": "", "source": "", "tags": [], "title": "", "unlisted": false}}] Received: {} at Object.toEqual (packages/docusaurus-plugin-content-blog/src/__tests__/blogUtils.test.ts:343:32)
});
});
16 changes: 16 additions & 0 deletions packages/docusaurus-plugin-content-blog/src/blogUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -446,3 +446,19 @@ export function linkify({

return newContent;
}

export async function applyProcessBlogPosts({
blogPosts,
processBlogPosts,
}: {
blogPosts: BlogPost[];
processBlogPosts: PluginOptions['processBlogPosts'];
}): Promise<BlogPost[]> {
const processedBlogPosts = processBlogPosts({blogPosts});
OzakIOne marked this conversation as resolved.
Show resolved Hide resolved

if (Array.isArray(processedBlogPosts)) {
return processedBlogPosts;
}

return blogPosts;
}
9 changes: 7 additions & 2 deletions packages/docusaurus-plugin-content-blog/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ import {
DEFAULT_PLUGIN_ID,
} from '@docusaurus/utils';
import {
generateBlogPosts,
getSourceToPermalink,
getBlogTags,
paginateBlogPosts,
shouldBeListed,
applyProcessBlogPosts,
generateBlogPosts,
} from './blogUtils';
import footnoteIDFixer from './remark/footnoteIDFixer';
import {translateContent, getTranslationFiles} from './translations';
Expand Down Expand Up @@ -113,7 +114,11 @@ export default async function pluginContentBlog(

const baseBlogUrl = normalizeUrl([baseUrl, routeBasePath]);
const blogTagsListPath = normalizeUrl([baseBlogUrl, tagsBasePath]);
const blogPosts = await generateBlogPosts(contentPaths, context, options);
let blogPosts = await generateBlogPosts(contentPaths, context, options);
blogPosts = await applyProcessBlogPosts({
blogPosts,
processBlogPosts: options.processBlogPosts,
});
const listedBlogPosts = blogPosts.filter(shouldBeListed);

if (!blogPosts.length) {
Expand Down
4 changes: 4 additions & 0 deletions packages/docusaurus-plugin-content-blog/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export const DEFAULT_OPTIONS: PluginOptions = {
authorsMapPath: 'authors.yml',
readingTime: ({content, defaultReadingTime}) => defaultReadingTime({content}),
sortPosts: 'descending',
processBlogPosts: () => undefined,
};

const PluginOptionSchema = Joi.object<PluginOptions>({
Expand Down Expand Up @@ -134,6 +135,9 @@ const PluginOptionSchema = Joi.object<PluginOptions>({
sortPosts: Joi.string()
.valid('descending', 'ascending')
.default(DEFAULT_OPTIONS.sortPosts),
processBlogPosts: Joi.function()
.optional()
.default(() => DEFAULT_OPTIONS.processBlogPosts),
}).default(DEFAULT_OPTIONS);

export function validateOptions({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,11 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the
defaultReadingTime: ReadingTimeFunction;
},
) => number | undefined;

export type ProcessBlogPostsFn = (params: {
blogPosts: BlogPost[];
}) => void | BlogPost[];
OzakIOne marked this conversation as resolved.
Show resolved Hide resolved

/**
* Plugin options after normalization.
*/
Expand Down Expand Up @@ -426,6 +431,8 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the
readingTime: ReadingTimeFunctionOption;
/** Governs the direction of blog post sorting. */
sortPosts: 'ascending' | 'descending';
/** TODO process blog posts. */
OzakIOne marked this conversation as resolved.
Show resolved Hide resolved
processBlogPosts: ProcessBlogPostsFn;
};

/**
Expand Down
9 changes: 9 additions & 0 deletions website/docs/api/plugins/plugin-content-blog.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ Accepted fields:
| `feedOptions.copyright` | `string` | `undefined` | Copyright message. |
| `feedOptions.language` | `string` (See [documentation](http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes) for possible values) | `undefined` | Language metadata of the feed. |
| `sortPosts` | <code>'descending' \| 'ascending' </code> | `'descending'` | Governs the direction of blog post sorting. |
| `processBlogPosts` | <code><a href="#ProcessBlogPostsFn">ProcessBlogPostsFn</a> </code> | `undefined` | An optional function which can be used to transform blog posts (filter, modify, delete, etc...). |
OzakIOne marked this conversation as resolved.
Show resolved Hide resolved

```mdx-code-block
</APITable>
Expand Down Expand Up @@ -131,6 +132,14 @@ type CreateFeedItemsFn = (params: {
}) => Promise<BlogFeedItem[]>;
```

#### `ProcessBlogPostsFn` {#ProcessBlogPostsFn}

```ts
type ProcessBlogPostsFn = (params: {
blogPosts: BlogPost[];
}) => Promise<void | BlogPost[]>;
```

### Example configuration {#ex-config}

You can configure this plugin through preset options or plugin options.
Expand Down