-
-
Notifications
You must be signed in to change notification settings - Fork 8k
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 sorting blog posts through a options.sortPosts
function hook
#9840
Changes from 14 commits
2d1d219
e096c38
5ef530e
a767e3e
cb04411
5d8bbd8
08d30a0
003f163
20093ad
93715e2
71ca16d
67f5f27
8bbc6c7
a9c5799
fa7ec65
c949c3f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,10 @@ import type { | |
BlogPost, | ||
BlogTags, | ||
BlogPaginated, | ||
Options, | ||
SortBlogPostsFn, | ||
SortPresets, | ||
SortBlogPostsPreset, | ||
} from '@docusaurus/plugin-content-blog'; | ||
import type {BlogContentPaths, BlogMarkdownLoaderOptions} from './types'; | ||
|
||
|
@@ -363,6 +367,62 @@ async function processBlogSourceFile( | |
}; | ||
} | ||
|
||
const sortPresets: SortPresets = { | ||
descending: ({blogPosts}) => | ||
blogPosts.sort( | ||
(a, b) => b.metadata.date.getTime() - a.metadata.date.getTime(), | ||
), | ||
ascending: ({blogPosts}) => | ||
blogPosts.sort( | ||
(a, b) => a.metadata.date.getTime() - b.metadata.date.getTime(), | ||
), | ||
}; | ||
|
||
interface SortBlogPostsOptions { | ||
blogPosts: BlogPost[]; | ||
sortPosts: SortBlogPostsPreset | SortBlogPostsFn; | ||
} | ||
|
||
function getSortFunction(sortPosts: Options['sortPosts']): SortBlogPostsFn { | ||
if (typeof sortPosts === 'function') { | ||
return sortPosts; | ||
} | ||
|
||
if (typeof sortPosts === 'string') { | ||
const presetFn = sortPresets[sortPosts]; | ||
if (!presetFn) { | ||
throw new Error( | ||
`sortPosts preset ${sortPosts} does not exist, valid presets are: ${Object.keys( | ||
sortPresets, | ||
).join(', ')}`, | ||
); | ||
} | ||
return presetFn; | ||
} | ||
|
||
return () => {}; | ||
} | ||
|
||
export function sortBlogPosts({ | ||
blogPosts, | ||
sortPosts, | ||
}: SortBlogPostsOptions): BlogPost[] { | ||
const sortFunction = getSortFunction(sortPosts); | ||
const sortedBlogPosts = sortFunction({blogPosts}); | ||
|
||
if (sortedBlogPosts !== undefined) { | ||
if (sortedBlogPosts.length === 0) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure why someone would return an empty array by mistakes. Users are likely to either return undefined, or return a new sorted list of posts. If we want to prevent mistakes, we should check that We could check that the returned value is an array, because users might use JS in config files and return an unsafe value such as a number 🤷♂️ But I'm not sure we want to prevent that anyway, because Maybe |
||
logger.warn( | ||
`Sorting function returned an empty array. Reverting to the original list to prevent issues.`, | ||
); | ||
return blogPosts; | ||
} | ||
return sortedBlogPosts; | ||
} | ||
|
||
return blogPosts; | ||
} | ||
|
||
export async function generateBlogPosts( | ||
contentPaths: BlogContentPaths, | ||
context: LoadContext, | ||
|
@@ -405,14 +465,12 @@ export async function generateBlogPosts( | |
await Promise.all(blogSourceFiles.map(doProcessBlogSourceFile)) | ||
).filter(Boolean) as BlogPost[]; | ||
|
||
blogPosts.sort( | ||
(a, b) => b.metadata.date.getTime() - a.metadata.date.getTime(), | ||
); | ||
const sortedPosts = sortBlogPosts({ | ||
blogPosts, | ||
sortPosts: options.sortPosts, | ||
}); | ||
|
||
if (options.sortPosts === 'ascending') { | ||
return blogPosts.reverse(); | ||
} | ||
return blogPosts; | ||
return sortedPosts; | ||
slorber marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
export type LinkifyParams = { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
too verbose test code, create a helper that can accept partial blog post args and let us focus on what matters
Your test should be as readable as this (pseudo code), with the intent being super clear
It's preferable if each test create its own inputs, instead of relying on a shared list of posts for all tests. As we add tests, this list will only grow over time and tests will become harder to understand and maintain