@docusaurus/plugin-content-blog 3.2.1 → 3.3.0
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 +1 -0
- package/lib/blogUtils.d.ts +1 -0
- package/lib/client/index.d.ts +1 -0
- package/lib/feed.d.ts +1 -0
- package/lib/frontMatter.d.ts +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +12 -138
- package/lib/options.d.ts +1 -0
- package/lib/props.d.ts +1 -0
- package/lib/routes.d.ts +19 -0
- package/lib/routes.js +182 -0
- package/lib/translations.d.ts +1 -0
- package/package.json +9 -9
- package/src/index.ts +13 -217
- package/src/routes.ts +263 -0
package/lib/authors.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
+
/// <reference path="../src/plugin-content-blog.d.ts" />
|
|
7
8
|
import type { BlogContentPaths } from './types';
|
|
8
9
|
import type { Author, BlogPostFrontMatter } from '@docusaurus/plugin-content-blog';
|
|
9
10
|
export type AuthorsMap = {
|
package/lib/blogUtils.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
+
/// <reference path="../src/plugin-content-blog.d.ts" />
|
|
7
8
|
import type { LoadContext } from '@docusaurus/types';
|
|
8
9
|
import type { PluginOptions, BlogPost, BlogTags, BlogPaginated } from '@docusaurus/plugin-content-blog';
|
|
9
10
|
import type { BlogContentPaths, BlogMarkdownLoaderOptions } from './types';
|
package/lib/client/index.d.ts
CHANGED
|
@@ -4,5 +4,6 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
+
/// <reference path="../../src/plugin-content-blog.d.ts" />
|
|
7
8
|
import type { BlogMetadata } from '@docusaurus/plugin-content-blog';
|
|
8
9
|
export declare function useBlogMetadata(): BlogMetadata;
|
package/lib/feed.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
+
/// <reference path="../src/plugin-content-blog.d.ts" />
|
|
7
8
|
import type { DocusaurusConfig } from '@docusaurus/types';
|
|
8
9
|
import type { PluginOptions, BlogPost } from '@docusaurus/plugin-content-blog';
|
|
9
10
|
export declare function createBlogFeedFiles({ blogPosts: allBlogPosts, options, siteConfig, outDir, locale, }: {
|
package/lib/frontMatter.d.ts
CHANGED
package/lib/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
+
/// <reference path="../src/plugin-content-blog.d.ts" />
|
|
7
8
|
import type { LoadContext, Plugin } from '@docusaurus/types';
|
|
8
9
|
import type { PluginOptions, BlogContent } from '@docusaurus/plugin-content-blog';
|
|
9
10
|
export default function pluginContentBlog(context: LoadContext, options: PluginOptions): Promise<Plugin<BlogContent>>;
|
package/lib/index.js
CHANGED
|
@@ -15,7 +15,7 @@ const blogUtils_1 = require("./blogUtils");
|
|
|
15
15
|
const footnoteIDFixer_1 = tslib_1.__importDefault(require("./remark/footnoteIDFixer"));
|
|
16
16
|
const translations_1 = require("./translations");
|
|
17
17
|
const feed_1 = require("./feed");
|
|
18
|
-
const
|
|
18
|
+
const routes_1 = require("./routes");
|
|
19
19
|
async function pluginContentBlog(context, options) {
|
|
20
20
|
const { siteDir, siteConfig, generatedFilesDir, localizationDir, i18n: { currentLocale }, } = context;
|
|
21
21
|
const { onBrokenMarkdownLinks, baseUrl } = siteConfig;
|
|
@@ -30,6 +30,9 @@ async function pluginContentBlog(context, options) {
|
|
|
30
30
|
const pluginId = options.id ?? utils_1.DEFAULT_PLUGIN_ID;
|
|
31
31
|
const pluginDataDirRoot = path_1.default.join(generatedFilesDir, 'docusaurus-plugin-content-blog');
|
|
32
32
|
const dataDir = path_1.default.join(pluginDataDirRoot, pluginId);
|
|
33
|
+
// TODO Docusaurus v4 breaking change
|
|
34
|
+
// module aliasing should be automatic
|
|
35
|
+
// we should never find local absolute FS paths in the codegen registry
|
|
33
36
|
const aliasedSource = (source) => `~blog/${(0, utils_1.posixPath)(path_1.default.relative(pluginDataDirRoot, source))}`;
|
|
34
37
|
const authorsMapFilePath = await (0, utils_1.getDataFilePath)({
|
|
35
38
|
filePath: options.authorsMapPath,
|
|
@@ -107,143 +110,14 @@ async function pluginContentBlog(context, options) {
|
|
|
107
110
|
blogTagsListPath,
|
|
108
111
|
};
|
|
109
112
|
},
|
|
110
|
-
async contentLoaded({ content
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
: blogPosts.slice(0, options.blogSidebarCount);
|
|
119
|
-
function blogPostItemsModule(items) {
|
|
120
|
-
return items.map((postId) => {
|
|
121
|
-
const blogPostMetadata = blogItemsToMetadata[postId];
|
|
122
|
-
return {
|
|
123
|
-
content: {
|
|
124
|
-
__import: true,
|
|
125
|
-
path: blogPostMetadata.source,
|
|
126
|
-
query: {
|
|
127
|
-
truncated: true,
|
|
128
|
-
},
|
|
129
|
-
},
|
|
130
|
-
};
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
if (archiveBasePath && listedBlogPosts.length) {
|
|
134
|
-
const archiveUrl = (0, utils_1.normalizeUrl)([
|
|
135
|
-
baseUrl,
|
|
136
|
-
routeBasePath,
|
|
137
|
-
archiveBasePath,
|
|
138
|
-
]);
|
|
139
|
-
// Create a blog archive route
|
|
140
|
-
const archiveProp = await createData(`${(0, utils_1.docuHash)(archiveUrl)}.json`, JSON.stringify({ blogPosts: listedBlogPosts }, null, 2));
|
|
141
|
-
addRoute({
|
|
142
|
-
path: archiveUrl,
|
|
143
|
-
component: blogArchiveComponent,
|
|
144
|
-
exact: true,
|
|
145
|
-
modules: {
|
|
146
|
-
archive: aliasedSource(archiveProp),
|
|
147
|
-
},
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
// This prop is useful to provide the blog list sidebar
|
|
151
|
-
const sidebarProp = await createData(
|
|
152
|
-
// Note that this created data path must be in sync with
|
|
153
|
-
// metadataPath provided to mdx-loader.
|
|
154
|
-
`blog-post-list-prop-${pluginId}.json`, JSON.stringify({
|
|
155
|
-
title: blogSidebarTitle,
|
|
156
|
-
items: sidebarBlogPosts.map((blogPost) => ({
|
|
157
|
-
title: blogPost.metadata.title,
|
|
158
|
-
permalink: blogPost.metadata.permalink,
|
|
159
|
-
unlisted: blogPost.metadata.unlisted,
|
|
160
|
-
})),
|
|
161
|
-
}, null, 2));
|
|
162
|
-
const blogMetadata = {
|
|
163
|
-
blogBasePath: (0, utils_1.normalizeUrl)([baseUrl, routeBasePath]),
|
|
164
|
-
blogTitle,
|
|
165
|
-
};
|
|
166
|
-
const blogMetadataPath = await createData(`blogMetadata-${pluginId}.json`, JSON.stringify(blogMetadata, null, 2));
|
|
167
|
-
function createBlogPostRouteMetadata(blogPostMeta) {
|
|
168
|
-
return {
|
|
169
|
-
sourceFilePath: (0, utils_1.aliasedSitePathToRelativePath)(blogPostMeta.source),
|
|
170
|
-
lastUpdatedAt: blogPostMeta.lastUpdatedAt,
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
|
-
// Create routes for blog entries.
|
|
174
|
-
await Promise.all(blogPosts.map(async (blogPost) => {
|
|
175
|
-
const { id, metadata } = blogPost;
|
|
176
|
-
await createData(
|
|
177
|
-
// Note that this created data path must be in sync with
|
|
178
|
-
// metadataPath provided to mdx-loader.
|
|
179
|
-
`${(0, utils_1.docuHash)(metadata.source)}.json`, JSON.stringify(metadata, null, 2));
|
|
180
|
-
addRoute({
|
|
181
|
-
path: metadata.permalink,
|
|
182
|
-
component: blogPostComponent,
|
|
183
|
-
exact: true,
|
|
184
|
-
modules: {
|
|
185
|
-
sidebar: aliasedSource(sidebarProp),
|
|
186
|
-
content: metadata.source,
|
|
187
|
-
},
|
|
188
|
-
metadata: createBlogPostRouteMetadata(metadata),
|
|
189
|
-
context: {
|
|
190
|
-
blogMetadata: aliasedSource(blogMetadataPath),
|
|
191
|
-
},
|
|
192
|
-
});
|
|
193
|
-
blogItemsToMetadata[id] = metadata;
|
|
194
|
-
}));
|
|
195
|
-
// Create routes for blog's paginated list entries.
|
|
196
|
-
await Promise.all(blogListPaginated.map(async (listPage) => {
|
|
197
|
-
const { metadata, items } = listPage;
|
|
198
|
-
const { permalink } = metadata;
|
|
199
|
-
const pageMetadataPath = await createData(`${(0, utils_1.docuHash)(permalink)}.json`, JSON.stringify(metadata, null, 2));
|
|
200
|
-
addRoute({
|
|
201
|
-
path: permalink,
|
|
202
|
-
component: blogListComponent,
|
|
203
|
-
exact: true,
|
|
204
|
-
modules: {
|
|
205
|
-
sidebar: aliasedSource(sidebarProp),
|
|
206
|
-
items: blogPostItemsModule(items),
|
|
207
|
-
metadata: aliasedSource(pageMetadataPath),
|
|
208
|
-
},
|
|
209
|
-
});
|
|
210
|
-
}));
|
|
211
|
-
// Tags. This is the last part so we early-return if there are no tags.
|
|
212
|
-
if (Object.keys(blogTags).length === 0) {
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
async function createTagsListPage() {
|
|
216
|
-
const tagsPropPath = await createData(`${(0, utils_1.docuHash)(`${blogTagsListPath}-tags`)}.json`, JSON.stringify((0, props_1.toTagsProp)({ blogTags }), null, 2));
|
|
217
|
-
addRoute({
|
|
218
|
-
path: blogTagsListPath,
|
|
219
|
-
component: blogTagsListComponent,
|
|
220
|
-
exact: true,
|
|
221
|
-
modules: {
|
|
222
|
-
sidebar: aliasedSource(sidebarProp),
|
|
223
|
-
tags: aliasedSource(tagsPropPath),
|
|
224
|
-
},
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
async function createTagPostsListPage(tag) {
|
|
228
|
-
await Promise.all(tag.pages.map(async (blogPaginated) => {
|
|
229
|
-
const { metadata, items } = blogPaginated;
|
|
230
|
-
const tagPropPath = await createData(`${(0, utils_1.docuHash)(metadata.permalink)}.json`, JSON.stringify((0, props_1.toTagProp)({ tag, blogTagsListPath }), null, 2));
|
|
231
|
-
const listMetadataPath = await createData(`${(0, utils_1.docuHash)(metadata.permalink)}-list.json`, JSON.stringify(metadata, null, 2));
|
|
232
|
-
addRoute({
|
|
233
|
-
path: metadata.permalink,
|
|
234
|
-
component: blogTagsPostsComponent,
|
|
235
|
-
exact: true,
|
|
236
|
-
modules: {
|
|
237
|
-
sidebar: aliasedSource(sidebarProp),
|
|
238
|
-
items: blogPostItemsModule(items),
|
|
239
|
-
tag: aliasedSource(tagPropPath),
|
|
240
|
-
listMetadata: aliasedSource(listMetadataPath),
|
|
241
|
-
},
|
|
242
|
-
});
|
|
243
|
-
}));
|
|
244
|
-
}
|
|
245
|
-
await createTagsListPage();
|
|
246
|
-
await Promise.all(Object.values(blogTags).map(createTagPostsListPage));
|
|
113
|
+
async contentLoaded({ content, actions }) {
|
|
114
|
+
await (0, routes_1.createAllRoutes)({
|
|
115
|
+
baseUrl,
|
|
116
|
+
content,
|
|
117
|
+
actions,
|
|
118
|
+
options,
|
|
119
|
+
aliasedSource,
|
|
120
|
+
});
|
|
247
121
|
},
|
|
248
122
|
translateContent({ content, translationFiles }) {
|
|
249
123
|
return (0, translations_1.translateContent)(content, translationFiles);
|
package/lib/options.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
+
/// <reference path="../src/plugin-content-blog.d.ts" />
|
|
7
8
|
import type { PluginOptions, Options } from '@docusaurus/plugin-content-blog';
|
|
8
9
|
import type { OptionValidationContext } from '@docusaurus/types';
|
|
9
10
|
export declare const DEFAULT_OPTIONS: PluginOptions;
|
package/lib/props.d.ts
CHANGED
package/lib/routes.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
/// <reference path="../src/plugin-content-blog.d.ts" />
|
|
8
|
+
import type { PluginContentLoadedActions, RouteConfig } from '@docusaurus/types';
|
|
9
|
+
import type { BlogContent, PluginOptions } from '@docusaurus/plugin-content-blog';
|
|
10
|
+
type CreateAllRoutesParam = {
|
|
11
|
+
baseUrl: string;
|
|
12
|
+
content: BlogContent;
|
|
13
|
+
options: PluginOptions;
|
|
14
|
+
actions: PluginContentLoadedActions;
|
|
15
|
+
aliasedSource: (str: string) => string;
|
|
16
|
+
};
|
|
17
|
+
export declare function createAllRoutes(param: CreateAllRoutesParam): Promise<void>;
|
|
18
|
+
export declare function buildAllRoutes({ baseUrl, content, actions, options, aliasedSource, }: CreateAllRoutesParam): Promise<RouteConfig[]>;
|
|
19
|
+
export {};
|
package/lib/routes.js
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.buildAllRoutes = exports.createAllRoutes = void 0;
|
|
10
|
+
const tslib_1 = require("tslib");
|
|
11
|
+
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
12
|
+
const utils_1 = require("@docusaurus/utils");
|
|
13
|
+
const blogUtils_1 = require("./blogUtils");
|
|
14
|
+
const props_1 = require("./props");
|
|
15
|
+
async function createAllRoutes(param) {
|
|
16
|
+
const routes = await buildAllRoutes(param);
|
|
17
|
+
routes.forEach(param.actions.addRoute);
|
|
18
|
+
}
|
|
19
|
+
exports.createAllRoutes = createAllRoutes;
|
|
20
|
+
async function buildAllRoutes({ baseUrl, content, actions, options, aliasedSource, }) {
|
|
21
|
+
const { blogListComponent, blogPostComponent, blogTagsListComponent, blogTagsPostsComponent, blogArchiveComponent, routeBasePath, archiveBasePath, blogTitle, } = options;
|
|
22
|
+
const pluginId = options.id;
|
|
23
|
+
const { createData } = actions;
|
|
24
|
+
const { blogSidebarTitle, blogPosts, blogListPaginated, blogTags, blogTagsListPath, } = content;
|
|
25
|
+
const listedBlogPosts = blogPosts.filter(blogUtils_1.shouldBeListed);
|
|
26
|
+
const blogPostsById = lodash_1.default.keyBy(blogPosts, (post) => post.id);
|
|
27
|
+
function getBlogPostById(id) {
|
|
28
|
+
const blogPost = blogPostsById[id];
|
|
29
|
+
if (!blogPost) {
|
|
30
|
+
throw new Error(`unexpected, can't find blog post id=${id}`);
|
|
31
|
+
}
|
|
32
|
+
return blogPost;
|
|
33
|
+
}
|
|
34
|
+
const sidebarBlogPosts = options.blogSidebarCount === 'ALL'
|
|
35
|
+
? blogPosts
|
|
36
|
+
: blogPosts.slice(0, options.blogSidebarCount);
|
|
37
|
+
async function createSidebarModule() {
|
|
38
|
+
const sidebar = {
|
|
39
|
+
title: blogSidebarTitle,
|
|
40
|
+
items: sidebarBlogPosts.map((blogPost) => ({
|
|
41
|
+
title: blogPost.metadata.title,
|
|
42
|
+
permalink: blogPost.metadata.permalink,
|
|
43
|
+
unlisted: blogPost.metadata.unlisted,
|
|
44
|
+
})),
|
|
45
|
+
};
|
|
46
|
+
const modulePath = await createData(`blog-post-list-prop-${pluginId}.json`, sidebar);
|
|
47
|
+
return aliasedSource(modulePath);
|
|
48
|
+
}
|
|
49
|
+
async function createBlogMetadataModule() {
|
|
50
|
+
const blogMetadata = {
|
|
51
|
+
blogBasePath: (0, utils_1.normalizeUrl)([baseUrl, routeBasePath]),
|
|
52
|
+
blogTitle,
|
|
53
|
+
};
|
|
54
|
+
const modulePath = await createData(`blogMetadata-${pluginId}.json`, blogMetadata);
|
|
55
|
+
return aliasedSource(modulePath);
|
|
56
|
+
}
|
|
57
|
+
// TODO we should have a parent blog route,
|
|
58
|
+
// and inject blog metadata + sidebar as a parent context
|
|
59
|
+
// unfortunately we can't have a parent route for blog yet
|
|
60
|
+
// because if both blog/docs are using routeBasePath /,
|
|
61
|
+
// React router config rendering doesn't support that well
|
|
62
|
+
const sidebarModulePath = await createSidebarModule();
|
|
63
|
+
const blogMetadataModulePath = await createBlogMetadataModule();
|
|
64
|
+
function blogPostItemsModule(ids) {
|
|
65
|
+
return ids.map((id) => {
|
|
66
|
+
return {
|
|
67
|
+
content: {
|
|
68
|
+
__import: true,
|
|
69
|
+
path: getBlogPostById(id).metadata.source,
|
|
70
|
+
query: {
|
|
71
|
+
truncated: true,
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
function createArchiveRoute() {
|
|
78
|
+
if (archiveBasePath && listedBlogPosts.length) {
|
|
79
|
+
return [
|
|
80
|
+
{
|
|
81
|
+
path: (0, utils_1.normalizeUrl)([baseUrl, routeBasePath, archiveBasePath]),
|
|
82
|
+
component: blogArchiveComponent,
|
|
83
|
+
exact: true,
|
|
84
|
+
props: {
|
|
85
|
+
archive: { blogPosts: listedBlogPosts },
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
];
|
|
89
|
+
}
|
|
90
|
+
return [];
|
|
91
|
+
}
|
|
92
|
+
function createBlogPostRouteMetadata(blogPostMeta) {
|
|
93
|
+
return {
|
|
94
|
+
sourceFilePath: (0, utils_1.aliasedSitePathToRelativePath)(blogPostMeta.source),
|
|
95
|
+
lastUpdatedAt: blogPostMeta.lastUpdatedAt,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
await Promise.all(blogPosts.map(async (blogPost) => {
|
|
99
|
+
const { metadata } = blogPost;
|
|
100
|
+
await createData(
|
|
101
|
+
// Note that this created data path must be in sync with
|
|
102
|
+
// metadataPath provided to mdx-loader.
|
|
103
|
+
`${(0, utils_1.docuHash)(metadata.source)}.json`, metadata);
|
|
104
|
+
}));
|
|
105
|
+
function createBlogPostRoute(blogPost) {
|
|
106
|
+
return {
|
|
107
|
+
path: blogPost.metadata.permalink,
|
|
108
|
+
component: blogPostComponent,
|
|
109
|
+
exact: true,
|
|
110
|
+
modules: {
|
|
111
|
+
sidebar: sidebarModulePath,
|
|
112
|
+
content: blogPost.metadata.source,
|
|
113
|
+
},
|
|
114
|
+
metadata: createBlogPostRouteMetadata(blogPost.metadata),
|
|
115
|
+
context: {
|
|
116
|
+
blogMetadata: blogMetadataModulePath,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function createBlogPostRoutes() {
|
|
121
|
+
return blogPosts.map(createBlogPostRoute);
|
|
122
|
+
}
|
|
123
|
+
function createBlogPostsPaginatedRoutes() {
|
|
124
|
+
return blogListPaginated.map((paginated) => {
|
|
125
|
+
return {
|
|
126
|
+
path: paginated.metadata.permalink,
|
|
127
|
+
component: blogListComponent,
|
|
128
|
+
exact: true,
|
|
129
|
+
modules: {
|
|
130
|
+
sidebar: sidebarModulePath,
|
|
131
|
+
items: blogPostItemsModule(paginated.items),
|
|
132
|
+
},
|
|
133
|
+
props: {
|
|
134
|
+
metadata: paginated.metadata,
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
function createTagsRoutes() {
|
|
140
|
+
// Tags. This is the last part so we early-return if there are no tags.
|
|
141
|
+
if (Object.keys(blogTags).length === 0) {
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
const tagsListRoute = {
|
|
145
|
+
path: blogTagsListPath,
|
|
146
|
+
component: blogTagsListComponent,
|
|
147
|
+
exact: true,
|
|
148
|
+
modules: {
|
|
149
|
+
sidebar: sidebarModulePath,
|
|
150
|
+
},
|
|
151
|
+
props: {
|
|
152
|
+
tags: (0, props_1.toTagsProp)({ blogTags }),
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
function createTagPaginatedRoutes(tag) {
|
|
156
|
+
return tag.pages.map((paginated) => {
|
|
157
|
+
return {
|
|
158
|
+
path: paginated.metadata.permalink,
|
|
159
|
+
component: blogTagsPostsComponent,
|
|
160
|
+
exact: true,
|
|
161
|
+
modules: {
|
|
162
|
+
sidebar: sidebarModulePath,
|
|
163
|
+
items: blogPostItemsModule(paginated.items),
|
|
164
|
+
},
|
|
165
|
+
props: {
|
|
166
|
+
tag: (0, props_1.toTagProp)({ tag, blogTagsListPath }),
|
|
167
|
+
listMetadata: paginated.metadata,
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
const tagsPaginatedRoutes = Object.values(blogTags).flatMap(createTagPaginatedRoutes);
|
|
173
|
+
return [tagsListRoute, ...tagsPaginatedRoutes];
|
|
174
|
+
}
|
|
175
|
+
return [
|
|
176
|
+
...createBlogPostRoutes(),
|
|
177
|
+
...createBlogPostsPaginatedRoutes(),
|
|
178
|
+
...createTagsRoutes(),
|
|
179
|
+
...createArchiveRoute(),
|
|
180
|
+
];
|
|
181
|
+
}
|
|
182
|
+
exports.buildAllRoutes = buildAllRoutes;
|
package/lib/translations.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
+
/// <reference path="../src/plugin-content-blog.d.ts" />
|
|
7
8
|
import type { TranslationFile } from '@docusaurus/types';
|
|
8
9
|
import type { PluginOptions, BlogContent } from '@docusaurus/plugin-content-blog';
|
|
9
10
|
export declare function getTranslationFiles(options: PluginOptions): TranslationFile[];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/plugin-content-blog",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.3.0",
|
|
4
4
|
"description": "Blog plugin for Docusaurus.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "src/plugin-content-blog.d.ts",
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
},
|
|
32
32
|
"license": "MIT",
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@docusaurus/core": "3.
|
|
35
|
-
"@docusaurus/logger": "3.
|
|
36
|
-
"@docusaurus/mdx-loader": "3.
|
|
37
|
-
"@docusaurus/types": "3.
|
|
38
|
-
"@docusaurus/utils": "3.
|
|
39
|
-
"@docusaurus/utils-common": "3.
|
|
40
|
-
"@docusaurus/utils-validation": "3.
|
|
34
|
+
"@docusaurus/core": "3.3.0",
|
|
35
|
+
"@docusaurus/logger": "3.3.0",
|
|
36
|
+
"@docusaurus/mdx-loader": "3.3.0",
|
|
37
|
+
"@docusaurus/types": "3.3.0",
|
|
38
|
+
"@docusaurus/utils": "3.3.0",
|
|
39
|
+
"@docusaurus/utils-common": "3.3.0",
|
|
40
|
+
"@docusaurus/utils-validation": "3.3.0",
|
|
41
41
|
"cheerio": "^1.0.0-rc.12",
|
|
42
42
|
"feed": "^4.2.2",
|
|
43
43
|
"fs-extra": "^11.1.1",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@total-typescript/shoehorn": "^0.1.2"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "2ec4e078b5ca0c57f2cc04f2fe564d524bb5e858"
|
|
63
63
|
}
|
package/src/index.ts
CHANGED
|
@@ -11,7 +11,6 @@ import {
|
|
|
11
11
|
normalizeUrl,
|
|
12
12
|
docuHash,
|
|
13
13
|
aliasedSitePath,
|
|
14
|
-
aliasedSitePathToRelativePath,
|
|
15
14
|
getPluginI18nPath,
|
|
16
15
|
posixPath,
|
|
17
16
|
addTrailingPathSeparator,
|
|
@@ -32,24 +31,17 @@ import footnoteIDFixer from './remark/footnoteIDFixer';
|
|
|
32
31
|
import {translateContent, getTranslationFiles} from './translations';
|
|
33
32
|
import {createBlogFeedFiles} from './feed';
|
|
34
33
|
|
|
35
|
-
import {
|
|
34
|
+
import {createAllRoutes} from './routes';
|
|
36
35
|
import type {BlogContentPaths, BlogMarkdownLoaderOptions} from './types';
|
|
37
|
-
import type {
|
|
38
|
-
LoadContext,
|
|
39
|
-
Plugin,
|
|
40
|
-
HtmlTags,
|
|
41
|
-
RouteMetadata,
|
|
42
|
-
} from '@docusaurus/types';
|
|
36
|
+
import type {LoadContext, Plugin, HtmlTags} from '@docusaurus/types';
|
|
43
37
|
import type {
|
|
44
38
|
PluginOptions,
|
|
45
39
|
BlogPostFrontMatter,
|
|
46
40
|
BlogPostMetadata,
|
|
47
41
|
Assets,
|
|
48
|
-
BlogTag,
|
|
49
42
|
BlogTags,
|
|
50
43
|
BlogContent,
|
|
51
44
|
BlogPaginated,
|
|
52
|
-
BlogMetadata,
|
|
53
45
|
} from '@docusaurus/plugin-content-blog';
|
|
54
46
|
|
|
55
47
|
export default async function pluginContentBlog(
|
|
@@ -80,6 +72,9 @@ export default async function pluginContentBlog(
|
|
|
80
72
|
'docusaurus-plugin-content-blog',
|
|
81
73
|
);
|
|
82
74
|
const dataDir = path.join(pluginDataDirRoot, pluginId);
|
|
75
|
+
// TODO Docusaurus v4 breaking change
|
|
76
|
+
// module aliasing should be automatic
|
|
77
|
+
// we should never find local absolute FS paths in the codegen registry
|
|
83
78
|
const aliasedSource = (source: string) =>
|
|
84
79
|
`~blog/${posixPath(path.relative(pluginDataDirRoot, source))}`;
|
|
85
80
|
|
|
@@ -185,213 +180,14 @@ export default async function pluginContentBlog(
|
|
|
185
180
|
};
|
|
186
181
|
},
|
|
187
182
|
|
|
188
|
-
async contentLoaded({content
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
archiveBasePath,
|
|
197
|
-
blogTitle,
|
|
198
|
-
} = options;
|
|
199
|
-
|
|
200
|
-
const {addRoute, createData} = actions;
|
|
201
|
-
const {
|
|
202
|
-
blogSidebarTitle,
|
|
203
|
-
blogPosts,
|
|
204
|
-
blogListPaginated,
|
|
205
|
-
blogTags,
|
|
206
|
-
blogTagsListPath,
|
|
207
|
-
} = blogContents;
|
|
208
|
-
|
|
209
|
-
const listedBlogPosts = blogPosts.filter(shouldBeListed);
|
|
210
|
-
|
|
211
|
-
const blogItemsToMetadata: {[postId: string]: BlogPostMetadata} = {};
|
|
212
|
-
|
|
213
|
-
const sidebarBlogPosts =
|
|
214
|
-
options.blogSidebarCount === 'ALL'
|
|
215
|
-
? blogPosts
|
|
216
|
-
: blogPosts.slice(0, options.blogSidebarCount);
|
|
217
|
-
|
|
218
|
-
function blogPostItemsModule(items: string[]) {
|
|
219
|
-
return items.map((postId) => {
|
|
220
|
-
const blogPostMetadata = blogItemsToMetadata[postId]!;
|
|
221
|
-
return {
|
|
222
|
-
content: {
|
|
223
|
-
__import: true,
|
|
224
|
-
path: blogPostMetadata.source,
|
|
225
|
-
query: {
|
|
226
|
-
truncated: true,
|
|
227
|
-
},
|
|
228
|
-
},
|
|
229
|
-
};
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
if (archiveBasePath && listedBlogPosts.length) {
|
|
234
|
-
const archiveUrl = normalizeUrl([
|
|
235
|
-
baseUrl,
|
|
236
|
-
routeBasePath,
|
|
237
|
-
archiveBasePath,
|
|
238
|
-
]);
|
|
239
|
-
// Create a blog archive route
|
|
240
|
-
const archiveProp = await createData(
|
|
241
|
-
`${docuHash(archiveUrl)}.json`,
|
|
242
|
-
JSON.stringify({blogPosts: listedBlogPosts}, null, 2),
|
|
243
|
-
);
|
|
244
|
-
addRoute({
|
|
245
|
-
path: archiveUrl,
|
|
246
|
-
component: blogArchiveComponent,
|
|
247
|
-
exact: true,
|
|
248
|
-
modules: {
|
|
249
|
-
archive: aliasedSource(archiveProp),
|
|
250
|
-
},
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// This prop is useful to provide the blog list sidebar
|
|
255
|
-
const sidebarProp = await createData(
|
|
256
|
-
// Note that this created data path must be in sync with
|
|
257
|
-
// metadataPath provided to mdx-loader.
|
|
258
|
-
`blog-post-list-prop-${pluginId}.json`,
|
|
259
|
-
JSON.stringify(
|
|
260
|
-
{
|
|
261
|
-
title: blogSidebarTitle,
|
|
262
|
-
items: sidebarBlogPosts.map((blogPost) => ({
|
|
263
|
-
title: blogPost.metadata.title,
|
|
264
|
-
permalink: blogPost.metadata.permalink,
|
|
265
|
-
unlisted: blogPost.metadata.unlisted,
|
|
266
|
-
})),
|
|
267
|
-
},
|
|
268
|
-
null,
|
|
269
|
-
2,
|
|
270
|
-
),
|
|
271
|
-
);
|
|
272
|
-
|
|
273
|
-
const blogMetadata: BlogMetadata = {
|
|
274
|
-
blogBasePath: normalizeUrl([baseUrl, routeBasePath]),
|
|
275
|
-
blogTitle,
|
|
276
|
-
};
|
|
277
|
-
const blogMetadataPath = await createData(
|
|
278
|
-
`blogMetadata-${pluginId}.json`,
|
|
279
|
-
JSON.stringify(blogMetadata, null, 2),
|
|
280
|
-
);
|
|
281
|
-
|
|
282
|
-
function createBlogPostRouteMetadata(
|
|
283
|
-
blogPostMeta: BlogPostMetadata,
|
|
284
|
-
): RouteMetadata {
|
|
285
|
-
return {
|
|
286
|
-
sourceFilePath: aliasedSitePathToRelativePath(blogPostMeta.source),
|
|
287
|
-
lastUpdatedAt: blogPostMeta.lastUpdatedAt,
|
|
288
|
-
};
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// Create routes for blog entries.
|
|
292
|
-
await Promise.all(
|
|
293
|
-
blogPosts.map(async (blogPost) => {
|
|
294
|
-
const {id, metadata} = blogPost;
|
|
295
|
-
await createData(
|
|
296
|
-
// Note that this created data path must be in sync with
|
|
297
|
-
// metadataPath provided to mdx-loader.
|
|
298
|
-
`${docuHash(metadata.source)}.json`,
|
|
299
|
-
JSON.stringify(metadata, null, 2),
|
|
300
|
-
);
|
|
301
|
-
|
|
302
|
-
addRoute({
|
|
303
|
-
path: metadata.permalink,
|
|
304
|
-
component: blogPostComponent,
|
|
305
|
-
exact: true,
|
|
306
|
-
modules: {
|
|
307
|
-
sidebar: aliasedSource(sidebarProp),
|
|
308
|
-
content: metadata.source,
|
|
309
|
-
},
|
|
310
|
-
metadata: createBlogPostRouteMetadata(metadata),
|
|
311
|
-
context: {
|
|
312
|
-
blogMetadata: aliasedSource(blogMetadataPath),
|
|
313
|
-
},
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
blogItemsToMetadata[id] = metadata;
|
|
317
|
-
}),
|
|
318
|
-
);
|
|
319
|
-
|
|
320
|
-
// Create routes for blog's paginated list entries.
|
|
321
|
-
await Promise.all(
|
|
322
|
-
blogListPaginated.map(async (listPage) => {
|
|
323
|
-
const {metadata, items} = listPage;
|
|
324
|
-
const {permalink} = metadata;
|
|
325
|
-
const pageMetadataPath = await createData(
|
|
326
|
-
`${docuHash(permalink)}.json`,
|
|
327
|
-
JSON.stringify(metadata, null, 2),
|
|
328
|
-
);
|
|
329
|
-
|
|
330
|
-
addRoute({
|
|
331
|
-
path: permalink,
|
|
332
|
-
component: blogListComponent,
|
|
333
|
-
exact: true,
|
|
334
|
-
modules: {
|
|
335
|
-
sidebar: aliasedSource(sidebarProp),
|
|
336
|
-
items: blogPostItemsModule(items),
|
|
337
|
-
metadata: aliasedSource(pageMetadataPath),
|
|
338
|
-
},
|
|
339
|
-
});
|
|
340
|
-
}),
|
|
341
|
-
);
|
|
342
|
-
|
|
343
|
-
// Tags. This is the last part so we early-return if there are no tags.
|
|
344
|
-
if (Object.keys(blogTags).length === 0) {
|
|
345
|
-
return;
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
async function createTagsListPage() {
|
|
349
|
-
const tagsPropPath = await createData(
|
|
350
|
-
`${docuHash(`${blogTagsListPath}-tags`)}.json`,
|
|
351
|
-
JSON.stringify(toTagsProp({blogTags}), null, 2),
|
|
352
|
-
);
|
|
353
|
-
addRoute({
|
|
354
|
-
path: blogTagsListPath,
|
|
355
|
-
component: blogTagsListComponent,
|
|
356
|
-
exact: true,
|
|
357
|
-
modules: {
|
|
358
|
-
sidebar: aliasedSource(sidebarProp),
|
|
359
|
-
tags: aliasedSource(tagsPropPath),
|
|
360
|
-
},
|
|
361
|
-
});
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
async function createTagPostsListPage(tag: BlogTag): Promise<void> {
|
|
365
|
-
await Promise.all(
|
|
366
|
-
tag.pages.map(async (blogPaginated) => {
|
|
367
|
-
const {metadata, items} = blogPaginated;
|
|
368
|
-
const tagPropPath = await createData(
|
|
369
|
-
`${docuHash(metadata.permalink)}.json`,
|
|
370
|
-
JSON.stringify(toTagProp({tag, blogTagsListPath}), null, 2),
|
|
371
|
-
);
|
|
372
|
-
|
|
373
|
-
const listMetadataPath = await createData(
|
|
374
|
-
`${docuHash(metadata.permalink)}-list.json`,
|
|
375
|
-
JSON.stringify(metadata, null, 2),
|
|
376
|
-
);
|
|
377
|
-
|
|
378
|
-
addRoute({
|
|
379
|
-
path: metadata.permalink,
|
|
380
|
-
component: blogTagsPostsComponent,
|
|
381
|
-
exact: true,
|
|
382
|
-
modules: {
|
|
383
|
-
sidebar: aliasedSource(sidebarProp),
|
|
384
|
-
items: blogPostItemsModule(items),
|
|
385
|
-
tag: aliasedSource(tagPropPath),
|
|
386
|
-
listMetadata: aliasedSource(listMetadataPath),
|
|
387
|
-
},
|
|
388
|
-
});
|
|
389
|
-
}),
|
|
390
|
-
);
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
await createTagsListPage();
|
|
394
|
-
await Promise.all(Object.values(blogTags).map(createTagPostsListPage));
|
|
183
|
+
async contentLoaded({content, actions}) {
|
|
184
|
+
await createAllRoutes({
|
|
185
|
+
baseUrl,
|
|
186
|
+
content,
|
|
187
|
+
actions,
|
|
188
|
+
options,
|
|
189
|
+
aliasedSource,
|
|
190
|
+
});
|
|
395
191
|
},
|
|
396
192
|
|
|
397
193
|
translateContent({content, translationFiles}) {
|
package/src/routes.ts
ADDED
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import _ from 'lodash';
|
|
9
|
+
import {
|
|
10
|
+
normalizeUrl,
|
|
11
|
+
docuHash,
|
|
12
|
+
aliasedSitePathToRelativePath,
|
|
13
|
+
} from '@docusaurus/utils';
|
|
14
|
+
import {shouldBeListed} from './blogUtils';
|
|
15
|
+
|
|
16
|
+
import {toTagProp, toTagsProp} from './props';
|
|
17
|
+
import type {
|
|
18
|
+
PluginContentLoadedActions,
|
|
19
|
+
RouteConfig,
|
|
20
|
+
RouteMetadata,
|
|
21
|
+
} from '@docusaurus/types';
|
|
22
|
+
import type {
|
|
23
|
+
BlogPostMetadata,
|
|
24
|
+
BlogTag,
|
|
25
|
+
BlogMetadata,
|
|
26
|
+
BlogContent,
|
|
27
|
+
PluginOptions,
|
|
28
|
+
BlogPost,
|
|
29
|
+
BlogSidebar,
|
|
30
|
+
} from '@docusaurus/plugin-content-blog';
|
|
31
|
+
|
|
32
|
+
type CreateAllRoutesParam = {
|
|
33
|
+
baseUrl: string;
|
|
34
|
+
content: BlogContent;
|
|
35
|
+
options: PluginOptions;
|
|
36
|
+
actions: PluginContentLoadedActions;
|
|
37
|
+
aliasedSource: (str: string) => string;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export async function createAllRoutes(
|
|
41
|
+
param: CreateAllRoutesParam,
|
|
42
|
+
): Promise<void> {
|
|
43
|
+
const routes = await buildAllRoutes(param);
|
|
44
|
+
routes.forEach(param.actions.addRoute);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export async function buildAllRoutes({
|
|
48
|
+
baseUrl,
|
|
49
|
+
content,
|
|
50
|
+
actions,
|
|
51
|
+
options,
|
|
52
|
+
aliasedSource,
|
|
53
|
+
}: CreateAllRoutesParam): Promise<RouteConfig[]> {
|
|
54
|
+
const {
|
|
55
|
+
blogListComponent,
|
|
56
|
+
blogPostComponent,
|
|
57
|
+
blogTagsListComponent,
|
|
58
|
+
blogTagsPostsComponent,
|
|
59
|
+
blogArchiveComponent,
|
|
60
|
+
routeBasePath,
|
|
61
|
+
archiveBasePath,
|
|
62
|
+
blogTitle,
|
|
63
|
+
} = options;
|
|
64
|
+
const pluginId = options.id!;
|
|
65
|
+
const {createData} = actions;
|
|
66
|
+
const {
|
|
67
|
+
blogSidebarTitle,
|
|
68
|
+
blogPosts,
|
|
69
|
+
blogListPaginated,
|
|
70
|
+
blogTags,
|
|
71
|
+
blogTagsListPath,
|
|
72
|
+
} = content;
|
|
73
|
+
|
|
74
|
+
const listedBlogPosts = blogPosts.filter(shouldBeListed);
|
|
75
|
+
|
|
76
|
+
const blogPostsById = _.keyBy(blogPosts, (post) => post.id);
|
|
77
|
+
function getBlogPostById(id: string): BlogPost {
|
|
78
|
+
const blogPost = blogPostsById[id];
|
|
79
|
+
if (!blogPost) {
|
|
80
|
+
throw new Error(`unexpected, can't find blog post id=${id}`);
|
|
81
|
+
}
|
|
82
|
+
return blogPost;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const sidebarBlogPosts =
|
|
86
|
+
options.blogSidebarCount === 'ALL'
|
|
87
|
+
? blogPosts
|
|
88
|
+
: blogPosts.slice(0, options.blogSidebarCount);
|
|
89
|
+
|
|
90
|
+
async function createSidebarModule() {
|
|
91
|
+
const sidebar: BlogSidebar = {
|
|
92
|
+
title: blogSidebarTitle,
|
|
93
|
+
items: sidebarBlogPosts.map((blogPost) => ({
|
|
94
|
+
title: blogPost.metadata.title,
|
|
95
|
+
permalink: blogPost.metadata.permalink,
|
|
96
|
+
unlisted: blogPost.metadata.unlisted,
|
|
97
|
+
})),
|
|
98
|
+
};
|
|
99
|
+
const modulePath = await createData(
|
|
100
|
+
`blog-post-list-prop-${pluginId}.json`,
|
|
101
|
+
sidebar,
|
|
102
|
+
);
|
|
103
|
+
return aliasedSource(modulePath);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function createBlogMetadataModule() {
|
|
107
|
+
const blogMetadata: BlogMetadata = {
|
|
108
|
+
blogBasePath: normalizeUrl([baseUrl, routeBasePath]),
|
|
109
|
+
blogTitle,
|
|
110
|
+
};
|
|
111
|
+
const modulePath = await createData(
|
|
112
|
+
`blogMetadata-${pluginId}.json`,
|
|
113
|
+
blogMetadata,
|
|
114
|
+
);
|
|
115
|
+
return aliasedSource(modulePath);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// TODO we should have a parent blog route,
|
|
119
|
+
// and inject blog metadata + sidebar as a parent context
|
|
120
|
+
// unfortunately we can't have a parent route for blog yet
|
|
121
|
+
// because if both blog/docs are using routeBasePath /,
|
|
122
|
+
// React router config rendering doesn't support that well
|
|
123
|
+
const sidebarModulePath = await createSidebarModule();
|
|
124
|
+
const blogMetadataModulePath = await createBlogMetadataModule();
|
|
125
|
+
|
|
126
|
+
function blogPostItemsModule(ids: string[]) {
|
|
127
|
+
return ids.map((id) => {
|
|
128
|
+
return {
|
|
129
|
+
content: {
|
|
130
|
+
__import: true,
|
|
131
|
+
path: getBlogPostById(id).metadata.source,
|
|
132
|
+
query: {
|
|
133
|
+
truncated: true,
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function createArchiveRoute(): RouteConfig[] {
|
|
141
|
+
if (archiveBasePath && listedBlogPosts.length) {
|
|
142
|
+
return [
|
|
143
|
+
{
|
|
144
|
+
path: normalizeUrl([baseUrl, routeBasePath, archiveBasePath]),
|
|
145
|
+
component: blogArchiveComponent,
|
|
146
|
+
exact: true,
|
|
147
|
+
props: {
|
|
148
|
+
archive: {blogPosts: listedBlogPosts},
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
];
|
|
152
|
+
}
|
|
153
|
+
return [];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function createBlogPostRouteMetadata(
|
|
157
|
+
blogPostMeta: BlogPostMetadata,
|
|
158
|
+
): RouteMetadata {
|
|
159
|
+
return {
|
|
160
|
+
sourceFilePath: aliasedSitePathToRelativePath(blogPostMeta.source),
|
|
161
|
+
lastUpdatedAt: blogPostMeta.lastUpdatedAt,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
await Promise.all(
|
|
166
|
+
blogPosts.map(async (blogPost) => {
|
|
167
|
+
const {metadata} = blogPost;
|
|
168
|
+
await createData(
|
|
169
|
+
// Note that this created data path must be in sync with
|
|
170
|
+
// metadataPath provided to mdx-loader.
|
|
171
|
+
`${docuHash(metadata.source)}.json`,
|
|
172
|
+
metadata,
|
|
173
|
+
);
|
|
174
|
+
}),
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
function createBlogPostRoute(blogPost: BlogPost): RouteConfig {
|
|
178
|
+
return {
|
|
179
|
+
path: blogPost.metadata.permalink,
|
|
180
|
+
component: blogPostComponent,
|
|
181
|
+
exact: true,
|
|
182
|
+
modules: {
|
|
183
|
+
sidebar: sidebarModulePath,
|
|
184
|
+
content: blogPost.metadata.source,
|
|
185
|
+
},
|
|
186
|
+
metadata: createBlogPostRouteMetadata(blogPost.metadata),
|
|
187
|
+
context: {
|
|
188
|
+
blogMetadata: blogMetadataModulePath,
|
|
189
|
+
},
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function createBlogPostRoutes(): RouteConfig[] {
|
|
194
|
+
return blogPosts.map(createBlogPostRoute);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function createBlogPostsPaginatedRoutes(): RouteConfig[] {
|
|
198
|
+
return blogListPaginated.map((paginated) => {
|
|
199
|
+
return {
|
|
200
|
+
path: paginated.metadata.permalink,
|
|
201
|
+
component: blogListComponent,
|
|
202
|
+
exact: true,
|
|
203
|
+
modules: {
|
|
204
|
+
sidebar: sidebarModulePath,
|
|
205
|
+
items: blogPostItemsModule(paginated.items),
|
|
206
|
+
},
|
|
207
|
+
props: {
|
|
208
|
+
metadata: paginated.metadata,
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
function createTagsRoutes(): RouteConfig[] {
|
|
215
|
+
// Tags. This is the last part so we early-return if there are no tags.
|
|
216
|
+
if (Object.keys(blogTags).length === 0) {
|
|
217
|
+
return [];
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const tagsListRoute: RouteConfig = {
|
|
221
|
+
path: blogTagsListPath,
|
|
222
|
+
component: blogTagsListComponent,
|
|
223
|
+
exact: true,
|
|
224
|
+
modules: {
|
|
225
|
+
sidebar: sidebarModulePath,
|
|
226
|
+
},
|
|
227
|
+
props: {
|
|
228
|
+
tags: toTagsProp({blogTags}),
|
|
229
|
+
},
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
function createTagPaginatedRoutes(tag: BlogTag): RouteConfig[] {
|
|
233
|
+
return tag.pages.map((paginated) => {
|
|
234
|
+
return {
|
|
235
|
+
path: paginated.metadata.permalink,
|
|
236
|
+
component: blogTagsPostsComponent,
|
|
237
|
+
exact: true,
|
|
238
|
+
modules: {
|
|
239
|
+
sidebar: sidebarModulePath,
|
|
240
|
+
items: blogPostItemsModule(paginated.items),
|
|
241
|
+
},
|
|
242
|
+
props: {
|
|
243
|
+
tag: toTagProp({tag, blogTagsListPath}),
|
|
244
|
+
listMetadata: paginated.metadata,
|
|
245
|
+
},
|
|
246
|
+
};
|
|
247
|
+
});
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
const tagsPaginatedRoutes: RouteConfig[] = Object.values(blogTags).flatMap(
|
|
251
|
+
createTagPaginatedRoutes,
|
|
252
|
+
);
|
|
253
|
+
|
|
254
|
+
return [tagsListRoute, ...tagsPaginatedRoutes];
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return [
|
|
258
|
+
...createBlogPostRoutes(),
|
|
259
|
+
...createBlogPostsPaginatedRoutes(),
|
|
260
|
+
...createTagsRoutes(),
|
|
261
|
+
...createArchiveRoute(),
|
|
262
|
+
];
|
|
263
|
+
}
|