@docusaurus/plugin-content-blog 2.0.0-beta.17 → 2.0.0-beta.18
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 +3 -1
- package/lib/authors.js +10 -2
- package/lib/blogUtils.d.ts +3 -1
- package/lib/blogUtils.js +9 -7
- package/lib/feed.d.ts +2 -1
- package/lib/feed.js +9 -8
- package/lib/{blogFrontMatter.d.ts → frontMatter.d.ts} +3 -1
- package/lib/{blogFrontMatter.js → frontMatter.js} +0 -0
- package/lib/index.d.ts +2 -2
- package/lib/index.js +6 -14
- package/lib/markdownLoader.js +1 -1
- package/lib/options.d.ts +10 -0
- package/lib/{pluginOptionSchema.js → options.js} +8 -3
- package/lib/translations.js +4 -4
- package/lib/types.d.ts +7 -49
- package/package.json +10 -10
- package/src/authors.ts +29 -18
- package/src/blogUtils.ts +14 -12
- package/src/deps.d.ts +1 -1
- package/src/feed.ts +11 -6
- package/src/{blogFrontMatter.ts → frontMatter.ts} +3 -3
- package/src/index.ts +17 -34
- package/src/markdownLoader.ts +1 -1
- package/src/{pluginOptionSchema.ts → options.ts} +15 -3
- package/src/plugin-content-blog.d.ts +390 -69
- package/src/translations.ts +6 -4
- package/src/types.ts +5 -61
- package/lib/pluginOptionSchema.d.ts +0 -10
package/lib/authors.d.ts
CHANGED
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import type { BlogContentPaths } from './types';
|
|
8
8
|
import type { Author, BlogPostFrontMatter } from '@docusaurus/plugin-content-blog';
|
|
9
|
-
export declare type AuthorsMap =
|
|
9
|
+
export declare type AuthorsMap = {
|
|
10
|
+
[authorKey: string]: Author;
|
|
11
|
+
};
|
|
10
12
|
export declare function validateAuthorsMap(content: unknown): AuthorsMap;
|
|
11
13
|
export declare function getAuthorsMap(params: {
|
|
12
14
|
authorsMapPath: string;
|
package/lib/authors.js
CHANGED
|
@@ -9,7 +9,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
9
9
|
exports.getBlogPostAuthors = exports.getAuthorsMap = exports.validateAuthorsMap = void 0;
|
|
10
10
|
const utils_1 = require("@docusaurus/utils");
|
|
11
11
|
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
12
|
-
const AuthorsMapSchema = utils_validation_1.Joi.object()
|
|
12
|
+
const AuthorsMapSchema = utils_validation_1.Joi.object()
|
|
13
|
+
.pattern(utils_validation_1.Joi.string(), utils_validation_1.Joi.object({
|
|
13
14
|
name: utils_validation_1.Joi.string(),
|
|
14
15
|
url: utils_validation_1.URISchema,
|
|
15
16
|
imageURL: utils_validation_1.URISchema,
|
|
@@ -19,7 +20,14 @@ const AuthorsMapSchema = utils_validation_1.Joi.object().pattern(utils_validatio
|
|
|
19
20
|
.rename('image_url', 'imageURL')
|
|
20
21
|
.or('name', 'imageURL')
|
|
21
22
|
.unknown()
|
|
22
|
-
.required()
|
|
23
|
+
.required()
|
|
24
|
+
.messages({
|
|
25
|
+
'object.base': '{#label} should be an author object containing properties like name, title, and imageURL.',
|
|
26
|
+
'any.required': '{#label} cannot be undefined. It should be an author object containing properties like name, title, and imageURL.',
|
|
27
|
+
}))
|
|
28
|
+
.messages({
|
|
29
|
+
'object.base': "The authors map file should contain an object where each entry contains an author key and the corresponding author's data.",
|
|
30
|
+
});
|
|
23
31
|
function validateAuthorsMap(content) {
|
|
24
32
|
return utils_validation_1.Joi.attempt(content, AuthorsMapSchema);
|
|
25
33
|
}
|
package/lib/blogUtils.d.ts
CHANGED
|
@@ -8,7 +8,9 @@ import type { BlogPost, BlogContentPaths, BlogMarkdownLoaderOptions, BlogTags, B
|
|
|
8
8
|
import type { LoadContext } from '@docusaurus/types';
|
|
9
9
|
import type { PluginOptions } from '@docusaurus/plugin-content-blog';
|
|
10
10
|
export declare function truncate(fileString: string, truncateMarker: RegExp): string;
|
|
11
|
-
export declare function getSourceToPermalink(blogPosts: BlogPost[]):
|
|
11
|
+
export declare function getSourceToPermalink(blogPosts: BlogPost[]): {
|
|
12
|
+
[aliasedPath: string]: string;
|
|
13
|
+
};
|
|
12
14
|
export declare function paginateBlogPosts({ blogPosts, basePageUrl, blogTitle, blogDescription, postsPerPageOption, }: {
|
|
13
15
|
blogPosts: BlogPost[];
|
|
14
16
|
basePageUrl: string;
|
package/lib/blogUtils.js
CHANGED
|
@@ -13,7 +13,7 @@ const path_1 = tslib_1.__importDefault(require("path"));
|
|
|
13
13
|
const reading_time_1 = tslib_1.__importDefault(require("reading-time"));
|
|
14
14
|
const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
15
15
|
const utils_1 = require("@docusaurus/utils");
|
|
16
|
-
const
|
|
16
|
+
const frontMatter_1 = require("./frontMatter");
|
|
17
17
|
const authors_1 = require("./authors");
|
|
18
18
|
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
19
19
|
function truncate(fileString, truncateMarker) {
|
|
@@ -30,7 +30,9 @@ function paginateBlogPosts({ blogPosts, basePageUrl, blogTitle, blogDescription,
|
|
|
30
30
|
const numberOfPages = Math.ceil(totalCount / postsPerPage);
|
|
31
31
|
const pages = [];
|
|
32
32
|
function permalink(page) {
|
|
33
|
-
return page > 0
|
|
33
|
+
return page > 0
|
|
34
|
+
? (0, utils_1.normalizeUrl)([basePageUrl, `page/${page + 1}`])
|
|
35
|
+
: basePageUrl;
|
|
34
36
|
}
|
|
35
37
|
for (let page = 0; page < numberOfPages; page += 1) {
|
|
36
38
|
pages.push({
|
|
@@ -43,8 +45,8 @@ function paginateBlogPosts({ blogPosts, basePageUrl, blogTitle, blogDescription,
|
|
|
43
45
|
postsPerPage,
|
|
44
46
|
totalPages: numberOfPages,
|
|
45
47
|
totalCount,
|
|
46
|
-
previousPage: page !== 0 ? permalink(page - 1) :
|
|
47
|
-
nextPage: page < numberOfPages - 1 ? permalink(page + 1) :
|
|
48
|
+
previousPage: page !== 0 ? permalink(page - 1) : undefined,
|
|
49
|
+
nextPage: page < numberOfPages - 1 ? permalink(page + 1) : undefined,
|
|
48
50
|
blogDescription,
|
|
49
51
|
blogTitle,
|
|
50
52
|
},
|
|
@@ -76,7 +78,7 @@ function parseBlogFileName(blogSourceRelative) {
|
|
|
76
78
|
const date = new Date(`${dateString}Z`);
|
|
77
79
|
const slugDate = dateString.replace(/-/g, '/');
|
|
78
80
|
const slug = `/${slugDate}/${folder}${text}`;
|
|
79
|
-
return { date, text, slug };
|
|
81
|
+
return { date, text: text, slug };
|
|
80
82
|
}
|
|
81
83
|
const text = blogSourceRelative.replace(/(?:\/index)?\.mdx?$/, '');
|
|
82
84
|
const slug = `/${text}`;
|
|
@@ -105,7 +107,7 @@ async function parseBlogPostMarkdownFile(blogSourceAbsolute) {
|
|
|
105
107
|
});
|
|
106
108
|
return {
|
|
107
109
|
...result,
|
|
108
|
-
frontMatter: (0,
|
|
110
|
+
frontMatter: (0, frontMatter_1.validateBlogPostFrontMatter)(result.frontMatter),
|
|
109
111
|
};
|
|
110
112
|
}
|
|
111
113
|
catch (err) {
|
|
@@ -150,7 +152,7 @@ async function processBlogSourceFile(blogSourceRelative, contentPaths, context,
|
|
|
150
152
|
return result.date;
|
|
151
153
|
}
|
|
152
154
|
catch (err) {
|
|
153
|
-
logger_1.default.
|
|
155
|
+
logger_1.default.warn(err);
|
|
154
156
|
return (await fs_extra_1.default.stat(blogSourceAbsolute)).birthtime;
|
|
155
157
|
}
|
|
156
158
|
}
|
package/lib/feed.d.ts
CHANGED
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
import type { BlogPost } from './types';
|
|
8
8
|
import type { DocusaurusConfig } from '@docusaurus/types';
|
|
9
9
|
import type { PluginOptions } from '@docusaurus/plugin-content-blog';
|
|
10
|
-
export declare function createBlogFeedFiles({ blogPosts, options, siteConfig, outDir, }: {
|
|
10
|
+
export declare function createBlogFeedFiles({ blogPosts, options, siteConfig, outDir, locale, }: {
|
|
11
11
|
blogPosts: BlogPost[];
|
|
12
12
|
options: PluginOptions;
|
|
13
13
|
siteConfig: DocusaurusConfig;
|
|
14
14
|
outDir: string;
|
|
15
|
+
locale: string;
|
|
15
16
|
}): Promise<void>;
|
package/lib/feed.js
CHANGED
|
@@ -10,25 +10,25 @@ exports.createBlogFeedFiles = void 0;
|
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const feed_1 = require("feed");
|
|
12
12
|
const utils_1 = require("@docusaurus/utils");
|
|
13
|
-
const cheerio_1 =
|
|
13
|
+
const cheerio_1 = require("cheerio");
|
|
14
14
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
15
15
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
16
16
|
const utils_common_1 = require("@docusaurus/utils-common");
|
|
17
|
-
async function generateBlogFeed({ blogPosts, options, siteConfig, outDir, }) {
|
|
17
|
+
async function generateBlogFeed({ blogPosts, options, siteConfig, outDir, locale, }) {
|
|
18
18
|
if (!blogPosts.length) {
|
|
19
19
|
return null;
|
|
20
20
|
}
|
|
21
21
|
const { feedOptions, routeBasePath } = options;
|
|
22
22
|
const { url: siteUrl, baseUrl, title, favicon } = siteConfig;
|
|
23
23
|
const blogBaseUrl = (0, utils_1.normalizeUrl)([siteUrl, baseUrl, routeBasePath]);
|
|
24
|
-
const updated = blogPosts[0]
|
|
24
|
+
const updated = blogPosts[0]?.metadata.date;
|
|
25
25
|
const feed = new feed_1.Feed({
|
|
26
26
|
id: blogBaseUrl,
|
|
27
|
-
title: feedOptions.title
|
|
27
|
+
title: feedOptions.title ?? `${title} Blog`,
|
|
28
28
|
updated,
|
|
29
|
-
language: feedOptions.language,
|
|
29
|
+
language: feedOptions.language ?? locale,
|
|
30
30
|
link: blogBaseUrl,
|
|
31
|
-
description: feedOptions.description
|
|
31
|
+
description: feedOptions.description ?? `${siteConfig.title} Blog`,
|
|
32
32
|
favicon: favicon ? (0, utils_1.normalizeUrl)([siteUrl, baseUrl, favicon]) : undefined,
|
|
33
33
|
copyright: feedOptions.copyright,
|
|
34
34
|
});
|
|
@@ -38,7 +38,7 @@ async function generateBlogFeed({ blogPosts, options, siteConfig, outDir, }) {
|
|
|
38
38
|
await (0, utils_1.mapAsyncSequential)(blogPosts, async (post) => {
|
|
39
39
|
const { id, metadata: { title: metadataTitle, permalink, date, description, authors, tags, }, } = post;
|
|
40
40
|
const content = await (0, utils_1.readOutputHTMLFile)(permalink.replace(siteConfig.baseUrl, ''), outDir, siteConfig.trailingSlash);
|
|
41
|
-
const $ = cheerio_1.
|
|
41
|
+
const $ = (0, cheerio_1.load)(content);
|
|
42
42
|
const feedItem = {
|
|
43
43
|
title: metadataTitle,
|
|
44
44
|
id,
|
|
@@ -79,12 +79,13 @@ async function createBlogFeedFile({ feed, feedType, generatePath, }) {
|
|
|
79
79
|
throw new Error(`Generating ${feedType} feed failed: ${err}.`);
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
|
-
async function createBlogFeedFiles({ blogPosts, options, siteConfig, outDir, }) {
|
|
82
|
+
async function createBlogFeedFiles({ blogPosts, options, siteConfig, outDir, locale, }) {
|
|
83
83
|
const feed = await generateBlogFeed({
|
|
84
84
|
blogPosts,
|
|
85
85
|
options,
|
|
86
86
|
siteConfig,
|
|
87
87
|
outDir,
|
|
88
|
+
locale,
|
|
88
89
|
});
|
|
89
90
|
const feedTypes = options.feedOptions.type;
|
|
90
91
|
if (!feed || !feedTypes) {
|
|
@@ -5,4 +5,6 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import type { BlogPostFrontMatter } from '@docusaurus/plugin-content-blog';
|
|
8
|
-
export declare function validateBlogPostFrontMatter(frontMatter:
|
|
8
|
+
export declare function validateBlogPostFrontMatter(frontMatter: {
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
}): BlogPostFrontMatter;
|
|
File without changes
|
package/lib/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import type { BlogContent } from './types';
|
|
8
|
-
import type { LoadContext, Plugin
|
|
8
|
+
import type { LoadContext, Plugin } from '@docusaurus/types';
|
|
9
9
|
import type { PluginOptions } from '@docusaurus/plugin-content-blog';
|
|
10
10
|
export default function pluginContentBlog(context: LoadContext, options: PluginOptions): Promise<Plugin<BlogContent>>;
|
|
11
|
-
export
|
|
11
|
+
export { validateOptions } from './options';
|
package/lib/index.js
CHANGED
|
@@ -12,7 +12,6 @@ const path_1 = tslib_1.__importDefault(require("path"));
|
|
|
12
12
|
const remark_admonitions_1 = tslib_1.__importDefault(require("remark-admonitions"));
|
|
13
13
|
const utils_1 = require("@docusaurus/utils");
|
|
14
14
|
const translations_1 = require("./translations");
|
|
15
|
-
const pluginOptionSchema_1 = require("./pluginOptionSchema");
|
|
16
15
|
const blogUtils_1 = require("./blogUtils");
|
|
17
16
|
const feed_1 = require("./feed");
|
|
18
17
|
async function pluginContentBlog(context, options) {
|
|
@@ -116,7 +115,7 @@ async function pluginContentBlog(context, options) {
|
|
|
116
115
|
const sidebarBlogPosts = options.blogSidebarCount === 'ALL'
|
|
117
116
|
? blogPosts
|
|
118
117
|
: blogPosts.slice(0, options.blogSidebarCount);
|
|
119
|
-
if (archiveBasePath) {
|
|
118
|
+
if (archiveBasePath && blogPosts.length) {
|
|
120
119
|
const archiveUrl = (0, utils_1.normalizeUrl)([
|
|
121
120
|
baseUrl,
|
|
122
121
|
routeBasePath,
|
|
@@ -193,10 +192,9 @@ async function pluginContentBlog(context, options) {
|
|
|
193
192
|
if (blogTagsListPath === null) {
|
|
194
193
|
return;
|
|
195
194
|
}
|
|
196
|
-
const tagsModule = Object.fromEntries(Object.entries(blogTags).map(([
|
|
195
|
+
const tagsModule = Object.fromEntries(Object.entries(blogTags).map(([, tag]) => {
|
|
197
196
|
const tagModule = {
|
|
198
197
|
allTagsPath: blogTagsListPath,
|
|
199
|
-
slug: tagKey,
|
|
200
198
|
name: tag.name,
|
|
201
199
|
count: tag.items.length,
|
|
202
200
|
permalink: tag.permalink,
|
|
@@ -330,6 +328,7 @@ async function pluginContentBlog(context, options) {
|
|
|
330
328
|
options,
|
|
331
329
|
outDir,
|
|
332
330
|
siteConfig,
|
|
331
|
+
locale: currentLocale,
|
|
333
332
|
});
|
|
334
333
|
},
|
|
335
334
|
injectHtmlTags({ content }) {
|
|
@@ -360,11 +359,7 @@ async function pluginContentBlog(context, options) {
|
|
|
360
359
|
};
|
|
361
360
|
const headTags = [];
|
|
362
361
|
feedTypes.forEach((feedType) => {
|
|
363
|
-
const
|
|
364
|
-
if (!feedsConfig) {
|
|
365
|
-
return;
|
|
366
|
-
}
|
|
367
|
-
const { type, path: feedConfigPath, title: feedConfigTitle } = feedConfig;
|
|
362
|
+
const { type, path: feedConfigPath, title: feedConfigTitle, } = feedsConfig[feedType];
|
|
368
363
|
headTags.push({
|
|
369
364
|
tagName: 'link',
|
|
370
365
|
attributes: {
|
|
@@ -386,8 +381,5 @@ async function pluginContentBlog(context, options) {
|
|
|
386
381
|
};
|
|
387
382
|
}
|
|
388
383
|
exports.default = pluginContentBlog;
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
return validatedOptions;
|
|
392
|
-
}
|
|
393
|
-
exports.validateOptions = validateOptions;
|
|
384
|
+
var options_1 = require("./options");
|
|
385
|
+
Object.defineProperty(exports, "validateOptions", { enumerable: true, get: function () { return options_1.validateOptions; } });
|
package/lib/markdownLoader.js
CHANGED
|
@@ -25,6 +25,6 @@ function markdownLoader(source) {
|
|
|
25
25
|
if (truncated) {
|
|
26
26
|
finalContent = (0, blogUtils_1.truncate)(finalContent, markdownLoaderOptions.truncateMarker);
|
|
27
27
|
}
|
|
28
|
-
return callback
|
|
28
|
+
return callback?.(null, finalContent);
|
|
29
29
|
}
|
|
30
30
|
exports.default = markdownLoader;
|
package/lib/options.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
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
|
+
import type { PluginOptions, Options } from '@docusaurus/plugin-content-blog';
|
|
8
|
+
import type { OptionValidationContext } from '@docusaurus/types';
|
|
9
|
+
export declare const DEFAULT_OPTIONS: PluginOptions;
|
|
10
|
+
export declare function validateOptions({ validate, options, }: OptionValidationContext<Options, PluginOptions>): PluginOptions;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.
|
|
9
|
+
exports.validateOptions = exports.DEFAULT_OPTIONS = void 0;
|
|
10
10
|
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
11
11
|
const utils_1 = require("@docusaurus/utils");
|
|
12
12
|
exports.DEFAULT_OPTIONS = {
|
|
@@ -39,7 +39,7 @@ exports.DEFAULT_OPTIONS = {
|
|
|
39
39
|
readingTime: ({ content, defaultReadingTime }) => defaultReadingTime({ content }),
|
|
40
40
|
sortPosts: 'descending',
|
|
41
41
|
};
|
|
42
|
-
|
|
42
|
+
const PluginOptionSchema = utils_validation_1.Joi.object({
|
|
43
43
|
path: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.path),
|
|
44
44
|
archiveBasePath: utils_validation_1.Joi.string()
|
|
45
45
|
.default(exports.DEFAULT_OPTIONS.archiveBasePath)
|
|
@@ -100,4 +100,9 @@ exports.PluginOptionSchema = utils_validation_1.Joi.object({
|
|
|
100
100
|
sortPosts: utils_validation_1.Joi.string()
|
|
101
101
|
.valid('descending', 'ascending')
|
|
102
102
|
.default(exports.DEFAULT_OPTIONS.sortPosts),
|
|
103
|
-
});
|
|
103
|
+
}).default(exports.DEFAULT_OPTIONS);
|
|
104
|
+
function validateOptions({ validate, options, }) {
|
|
105
|
+
const validatedOptions = validate(PluginOptionSchema, options);
|
|
106
|
+
return validatedOptions;
|
|
107
|
+
}
|
|
108
|
+
exports.validateOptions = validateOptions;
|
package/lib/translations.js
CHANGED
|
@@ -14,8 +14,8 @@ function translateListPage(blogListPaginated, translations) {
|
|
|
14
14
|
items,
|
|
15
15
|
metadata: {
|
|
16
16
|
...metadata,
|
|
17
|
-
blogTitle: translations.title.
|
|
18
|
-
blogDescription: translations.description.
|
|
17
|
+
blogTitle: translations.title?.message ?? page.metadata.blogTitle,
|
|
18
|
+
blogDescription: translations.description?.message ?? page.metadata.blogDescription,
|
|
19
19
|
},
|
|
20
20
|
};
|
|
21
21
|
});
|
|
@@ -43,10 +43,10 @@ function getTranslationFiles(options) {
|
|
|
43
43
|
}
|
|
44
44
|
exports.getTranslationFiles = getTranslationFiles;
|
|
45
45
|
function translateContent(content, translationFiles) {
|
|
46
|
-
const
|
|
46
|
+
const { content: optionsTranslations } = translationFiles[0];
|
|
47
47
|
return {
|
|
48
48
|
...content,
|
|
49
|
-
blogSidebarTitle: optionsTranslations['sidebar.title'].
|
|
49
|
+
blogSidebarTitle: optionsTranslations['sidebar.title']?.message ?? content.blogSidebarTitle,
|
|
50
50
|
blogListPaginated: translateListPage(content.blogListPaginated, optionsTranslations),
|
|
51
51
|
};
|
|
52
52
|
}
|
package/lib/types.d.ts
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
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 {
|
|
8
|
-
import type {
|
|
9
|
-
import type {
|
|
7
|
+
import type { BrokenMarkdownLink, ContentPaths } from '@docusaurus/utils';
|
|
8
|
+
import type { BlogPostMetadata } from '@docusaurus/plugin-content-blog';
|
|
9
|
+
import type { Metadata as BlogPaginatedMetadata } from '@theme/BlogListPage';
|
|
10
10
|
export declare type BlogContentPaths = ContentPaths;
|
|
11
11
|
export interface BlogContent {
|
|
12
12
|
blogSidebarTitle: string;
|
|
@@ -26,62 +26,20 @@ export interface BlogTag {
|
|
|
26
26
|
}
|
|
27
27
|
export interface BlogPost {
|
|
28
28
|
id: string;
|
|
29
|
-
metadata:
|
|
29
|
+
metadata: BlogPostMetadata;
|
|
30
30
|
content: string;
|
|
31
31
|
}
|
|
32
|
-
export interface BlogPaginatedMetadata {
|
|
33
|
-
permalink: string;
|
|
34
|
-
page: number;
|
|
35
|
-
postsPerPage: number;
|
|
36
|
-
totalPages: number;
|
|
37
|
-
totalCount: number;
|
|
38
|
-
previousPage: string | null;
|
|
39
|
-
nextPage: string | null;
|
|
40
|
-
blogTitle: string;
|
|
41
|
-
blogDescription: string;
|
|
42
|
-
}
|
|
43
32
|
export interface BlogPaginated {
|
|
44
33
|
metadata: BlogPaginatedMetadata;
|
|
45
34
|
items: string[];
|
|
46
35
|
}
|
|
47
|
-
export interface MetaData {
|
|
48
|
-
permalink: string;
|
|
49
|
-
source: string;
|
|
50
|
-
description: string;
|
|
51
|
-
date: Date;
|
|
52
|
-
formattedDate: string;
|
|
53
|
-
tags: Tag[];
|
|
54
|
-
title: string;
|
|
55
|
-
readingTime?: number;
|
|
56
|
-
prevItem?: Paginator;
|
|
57
|
-
nextItem?: Paginator;
|
|
58
|
-
truncated: boolean;
|
|
59
|
-
editUrl?: string;
|
|
60
|
-
authors: Author[];
|
|
61
|
-
frontMatter: BlogPostFrontMatter & Record<string, unknown>;
|
|
62
|
-
}
|
|
63
|
-
export interface Paginator {
|
|
64
|
-
title: string;
|
|
65
|
-
permalink: string;
|
|
66
|
-
}
|
|
67
|
-
export interface BlogItemsToMetadata {
|
|
68
|
-
[key: string]: MetaData;
|
|
69
|
-
}
|
|
70
|
-
export interface TagsModule {
|
|
71
|
-
[key: string]: TagModule;
|
|
72
|
-
}
|
|
73
|
-
export interface TagModule {
|
|
74
|
-
allTagsPath: string;
|
|
75
|
-
slug: string;
|
|
76
|
-
name: string;
|
|
77
|
-
count: number;
|
|
78
|
-
permalink: string;
|
|
79
|
-
}
|
|
80
36
|
export declare type BlogBrokenMarkdownLink = BrokenMarkdownLink<BlogContentPaths>;
|
|
81
37
|
export declare type BlogMarkdownLoaderOptions = {
|
|
82
38
|
siteDir: string;
|
|
83
39
|
contentPaths: BlogContentPaths;
|
|
84
40
|
truncateMarker: RegExp;
|
|
85
|
-
sourceToPermalink:
|
|
41
|
+
sourceToPermalink: {
|
|
42
|
+
[aliasedPath: string]: string;
|
|
43
|
+
};
|
|
86
44
|
onBrokenMarkdownLink: (brokenMarkdownLink: BlogBrokenMarkdownLink) => void;
|
|
87
45
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/plugin-content-blog",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.18",
|
|
4
4
|
"description": "Blog plugin for Docusaurus.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "src/plugin-content-blog.d.ts",
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
},
|
|
19
19
|
"license": "MIT",
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@docusaurus/core": "2.0.0-beta.
|
|
22
|
-
"@docusaurus/logger": "2.0.0-beta.
|
|
23
|
-
"@docusaurus/mdx-loader": "2.0.0-beta.
|
|
24
|
-
"@docusaurus/utils": "2.0.0-beta.
|
|
25
|
-
"@docusaurus/utils-common": "2.0.0-beta.
|
|
26
|
-
"@docusaurus/utils-validation": "2.0.0-beta.
|
|
21
|
+
"@docusaurus/core": "2.0.0-beta.18",
|
|
22
|
+
"@docusaurus/logger": "2.0.0-beta.18",
|
|
23
|
+
"@docusaurus/mdx-loader": "2.0.0-beta.18",
|
|
24
|
+
"@docusaurus/utils": "2.0.0-beta.18",
|
|
25
|
+
"@docusaurus/utils-common": "2.0.0-beta.18",
|
|
26
|
+
"@docusaurus/utils-validation": "2.0.0-beta.18",
|
|
27
27
|
"cheerio": "^1.0.0-rc.10",
|
|
28
28
|
"feed": "^4.2.2",
|
|
29
29
|
"fs-extra": "^10.0.1",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"remark-admonitions": "^1.2.1",
|
|
33
33
|
"tslib": "^2.3.1",
|
|
34
34
|
"utility-types": "^3.10.0",
|
|
35
|
-
"webpack": "^5.
|
|
35
|
+
"webpack": "^5.70.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@docusaurus/types": "2.0.0-beta.
|
|
38
|
+
"@docusaurus/types": "2.0.0-beta.18",
|
|
39
39
|
"escape-string-regexp": "^4.0.0"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
@@ -45,5 +45,5 @@
|
|
|
45
45
|
"engines": {
|
|
46
46
|
"node": ">=14"
|
|
47
47
|
},
|
|
48
|
-
"gitHead": "
|
|
48
|
+
"gitHead": "1a945d06993d53376e61bed2c942799fe07dc336"
|
|
49
49
|
}
|
package/src/authors.ts
CHANGED
|
@@ -15,22 +15,33 @@ import type {
|
|
|
15
15
|
BlogPostFrontMatterAuthors,
|
|
16
16
|
} from '@docusaurus/plugin-content-blog';
|
|
17
17
|
|
|
18
|
-
export type AuthorsMap =
|
|
19
|
-
|
|
20
|
-
const AuthorsMapSchema = Joi.object<AuthorsMap>()
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
)
|
|
18
|
+
export type AuthorsMap = {[authorKey: string]: Author};
|
|
19
|
+
|
|
20
|
+
const AuthorsMapSchema = Joi.object<AuthorsMap>()
|
|
21
|
+
.pattern(
|
|
22
|
+
Joi.string(),
|
|
23
|
+
Joi.object({
|
|
24
|
+
name: Joi.string(),
|
|
25
|
+
url: URISchema,
|
|
26
|
+
imageURL: URISchema,
|
|
27
|
+
title: Joi.string(),
|
|
28
|
+
email: Joi.string(),
|
|
29
|
+
})
|
|
30
|
+
.rename('image_url', 'imageURL')
|
|
31
|
+
.or('name', 'imageURL')
|
|
32
|
+
.unknown()
|
|
33
|
+
.required()
|
|
34
|
+
.messages({
|
|
35
|
+
'object.base':
|
|
36
|
+
'{#label} should be an author object containing properties like name, title, and imageURL.',
|
|
37
|
+
'any.required':
|
|
38
|
+
'{#label} cannot be undefined. It should be an author object containing properties like name, title, and imageURL.',
|
|
39
|
+
}),
|
|
40
|
+
)
|
|
41
|
+
.messages({
|
|
42
|
+
'object.base':
|
|
43
|
+
"The authors map file should contain an object where each entry contains an author key and the corresponding author's data.",
|
|
44
|
+
});
|
|
34
45
|
|
|
35
46
|
export function validateAuthorsMap(content: unknown): AuthorsMap {
|
|
36
47
|
return Joi.attempt(content, AuthorsMapSchema);
|
|
@@ -59,7 +70,7 @@ type AuthorsParam = {
|
|
|
59
70
|
// We may want to deprecate those in favor of using only frontMatter.authors
|
|
60
71
|
function getFrontMatterAuthorLegacy(
|
|
61
72
|
frontMatter: BlogPostFrontMatter,
|
|
62
|
-
):
|
|
73
|
+
): Author | undefined {
|
|
63
74
|
const name = frontMatter.author;
|
|
64
75
|
const title = frontMatter.author_title ?? frontMatter.authorTitle;
|
|
65
76
|
const url = frontMatter.author_url ?? frontMatter.authorURL;
|
|
@@ -81,7 +92,7 @@ function normalizeFrontMatterAuthors(
|
|
|
81
92
|
frontMatterAuthors: BlogPostFrontMatterAuthors = [],
|
|
82
93
|
): BlogPostFrontMatterAuthor[] {
|
|
83
94
|
function normalizeAuthor(
|
|
84
|
-
authorInput: string |
|
|
95
|
+
authorInput: string | Author,
|
|
85
96
|
): BlogPostFrontMatterAuthor {
|
|
86
97
|
if (typeof authorInput === 'string') {
|
|
87
98
|
// Technically, we could allow users to provide an author's name here, but
|
package/src/blogUtils.ts
CHANGED
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
getContentPathList,
|
|
32
32
|
} from '@docusaurus/utils';
|
|
33
33
|
import type {LoadContext} from '@docusaurus/types';
|
|
34
|
-
import {validateBlogPostFrontMatter} from './
|
|
34
|
+
import {validateBlogPostFrontMatter} from './frontMatter';
|
|
35
35
|
import {type AuthorsMap, getAuthorsMap, getBlogPostAuthors} from './authors';
|
|
36
36
|
import logger from '@docusaurus/logger';
|
|
37
37
|
import type {
|
|
@@ -43,9 +43,9 @@ export function truncate(fileString: string, truncateMarker: RegExp): string {
|
|
|
43
43
|
return fileString.split(truncateMarker, 1).shift()!;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
export function getSourceToPermalink(
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
export function getSourceToPermalink(blogPosts: BlogPost[]): {
|
|
47
|
+
[aliasedPath: string]: string;
|
|
48
|
+
} {
|
|
49
49
|
return Object.fromEntries(
|
|
50
50
|
blogPosts.map(({metadata: {source, permalink}}) => [source, permalink]),
|
|
51
51
|
);
|
|
@@ -72,7 +72,9 @@ export function paginateBlogPosts({
|
|
|
72
72
|
const pages: BlogPaginated[] = [];
|
|
73
73
|
|
|
74
74
|
function permalink(page: number) {
|
|
75
|
-
return page > 0
|
|
75
|
+
return page > 0
|
|
76
|
+
? normalizeUrl([basePageUrl, `page/${page + 1}`])
|
|
77
|
+
: basePageUrl;
|
|
76
78
|
}
|
|
77
79
|
|
|
78
80
|
for (let page = 0; page < numberOfPages; page += 1) {
|
|
@@ -86,8 +88,8 @@ export function paginateBlogPosts({
|
|
|
86
88
|
postsPerPage,
|
|
87
89
|
totalPages: numberOfPages,
|
|
88
90
|
totalCount,
|
|
89
|
-
previousPage: page !== 0 ? permalink(page - 1) :
|
|
90
|
-
nextPage: page < numberOfPages - 1 ? permalink(page + 1) :
|
|
91
|
+
previousPage: page !== 0 ? permalink(page - 1) : undefined,
|
|
92
|
+
nextPage: page < numberOfPages - 1 ? permalink(page + 1) : undefined,
|
|
91
93
|
blogDescription,
|
|
92
94
|
blogTitle,
|
|
93
95
|
},
|
|
@@ -139,10 +141,10 @@ export function parseBlogFileName(
|
|
|
139
141
|
if (dateFilenameMatch) {
|
|
140
142
|
const {folder, text, date: dateString} = dateFilenameMatch.groups!;
|
|
141
143
|
// Always treat dates as UTC by adding the `Z`
|
|
142
|
-
const date = new Date(`${dateString}Z`);
|
|
143
|
-
const slugDate = dateString
|
|
144
|
-
const slug = `/${slugDate}/${folder}${text}`;
|
|
145
|
-
return {date, text
|
|
144
|
+
const date = new Date(`${dateString!}Z`);
|
|
145
|
+
const slugDate = dateString!.replace(/-/g, '/');
|
|
146
|
+
const slug = `/${slugDate}/${folder!}${text!}`;
|
|
147
|
+
return {date, text: text!, slug};
|
|
146
148
|
}
|
|
147
149
|
const text = blogSourceRelative.replace(/(?:\/index)?\.mdx?$/, '');
|
|
148
150
|
const slug = `/${text}`;
|
|
@@ -245,7 +247,7 @@ async function processBlogSourceFile(
|
|
|
245
247
|
});
|
|
246
248
|
return result.date;
|
|
247
249
|
} catch (err) {
|
|
248
|
-
logger.
|
|
250
|
+
logger.warn(err);
|
|
249
251
|
return (await fs.stat(blogSourceAbsolute)).birthtime;
|
|
250
252
|
}
|
|
251
253
|
}
|