@docusaurus/plugin-content-blog 0.0.0-6010 → 0.0.0-6014
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/authors.d.ts +9 -10
- package/lib/authors.js +41 -78
- package/lib/authorsMap.d.ts +23 -0
- package/lib/authorsMap.js +116 -0
- package/lib/blogUtils.d.ts +2 -2
- package/lib/blogUtils.js +2 -6
- package/lib/index.js +15 -2
- package/lib/options.js +8 -0
- package/lib/props.d.ts +5 -1
- package/lib/props.js +7 -0
- package/lib/routes.js +75 -2
- package/package.json +10 -10
- package/src/authors.ts +57 -111
- package/src/authorsMap.ts +171 -0
- package/src/blogUtils.ts +4 -7
- package/src/index.ts +23 -1
- package/src/options.ts +12 -0
- package/src/plugin-content-blog.d.ts +90 -12
- package/src/props.ts +15 -0
- package/src/routes.ts +97 -2
|
@@ -22,13 +22,7 @@ declare module '@docusaurus/plugin-content-blog' {
|
|
|
22
22
|
|
|
23
23
|
export type Assets = {
|
|
24
24
|
/**
|
|
25
|
-
* If `metadata.
|
|
26
|
-
4
|
|
27
|
-
yarn workspace v1.22.19yarn workspace website typecheck
|
|
28
|
-
4
|
|
29
|
-
yarn workspace v1.22.19yarn workspace website typecheck
|
|
30
|
-
4
|
|
31
|
-
yarn workspace v1.22.19image` is a collocated image path, this entry will be the
|
|
25
|
+
* If `metadata.image` is a collocated image path, this entry will be the
|
|
32
26
|
* bundler-generated image path. Otherwise, it's empty, and the image URL
|
|
33
27
|
* should be accessed through `frontMatter.image`.
|
|
34
28
|
*/
|
|
@@ -66,9 +60,7 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the
|
|
|
66
60
|
[customAuthorSocialPlatform: string]: string;
|
|
67
61
|
};
|
|
68
62
|
|
|
69
|
-
export type
|
|
70
|
-
key?: string; // TODO temporary, need refactor
|
|
71
|
-
|
|
63
|
+
export type AuthorAttributes = {
|
|
72
64
|
/**
|
|
73
65
|
* If `name` doesn't exist, an `imageURL` is expected.
|
|
74
66
|
*/
|
|
@@ -98,11 +90,45 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the
|
|
|
98
90
|
*/
|
|
99
91
|
socials?: AuthorSocials;
|
|
100
92
|
/**
|
|
101
|
-
*
|
|
93
|
+
* Description of the author.
|
|
94
|
+
*/
|
|
95
|
+
description?: string;
|
|
96
|
+
/**
|
|
97
|
+
* Unknown keys are allowed, so that we can pass custom fields to authors.
|
|
102
98
|
*/
|
|
103
99
|
[customAuthorAttribute: string]: unknown;
|
|
104
100
|
};
|
|
105
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Metadata of the author's page, if it exists.
|
|
104
|
+
*/
|
|
105
|
+
export type AuthorPage = {permalink: string};
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Normalized author metadata.
|
|
109
|
+
*/
|
|
110
|
+
export type Author = AuthorAttributes & {
|
|
111
|
+
/**
|
|
112
|
+
* Author key, if the author was loaded from the authors map.
|
|
113
|
+
* `null` means the author was declared inline.
|
|
114
|
+
*/
|
|
115
|
+
key: string | null;
|
|
116
|
+
/**
|
|
117
|
+
* Metadata of the author's page.
|
|
118
|
+
* `null` means the author doesn't have a dedicated author page.
|
|
119
|
+
*/
|
|
120
|
+
page: AuthorPage | null;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/** Authors coming from the AuthorsMap always have a key */
|
|
124
|
+
export type AuthorWithKey = Author & {key: string};
|
|
125
|
+
|
|
126
|
+
/** What the authors list page should know about each author. */
|
|
127
|
+
export type AuthorItemProp = AuthorWithKey & {
|
|
128
|
+
/** Number of blog posts with this author. */
|
|
129
|
+
count: number;
|
|
130
|
+
};
|
|
131
|
+
|
|
106
132
|
/**
|
|
107
133
|
* Everything is partial/unnormalized, because front matter is always
|
|
108
134
|
* preserved as-is. Default values will be applied when generating metadata
|
|
@@ -194,7 +220,7 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the
|
|
|
194
220
|
last_update?: FrontMatterLastUpdate;
|
|
195
221
|
};
|
|
196
222
|
|
|
197
|
-
export type BlogPostFrontMatterAuthor =
|
|
223
|
+
export type BlogPostFrontMatterAuthor = AuthorAttributes & {
|
|
198
224
|
/**
|
|
199
225
|
* Will be normalized into the `imageURL` prop.
|
|
200
226
|
*/
|
|
@@ -427,6 +453,10 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the
|
|
|
427
453
|
blogTagsListComponent: string;
|
|
428
454
|
/** Root component of the "posts containing tag" page. */
|
|
429
455
|
blogTagsPostsComponent: string;
|
|
456
|
+
/** Root component of the authors list page. */
|
|
457
|
+
blogAuthorsListComponent: string;
|
|
458
|
+
/** Root component of the "posts containing author" page. */
|
|
459
|
+
blogAuthorsPostsComponent: string;
|
|
430
460
|
/** Root component of the blog archive page. */
|
|
431
461
|
blogArchiveComponent: string;
|
|
432
462
|
/** Blog page title for better SEO. */
|
|
@@ -471,6 +501,8 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the
|
|
|
471
501
|
* (filter, modify, delete, etc...).
|
|
472
502
|
*/
|
|
473
503
|
processBlogPosts: ProcessBlogPostsFn;
|
|
504
|
+
/* Base path for the authors page */
|
|
505
|
+
authorsBasePath: string;
|
|
474
506
|
/** The behavior of Docusaurus when it finds inline authors. */
|
|
475
507
|
onInlineAuthors: 'ignore' | 'log' | 'warn' | 'throw';
|
|
476
508
|
};
|
|
@@ -508,17 +540,22 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the
|
|
|
508
540
|
items: BlogSidebarItem[];
|
|
509
541
|
};
|
|
510
542
|
|
|
543
|
+
export type AuthorsMap = {[authorKey: string]: AuthorWithKey};
|
|
544
|
+
|
|
511
545
|
export type BlogContent = {
|
|
512
546
|
blogSidebarTitle: string;
|
|
513
547
|
blogPosts: BlogPost[];
|
|
514
548
|
blogListPaginated: BlogPaginated[];
|
|
515
549
|
blogTags: BlogTags;
|
|
516
550
|
blogTagsListPath: string;
|
|
551
|
+
authorsMap?: AuthorsMap;
|
|
517
552
|
};
|
|
518
553
|
|
|
519
554
|
export type BlogMetadata = {
|
|
520
555
|
/** the path to the base of the blog */
|
|
521
556
|
blogBasePath: string;
|
|
557
|
+
/** the path to the authors list page */
|
|
558
|
+
authorsListPath: string;
|
|
522
559
|
/** title of the overall blog */
|
|
523
560
|
blogTitle: string;
|
|
524
561
|
};
|
|
@@ -679,6 +716,47 @@ declare module '@theme/BlogTagsListPage' {
|
|
|
679
716
|
export default function BlogTagsListPage(props: Props): JSX.Element;
|
|
680
717
|
}
|
|
681
718
|
|
|
719
|
+
declare module '@theme/Blog/Pages/BlogAuthorsListPage' {
|
|
720
|
+
import type {
|
|
721
|
+
AuthorItemProp,
|
|
722
|
+
BlogSidebar,
|
|
723
|
+
} from '@docusaurus/plugin-content-blog';
|
|
724
|
+
|
|
725
|
+
export interface Props {
|
|
726
|
+
/** Blog sidebar. */
|
|
727
|
+
readonly sidebar: BlogSidebar;
|
|
728
|
+
/** All authors declared in this blog. */
|
|
729
|
+
readonly authors: AuthorItemProp[];
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
export default function BlogAuthorsListPage(props: Props): JSX.Element;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
declare module '@theme/Blog/Pages/BlogAuthorsPostsPage' {
|
|
736
|
+
import type {Content} from '@theme/BlogPostPage';
|
|
737
|
+
import type {
|
|
738
|
+
AuthorItemProp,
|
|
739
|
+
BlogSidebar,
|
|
740
|
+
BlogPaginatedMetadata,
|
|
741
|
+
} from '@docusaurus/plugin-content-blog';
|
|
742
|
+
|
|
743
|
+
export interface Props {
|
|
744
|
+
/** Blog sidebar. */
|
|
745
|
+
readonly sidebar: BlogSidebar;
|
|
746
|
+
/** Metadata of this author. */
|
|
747
|
+
readonly author: AuthorItemProp;
|
|
748
|
+
/** Looks exactly the same as the posts list page */
|
|
749
|
+
readonly listMetadata: BlogPaginatedMetadata;
|
|
750
|
+
/**
|
|
751
|
+
* Array of blog posts included on this page. Every post's metadata is also
|
|
752
|
+
* available.
|
|
753
|
+
*/
|
|
754
|
+
readonly items: readonly {readonly content: Content}[];
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
export default function BlogAuthorsPostsPage(props: Props): JSX.Element;
|
|
758
|
+
}
|
|
759
|
+
|
|
682
760
|
declare module '@theme/BlogTagsPostsPage' {
|
|
683
761
|
import type {Content} from '@theme/BlogPostPage';
|
|
684
762
|
import type {
|
package/src/props.ts
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type {TagsListItem, TagModule} from '@docusaurus/utils';
|
|
8
8
|
import type {
|
|
9
|
+
AuthorItemProp,
|
|
10
|
+
AuthorWithKey,
|
|
9
11
|
BlogPost,
|
|
10
12
|
BlogSidebar,
|
|
11
13
|
BlogTag,
|
|
@@ -40,6 +42,19 @@ export function toTagProp({
|
|
|
40
42
|
};
|
|
41
43
|
}
|
|
42
44
|
|
|
45
|
+
export function toAuthorItemProp({
|
|
46
|
+
author,
|
|
47
|
+
count,
|
|
48
|
+
}: {
|
|
49
|
+
author: AuthorWithKey;
|
|
50
|
+
count: number;
|
|
51
|
+
}): AuthorItemProp {
|
|
52
|
+
return {
|
|
53
|
+
...author,
|
|
54
|
+
count,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
43
58
|
export function toBlogSidebarProp({
|
|
44
59
|
blogSidebarTitle,
|
|
45
60
|
blogPosts,
|
package/src/routes.ts
CHANGED
|
@@ -11,9 +11,15 @@ import {
|
|
|
11
11
|
docuHash,
|
|
12
12
|
aliasedSitePathToRelativePath,
|
|
13
13
|
} from '@docusaurus/utils';
|
|
14
|
-
import {shouldBeListed} from './blogUtils';
|
|
14
|
+
import {paginateBlogPosts, shouldBeListed} from './blogUtils';
|
|
15
15
|
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
toAuthorItemProp,
|
|
18
|
+
toBlogSidebarProp,
|
|
19
|
+
toTagProp,
|
|
20
|
+
toTagsProp,
|
|
21
|
+
} from './props';
|
|
22
|
+
import {groupBlogPostsByAuthorKey} from './authors';
|
|
17
23
|
import type {
|
|
18
24
|
PluginContentLoadedActions,
|
|
19
25
|
RouteConfig,
|
|
@@ -26,6 +32,7 @@ import type {
|
|
|
26
32
|
BlogContent,
|
|
27
33
|
PluginOptions,
|
|
28
34
|
BlogPost,
|
|
35
|
+
AuthorWithKey,
|
|
29
36
|
} from '@docusaurus/plugin-content-blog';
|
|
30
37
|
|
|
31
38
|
type CreateAllRoutesParam = {
|
|
@@ -54,11 +61,16 @@ export async function buildAllRoutes({
|
|
|
54
61
|
blogListComponent,
|
|
55
62
|
blogPostComponent,
|
|
56
63
|
blogTagsListComponent,
|
|
64
|
+
blogAuthorsListComponent,
|
|
65
|
+
blogAuthorsPostsComponent,
|
|
57
66
|
blogTagsPostsComponent,
|
|
58
67
|
blogArchiveComponent,
|
|
59
68
|
routeBasePath,
|
|
60
69
|
archiveBasePath,
|
|
61
70
|
blogTitle,
|
|
71
|
+
authorsBasePath,
|
|
72
|
+
postsPerPage,
|
|
73
|
+
blogDescription,
|
|
62
74
|
} = options;
|
|
63
75
|
const pluginId = options.id!;
|
|
64
76
|
const {createData} = actions;
|
|
@@ -68,8 +80,15 @@ export async function buildAllRoutes({
|
|
|
68
80
|
blogListPaginated,
|
|
69
81
|
blogTags,
|
|
70
82
|
blogTagsListPath,
|
|
83
|
+
authorsMap,
|
|
71
84
|
} = content;
|
|
72
85
|
|
|
86
|
+
const authorsListPath = normalizeUrl([
|
|
87
|
+
baseUrl,
|
|
88
|
+
routeBasePath,
|
|
89
|
+
authorsBasePath,
|
|
90
|
+
]);
|
|
91
|
+
|
|
73
92
|
const listedBlogPosts = blogPosts.filter(shouldBeListed);
|
|
74
93
|
|
|
75
94
|
const blogPostsById = _.keyBy(blogPosts, (post) => post.id);
|
|
@@ -102,6 +121,7 @@ export async function buildAllRoutes({
|
|
|
102
121
|
const blogMetadata: BlogMetadata = {
|
|
103
122
|
blogBasePath: normalizeUrl([baseUrl, routeBasePath]),
|
|
104
123
|
blogTitle,
|
|
124
|
+
authorsListPath,
|
|
105
125
|
};
|
|
106
126
|
const modulePath = await createData(
|
|
107
127
|
`blogMetadata-${pluginId}.json`,
|
|
@@ -249,10 +269,85 @@ export async function buildAllRoutes({
|
|
|
249
269
|
return [tagsListRoute, ...tagsPaginatedRoutes];
|
|
250
270
|
}
|
|
251
271
|
|
|
272
|
+
function createAuthorsRoutes(): RouteConfig[] {
|
|
273
|
+
if (authorsMap === undefined || Object.keys(authorsMap).length === 0) {
|
|
274
|
+
return [];
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
const blogPostsByAuthorKey = groupBlogPostsByAuthorKey({
|
|
278
|
+
authorsMap,
|
|
279
|
+
blogPosts,
|
|
280
|
+
});
|
|
281
|
+
const authors = Object.values(authorsMap);
|
|
282
|
+
|
|
283
|
+
return [
|
|
284
|
+
createAuthorListRoute(),
|
|
285
|
+
...authors.flatMap(createAuthorPaginatedRoute),
|
|
286
|
+
];
|
|
287
|
+
|
|
288
|
+
function createAuthorListRoute(): RouteConfig {
|
|
289
|
+
return {
|
|
290
|
+
path: authorsListPath,
|
|
291
|
+
component: blogAuthorsListComponent,
|
|
292
|
+
exact: true,
|
|
293
|
+
modules: {
|
|
294
|
+
sidebar: sidebarModulePath,
|
|
295
|
+
},
|
|
296
|
+
props: {
|
|
297
|
+
authors: authors.map((author) =>
|
|
298
|
+
toAuthorItemProp({
|
|
299
|
+
author,
|
|
300
|
+
count: blogPostsByAuthorKey[author.key]?.length ?? 0,
|
|
301
|
+
}),
|
|
302
|
+
),
|
|
303
|
+
},
|
|
304
|
+
context: {
|
|
305
|
+
blogMetadata: blogMetadataModulePath,
|
|
306
|
+
},
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
function createAuthorPaginatedRoute(author: AuthorWithKey): RouteConfig[] {
|
|
311
|
+
const authorBlogPosts = blogPostsByAuthorKey[author.key] ?? [];
|
|
312
|
+
if (!author.page) {
|
|
313
|
+
return [];
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
const pages = paginateBlogPosts({
|
|
317
|
+
blogPosts: authorBlogPosts,
|
|
318
|
+
basePageUrl: author.page.permalink,
|
|
319
|
+
blogDescription,
|
|
320
|
+
blogTitle,
|
|
321
|
+
pageBasePath: authorsBasePath,
|
|
322
|
+
postsPerPageOption: postsPerPage,
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
return pages.map(({metadata, items}) => {
|
|
326
|
+
return {
|
|
327
|
+
path: metadata.permalink,
|
|
328
|
+
component: blogAuthorsPostsComponent,
|
|
329
|
+
exact: true,
|
|
330
|
+
modules: {
|
|
331
|
+
items: blogPostItemsModule(items),
|
|
332
|
+
sidebar: sidebarModulePath,
|
|
333
|
+
},
|
|
334
|
+
props: {
|
|
335
|
+
author: toAuthorItemProp({author, count: authorBlogPosts.length}),
|
|
336
|
+
listMetadata: metadata,
|
|
337
|
+
},
|
|
338
|
+
context: {
|
|
339
|
+
blogMetadata: blogMetadataModulePath,
|
|
340
|
+
},
|
|
341
|
+
};
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
252
346
|
return [
|
|
253
347
|
...createBlogPostRoutes(),
|
|
254
348
|
...createBlogPostsPaginatedRoutes(),
|
|
255
349
|
...createTagsRoutes(),
|
|
256
350
|
...createArchiveRoute(),
|
|
351
|
+
...createAuthorsRoutes(),
|
|
257
352
|
];
|
|
258
353
|
}
|