Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ import {
linkify,
getSourceToPermalink,
paginateBlogPosts,
applyProcessBlogPosts,
type LinkifyParams,
} from '../blogUtils';
import type {BlogBrokenMarkdownLink, BlogContentPaths} from '../types';
import type {BlogPost} from '@docusaurus/plugin-content-blog';
import type {DeepPartial} from 'utility-types';

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

const createBlogPost = (args: DeepPartial<BlogPost>): BlogPost => ({
id: '',
metadata: {
source: '',
title: '',
formattedDate: '',
permalink: '',
description: '',
hasTruncateMarker: false,
authors: [],
frontMatter: {},
tags: [],
unlisted: false,
...args.metadata,
} as BlogPost['metadata'],
content: args.content || '',
});

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

it('filter blogs only from 2024', async () => {
const processedBlogPosts = await applyProcessBlogPosts({
blogPosts: [blogPost2022, blogPost2023, blogPost2024],
processBlogPosts: ({blogPosts}: {blogPosts: BlogPost[]}) =>
blogPosts.filter(
(blogPost) => blogPost.metadata.date.getFullYear() === 2024,
),
});

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

it('sort blogs by date in ascending order', async () => {
const processedBlogPosts = await applyProcessBlogPosts({
blogPosts: [blogPost2023, blogPost2022, blogPost2024],
processBlogPosts: ({blogPosts}: {blogPosts: BlogPost[]}) =>
blogPosts.sort(
(a, b) => a.metadata.date.getTime() - b.metadata.date.getTime(),
),
});

expect(processedBlogPosts).toEqual([
blogPost2022,
blogPost2023,
blogPost2024,
]);
});

it('sort blogs by date in descending order', async () => {
const processedBlogPosts = await applyProcessBlogPosts({
blogPosts: [blogPost2023, blogPost2022, blogPost2024],
processBlogPosts: ({blogPosts}: {blogPosts: BlogPost[]}) =>
blogPosts.sort(
(a, b) => b.metadata.date.getTime() - a.metadata.date.getTime(),
),
});

expect(processedBlogPosts).toEqual([
blogPost2024,
blogPost2023,
blogPost2022,
]);
});
});
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});

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[];

/**
* 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. */
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...). |

```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