@docusaurus/plugin-content-blog 3.4.0 → 3.5.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/assets/atom.css +75 -0
- package/assets/atom.xsl +92 -0
- package/assets/rss.css +75 -0
- package/assets/rss.xsl +86 -0
- package/lib/authors.d.ts +9 -11
- package/lib/authors.js +42 -64
- package/lib/authorsMap.d.ts +23 -0
- package/lib/authorsMap.js +116 -0
- package/lib/authorsProblems.d.ts +21 -0
- package/lib/authorsProblems.js +51 -0
- package/lib/authorsSocials.d.ts +10 -0
- package/lib/authorsSocials.js +48 -0
- package/lib/blogUtils.d.ts +6 -3
- package/lib/blogUtils.js +29 -14
- package/lib/client/contexts.d.ts +33 -0
- package/lib/client/contexts.js +54 -0
- package/lib/client/index.d.ts +3 -3
- package/lib/client/index.js +3 -9
- package/lib/client/sidebarUtils.d.ts +21 -0
- package/lib/client/sidebarUtils.js +49 -0
- package/lib/client/sidebarUtils.test.d.ts +7 -0
- package/lib/client/sidebarUtils.test.js +43 -0
- package/lib/client/structuredDataUtils.d.ts +10 -0
- package/lib/client/structuredDataUtils.js +122 -0
- package/lib/feed.d.ts +3 -2
- package/lib/feed.js +69 -21
- package/lib/frontMatter.d.ts +0 -1
- package/lib/frontMatter.js +3 -2
- package/lib/index.d.ts +0 -1
- package/lib/index.js +23 -4
- package/lib/markdownLoader.js +1 -1
- package/lib/options.d.ts +4 -1
- package/lib/options.js +98 -26
- package/lib/props.d.ts +9 -2
- package/lib/props.js +21 -3
- package/lib/remark/footnoteIDFixer.js +1 -1
- package/lib/routes.d.ts +0 -1
- package/lib/routes.js +82 -14
- package/lib/translations.d.ts +0 -1
- package/lib/translations.js +2 -3
- package/package.json +13 -10
- package/src/authors.ts +56 -93
- package/src/authorsMap.ts +171 -0
- package/src/authorsProblems.ts +72 -0
- package/src/authorsSocials.ts +64 -0
- package/src/blogUtils.ts +34 -7
- package/src/client/contexts.tsx +95 -0
- package/src/client/index.tsx +24 -0
- package/src/client/sidebarUtils.test.ts +52 -0
- package/src/client/sidebarUtils.tsx +85 -0
- package/src/client/structuredDataUtils.ts +178 -0
- package/src/feed.ts +140 -17
- package/src/frontMatter.ts +2 -0
- package/src/index.ts +31 -1
- package/src/options.ts +123 -32
- package/src/plugin-content-blog.d.ts +150 -12
- package/src/props.ts +39 -1
- package/src/routes.ts +102 -12
- package/src/client/index.ts +0 -20
package/lib/feed.js
CHANGED
|
@@ -6,16 +6,17 @@
|
|
|
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.createBlogFeedFiles = createBlogFeedFiles;
|
|
10
|
+
exports.createFeedHtmlHeadTags = createFeedHtmlHeadTags;
|
|
10
11
|
const tslib_1 = require("tslib");
|
|
11
12
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
12
13
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
13
|
-
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
14
14
|
const feed_1 = require("feed");
|
|
15
15
|
const srcset = tslib_1.__importStar(require("srcset"));
|
|
16
16
|
const utils_1 = require("@docusaurus/utils");
|
|
17
17
|
const utils_common_1 = require("@docusaurus/utils-common");
|
|
18
18
|
const cheerio_1 = require("cheerio");
|
|
19
|
+
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
19
20
|
async function generateBlogFeed({ blogPosts, options, siteConfig, outDir, locale, }) {
|
|
20
21
|
if (!blogPosts.length) {
|
|
21
22
|
return null;
|
|
@@ -105,25 +106,72 @@ async function defaultCreateFeedItems({ blogPosts, siteConfig, outDir, }) {
|
|
|
105
106
|
return feedItem;
|
|
106
107
|
}));
|
|
107
108
|
}
|
|
108
|
-
async function
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
|
|
109
|
+
async function resolveXsltFilePaths({ xsltFilePath, contentPaths, }) {
|
|
110
|
+
const xsltAbsolutePath = path_1.default.isAbsolute(xsltFilePath)
|
|
111
|
+
? xsltFilePath
|
|
112
|
+
: (await (0, utils_1.getDataFilePath)({ filePath: xsltFilePath, contentPaths })) ??
|
|
113
|
+
path_1.default.resolve(contentPaths.contentPath, xsltFilePath);
|
|
114
|
+
if (!(await fs_extra_1.default.pathExists(xsltAbsolutePath))) {
|
|
115
|
+
throw new Error(logger_1.default.interpolate `Blog feed XSLT file not found at path=${path_1.default.relative(process.cwd(), xsltAbsolutePath)}`);
|
|
116
|
+
}
|
|
117
|
+
const parsedPath = path_1.default.parse(xsltAbsolutePath);
|
|
118
|
+
const cssAbsolutePath = path_1.default.resolve(parsedPath.dir, `${parsedPath.name}.css`);
|
|
119
|
+
if (!(await fs_extra_1.default.pathExists(xsltAbsolutePath))) {
|
|
120
|
+
throw new Error(logger_1.default.interpolate `Blog feed XSLT file was found at path=${path_1.default.relative(process.cwd(), xsltAbsolutePath)}
|
|
121
|
+
But its expected co-located CSS file could not be found at path=${path_1.default.relative(process.cwd(), cssAbsolutePath)}
|
|
122
|
+
If you want to provide a custom XSLT file, you must provide a CSS file with the exact same name.`);
|
|
123
|
+
}
|
|
124
|
+
return { xsltAbsolutePath, cssAbsolutePath };
|
|
125
|
+
}
|
|
126
|
+
async function generateXsltFiles({ xsltFilePath, generatePath, contentPaths, }) {
|
|
127
|
+
const { xsltAbsolutePath, cssAbsolutePath } = await resolveXsltFilePaths({
|
|
128
|
+
xsltFilePath,
|
|
129
|
+
contentPaths,
|
|
130
|
+
});
|
|
131
|
+
const xsltOutputPath = path_1.default.join(generatePath, path_1.default.basename(xsltAbsolutePath));
|
|
132
|
+
const cssOutputPath = path_1.default.join(generatePath, path_1.default.basename(cssAbsolutePath));
|
|
133
|
+
await fs_extra_1.default.copy(xsltAbsolutePath, xsltOutputPath);
|
|
134
|
+
await fs_extra_1.default.copy(cssAbsolutePath, cssOutputPath);
|
|
135
|
+
}
|
|
136
|
+
// This modifies the XML feed content to add a relative href to the XSLT file
|
|
137
|
+
// Good enough for now: we probably don't need a full XML parser just for that
|
|
138
|
+
// See also https://darekkay.com/blog/rss-styling/
|
|
139
|
+
function injectXslt({ feedContent, xsltFilePath, }) {
|
|
140
|
+
return feedContent.replace('<?xml version="1.0" encoding="utf-8"?>', `<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type="text/xsl" href="${path_1.default.basename(xsltFilePath)}"?>`);
|
|
141
|
+
}
|
|
142
|
+
const FeedConfigs = {
|
|
143
|
+
rss: {
|
|
144
|
+
outputFileName: 'rss.xml',
|
|
145
|
+
getContent: (feed) => feed.rss2(),
|
|
146
|
+
getXsltFilePath: (xslt) => xslt.rss,
|
|
147
|
+
},
|
|
148
|
+
atom: {
|
|
149
|
+
outputFileName: 'atom.xml',
|
|
150
|
+
getContent: (feed) => feed.atom1(),
|
|
151
|
+
getXsltFilePath: (xslt) => xslt.atom,
|
|
152
|
+
},
|
|
153
|
+
json: {
|
|
154
|
+
outputFileName: 'feed.json',
|
|
155
|
+
getContent: (feed) => feed.json1(),
|
|
156
|
+
getXsltFilePath: () => null,
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
async function createBlogFeedFile({ feed, feedType, generatePath, feedOptions, contentPaths, }) {
|
|
121
160
|
try {
|
|
122
|
-
|
|
161
|
+
const feedConfig = FeedConfigs[feedType];
|
|
162
|
+
let feedContent = feedConfig.getContent(feed);
|
|
163
|
+
const xsltFilePath = feedConfig.getXsltFilePath(feedOptions.xslt);
|
|
164
|
+
if (xsltFilePath) {
|
|
165
|
+
await generateXsltFiles({ xsltFilePath, contentPaths, generatePath });
|
|
166
|
+
feedContent = injectXslt({ feedContent, xsltFilePath });
|
|
167
|
+
}
|
|
168
|
+
const outputPath = path_1.default.join(generatePath, feedConfig.outputFileName);
|
|
169
|
+
await fs_extra_1.default.outputFile(outputPath, feedContent);
|
|
123
170
|
}
|
|
124
171
|
catch (err) {
|
|
125
|
-
|
|
126
|
-
|
|
172
|
+
throw new Error(`Generating ${feedType} feed failed.`, {
|
|
173
|
+
cause: err,
|
|
174
|
+
});
|
|
127
175
|
}
|
|
128
176
|
}
|
|
129
177
|
function shouldBeInFeed(blogPost) {
|
|
@@ -131,7 +179,7 @@ function shouldBeInFeed(blogPost) {
|
|
|
131
179
|
blogPost.metadata.frontMatter.unlisted;
|
|
132
180
|
return !excluded;
|
|
133
181
|
}
|
|
134
|
-
async function createBlogFeedFiles({ blogPosts: allBlogPosts, options, siteConfig, outDir, locale, }) {
|
|
182
|
+
async function createBlogFeedFiles({ blogPosts: allBlogPosts, options, siteConfig, outDir, locale, contentPaths, }) {
|
|
135
183
|
const blogPosts = allBlogPosts.filter(shouldBeInFeed);
|
|
136
184
|
const feed = await generateBlogFeed({
|
|
137
185
|
blogPosts,
|
|
@@ -148,9 +196,10 @@ async function createBlogFeedFiles({ blogPosts: allBlogPosts, options, siteConfi
|
|
|
148
196
|
feed,
|
|
149
197
|
feedType,
|
|
150
198
|
generatePath: path_1.default.join(outDir, options.routeBasePath),
|
|
199
|
+
feedOptions: options.feedOptions,
|
|
200
|
+
contentPaths,
|
|
151
201
|
})));
|
|
152
202
|
}
|
|
153
|
-
exports.createBlogFeedFiles = createBlogFeedFiles;
|
|
154
203
|
function createFeedHtmlHeadTags({ context, options, }) {
|
|
155
204
|
const feedTypes = options.feedOptions.type;
|
|
156
205
|
if (!feedTypes) {
|
|
@@ -193,4 +242,3 @@ function createFeedHtmlHeadTags({ context, options, }) {
|
|
|
193
242
|
});
|
|
194
243
|
return headTags;
|
|
195
244
|
}
|
|
196
|
-
exports.createFeedHtmlHeadTags = createFeedHtmlHeadTags;
|
package/lib/frontMatter.d.ts
CHANGED
package/lib/frontMatter.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.validateBlogPostFrontMatter =
|
|
3
|
+
exports.validateBlogPostFrontMatter = validateBlogPostFrontMatter;
|
|
4
4
|
/**
|
|
5
5
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
6
6
|
*
|
|
@@ -8,12 +8,14 @@ exports.validateBlogPostFrontMatter = void 0;
|
|
|
8
8
|
* LICENSE file in the root directory of this source tree.
|
|
9
9
|
*/
|
|
10
10
|
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
11
|
+
const authorsSocials_1 = require("./authorsSocials");
|
|
11
12
|
const BlogPostFrontMatterAuthorSchema = utils_validation_1.JoiFrontMatter.object({
|
|
12
13
|
key: utils_validation_1.JoiFrontMatter.string(),
|
|
13
14
|
name: utils_validation_1.JoiFrontMatter.string(),
|
|
14
15
|
title: utils_validation_1.JoiFrontMatter.string(),
|
|
15
16
|
url: utils_validation_1.URISchema,
|
|
16
17
|
imageURL: utils_validation_1.JoiFrontMatter.string(),
|
|
18
|
+
socials: authorsSocials_1.AuthorSocialsSchema,
|
|
17
19
|
})
|
|
18
20
|
.or('key', 'name', 'imageURL')
|
|
19
21
|
.rename('image_url', 'imageURL', { alias: true });
|
|
@@ -61,4 +63,3 @@ const BlogFrontMatterSchema = utils_validation_1.JoiFrontMatter.object({
|
|
|
61
63
|
function validateBlogPostFrontMatter(frontMatter) {
|
|
62
64
|
return (0, utils_validation_1.validateFrontMatter)(frontMatter, BlogFrontMatterSchema);
|
|
63
65
|
}
|
|
64
|
-
exports.validateBlogPostFrontMatter = validateBlogPostFrontMatter;
|
package/lib/index.d.ts
CHANGED
|
@@ -4,7 +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" />
|
|
8
7
|
import type { LoadContext, Plugin } from '@docusaurus/types';
|
|
9
8
|
import type { PluginOptions, BlogContent } from '@docusaurus/plugin-content-blog';
|
|
10
9
|
export default function pluginContentBlog(context: LoadContext, options: PluginOptions): Promise<Plugin<BlogContent>>;
|
package/lib/index.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.validateOptions = void 0;
|
|
10
|
+
exports.default = pluginContentBlog;
|
|
10
11
|
const tslib_1 = require("tslib");
|
|
11
12
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
12
13
|
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
@@ -17,6 +18,7 @@ const footnoteIDFixer_1 = tslib_1.__importDefault(require("./remark/footnoteIDFi
|
|
|
17
18
|
const translations_1 = require("./translations");
|
|
18
19
|
const feed_1 = require("./feed");
|
|
19
20
|
const routes_1 = require("./routes");
|
|
21
|
+
const authorsMap_1 = require("./authorsMap");
|
|
20
22
|
const PluginName = 'docusaurus-plugin-content-blog';
|
|
21
23
|
// TODO this is bad, we should have a better way to do this (new lifecycle?)
|
|
22
24
|
// The source to permalink is currently a mutable map passed to the mdx loader
|
|
@@ -87,14 +89,28 @@ async function pluginContentBlog(context, options) {
|
|
|
87
89
|
},
|
|
88
90
|
// Fetches blog contents and returns metadata for the necessary routes.
|
|
89
91
|
async loadContent() {
|
|
90
|
-
const { postsPerPage: postsPerPageOption, routeBasePath, tagsBasePath, blogDescription, blogTitle, blogSidebarTitle, pageBasePath, } = options;
|
|
92
|
+
const { postsPerPage: postsPerPageOption, routeBasePath, tagsBasePath, blogDescription, blogTitle, blogSidebarTitle, pageBasePath, authorsBasePath, authorsMapPath, } = options;
|
|
91
93
|
const baseBlogUrl = (0, utils_1.normalizeUrl)([baseUrl, routeBasePath]);
|
|
92
94
|
const blogTagsListPath = (0, utils_1.normalizeUrl)([baseBlogUrl, tagsBasePath]);
|
|
93
|
-
|
|
95
|
+
const authorsMap = await (0, authorsMap_1.getAuthorsMap)({
|
|
96
|
+
contentPaths,
|
|
97
|
+
authorsMapPath,
|
|
98
|
+
authorsBaseRoutePath: (0, utils_1.normalizeUrl)([
|
|
99
|
+
baseUrl,
|
|
100
|
+
routeBasePath,
|
|
101
|
+
authorsBasePath,
|
|
102
|
+
]),
|
|
103
|
+
});
|
|
104
|
+
(0, authorsMap_1.checkAuthorsMapPermalinkCollisions)(authorsMap);
|
|
105
|
+
let blogPosts = await (0, blogUtils_1.generateBlogPosts)(contentPaths, context, options, authorsMap);
|
|
94
106
|
blogPosts = await (0, blogUtils_1.applyProcessBlogPosts)({
|
|
95
107
|
blogPosts,
|
|
96
108
|
processBlogPosts: options.processBlogPosts,
|
|
97
109
|
});
|
|
110
|
+
(0, blogUtils_1.reportUntruncatedBlogPosts)({
|
|
111
|
+
blogPosts,
|
|
112
|
+
onUntruncatedBlogPosts: options.onUntruncatedBlogPosts,
|
|
113
|
+
});
|
|
98
114
|
const listedBlogPosts = blogPosts.filter(blogUtils_1.shouldBeListed);
|
|
99
115
|
if (!blogPosts.length) {
|
|
100
116
|
return {
|
|
@@ -103,6 +119,7 @@ async function pluginContentBlog(context, options) {
|
|
|
103
119
|
blogListPaginated: [],
|
|
104
120
|
blogTags: {},
|
|
105
121
|
blogTagsListPath,
|
|
122
|
+
authorsMap,
|
|
106
123
|
};
|
|
107
124
|
}
|
|
108
125
|
// Collocate next and prev metadata.
|
|
@@ -145,6 +162,7 @@ async function pluginContentBlog(context, options) {
|
|
|
145
162
|
blogListPaginated,
|
|
146
163
|
blogTags,
|
|
147
164
|
blogTagsListPath,
|
|
165
|
+
authorsMap,
|
|
148
166
|
};
|
|
149
167
|
},
|
|
150
168
|
async contentLoaded({ content, actions }) {
|
|
@@ -161,13 +179,14 @@ async function pluginContentBlog(context, options) {
|
|
|
161
179
|
return (0, translations_1.translateContent)(content, translationFiles);
|
|
162
180
|
},
|
|
163
181
|
configureWebpack() {
|
|
164
|
-
const { admonitions, rehypePlugins, remarkPlugins, truncateMarker, beforeDefaultRemarkPlugins, beforeDefaultRehypePlugins, } = options;
|
|
182
|
+
const { admonitions, rehypePlugins, remarkPlugins, recmaPlugins, truncateMarker, beforeDefaultRemarkPlugins, beforeDefaultRehypePlugins, } = options;
|
|
165
183
|
const contentDirs = (0, utils_1.getContentPathList)(contentPaths);
|
|
166
184
|
function createMDXLoader() {
|
|
167
185
|
const loaderOptions = {
|
|
168
186
|
admonitions,
|
|
169
187
|
remarkPlugins,
|
|
170
188
|
rehypePlugins,
|
|
189
|
+
recmaPlugins,
|
|
171
190
|
beforeDefaultRemarkPlugins: [
|
|
172
191
|
footnoteIDFixer_1.default,
|
|
173
192
|
...beforeDefaultRemarkPlugins,
|
|
@@ -251,6 +270,7 @@ async function pluginContentBlog(context, options) {
|
|
|
251
270
|
outDir,
|
|
252
271
|
siteConfig,
|
|
253
272
|
locale: currentLocale,
|
|
273
|
+
contentPaths,
|
|
254
274
|
});
|
|
255
275
|
},
|
|
256
276
|
injectHtmlTags({ content }) {
|
|
@@ -263,6 +283,5 @@ async function pluginContentBlog(context, options) {
|
|
|
263
283
|
},
|
|
264
284
|
};
|
|
265
285
|
}
|
|
266
|
-
exports.default = pluginContentBlog;
|
|
267
286
|
var options_1 = require("./options");
|
|
268
287
|
Object.defineProperty(exports, "validateOptions", { enumerable: true, get: function () { return options_1.validateOptions; } });
|
package/lib/markdownLoader.js
CHANGED
|
@@ -6,6 +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.default = markdownLoader;
|
|
9
10
|
const blogUtils_1 = require("./blogUtils");
|
|
10
11
|
function markdownLoader(source) {
|
|
11
12
|
const fileString = source;
|
|
@@ -23,4 +24,3 @@ function markdownLoader(source) {
|
|
|
23
24
|
}
|
|
24
25
|
return callback(null, finalContent);
|
|
25
26
|
}
|
|
26
|
-
exports.default = markdownLoader;
|
package/lib/options.d.ts
CHANGED
|
@@ -4,8 +4,11 @@
|
|
|
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" />
|
|
8
7
|
import type { PluginOptions, Options } from '@docusaurus/plugin-content-blog';
|
|
9
8
|
import type { OptionValidationContext } from '@docusaurus/types';
|
|
10
9
|
export declare const DEFAULT_OPTIONS: PluginOptions;
|
|
10
|
+
export declare const XSLTBuiltInPaths: {
|
|
11
|
+
rss: string;
|
|
12
|
+
atom: string;
|
|
13
|
+
};
|
|
11
14
|
export declare function validateOptions({ validate, options, }: OptionValidationContext<Options | undefined, PluginOptions>): PluginOptions;
|
package/lib/options.js
CHANGED
|
@@ -6,20 +6,34 @@
|
|
|
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.XSLTBuiltInPaths = exports.DEFAULT_OPTIONS = void 0;
|
|
10
|
+
exports.validateOptions = validateOptions;
|
|
11
|
+
const tslib_1 = require("tslib");
|
|
12
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
10
13
|
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
11
14
|
const utils_1 = require("@docusaurus/utils");
|
|
12
15
|
exports.DEFAULT_OPTIONS = {
|
|
13
|
-
feedOptions: {
|
|
16
|
+
feedOptions: {
|
|
17
|
+
type: ['rss', 'atom'],
|
|
18
|
+
copyright: '',
|
|
19
|
+
limit: 20,
|
|
20
|
+
xslt: {
|
|
21
|
+
rss: null,
|
|
22
|
+
atom: null,
|
|
23
|
+
},
|
|
24
|
+
},
|
|
14
25
|
beforeDefaultRehypePlugins: [],
|
|
15
26
|
beforeDefaultRemarkPlugins: [],
|
|
16
27
|
admonitions: true,
|
|
17
28
|
truncateMarker: /<!--\s*truncate\s*-->|\{\/\*\s*truncate\s*\*\/\}/,
|
|
18
29
|
rehypePlugins: [],
|
|
19
30
|
remarkPlugins: [],
|
|
31
|
+
recmaPlugins: [],
|
|
20
32
|
showReadingTime: true,
|
|
21
33
|
blogTagsPostsComponent: '@theme/BlogTagsPostsPage',
|
|
22
34
|
blogTagsListComponent: '@theme/BlogTagsListPage',
|
|
35
|
+
blogAuthorsPostsComponent: '@theme/Blog/Pages/BlogAuthorsPostsPage',
|
|
36
|
+
blogAuthorsListComponent: '@theme/Blog/Pages/BlogAuthorsListPage',
|
|
23
37
|
blogPostComponent: '@theme/BlogPostPage',
|
|
24
38
|
blogListComponent: '@theme/BlogListPage',
|
|
25
39
|
blogArchiveComponent: '@theme/BlogArchivePage',
|
|
@@ -44,7 +58,76 @@ exports.DEFAULT_OPTIONS = {
|
|
|
44
58
|
processBlogPosts: async () => undefined,
|
|
45
59
|
onInlineTags: 'warn',
|
|
46
60
|
tags: undefined,
|
|
61
|
+
authorsBasePath: 'authors',
|
|
62
|
+
onInlineAuthors: 'warn',
|
|
63
|
+
onUntruncatedBlogPosts: 'warn',
|
|
64
|
+
};
|
|
65
|
+
exports.XSLTBuiltInPaths = {
|
|
66
|
+
rss: path_1.default.resolve(__dirname, '..', 'assets', 'rss.xsl'),
|
|
67
|
+
atom: path_1.default.resolve(__dirname, '..', 'assets', 'atom.xsl'),
|
|
47
68
|
};
|
|
69
|
+
function normalizeXsltOption(option, type) {
|
|
70
|
+
if (typeof option === 'string') {
|
|
71
|
+
return option;
|
|
72
|
+
}
|
|
73
|
+
if (option === true) {
|
|
74
|
+
return exports.XSLTBuiltInPaths[type];
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
function createXSLTFilePathSchema(type) {
|
|
79
|
+
return utils_validation_1.Joi.alternatives()
|
|
80
|
+
.try(utils_validation_1.Joi.string().required(), utils_validation_1.Joi.boolean()
|
|
81
|
+
.allow(null, () => undefined)
|
|
82
|
+
.custom((val) => normalizeXsltOption(val, type)))
|
|
83
|
+
.optional()
|
|
84
|
+
.default(null);
|
|
85
|
+
}
|
|
86
|
+
const FeedXSLTOptionsSchema = utils_validation_1.Joi.alternatives()
|
|
87
|
+
.try(utils_validation_1.Joi.object({
|
|
88
|
+
rss: createXSLTFilePathSchema('rss'),
|
|
89
|
+
atom: createXSLTFilePathSchema('atom'),
|
|
90
|
+
}).required(), utils_validation_1.Joi.boolean()
|
|
91
|
+
.allow(null, () => undefined)
|
|
92
|
+
.custom((val) => ({
|
|
93
|
+
rss: normalizeXsltOption(val, 'rss'),
|
|
94
|
+
atom: normalizeXsltOption(val, 'atom'),
|
|
95
|
+
})))
|
|
96
|
+
.optional()
|
|
97
|
+
.custom((val) => {
|
|
98
|
+
if (val === null) {
|
|
99
|
+
return {
|
|
100
|
+
rss: null,
|
|
101
|
+
atom: null,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
return val;
|
|
105
|
+
})
|
|
106
|
+
.default(exports.DEFAULT_OPTIONS.feedOptions.xslt);
|
|
107
|
+
const FeedOptionsSchema = utils_validation_1.Joi.object({
|
|
108
|
+
type: utils_validation_1.Joi.alternatives()
|
|
109
|
+
.try(utils_validation_1.Joi.array().items(utils_validation_1.Joi.string().equal('rss', 'atom', 'json')), utils_validation_1.Joi.alternatives().conditional(utils_validation_1.Joi.string().equal('all', 'rss', 'atom', 'json'), {
|
|
110
|
+
then: utils_validation_1.Joi.custom((val) => val === 'all' ? ['rss', 'atom', 'json'] : [val]),
|
|
111
|
+
}))
|
|
112
|
+
.allow(null)
|
|
113
|
+
.default(exports.DEFAULT_OPTIONS.feedOptions.type),
|
|
114
|
+
xslt: FeedXSLTOptionsSchema,
|
|
115
|
+
title: utils_validation_1.Joi.string().allow(''),
|
|
116
|
+
description: utils_validation_1.Joi.string().allow(''),
|
|
117
|
+
// Only add default value when user actually wants a feed (type is not null)
|
|
118
|
+
copyright: utils_validation_1.Joi.when('type', {
|
|
119
|
+
is: utils_validation_1.Joi.any().valid(null),
|
|
120
|
+
then: utils_validation_1.Joi.string().optional(),
|
|
121
|
+
otherwise: utils_validation_1.Joi.string()
|
|
122
|
+
.allow('')
|
|
123
|
+
.default(exports.DEFAULT_OPTIONS.feedOptions.copyright),
|
|
124
|
+
}),
|
|
125
|
+
language: utils_validation_1.Joi.string(),
|
|
126
|
+
createFeedItems: utils_validation_1.Joi.function(),
|
|
127
|
+
limit: utils_validation_1.Joi.alternatives()
|
|
128
|
+
.try(utils_validation_1.Joi.number(), utils_validation_1.Joi.valid(null), utils_validation_1.Joi.valid(false))
|
|
129
|
+
.default(exports.DEFAULT_OPTIONS.feedOptions.limit),
|
|
130
|
+
}).default(exports.DEFAULT_OPTIONS.feedOptions);
|
|
48
131
|
const PluginOptionSchema = utils_validation_1.Joi.object({
|
|
49
132
|
path: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.path),
|
|
50
133
|
archiveBasePath: utils_validation_1.Joi.string()
|
|
@@ -62,6 +145,8 @@ const PluginOptionSchema = utils_validation_1.Joi.object({
|
|
|
62
145
|
blogPostComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogPostComponent),
|
|
63
146
|
blogTagsListComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogTagsListComponent),
|
|
64
147
|
blogTagsPostsComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogTagsPostsComponent),
|
|
148
|
+
blogAuthorsPostsComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogAuthorsPostsComponent),
|
|
149
|
+
blogAuthorsListComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogAuthorsListComponent),
|
|
65
150
|
blogArchiveComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogArchiveComponent),
|
|
66
151
|
blogTitle: utils_validation_1.Joi.string().allow('').default(exports.DEFAULT_OPTIONS.blogTitle),
|
|
67
152
|
blogDescription: utils_validation_1.Joi.string()
|
|
@@ -74,35 +159,14 @@ const PluginOptionSchema = utils_validation_1.Joi.object({
|
|
|
74
159
|
showReadingTime: utils_validation_1.Joi.bool().default(exports.DEFAULT_OPTIONS.showReadingTime),
|
|
75
160
|
remarkPlugins: utils_validation_1.RemarkPluginsSchema.default(exports.DEFAULT_OPTIONS.remarkPlugins),
|
|
76
161
|
rehypePlugins: utils_validation_1.RehypePluginsSchema.default(exports.DEFAULT_OPTIONS.rehypePlugins),
|
|
162
|
+
recmaPlugins: utils_validation_1.RecmaPluginsSchema.default(exports.DEFAULT_OPTIONS.recmaPlugins),
|
|
77
163
|
admonitions: utils_validation_1.AdmonitionsSchema.default(exports.DEFAULT_OPTIONS.admonitions),
|
|
78
164
|
editUrl: utils_validation_1.Joi.alternatives().try(utils_validation_1.URISchema, utils_validation_1.Joi.function()),
|
|
79
165
|
editLocalizedFiles: utils_validation_1.Joi.boolean().default(exports.DEFAULT_OPTIONS.editLocalizedFiles),
|
|
80
166
|
truncateMarker: utils_validation_1.Joi.object().default(exports.DEFAULT_OPTIONS.truncateMarker),
|
|
81
167
|
beforeDefaultRemarkPlugins: utils_validation_1.RemarkPluginsSchema.default(exports.DEFAULT_OPTIONS.beforeDefaultRemarkPlugins),
|
|
82
168
|
beforeDefaultRehypePlugins: utils_validation_1.RehypePluginsSchema.default(exports.DEFAULT_OPTIONS.beforeDefaultRehypePlugins),
|
|
83
|
-
feedOptions:
|
|
84
|
-
type: utils_validation_1.Joi.alternatives()
|
|
85
|
-
.try(utils_validation_1.Joi.array().items(utils_validation_1.Joi.string().equal('rss', 'atom', 'json')), utils_validation_1.Joi.alternatives().conditional(utils_validation_1.Joi.string().equal('all', 'rss', 'atom', 'json'), {
|
|
86
|
-
then: utils_validation_1.Joi.custom((val) => val === 'all' ? ['rss', 'atom', 'json'] : [val]),
|
|
87
|
-
}))
|
|
88
|
-
.allow(null)
|
|
89
|
-
.default(exports.DEFAULT_OPTIONS.feedOptions.type),
|
|
90
|
-
title: utils_validation_1.Joi.string().allow(''),
|
|
91
|
-
description: utils_validation_1.Joi.string().allow(''),
|
|
92
|
-
// Only add default value when user actually wants a feed (type is not null)
|
|
93
|
-
copyright: utils_validation_1.Joi.when('type', {
|
|
94
|
-
is: utils_validation_1.Joi.any().valid(null),
|
|
95
|
-
then: utils_validation_1.Joi.string().optional(),
|
|
96
|
-
otherwise: utils_validation_1.Joi.string()
|
|
97
|
-
.allow('')
|
|
98
|
-
.default(exports.DEFAULT_OPTIONS.feedOptions.copyright),
|
|
99
|
-
}),
|
|
100
|
-
language: utils_validation_1.Joi.string(),
|
|
101
|
-
createFeedItems: utils_validation_1.Joi.function(),
|
|
102
|
-
limit: utils_validation_1.Joi.alternatives()
|
|
103
|
-
.try(utils_validation_1.Joi.number(), utils_validation_1.Joi.valid(null), utils_validation_1.Joi.valid(false))
|
|
104
|
-
.default(exports.DEFAULT_OPTIONS.feedOptions.limit),
|
|
105
|
-
}).default(exports.DEFAULT_OPTIONS.feedOptions),
|
|
169
|
+
feedOptions: FeedOptionsSchema,
|
|
106
170
|
authorsMapPath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.authorsMapPath),
|
|
107
171
|
readingTime: utils_validation_1.Joi.function().default(() => exports.DEFAULT_OPTIONS.readingTime),
|
|
108
172
|
sortPosts: utils_validation_1.Joi.string()
|
|
@@ -120,9 +184,17 @@ const PluginOptionSchema = utils_validation_1.Joi.object({
|
|
|
120
184
|
.disallow('')
|
|
121
185
|
.allow(null, false)
|
|
122
186
|
.default(() => exports.DEFAULT_OPTIONS.tags),
|
|
187
|
+
authorsBasePath: utils_validation_1.Joi.string()
|
|
188
|
+
.default(exports.DEFAULT_OPTIONS.authorsBasePath)
|
|
189
|
+
.disallow(''),
|
|
190
|
+
onInlineAuthors: utils_validation_1.Joi.string()
|
|
191
|
+
.equal('ignore', 'log', 'warn', 'throw')
|
|
192
|
+
.default(exports.DEFAULT_OPTIONS.onInlineAuthors),
|
|
193
|
+
onUntruncatedBlogPosts: utils_validation_1.Joi.string()
|
|
194
|
+
.equal('ignore', 'log', 'warn', 'throw')
|
|
195
|
+
.default(exports.DEFAULT_OPTIONS.onUntruncatedBlogPosts),
|
|
123
196
|
}).default(exports.DEFAULT_OPTIONS);
|
|
124
197
|
function validateOptions({ validate, options, }) {
|
|
125
198
|
const validatedOptions = validate(PluginOptionSchema, options);
|
|
126
199
|
return validatedOptions;
|
|
127
200
|
}
|
|
128
|
-
exports.validateOptions = validateOptions;
|
package/lib/props.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/// <reference path="../src/plugin-content-blog.d.ts" />
|
|
2
1
|
/**
|
|
3
2
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4
3
|
*
|
|
@@ -6,7 +5,7 @@
|
|
|
6
5
|
* LICENSE file in the root directory of this source tree.
|
|
7
6
|
*/
|
|
8
7
|
import type { TagsListItem, TagModule } from '@docusaurus/utils';
|
|
9
|
-
import type { BlogTag, BlogTags } from '@docusaurus/plugin-content-blog';
|
|
8
|
+
import type { AuthorItemProp, AuthorWithKey, BlogPost, BlogSidebar, BlogTag, BlogTags } from '@docusaurus/plugin-content-blog';
|
|
10
9
|
export declare function toTagsProp({ blogTags }: {
|
|
11
10
|
blogTags: BlogTags;
|
|
12
11
|
}): TagsListItem[];
|
|
@@ -14,3 +13,11 @@ export declare function toTagProp({ blogTagsListPath, tag, }: {
|
|
|
14
13
|
blogTagsListPath: string;
|
|
15
14
|
tag: BlogTag;
|
|
16
15
|
}): TagModule;
|
|
16
|
+
export declare function toAuthorItemProp({ author, count, }: {
|
|
17
|
+
author: AuthorWithKey;
|
|
18
|
+
count: number;
|
|
19
|
+
}): AuthorItemProp;
|
|
20
|
+
export declare function toBlogSidebarProp({ blogSidebarTitle, blogPosts, }: {
|
|
21
|
+
blogSidebarTitle: string;
|
|
22
|
+
blogPosts: BlogPost[];
|
|
23
|
+
}): BlogSidebar;
|
package/lib/props.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.toTagsProp = toTagsProp;
|
|
4
|
+
exports.toTagProp = toTagProp;
|
|
5
|
+
exports.toAuthorItemProp = toAuthorItemProp;
|
|
6
|
+
exports.toBlogSidebarProp = toBlogSidebarProp;
|
|
4
7
|
function toTagsProp({ blogTags }) {
|
|
5
8
|
return Object.values(blogTags)
|
|
6
9
|
.filter((tag) => !tag.unlisted)
|
|
@@ -11,7 +14,6 @@ function toTagsProp({ blogTags }) {
|
|
|
11
14
|
count: tag.items.length,
|
|
12
15
|
}));
|
|
13
16
|
}
|
|
14
|
-
exports.toTagsProp = toTagsProp;
|
|
15
17
|
function toTagProp({ blogTagsListPath, tag, }) {
|
|
16
18
|
return {
|
|
17
19
|
label: tag.label,
|
|
@@ -22,4 +24,20 @@ function toTagProp({ blogTagsListPath, tag, }) {
|
|
|
22
24
|
unlisted: tag.unlisted,
|
|
23
25
|
};
|
|
24
26
|
}
|
|
25
|
-
|
|
27
|
+
function toAuthorItemProp({ author, count, }) {
|
|
28
|
+
return {
|
|
29
|
+
...author,
|
|
30
|
+
count,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function toBlogSidebarProp({ blogSidebarTitle, blogPosts, }) {
|
|
34
|
+
return {
|
|
35
|
+
title: blogSidebarTitle,
|
|
36
|
+
items: blogPosts.map((blogPost) => ({
|
|
37
|
+
title: blogPost.metadata.title,
|
|
38
|
+
permalink: blogPost.metadata.permalink,
|
|
39
|
+
unlisted: blogPost.metadata.unlisted,
|
|
40
|
+
date: blogPost.metadata.date,
|
|
41
|
+
})),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -6,6 +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.default = plugin;
|
|
9
10
|
const utils_1 = require("@docusaurus/utils");
|
|
10
11
|
/**
|
|
11
12
|
* In the blog list view, each post will be compiled separately. However, they
|
|
@@ -25,4 +26,3 @@ function plugin() {
|
|
|
25
26
|
});
|
|
26
27
|
};
|
|
27
28
|
}
|
|
28
|
-
exports.default = plugin;
|
package/lib/routes.d.ts
CHANGED
|
@@ -4,7 +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" />
|
|
8
7
|
import type { PluginContentLoadedActions, RouteConfig } from '@docusaurus/types';
|
|
9
8
|
import type { BlogContent, PluginOptions } from '@docusaurus/plugin-content-blog';
|
|
10
9
|
type CreateAllRoutesParam = {
|