Skip to content

Commit 724f795

Browse files
feat(blog): add authors page (#7362)
1 parent 5575ff9 commit 724f795

7 files changed

Lines changed: 849 additions & 90 deletions

File tree

documentation/plugins/blog-plugin.js

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,16 @@ const DEFAULT_BLOG_CATEGORY = "Engineering";
1212
const DEFAULT_POSTS_PER_PAGE_MODE = "ALL";
1313
const PAGINATION_PATH_SEGMENT = "page";
1414
const RANDOM_POSTS_LIMIT = 3;
15+
const AUTHOR_POSTS_PREVIEW_LIMIT = 3;
1516
const CATEGORY_FALLBACK_SLUG = "category";
1617
const BLOG_BASE_PATH = "/blog";
1718
const BLOG_CATEGORIES_LIST_PATH = `${BLOG_BASE_PATH}/categories`;
19+
const BLOG_AUTHORS_LIST_PATH = `${BLOG_BASE_PATH}/authors`;
1820
const BLOG_AUTHORS_BASE_PATH = `${BLOG_BASE_PATH}/author`;
1921
const ALL_TAGS_LABEL = "All tags";
2022
const TAGS_DATA_SUFFIX = "-tags";
2123
const CATEGORIES_DATA_SUFFIX = "-categories";
24+
const AUTHORS_DATA_SUFFIX = "-authors";
2225
const CATEGORY_DATA_SUFFIX = "-category";
2326
const ALL_TAGS_DATA_SUFFIX = "-all-tags";
2427
const LIST_DATA_SUFFIX = "-list";
@@ -30,6 +33,8 @@ const IS_FEATURED_FRONTMATTER_KEY = "is_featured";
3033
const BLOG_POST_PAGE_COMPONENT = "@theme/BlogPostPage";
3134
const BLOG_LIST_PAGE_COMPONENT = "@theme/BlogListPage";
3235
const BLOG_AUTHOR_PAGE_COMPONENT = "@site/src/components/blog/author-page";
36+
const BLOG_AUTHORS_LIST_PAGE_COMPONENT =
37+
"@site/src/components/blog/authors-page";
3338
const BLOG_TAGS_POSTS_PAGE_COMPONENT = "@theme/BlogTagsPostsPage";
3439
const BLOG_CATEGORIES_LIST_PAGE_COMPONENT = "@theme/BlogCategoriesListPage";
3540
const BLOG_CATEGORY_POSTS_PAGE_COMPONENT = "@theme/BlogCategoryPostsPage";
@@ -208,6 +213,87 @@ function toPostInfo(post) {
208213
};
209214
}
210215

216+
function toComparableTimestamp(dateValue) {
217+
const timestamp = new Date(dateValue).getTime();
218+
219+
return Number.isNaN(timestamp) ? 0 : timestamp;
220+
}
221+
222+
function sortBlogPostsByDateDescending(blogPosts) {
223+
return [...blogPosts].sort((postA, postB) => {
224+
const timestampDiff =
225+
toComparableTimestamp(postB.metadata.date) -
226+
toComparableTimestamp(postA.metadata.date);
227+
228+
if (timestampDiff !== 0) {
229+
return timestampDiff;
230+
}
231+
232+
return `${postA.metadata.title ?? ""}`.localeCompare(
233+
`${postB.metadata.title ?? ""}`,
234+
);
235+
});
236+
}
237+
238+
function createBlogAuthors({ allBlogPosts, blogCategories }) {
239+
const authorsMap = new Map();
240+
241+
allBlogPosts.forEach((post) => {
242+
const author = post.metadata.authors?.[0];
243+
244+
if (!author?.key) {
245+
return;
246+
}
247+
248+
const existingEntry = authorsMap.get(author.key);
249+
250+
if (existingEntry) {
251+
existingEntry.posts.push(post);
252+
return;
253+
}
254+
255+
authorsMap.set(author.key, {
256+
author,
257+
permalink: `${BLOG_AUTHORS_BASE_PATH}/${author.key}`,
258+
posts: [post],
259+
});
260+
});
261+
262+
return [...authorsMap.values()]
263+
.map(({ author, permalink, posts }) => {
264+
const sortedPosts = sortBlogPostsByDateDescending(posts);
265+
266+
return {
267+
author,
268+
permalink,
269+
count: sortedPosts.length,
270+
recentPosts: sortedPosts
271+
.slice(0, AUTHOR_POSTS_PREVIEW_LIMIT)
272+
.map((post) => ({
273+
title: post.metadata.title,
274+
permalink: post.metadata.permalink,
275+
date: post.metadata.date,
276+
formattedDate: post.metadata.formattedDate,
277+
category: getBlogPostCategoryData({
278+
frontMatter: post.metadata.frontMatter,
279+
blogCategories,
280+
}),
281+
})),
282+
};
283+
})
284+
.sort((authorA, authorB) => {
285+
const countDiff = (authorB.count ?? 0) - (authorA.count ?? 0);
286+
287+
if (countDiff !== 0) {
288+
return countDiff;
289+
}
290+
291+
return `${authorA.author?.name ?? ""}`.localeCompare(
292+
`${authorB.author?.name ?? ""}`,
293+
);
294+
});
295+
}
296+
211297
function getRelatedPosts(allBlogPosts, metadata) {
212298
const currentPostTags = normalizeTags(metadata.frontMatter.tags);
213299
const currentPostCategory = getBlogPostCategory(metadata.frontMatter);
@@ -732,6 +818,29 @@ async function blogPluginExtended(...pluginArgs) {
732818
}),
733819
);
734820

821+
const blogAuthors = createBlogAuthors({
822+
allBlogPosts,
823+
blogCategories,
824+
});
825+
826+
if (blogAuthors.length > 0) {
827+
const authorsPropPath = await createData(
828+
`${utils.docuHash(
829+
`${BLOG_AUTHORS_LIST_PATH}${AUTHORS_DATA_SUFFIX}`,
830+
)}${JSON_FILE_EXTENSION}`,
831+
JSON.stringify(blogAuthors, null, 2),
832+
);
833+
834+
addRoute({
835+
path: BLOG_AUTHORS_LIST_PATH,
836+
component: BLOG_AUTHORS_LIST_PAGE_COMPONENT,
837+
exact: true,
838+
modules: {
839+
authors: aliasedSource(authorsPropPath),
840+
},
841+
});
842+
}
843+
735844
const authorsArray = allBlogPosts
736845
.map((post) => post.metadata.frontMatter.authors)
737846
.filter((authorName) => authorName !== undefined);

0 commit comments

Comments
 (0)