@docusaurus/plugin-content-blog 3.9.1-canary-6425 → 3.9.2-alpha.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/blogUtils.d.ts +2 -1
- package/lib/blogUtils.js +6 -14
- package/lib/feed.js +1 -1
- package/lib/index.js +28 -22
- package/lib/options.js +1 -0
- package/lib/routes.js +29 -16
- package/lib/translations.js +4 -16
- package/package.json +11 -10
- package/src/blogUtils.ts +7 -13
- package/src/feed.ts +1 -1
- package/src/index.ts +34 -27
- package/src/options.ts +2 -1
- package/src/plugin-content-blog.d.ts +4 -3
- package/src/routes.ts +31 -19
- package/src/translations.ts +7 -30
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
|
+
import type { TagsFile } from '@docusaurus/utils';
|
|
7
8
|
import type { LoadContext } from '@docusaurus/types';
|
|
8
9
|
import type { AuthorsMap, PluginOptions, BlogPost, BlogTags, BlogPaginated } from '@docusaurus/plugin-content-blog';
|
|
9
10
|
import type { BlogContentPaths } from './types';
|
|
@@ -34,7 +35,7 @@ type ParsedBlogFileName = {
|
|
|
34
35
|
slug: string;
|
|
35
36
|
};
|
|
36
37
|
export declare function parseBlogFileName(blogSourceRelative: string): ParsedBlogFileName;
|
|
37
|
-
export declare function generateBlogPosts(contentPaths: BlogContentPaths, context: LoadContext, options: PluginOptions, authorsMap?: AuthorsMap): Promise<BlogPost[]>;
|
|
38
|
+
export declare function generateBlogPosts(contentPaths: BlogContentPaths, context: LoadContext, options: PluginOptions, tagsFile: TagsFile | null, authorsMap?: AuthorsMap): Promise<BlogPost[]>;
|
|
38
39
|
export declare function applyProcessBlogPosts({ blogPosts, processBlogPosts, }: {
|
|
39
40
|
blogPosts: BlogPost[];
|
|
40
41
|
processBlogPosts: PluginOptions['processBlogPosts'];
|
package/lib/blogUtils.js
CHANGED
|
@@ -20,7 +20,6 @@ const path_1 = tslib_1.__importDefault(require("path"));
|
|
|
20
20
|
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
21
21
|
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
22
22
|
const utils_1 = require("@docusaurus/utils");
|
|
23
|
-
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
24
23
|
const frontMatter_1 = require("./frontMatter");
|
|
25
24
|
const authors_1 = require("./authors");
|
|
26
25
|
const authorsProblems_1 = require("./authorsProblems");
|
|
@@ -132,7 +131,7 @@ async function parseBlogPostMarkdownFile({ filePath, parseFrontMatter, }) {
|
|
|
132
131
|
}
|
|
133
132
|
const defaultReadingTime = ({ content, locale, options }) => (0, readingTime_1.calculateReadingTime)(content, locale, options);
|
|
134
133
|
async function processBlogSourceFile(blogSourceRelative, contentPaths, context, options, tagsFile, authorsMap) {
|
|
135
|
-
const { siteConfig: { baseUrl, markdown: { parseFrontMatter }, }, siteDir, i18n, } = context;
|
|
134
|
+
const { siteConfig: { baseUrl, markdown: { parseFrontMatter }, future: { experimental_vcs: vcs }, }, siteDir, i18n, } = context;
|
|
136
135
|
const { routeBasePath, tagsBasePath: tagsRouteBasePath, truncateMarker, showReadingTime, editUrl, } = options;
|
|
137
136
|
// Lookup in localized folder in priority
|
|
138
137
|
const blogDirPath = await (0, utils_1.getFolderContainingFile)((0, utils_1.getContentPathList)(contentPaths), blogSourceRelative);
|
|
@@ -142,7 +141,7 @@ async function processBlogSourceFile(blogSourceRelative, contentPaths, context,
|
|
|
142
141
|
parseFrontMatter,
|
|
143
142
|
});
|
|
144
143
|
const aliasedSource = (0, utils_1.aliasedSitePath)(blogSourceAbsolute, siteDir);
|
|
145
|
-
const lastUpdate = await (0, utils_1.readLastUpdateData)(blogSourceAbsolute, options, frontMatter.last_update);
|
|
144
|
+
const lastUpdate = await (0, utils_1.readLastUpdateData)(blogSourceAbsolute, options, frontMatter.last_update, vcs);
|
|
146
145
|
const draft = (0, utils_1.isDraft)({ frontMatter });
|
|
147
146
|
const unlisted = (0, utils_1.isUnlisted)({ frontMatter });
|
|
148
147
|
if (draft) {
|
|
@@ -165,17 +164,11 @@ async function processBlogSourceFile(blogSourceRelative, contentPaths, context,
|
|
|
165
164
|
else if (parsedBlogFileName.date) {
|
|
166
165
|
return parsedBlogFileName.date;
|
|
167
166
|
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
age: 'oldest',
|
|
171
|
-
includeAuthor: false,
|
|
172
|
-
});
|
|
173
|
-
return result.date;
|
|
174
|
-
}
|
|
175
|
-
catch (err) {
|
|
176
|
-
logger_1.default.warn(err);
|
|
167
|
+
const result = await vcs.getFileCreationInfo(blogSourceAbsolute);
|
|
168
|
+
if (result == null) {
|
|
177
169
|
return (await fs_extra_1.default.stat(blogSourceAbsolute)).birthtime;
|
|
178
170
|
}
|
|
171
|
+
return new Date(result.timestamp);
|
|
179
172
|
}
|
|
180
173
|
const date = await getDate();
|
|
181
174
|
const title = frontMatter.title ?? contentTitle ?? parsedBlogFileName.text;
|
|
@@ -253,7 +246,7 @@ async function processBlogSourceFile(blogSourceRelative, contentPaths, context,
|
|
|
253
246
|
content,
|
|
254
247
|
};
|
|
255
248
|
}
|
|
256
|
-
async function generateBlogPosts(contentPaths, context, options, authorsMap) {
|
|
249
|
+
async function generateBlogPosts(contentPaths, context, options, tagsFile, authorsMap) {
|
|
257
250
|
const { include, exclude } = options;
|
|
258
251
|
if (!(await fs_extra_1.default.pathExists(contentPaths.contentPath))) {
|
|
259
252
|
return [];
|
|
@@ -262,7 +255,6 @@ async function generateBlogPosts(contentPaths, context, options, authorsMap) {
|
|
|
262
255
|
cwd: contentPaths.contentPath,
|
|
263
256
|
ignore: exclude,
|
|
264
257
|
});
|
|
265
|
-
const tagsFile = await (0, utils_validation_1.getTagsFile)({ contentPaths, tags: options.tags });
|
|
266
258
|
async function doProcessBlogSourceFile(blogSourceFile) {
|
|
267
259
|
try {
|
|
268
260
|
return await processBlogSourceFile(blogSourceFile, contentPaths, context, options, tagsFile, authorsMap);
|
package/lib/feed.js
CHANGED
|
@@ -116,7 +116,7 @@ async function resolveXsltFilePaths({ xsltFilePath, contentPaths, }) {
|
|
|
116
116
|
}
|
|
117
117
|
const parsedPath = path_1.default.parse(xsltAbsolutePath);
|
|
118
118
|
const cssAbsolutePath = path_1.default.resolve(parsedPath.dir, `${parsedPath.name}.css`);
|
|
119
|
-
if (!(await fs_extra_1.default.pathExists(
|
|
119
|
+
if (!(await fs_extra_1.default.pathExists(cssAbsolutePath))) {
|
|
120
120
|
throw new Error(logger_1.default.interpolate `Blog feed XSLT file was found at path=${path_1.default.relative(process.cwd(), xsltAbsolutePath)}
|
|
121
121
|
But its expected co-located CSS file could not be found at path=${path_1.default.relative(process.cwd(), cssAbsolutePath)}
|
|
122
122
|
If you want to provide a custom XSLT file, you must provide a CSS file with the exact same name.`);
|
package/lib/index.js
CHANGED
|
@@ -11,6 +11,7 @@ exports.default = pluginContentBlog;
|
|
|
11
11
|
const tslib_1 = require("tslib");
|
|
12
12
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
13
13
|
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
14
|
+
const combine_promises_1 = tslib_1.__importDefault(require("combine-promises"));
|
|
14
15
|
const utils_1 = require("@docusaurus/utils");
|
|
15
16
|
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
16
17
|
const mdx_loader_1 = require("@docusaurus/mdx-loader");
|
|
@@ -41,7 +42,7 @@ async function pluginContentBlog(context, options) {
|
|
|
41
42
|
})
|
|
42
43
|
: undefined,
|
|
43
44
|
};
|
|
44
|
-
const pluginId = options.id
|
|
45
|
+
const pluginId = options.id;
|
|
45
46
|
const pluginDataDirRoot = path_1.default.join(generatedFilesDir, PluginName);
|
|
46
47
|
const dataDir = path_1.default.join(pluginDataDirRoot, pluginId);
|
|
47
48
|
// TODO Docusaurus v4 breaking change
|
|
@@ -57,7 +58,7 @@ async function pluginContentBlog(context, options) {
|
|
|
57
58
|
const { admonitions, rehypePlugins, remarkPlugins, recmaPlugins, truncateMarker, beforeDefaultRemarkPlugins, beforeDefaultRehypePlugins, } = options;
|
|
58
59
|
const contentDirs = (0, utils_1.getContentPathList)(contentPaths);
|
|
59
60
|
const mdxLoaderItem = await (0, mdx_loader_1.createMDXLoaderItem)({
|
|
60
|
-
useCrossCompilerCache: siteConfig.future.
|
|
61
|
+
useCrossCompilerCache: siteConfig.future.faster.mdxCrossCompilerCache,
|
|
61
62
|
admonitions,
|
|
62
63
|
remarkPlugins,
|
|
63
64
|
rehypePlugins,
|
|
@@ -141,18 +142,26 @@ async function pluginContentBlog(context, options) {
|
|
|
141
142
|
const { postsPerPage: postsPerPageOption, routeBasePath, tagsBasePath, blogDescription, blogTitle, blogSidebarTitle, pageBasePath, authorsBasePath, authorsMapPath, } = options;
|
|
142
143
|
const baseBlogUrl = (0, utils_1.normalizeUrl)([baseUrl, routeBasePath]);
|
|
143
144
|
const blogTagsListPath = (0, utils_1.normalizeUrl)([baseBlogUrl, tagsBasePath]);
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
async function getAuthorsMapChecked() {
|
|
146
|
+
const result = await (0, authorsMap_1.getAuthorsMap)({
|
|
147
|
+
contentPaths,
|
|
148
|
+
authorsMapPath,
|
|
149
|
+
authorsBaseRoutePath: (0, utils_1.normalizeUrl)([
|
|
150
|
+
baseUrl,
|
|
151
|
+
routeBasePath,
|
|
152
|
+
authorsBasePath,
|
|
153
|
+
]),
|
|
148
154
|
baseUrl,
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
155
|
+
});
|
|
156
|
+
(0, authorsMap_1.checkAuthorsMapPermalinkCollisions)(result);
|
|
157
|
+
return result;
|
|
158
|
+
}
|
|
159
|
+
// Read all the input files in parallel
|
|
160
|
+
const { authorsMap, tagsFile } = await (0, combine_promises_1.default)({
|
|
161
|
+
authorsMap: getAuthorsMapChecked(),
|
|
162
|
+
tagsFile: (0, utils_validation_1.getTagsFile)({ contentPaths, tags: options.tags }),
|
|
153
163
|
});
|
|
154
|
-
(0,
|
|
155
|
-
let blogPosts = await (0, blogUtils_1.generateBlogPosts)(contentPaths, context, options, authorsMap);
|
|
164
|
+
let blogPosts = await (0, blogUtils_1.generateBlogPosts)(contentPaths, context, options, tagsFile, authorsMap);
|
|
156
165
|
blogPosts = await (0, blogUtils_1.applyProcessBlogPosts)({
|
|
157
166
|
blogPosts,
|
|
158
167
|
processBlogPosts: options.processBlogPosts,
|
|
@@ -164,9 +173,10 @@ async function pluginContentBlog(context, options) {
|
|
|
164
173
|
const listedBlogPosts = blogPosts.filter(blogUtils_1.shouldBeListed);
|
|
165
174
|
if (!blogPosts.length) {
|
|
166
175
|
return {
|
|
176
|
+
blogTitle,
|
|
177
|
+
blogDescription,
|
|
167
178
|
blogSidebarTitle,
|
|
168
179
|
blogPosts: [],
|
|
169
|
-
blogListPaginated: [],
|
|
170
180
|
blogTags: {},
|
|
171
181
|
blogTagsListPath,
|
|
172
182
|
authorsMap,
|
|
@@ -191,14 +201,9 @@ async function pluginContentBlog(context, options) {
|
|
|
191
201
|
};
|
|
192
202
|
}
|
|
193
203
|
});
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
blogDescription,
|
|
198
|
-
postsPerPageOption,
|
|
199
|
-
basePageUrl: baseBlogUrl,
|
|
200
|
-
pageBasePath,
|
|
201
|
-
});
|
|
204
|
+
// TODO this is not the correct place to aggregate and paginate tags
|
|
205
|
+
// for reasons similar to https://github.com/facebook/docusaurus/pull/11562
|
|
206
|
+
// What we should do here is only read the tags file (similar to authors)
|
|
202
207
|
const blogTags = (0, blogUtils_1.getBlogTags)({
|
|
203
208
|
blogPosts,
|
|
204
209
|
postsPerPageOption,
|
|
@@ -207,9 +212,10 @@ async function pluginContentBlog(context, options) {
|
|
|
207
212
|
pageBasePath,
|
|
208
213
|
});
|
|
209
214
|
return {
|
|
215
|
+
blogTitle,
|
|
216
|
+
blogDescription,
|
|
210
217
|
blogSidebarTitle,
|
|
211
218
|
blogPosts,
|
|
212
|
-
blogListPaginated,
|
|
213
219
|
blogTags,
|
|
214
220
|
blogTagsListPath,
|
|
215
221
|
authorsMap,
|
package/lib/options.js
CHANGED
|
@@ -13,6 +13,7 @@ const path_1 = tslib_1.__importDefault(require("path"));
|
|
|
13
13
|
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
14
14
|
const utils_1 = require("@docusaurus/utils");
|
|
15
15
|
exports.DEFAULT_OPTIONS = {
|
|
16
|
+
id: utils_1.DEFAULT_PLUGIN_ID,
|
|
16
17
|
feedOptions: {
|
|
17
18
|
type: ['rss', 'atom'],
|
|
18
19
|
copyright: '',
|
package/lib/routes.js
CHANGED
|
@@ -19,15 +19,12 @@ async function createAllRoutes(param) {
|
|
|
19
19
|
routes.forEach(param.actions.addRoute);
|
|
20
20
|
}
|
|
21
21
|
async function buildAllRoutes({ baseUrl, content, actions, options, aliasedSource, }) {
|
|
22
|
-
const { blogListComponent, blogPostComponent, blogTagsListComponent, blogAuthorsListComponent, blogAuthorsPostsComponent, blogTagsPostsComponent, blogArchiveComponent, routeBasePath, archiveBasePath,
|
|
22
|
+
const { blogListComponent, blogPostComponent, blogTagsListComponent, blogAuthorsListComponent, blogAuthorsPostsComponent, blogTagsPostsComponent, blogArchiveComponent, routeBasePath, archiveBasePath, authorsBasePath, postsPerPage, pageBasePath, } = options;
|
|
23
23
|
const pluginId = options.id;
|
|
24
24
|
const { createData } = actions;
|
|
25
|
-
const { blogSidebarTitle, blogPosts,
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
routeBasePath,
|
|
29
|
-
authorsBasePath,
|
|
30
|
-
]);
|
|
25
|
+
const { blogTitle, blogDescription, blogSidebarTitle, blogPosts, blogTags, blogTagsListPath, authorsMap, } = content;
|
|
26
|
+
const blogBasePath = (0, utils_1.normalizeUrl)([baseUrl, routeBasePath]);
|
|
27
|
+
const authorsListPath = (0, utils_1.normalizeUrl)([blogBasePath, authorsBasePath]);
|
|
31
28
|
const listedBlogPosts = blogPosts.filter(blogUtils_1.shouldBeListed);
|
|
32
29
|
const blogPostsById = lodash_1.default.keyBy(blogPosts, (post) => post.id);
|
|
33
30
|
function getBlogPostById(id) {
|
|
@@ -50,7 +47,7 @@ async function buildAllRoutes({ baseUrl, content, actions, options, aliasedSourc
|
|
|
50
47
|
}
|
|
51
48
|
async function createBlogMetadataModule() {
|
|
52
49
|
const blogMetadata = {
|
|
53
|
-
blogBasePath
|
|
50
|
+
blogBasePath,
|
|
54
51
|
blogTitle,
|
|
55
52
|
authorsListPath,
|
|
56
53
|
};
|
|
@@ -81,7 +78,7 @@ async function buildAllRoutes({ baseUrl, content, actions, options, aliasedSourc
|
|
|
81
78
|
if (archiveBasePath && listedBlogPosts.length) {
|
|
82
79
|
return [
|
|
83
80
|
{
|
|
84
|
-
path: (0, utils_1.normalizeUrl)([
|
|
81
|
+
path: (0, utils_1.normalizeUrl)([blogBasePath, archiveBasePath]),
|
|
85
82
|
component: blogArchiveComponent,
|
|
86
83
|
exact: true,
|
|
87
84
|
props: {
|
|
@@ -124,6 +121,14 @@ async function buildAllRoutes({ baseUrl, content, actions, options, aliasedSourc
|
|
|
124
121
|
return blogPosts.map(createBlogPostRoute);
|
|
125
122
|
}
|
|
126
123
|
function createBlogPostsPaginatedRoutes() {
|
|
124
|
+
const blogListPaginated = (0, blogUtils_1.paginateBlogPosts)({
|
|
125
|
+
blogPosts: listedBlogPosts,
|
|
126
|
+
blogTitle,
|
|
127
|
+
blogDescription,
|
|
128
|
+
postsPerPageOption: postsPerPage,
|
|
129
|
+
basePageUrl: blogBasePath,
|
|
130
|
+
pageBasePath,
|
|
131
|
+
});
|
|
127
132
|
return blogListPaginated.map((paginated) => {
|
|
128
133
|
return {
|
|
129
134
|
path: paginated.metadata.permalink,
|
|
@@ -197,10 +202,14 @@ async function buildAllRoutes({ baseUrl, content, actions, options, aliasedSourc
|
|
|
197
202
|
sidebar: sidebarModulePath,
|
|
198
203
|
},
|
|
199
204
|
props: {
|
|
200
|
-
authors: authors.map((author) =>
|
|
201
|
-
author
|
|
202
|
-
|
|
203
|
-
|
|
205
|
+
authors: authors.map((author) => {
|
|
206
|
+
const authorPosts = blogPostsByAuthorKey[author.key] ?? [];
|
|
207
|
+
const listedAuthorPosts = authorPosts.filter(blogUtils_1.shouldBeListed);
|
|
208
|
+
return (0, props_1.toAuthorItemProp)({
|
|
209
|
+
author,
|
|
210
|
+
count: listedAuthorPosts.length,
|
|
211
|
+
});
|
|
212
|
+
}),
|
|
204
213
|
},
|
|
205
214
|
context: {
|
|
206
215
|
blogMetadata: blogMetadataModulePath,
|
|
@@ -209,15 +218,16 @@ async function buildAllRoutes({ baseUrl, content, actions, options, aliasedSourc
|
|
|
209
218
|
}
|
|
210
219
|
function createAuthorPaginatedRoute(author) {
|
|
211
220
|
const authorBlogPosts = blogPostsByAuthorKey[author.key] ?? [];
|
|
221
|
+
const listedAuthorBlogPosts = authorBlogPosts.filter(blogUtils_1.shouldBeListed);
|
|
212
222
|
if (!author.page) {
|
|
213
223
|
return [];
|
|
214
224
|
}
|
|
215
225
|
const pages = (0, blogUtils_1.paginateBlogPosts)({
|
|
216
|
-
blogPosts:
|
|
226
|
+
blogPosts: listedAuthorBlogPosts,
|
|
217
227
|
basePageUrl: author.page.permalink,
|
|
218
228
|
blogDescription,
|
|
219
229
|
blogTitle,
|
|
220
|
-
pageBasePath
|
|
230
|
+
pageBasePath,
|
|
221
231
|
postsPerPageOption: postsPerPage,
|
|
222
232
|
});
|
|
223
233
|
return pages.map(({ metadata, items }) => {
|
|
@@ -230,7 +240,10 @@ async function buildAllRoutes({ baseUrl, content, actions, options, aliasedSourc
|
|
|
230
240
|
sidebar: sidebarModulePath,
|
|
231
241
|
},
|
|
232
242
|
props: {
|
|
233
|
-
author: (0, props_1.toAuthorItemProp)({
|
|
243
|
+
author: (0, props_1.toAuthorItemProp)({
|
|
244
|
+
author,
|
|
245
|
+
count: listedAuthorBlogPosts.length,
|
|
246
|
+
}),
|
|
234
247
|
listMetadata: metadata,
|
|
235
248
|
},
|
|
236
249
|
context: {
|
package/lib/translations.js
CHANGED
|
@@ -8,19 +8,6 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.getTranslationFiles = getTranslationFiles;
|
|
10
10
|
exports.translateContent = translateContent;
|
|
11
|
-
function translateListPage(blogListPaginated, translations) {
|
|
12
|
-
return blogListPaginated.map((page) => {
|
|
13
|
-
const { items, metadata } = page;
|
|
14
|
-
return {
|
|
15
|
-
items,
|
|
16
|
-
metadata: {
|
|
17
|
-
...metadata,
|
|
18
|
-
blogTitle: translations.title?.message ?? page.metadata.blogTitle,
|
|
19
|
-
blogDescription: translations.description?.message ?? page.metadata.blogDescription,
|
|
20
|
-
},
|
|
21
|
-
};
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
11
|
function getTranslationFiles(options) {
|
|
25
12
|
return [
|
|
26
13
|
{
|
|
@@ -43,10 +30,11 @@ function getTranslationFiles(options) {
|
|
|
43
30
|
];
|
|
44
31
|
}
|
|
45
32
|
function translateContent(content, translationFiles) {
|
|
46
|
-
const { content:
|
|
33
|
+
const { content: translations } = translationFiles[0];
|
|
47
34
|
return {
|
|
48
35
|
...content,
|
|
49
|
-
|
|
50
|
-
|
|
36
|
+
blogTitle: translations.title?.message ?? content.blogTitle,
|
|
37
|
+
blogDescription: translations.description?.message ?? content.blogDescription,
|
|
38
|
+
blogSidebarTitle: translations['sidebar.title']?.message ?? content.blogSidebarTitle,
|
|
51
39
|
};
|
|
52
40
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/plugin-content-blog",
|
|
3
|
-
"version": "3.9.
|
|
3
|
+
"version": "3.9.2-alpha.0",
|
|
4
4
|
"description": "Blog plugin for Docusaurus.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "src/plugin-content-blog.d.ts",
|
|
@@ -31,15 +31,16 @@
|
|
|
31
31
|
},
|
|
32
32
|
"license": "MIT",
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@docusaurus/core": "3.9.
|
|
35
|
-
"@docusaurus/logger": "3.9.
|
|
36
|
-
"@docusaurus/mdx-loader": "3.9.
|
|
37
|
-
"@docusaurus/theme-common": "3.9.
|
|
38
|
-
"@docusaurus/types": "3.9.
|
|
39
|
-
"@docusaurus/utils": "3.9.
|
|
40
|
-
"@docusaurus/utils-common": "3.9.
|
|
41
|
-
"@docusaurus/utils-validation": "3.9.
|
|
34
|
+
"@docusaurus/core": "3.9.2-alpha.0",
|
|
35
|
+
"@docusaurus/logger": "3.9.2-alpha.0",
|
|
36
|
+
"@docusaurus/mdx-loader": "3.9.2-alpha.0",
|
|
37
|
+
"@docusaurus/theme-common": "3.9.2-alpha.0",
|
|
38
|
+
"@docusaurus/types": "3.9.2-alpha.0",
|
|
39
|
+
"@docusaurus/utils": "3.9.2-alpha.0",
|
|
40
|
+
"@docusaurus/utils-common": "3.9.2-alpha.0",
|
|
41
|
+
"@docusaurus/utils-validation": "3.9.2-alpha.0",
|
|
42
42
|
"cheerio": "1.0.0-rc.12",
|
|
43
|
+
"combine-promises": "^1.1.0",
|
|
43
44
|
"feed": "^4.2.2",
|
|
44
45
|
"fs-extra": "^11.1.1",
|
|
45
46
|
"lodash": "^4.17.21",
|
|
@@ -62,5 +63,5 @@
|
|
|
62
63
|
"@total-typescript/shoehorn": "^0.1.2",
|
|
63
64
|
"tree-node-cli": "^1.6.0"
|
|
64
65
|
},
|
|
65
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "27626cdd7a102277935f10cc4d8d3f93e211eafe"
|
|
66
67
|
}
|
package/src/blogUtils.ts
CHANGED
|
@@ -19,7 +19,6 @@ import {
|
|
|
19
19
|
Globby,
|
|
20
20
|
groupTaggedItems,
|
|
21
21
|
getTagVisibility,
|
|
22
|
-
getFileCommitDate,
|
|
23
22
|
getContentPathList,
|
|
24
23
|
isUnlisted,
|
|
25
24
|
isDraft,
|
|
@@ -27,7 +26,7 @@ import {
|
|
|
27
26
|
normalizeTags,
|
|
28
27
|
aliasedSitePathToRelativePath,
|
|
29
28
|
} from '@docusaurus/utils';
|
|
30
|
-
|
|
29
|
+
|
|
31
30
|
import {validateBlogPostFrontMatter} from './frontMatter';
|
|
32
31
|
import {getBlogPostAuthors} from './authors';
|
|
33
32
|
import {reportAuthorsProblems} from './authorsProblems';
|
|
@@ -225,6 +224,7 @@ async function processBlogSourceFile(
|
|
|
225
224
|
siteConfig: {
|
|
226
225
|
baseUrl,
|
|
227
226
|
markdown: {parseFrontMatter},
|
|
227
|
+
future: {experimental_vcs: vcs},
|
|
228
228
|
},
|
|
229
229
|
siteDir,
|
|
230
230
|
i18n,
|
|
@@ -257,6 +257,7 @@ async function processBlogSourceFile(
|
|
|
257
257
|
blogSourceAbsolute,
|
|
258
258
|
options,
|
|
259
259
|
frontMatter.last_update,
|
|
260
|
+
vcs,
|
|
260
261
|
);
|
|
261
262
|
|
|
262
263
|
const draft = isDraft({frontMatter});
|
|
@@ -285,17 +286,11 @@ async function processBlogSourceFile(
|
|
|
285
286
|
return parsedBlogFileName.date;
|
|
286
287
|
}
|
|
287
288
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
age: 'oldest',
|
|
291
|
-
includeAuthor: false,
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
return result.date;
|
|
295
|
-
} catch (err) {
|
|
296
|
-
logger.warn(err);
|
|
289
|
+
const result = await vcs.getFileCreationInfo(blogSourceAbsolute);
|
|
290
|
+
if (result == null) {
|
|
297
291
|
return (await fs.stat(blogSourceAbsolute)).birthtime;
|
|
298
292
|
}
|
|
293
|
+
return new Date(result.timestamp);
|
|
299
294
|
}
|
|
300
295
|
|
|
301
296
|
const date = await getDate();
|
|
@@ -393,6 +388,7 @@ export async function generateBlogPosts(
|
|
|
393
388
|
contentPaths: BlogContentPaths,
|
|
394
389
|
context: LoadContext,
|
|
395
390
|
options: PluginOptions,
|
|
391
|
+
tagsFile: TagsFile | null,
|
|
396
392
|
authorsMap?: AuthorsMap,
|
|
397
393
|
): Promise<BlogPost[]> {
|
|
398
394
|
const {include, exclude} = options;
|
|
@@ -406,8 +402,6 @@ export async function generateBlogPosts(
|
|
|
406
402
|
ignore: exclude,
|
|
407
403
|
});
|
|
408
404
|
|
|
409
|
-
const tagsFile = await getTagsFile({contentPaths, tags: options.tags});
|
|
410
|
-
|
|
411
405
|
async function doProcessBlogSourceFile(blogSourceFile: string) {
|
|
412
406
|
try {
|
|
413
407
|
return await processBlogSourceFile(
|
package/src/feed.ts
CHANGED
|
@@ -213,7 +213,7 @@ async function resolveXsltFilePaths({
|
|
|
213
213
|
parsedPath.dir,
|
|
214
214
|
`${parsedPath.name}.css`,
|
|
215
215
|
);
|
|
216
|
-
if (!(await fs.pathExists(
|
|
216
|
+
if (!(await fs.pathExists(cssAbsolutePath))) {
|
|
217
217
|
throw new Error(
|
|
218
218
|
logger.interpolate`Blog feed XSLT file was found at path=${path.relative(
|
|
219
219
|
process.cwd(),
|
package/src/index.ts
CHANGED
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import logger from '@docusaurus/logger';
|
|
10
|
+
import combinePromises from 'combine-promises';
|
|
11
|
+
|
|
10
12
|
import {
|
|
11
13
|
normalizeUrl,
|
|
12
14
|
docuHash,
|
|
@@ -17,15 +19,16 @@ import {
|
|
|
17
19
|
createAbsoluteFilePathMatcher,
|
|
18
20
|
getContentPathList,
|
|
19
21
|
getDataFilePath,
|
|
20
|
-
DEFAULT_PLUGIN_ID,
|
|
21
22
|
resolveMarkdownLinkPathname,
|
|
22
23
|
getLocaleConfig,
|
|
23
24
|
} from '@docusaurus/utils';
|
|
24
|
-
import {
|
|
25
|
+
import {
|
|
26
|
+
getTagsFilePathsToWatch,
|
|
27
|
+
getTagsFile,
|
|
28
|
+
} from '@docusaurus/utils-validation';
|
|
25
29
|
import {createMDXLoaderItem} from '@docusaurus/mdx-loader';
|
|
26
30
|
import {
|
|
27
31
|
getBlogTags,
|
|
28
|
-
paginateBlogPosts,
|
|
29
32
|
shouldBeListed,
|
|
30
33
|
applyProcessBlogPosts,
|
|
31
34
|
generateBlogPosts,
|
|
@@ -45,7 +48,6 @@ import type {
|
|
|
45
48
|
Assets,
|
|
46
49
|
BlogTags,
|
|
47
50
|
BlogContent,
|
|
48
|
-
BlogPaginated,
|
|
49
51
|
} from '@docusaurus/plugin-content-blog';
|
|
50
52
|
import type {RuleSetRule, RuleSetUseItem} from 'webpack';
|
|
51
53
|
|
|
@@ -85,7 +87,7 @@ export default async function pluginContentBlog(
|
|
|
85
87
|
})
|
|
86
88
|
: undefined,
|
|
87
89
|
};
|
|
88
|
-
const pluginId = options.id
|
|
90
|
+
const pluginId = options.id;
|
|
89
91
|
|
|
90
92
|
const pluginDataDirRoot = path.join(generatedFilesDir, PluginName);
|
|
91
93
|
const dataDir = path.join(pluginDataDirRoot, pluginId);
|
|
@@ -116,8 +118,7 @@ export default async function pluginContentBlog(
|
|
|
116
118
|
const contentDirs = getContentPathList(contentPaths);
|
|
117
119
|
|
|
118
120
|
const mdxLoaderItem = await createMDXLoaderItem({
|
|
119
|
-
useCrossCompilerCache:
|
|
120
|
-
siteConfig.future.experimental_faster.mdxCrossCompilerCache,
|
|
121
|
+
useCrossCompilerCache: siteConfig.future.faster.mdxCrossCompilerCache,
|
|
121
122
|
admonitions,
|
|
122
123
|
remarkPlugins,
|
|
123
124
|
rehypePlugins,
|
|
@@ -230,22 +231,32 @@ export default async function pluginContentBlog(
|
|
|
230
231
|
const baseBlogUrl = normalizeUrl([baseUrl, routeBasePath]);
|
|
231
232
|
const blogTagsListPath = normalizeUrl([baseBlogUrl, tagsBasePath]);
|
|
232
233
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
234
|
+
async function getAuthorsMapChecked() {
|
|
235
|
+
const result = await getAuthorsMap({
|
|
236
|
+
contentPaths,
|
|
237
|
+
authorsMapPath,
|
|
238
|
+
authorsBaseRoutePath: normalizeUrl([
|
|
239
|
+
baseUrl,
|
|
240
|
+
routeBasePath,
|
|
241
|
+
authorsBasePath,
|
|
242
|
+
]),
|
|
237
243
|
baseUrl,
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
244
|
+
});
|
|
245
|
+
checkAuthorsMapPermalinkCollisions(result);
|
|
246
|
+
return result;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// Read all the input files in parallel
|
|
250
|
+
const {authorsMap, tagsFile} = await combinePromises({
|
|
251
|
+
authorsMap: getAuthorsMapChecked(),
|
|
252
|
+
tagsFile: getTagsFile({contentPaths, tags: options.tags}),
|
|
242
253
|
});
|
|
243
|
-
checkAuthorsMapPermalinkCollisions(authorsMap);
|
|
244
254
|
|
|
245
255
|
let blogPosts = await generateBlogPosts(
|
|
246
256
|
contentPaths,
|
|
247
257
|
context,
|
|
248
258
|
options,
|
|
259
|
+
tagsFile,
|
|
249
260
|
authorsMap,
|
|
250
261
|
);
|
|
251
262
|
blogPosts = await applyProcessBlogPosts({
|
|
@@ -260,9 +271,10 @@ export default async function pluginContentBlog(
|
|
|
260
271
|
|
|
261
272
|
if (!blogPosts.length) {
|
|
262
273
|
return {
|
|
274
|
+
blogTitle,
|
|
275
|
+
blogDescription,
|
|
263
276
|
blogSidebarTitle,
|
|
264
277
|
blogPosts: [],
|
|
265
|
-
blogListPaginated: [],
|
|
266
278
|
blogTags: {},
|
|
267
279
|
blogTagsListPath,
|
|
268
280
|
authorsMap,
|
|
@@ -291,15 +303,9 @@ export default async function pluginContentBlog(
|
|
|
291
303
|
}
|
|
292
304
|
});
|
|
293
305
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
blogDescription,
|
|
298
|
-
postsPerPageOption,
|
|
299
|
-
basePageUrl: baseBlogUrl,
|
|
300
|
-
pageBasePath,
|
|
301
|
-
});
|
|
302
|
-
|
|
306
|
+
// TODO this is not the correct place to aggregate and paginate tags
|
|
307
|
+
// for reasons similar to https://github.com/facebook/docusaurus/pull/11562
|
|
308
|
+
// What we should do here is only read the tags file (similar to authors)
|
|
303
309
|
const blogTags: BlogTags = getBlogTags({
|
|
304
310
|
blogPosts,
|
|
305
311
|
postsPerPageOption,
|
|
@@ -309,9 +315,10 @@ export default async function pluginContentBlog(
|
|
|
309
315
|
});
|
|
310
316
|
|
|
311
317
|
return {
|
|
318
|
+
blogTitle,
|
|
319
|
+
blogDescription,
|
|
312
320
|
blogSidebarTitle,
|
|
313
321
|
blogPosts,
|
|
314
|
-
blogListPaginated,
|
|
315
322
|
blogTags,
|
|
316
323
|
blogTagsListPath,
|
|
317
324
|
authorsMap,
|
package/src/options.ts
CHANGED
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
RouteBasePathSchema,
|
|
16
16
|
URISchema,
|
|
17
17
|
} from '@docusaurus/utils-validation';
|
|
18
|
-
import {GlobExcludeDefault} from '@docusaurus/utils';
|
|
18
|
+
import {DEFAULT_PLUGIN_ID, GlobExcludeDefault} from '@docusaurus/utils';
|
|
19
19
|
import type {
|
|
20
20
|
PluginOptions,
|
|
21
21
|
Options,
|
|
@@ -25,6 +25,7 @@ import type {
|
|
|
25
25
|
import type {OptionValidationContext} from '@docusaurus/types';
|
|
26
26
|
|
|
27
27
|
export const DEFAULT_OPTIONS: PluginOptions = {
|
|
28
|
+
id: DEFAULT_PLUGIN_ID,
|
|
28
29
|
feedOptions: {
|
|
29
30
|
type: ['rss', 'atom'],
|
|
30
31
|
copyright: '',
|
|
@@ -431,7 +431,7 @@ declare module '@docusaurus/plugin-content-blog' {
|
|
|
431
431
|
export type PluginOptions = MDXOptions &
|
|
432
432
|
TagsPluginOptions & {
|
|
433
433
|
/** Plugin ID. */
|
|
434
|
-
id
|
|
434
|
+
id: string;
|
|
435
435
|
/**
|
|
436
436
|
* Path to the blog content directory on the file system, relative to site
|
|
437
437
|
* directory.
|
|
@@ -583,9 +583,10 @@ declare module '@docusaurus/plugin-content-blog' {
|
|
|
583
583
|
export type AuthorsMap = {[authorKey: string]: AuthorWithKey};
|
|
584
584
|
|
|
585
585
|
export type BlogContent = {
|
|
586
|
-
|
|
586
|
+
blogTitle: string; // for translation purposes
|
|
587
|
+
blogDescription: string; // for translation purposes
|
|
588
|
+
blogSidebarTitle: string; // for translation purposes
|
|
587
589
|
blogPosts: BlogPost[];
|
|
588
|
-
blogListPaginated: BlogPaginated[];
|
|
589
590
|
blogTags: BlogTags;
|
|
590
591
|
blogTagsListPath: string;
|
|
591
592
|
authorsMap?: AuthorsMap;
|
package/src/routes.ts
CHANGED
|
@@ -67,27 +67,24 @@ export async function buildAllRoutes({
|
|
|
67
67
|
blogArchiveComponent,
|
|
68
68
|
routeBasePath,
|
|
69
69
|
archiveBasePath,
|
|
70
|
-
blogTitle,
|
|
71
70
|
authorsBasePath,
|
|
72
71
|
postsPerPage,
|
|
73
|
-
|
|
72
|
+
pageBasePath,
|
|
74
73
|
} = options;
|
|
75
|
-
const pluginId = options.id
|
|
74
|
+
const pluginId = options.id;
|
|
76
75
|
const {createData} = actions;
|
|
77
76
|
const {
|
|
77
|
+
blogTitle,
|
|
78
|
+
blogDescription,
|
|
78
79
|
blogSidebarTitle,
|
|
79
80
|
blogPosts,
|
|
80
|
-
blogListPaginated,
|
|
81
81
|
blogTags,
|
|
82
82
|
blogTagsListPath,
|
|
83
83
|
authorsMap,
|
|
84
84
|
} = content;
|
|
85
85
|
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
routeBasePath,
|
|
89
|
-
authorsBasePath,
|
|
90
|
-
]);
|
|
86
|
+
const blogBasePath = normalizeUrl([baseUrl, routeBasePath]);
|
|
87
|
+
const authorsListPath = normalizeUrl([blogBasePath, authorsBasePath]);
|
|
91
88
|
|
|
92
89
|
const listedBlogPosts = blogPosts.filter(shouldBeListed);
|
|
93
90
|
|
|
@@ -119,7 +116,7 @@ export async function buildAllRoutes({
|
|
|
119
116
|
|
|
120
117
|
async function createBlogMetadataModule() {
|
|
121
118
|
const blogMetadata: BlogMetadata = {
|
|
122
|
-
blogBasePath
|
|
119
|
+
blogBasePath,
|
|
123
120
|
blogTitle,
|
|
124
121
|
authorsListPath,
|
|
125
122
|
};
|
|
@@ -156,7 +153,7 @@ export async function buildAllRoutes({
|
|
|
156
153
|
if (archiveBasePath && listedBlogPosts.length) {
|
|
157
154
|
return [
|
|
158
155
|
{
|
|
159
|
-
path: normalizeUrl([
|
|
156
|
+
path: normalizeUrl([blogBasePath, archiveBasePath]),
|
|
160
157
|
component: blogArchiveComponent,
|
|
161
158
|
exact: true,
|
|
162
159
|
props: {
|
|
@@ -210,6 +207,15 @@ export async function buildAllRoutes({
|
|
|
210
207
|
}
|
|
211
208
|
|
|
212
209
|
function createBlogPostsPaginatedRoutes(): RouteConfig[] {
|
|
210
|
+
const blogListPaginated = paginateBlogPosts({
|
|
211
|
+
blogPosts: listedBlogPosts,
|
|
212
|
+
blogTitle,
|
|
213
|
+
blogDescription,
|
|
214
|
+
postsPerPageOption: postsPerPage,
|
|
215
|
+
basePageUrl: blogBasePath,
|
|
216
|
+
pageBasePath,
|
|
217
|
+
});
|
|
218
|
+
|
|
213
219
|
return blogListPaginated.map((paginated) => {
|
|
214
220
|
return {
|
|
215
221
|
path: paginated.metadata.permalink,
|
|
@@ -294,12 +300,14 @@ export async function buildAllRoutes({
|
|
|
294
300
|
sidebar: sidebarModulePath,
|
|
295
301
|
},
|
|
296
302
|
props: {
|
|
297
|
-
authors: authors.map((author) =>
|
|
298
|
-
|
|
303
|
+
authors: authors.map((author) => {
|
|
304
|
+
const authorPosts = blogPostsByAuthorKey[author.key] ?? [];
|
|
305
|
+
const listedAuthorPosts = authorPosts.filter(shouldBeListed);
|
|
306
|
+
return toAuthorItemProp({
|
|
299
307
|
author,
|
|
300
|
-
count:
|
|
301
|
-
})
|
|
302
|
-
),
|
|
308
|
+
count: listedAuthorPosts.length,
|
|
309
|
+
});
|
|
310
|
+
}),
|
|
303
311
|
},
|
|
304
312
|
context: {
|
|
305
313
|
blogMetadata: blogMetadataModulePath,
|
|
@@ -309,16 +317,17 @@ export async function buildAllRoutes({
|
|
|
309
317
|
|
|
310
318
|
function createAuthorPaginatedRoute(author: AuthorWithKey): RouteConfig[] {
|
|
311
319
|
const authorBlogPosts = blogPostsByAuthorKey[author.key] ?? [];
|
|
320
|
+
const listedAuthorBlogPosts = authorBlogPosts.filter(shouldBeListed);
|
|
312
321
|
if (!author.page) {
|
|
313
322
|
return [];
|
|
314
323
|
}
|
|
315
324
|
|
|
316
325
|
const pages = paginateBlogPosts({
|
|
317
|
-
blogPosts:
|
|
326
|
+
blogPosts: listedAuthorBlogPosts,
|
|
318
327
|
basePageUrl: author.page.permalink,
|
|
319
328
|
blogDescription,
|
|
320
329
|
blogTitle,
|
|
321
|
-
pageBasePath
|
|
330
|
+
pageBasePath,
|
|
322
331
|
postsPerPageOption: postsPerPage,
|
|
323
332
|
});
|
|
324
333
|
|
|
@@ -332,7 +341,10 @@ export async function buildAllRoutes({
|
|
|
332
341
|
sidebar: sidebarModulePath,
|
|
333
342
|
},
|
|
334
343
|
props: {
|
|
335
|
-
author: toAuthorItemProp({
|
|
344
|
+
author: toAuthorItemProp({
|
|
345
|
+
author,
|
|
346
|
+
count: listedAuthorBlogPosts.length,
|
|
347
|
+
}),
|
|
336
348
|
listMetadata: metadata,
|
|
337
349
|
},
|
|
338
350
|
context: {
|
package/src/translations.ts
CHANGED
|
@@ -5,30 +5,8 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import type {
|
|
9
|
-
import type {
|
|
10
|
-
PluginOptions,
|
|
11
|
-
BlogContent,
|
|
12
|
-
BlogPaginated,
|
|
13
|
-
} from '@docusaurus/plugin-content-blog';
|
|
14
|
-
|
|
15
|
-
function translateListPage(
|
|
16
|
-
blogListPaginated: BlogPaginated[],
|
|
17
|
-
translations: TranslationFileContent,
|
|
18
|
-
) {
|
|
19
|
-
return blogListPaginated.map((page) => {
|
|
20
|
-
const {items, metadata} = page;
|
|
21
|
-
return {
|
|
22
|
-
items,
|
|
23
|
-
metadata: {
|
|
24
|
-
...metadata,
|
|
25
|
-
blogTitle: translations.title?.message ?? page.metadata.blogTitle,
|
|
26
|
-
blogDescription:
|
|
27
|
-
translations.description?.message ?? page.metadata.blogDescription,
|
|
28
|
-
},
|
|
29
|
-
};
|
|
30
|
-
});
|
|
31
|
-
}
|
|
8
|
+
import type {TranslationFile} from '@docusaurus/types';
|
|
9
|
+
import type {PluginOptions, BlogContent} from '@docusaurus/plugin-content-blog';
|
|
32
10
|
|
|
33
11
|
export function getTranslationFiles(options: PluginOptions): TranslationFile[] {
|
|
34
12
|
return [
|
|
@@ -56,14 +34,13 @@ export function translateContent(
|
|
|
56
34
|
content: BlogContent,
|
|
57
35
|
translationFiles: TranslationFile[],
|
|
58
36
|
): BlogContent {
|
|
59
|
-
const {content:
|
|
37
|
+
const {content: translations} = translationFiles[0]!;
|
|
60
38
|
return {
|
|
61
39
|
...content,
|
|
40
|
+
blogTitle: translations.title?.message ?? content.blogTitle,
|
|
41
|
+
blogDescription:
|
|
42
|
+
translations.description?.message ?? content.blogDescription,
|
|
62
43
|
blogSidebarTitle:
|
|
63
|
-
|
|
64
|
-
blogListPaginated: translateListPage(
|
|
65
|
-
content.blogListPaginated,
|
|
66
|
-
optionsTranslations,
|
|
67
|
-
),
|
|
44
|
+
translations['sidebar.title']?.message ?? content.blogSidebarTitle,
|
|
68
45
|
};
|
|
69
46
|
}
|