@docusaurus/plugin-content-blog 3.3.2 → 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 +7 -12
- package/lib/blogUtils.js +44 -34
- 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 +8 -3
- package/lib/feed.js +111 -20
- package/lib/frontMatter.d.ts +0 -1
- package/lib/frontMatter.js +3 -2
- package/lib/index.d.ts +0 -1
- package/lib/index.js +132 -105
- package/lib/markdownLoader.js +3 -7
- package/lib/options.d.ts +4 -1
- package/lib/options.js +107 -26
- package/lib/props.d.ts +9 -2
- package/lib/props.js +23 -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/lib/types.d.ts +1 -8
- 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 +51 -46
- 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 +197 -18
- package/src/frontMatter.ts +2 -0
- package/src/index.ts +182 -137
- package/src/markdownLoader.ts +3 -7
- package/src/options.ts +132 -32
- package/src/plugin-content-blog.d.ts +252 -113
- package/src/props.ts +41 -1
- package/src/routes.ts +102 -12
- package/src/types.ts +1 -6
- package/src/client/index.ts +0 -20
package/lib/index.js
CHANGED
|
@@ -7,28 +7,58 @@
|
|
|
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"));
|
|
13
14
|
const utils_1 = require("@docusaurus/utils");
|
|
15
|
+
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
14
16
|
const blogUtils_1 = require("./blogUtils");
|
|
15
17
|
const footnoteIDFixer_1 = tslib_1.__importDefault(require("./remark/footnoteIDFixer"));
|
|
16
18
|
const translations_1 = require("./translations");
|
|
17
19
|
const feed_1 = require("./feed");
|
|
18
20
|
const routes_1 = require("./routes");
|
|
21
|
+
const authorsMap_1 = require("./authorsMap");
|
|
22
|
+
const PluginName = 'docusaurus-plugin-content-blog';
|
|
23
|
+
// TODO this is bad, we should have a better way to do this (new lifecycle?)
|
|
24
|
+
// The source to permalink is currently a mutable map passed to the mdx loader
|
|
25
|
+
// for link resolution
|
|
26
|
+
// see https://github.com/facebook/docusaurus/pull/10185
|
|
27
|
+
function createSourceToPermalinkHelper() {
|
|
28
|
+
const sourceToPermalink = new Map();
|
|
29
|
+
function computeSourceToPermalink(content) {
|
|
30
|
+
return new Map(content.blogPosts.map(({ metadata: { source, permalink } }) => [
|
|
31
|
+
source,
|
|
32
|
+
permalink,
|
|
33
|
+
]));
|
|
34
|
+
}
|
|
35
|
+
// Mutable map update :/
|
|
36
|
+
function update(content) {
|
|
37
|
+
sourceToPermalink.clear();
|
|
38
|
+
computeSourceToPermalink(content).forEach((value, key) => {
|
|
39
|
+
sourceToPermalink.set(key, value);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return { get: () => sourceToPermalink, update };
|
|
43
|
+
}
|
|
19
44
|
async function pluginContentBlog(context, options) {
|
|
20
45
|
const { siteDir, siteConfig, generatedFilesDir, localizationDir, i18n: { currentLocale }, } = context;
|
|
46
|
+
const router = siteConfig.future.experimental_router;
|
|
47
|
+
const isBlogFeedDisabledBecauseOfHashRouter = router === 'hash' && !!options.feedOptions.type;
|
|
48
|
+
if (isBlogFeedDisabledBecauseOfHashRouter) {
|
|
49
|
+
logger_1.default.warn(`${PluginName} feed feature does not support the Hash Router. Feeds won't be generated.`);
|
|
50
|
+
}
|
|
21
51
|
const { onBrokenMarkdownLinks, baseUrl } = siteConfig;
|
|
22
52
|
const contentPaths = {
|
|
23
53
|
contentPath: path_1.default.resolve(siteDir, options.path),
|
|
24
54
|
contentPathLocalized: (0, utils_1.getPluginI18nPath)({
|
|
25
55
|
localizationDir,
|
|
26
|
-
pluginName:
|
|
56
|
+
pluginName: PluginName,
|
|
27
57
|
pluginId: options.id,
|
|
28
58
|
}),
|
|
29
59
|
};
|
|
30
60
|
const pluginId = options.id ?? utils_1.DEFAULT_PLUGIN_ID;
|
|
31
|
-
const pluginDataDirRoot = path_1.default.join(generatedFilesDir,
|
|
61
|
+
const pluginDataDirRoot = path_1.default.join(generatedFilesDir, PluginName);
|
|
32
62
|
const dataDir = path_1.default.join(pluginDataDirRoot, pluginId);
|
|
33
63
|
// TODO Docusaurus v4 breaking change
|
|
34
64
|
// module aliasing should be automatic
|
|
@@ -38,26 +68,49 @@ async function pluginContentBlog(context, options) {
|
|
|
38
68
|
filePath: options.authorsMapPath,
|
|
39
69
|
contentPaths,
|
|
40
70
|
});
|
|
71
|
+
const sourceToPermalinkHelper = createSourceToPermalinkHelper();
|
|
41
72
|
return {
|
|
42
|
-
name:
|
|
73
|
+
name: PluginName,
|
|
43
74
|
getPathsToWatch() {
|
|
44
75
|
const { include } = options;
|
|
45
76
|
const contentMarkdownGlobs = (0, utils_1.getContentPathList)(contentPaths).flatMap((contentPath) => include.map((pattern) => `${contentPath}/${pattern}`));
|
|
46
|
-
|
|
77
|
+
const tagsFilePaths = (0, utils_validation_1.getTagsFilePathsToWatch)({
|
|
78
|
+
contentPaths,
|
|
79
|
+
tags: options.tags,
|
|
80
|
+
});
|
|
81
|
+
return [
|
|
82
|
+
authorsMapFilePath,
|
|
83
|
+
...tagsFilePaths,
|
|
84
|
+
...contentMarkdownGlobs,
|
|
85
|
+
].filter(Boolean);
|
|
47
86
|
},
|
|
48
87
|
getTranslationFiles() {
|
|
49
88
|
return (0, translations_1.getTranslationFiles)(options);
|
|
50
89
|
},
|
|
51
90
|
// Fetches blog contents and returns metadata for the necessary routes.
|
|
52
91
|
async loadContent() {
|
|
53
|
-
const { postsPerPage: postsPerPageOption, routeBasePath, tagsBasePath, blogDescription, blogTitle, blogSidebarTitle, pageBasePath, } = options;
|
|
92
|
+
const { postsPerPage: postsPerPageOption, routeBasePath, tagsBasePath, blogDescription, blogTitle, blogSidebarTitle, pageBasePath, authorsBasePath, authorsMapPath, } = options;
|
|
54
93
|
const baseBlogUrl = (0, utils_1.normalizeUrl)([baseUrl, routeBasePath]);
|
|
55
94
|
const blogTagsListPath = (0, utils_1.normalizeUrl)([baseBlogUrl, tagsBasePath]);
|
|
56
|
-
|
|
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);
|
|
57
106
|
blogPosts = await (0, blogUtils_1.applyProcessBlogPosts)({
|
|
58
107
|
blogPosts,
|
|
59
108
|
processBlogPosts: options.processBlogPosts,
|
|
60
109
|
});
|
|
110
|
+
(0, blogUtils_1.reportUntruncatedBlogPosts)({
|
|
111
|
+
blogPosts,
|
|
112
|
+
onUntruncatedBlogPosts: options.onUntruncatedBlogPosts,
|
|
113
|
+
});
|
|
61
114
|
const listedBlogPosts = blogPosts.filter(blogUtils_1.shouldBeListed);
|
|
62
115
|
if (!blogPosts.length) {
|
|
63
116
|
return {
|
|
@@ -66,6 +119,7 @@ async function pluginContentBlog(context, options) {
|
|
|
66
119
|
blogListPaginated: [],
|
|
67
120
|
blogTags: {},
|
|
68
121
|
blogTagsListPath,
|
|
122
|
+
authorsMap,
|
|
69
123
|
};
|
|
70
124
|
}
|
|
71
125
|
// Collocate next and prev metadata.
|
|
@@ -108,9 +162,11 @@ async function pluginContentBlog(context, options) {
|
|
|
108
162
|
blogListPaginated,
|
|
109
163
|
blogTags,
|
|
110
164
|
blogTagsListPath,
|
|
165
|
+
authorsMap,
|
|
111
166
|
};
|
|
112
167
|
},
|
|
113
168
|
async contentLoaded({ content, actions }) {
|
|
169
|
+
sourceToPermalinkHelper.update(content);
|
|
114
170
|
await (0, routes_1.createAllRoutes)({
|
|
115
171
|
baseUrl,
|
|
116
172
|
content,
|
|
@@ -122,21 +178,67 @@ async function pluginContentBlog(context, options) {
|
|
|
122
178
|
translateContent({ content, translationFiles }) {
|
|
123
179
|
return (0, translations_1.translateContent)(content, translationFiles);
|
|
124
180
|
},
|
|
125
|
-
configureWebpack(
|
|
126
|
-
const { admonitions, rehypePlugins, remarkPlugins, truncateMarker, beforeDefaultRemarkPlugins, beforeDefaultRehypePlugins, } = options;
|
|
127
|
-
const markdownLoaderOptions = {
|
|
128
|
-
siteDir,
|
|
129
|
-
contentPaths,
|
|
130
|
-
truncateMarker,
|
|
131
|
-
sourceToPermalink: (0, blogUtils_1.getSourceToPermalink)(content.blogPosts),
|
|
132
|
-
onBrokenMarkdownLink: (brokenMarkdownLink) => {
|
|
133
|
-
if (onBrokenMarkdownLinks === 'ignore') {
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
logger_1.default.report(onBrokenMarkdownLinks) `Blog markdown link couldn't be resolved: (url=${brokenMarkdownLink.link}) in path=${brokenMarkdownLink.filePath}`;
|
|
137
|
-
},
|
|
138
|
-
};
|
|
181
|
+
configureWebpack() {
|
|
182
|
+
const { admonitions, rehypePlugins, remarkPlugins, recmaPlugins, truncateMarker, beforeDefaultRemarkPlugins, beforeDefaultRehypePlugins, } = options;
|
|
139
183
|
const contentDirs = (0, utils_1.getContentPathList)(contentPaths);
|
|
184
|
+
function createMDXLoader() {
|
|
185
|
+
const loaderOptions = {
|
|
186
|
+
admonitions,
|
|
187
|
+
remarkPlugins,
|
|
188
|
+
rehypePlugins,
|
|
189
|
+
recmaPlugins,
|
|
190
|
+
beforeDefaultRemarkPlugins: [
|
|
191
|
+
footnoteIDFixer_1.default,
|
|
192
|
+
...beforeDefaultRemarkPlugins,
|
|
193
|
+
],
|
|
194
|
+
beforeDefaultRehypePlugins,
|
|
195
|
+
staticDirs: siteConfig.staticDirectories.map((dir) => path_1.default.resolve(siteDir, dir)),
|
|
196
|
+
siteDir,
|
|
197
|
+
isMDXPartial: (0, utils_1.createAbsoluteFilePathMatcher)(options.exclude, contentDirs),
|
|
198
|
+
metadataPath: (mdxPath) => {
|
|
199
|
+
// Note that metadataPath must be the same/in-sync as
|
|
200
|
+
// the path from createData for each MDX.
|
|
201
|
+
const aliasedPath = (0, utils_1.aliasedSitePath)(mdxPath, siteDir);
|
|
202
|
+
return path_1.default.join(dataDir, `${(0, utils_1.docuHash)(aliasedPath)}.json`);
|
|
203
|
+
},
|
|
204
|
+
// For blog posts a title in markdown is always removed
|
|
205
|
+
// Blog posts title are rendered separately
|
|
206
|
+
removeContentTitle: true,
|
|
207
|
+
// Assets allow to convert some relative images paths to
|
|
208
|
+
// require() calls
|
|
209
|
+
// @ts-expect-error: TODO fix typing issue
|
|
210
|
+
createAssets: ({ frontMatter, metadata, }) => ({
|
|
211
|
+
image: frontMatter.image,
|
|
212
|
+
authorsImageUrls: metadata.authors.map((author) => author.imageURL),
|
|
213
|
+
}),
|
|
214
|
+
markdownConfig: siteConfig.markdown,
|
|
215
|
+
resolveMarkdownLink: ({ linkPathname, sourceFilePath }) => {
|
|
216
|
+
const permalink = (0, utils_1.resolveMarkdownLinkPathname)(linkPathname, {
|
|
217
|
+
sourceFilePath,
|
|
218
|
+
sourceToPermalink: sourceToPermalinkHelper.get(),
|
|
219
|
+
siteDir,
|
|
220
|
+
contentPaths,
|
|
221
|
+
});
|
|
222
|
+
if (permalink === null) {
|
|
223
|
+
logger_1.default.report(onBrokenMarkdownLinks) `Blog markdown link couldn't be resolved: (url=${linkPathname}) in source file path=${sourceFilePath}`;
|
|
224
|
+
}
|
|
225
|
+
return permalink;
|
|
226
|
+
},
|
|
227
|
+
};
|
|
228
|
+
return {
|
|
229
|
+
loader: require.resolve('@docusaurus/mdx-loader'),
|
|
230
|
+
options: loaderOptions,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
function createBlogMarkdownLoader() {
|
|
234
|
+
const loaderOptions = {
|
|
235
|
+
truncateMarker,
|
|
236
|
+
};
|
|
237
|
+
return {
|
|
238
|
+
loader: path_1.default.resolve(__dirname, './markdownLoader.js'),
|
|
239
|
+
options: loaderOptions,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
140
242
|
return {
|
|
141
243
|
resolve: {
|
|
142
244
|
alias: {
|
|
@@ -150,111 +252,36 @@ async function pluginContentBlog(context, options) {
|
|
|
150
252
|
include: contentDirs
|
|
151
253
|
// Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
|
|
152
254
|
.map(utils_1.addTrailingPathSeparator),
|
|
153
|
-
use: [
|
|
154
|
-
{
|
|
155
|
-
loader: require.resolve('@docusaurus/mdx-loader'),
|
|
156
|
-
options: {
|
|
157
|
-
admonitions,
|
|
158
|
-
remarkPlugins,
|
|
159
|
-
rehypePlugins,
|
|
160
|
-
beforeDefaultRemarkPlugins: [
|
|
161
|
-
footnoteIDFixer_1.default,
|
|
162
|
-
...beforeDefaultRemarkPlugins,
|
|
163
|
-
],
|
|
164
|
-
beforeDefaultRehypePlugins,
|
|
165
|
-
staticDirs: siteConfig.staticDirectories.map((dir) => path_1.default.resolve(siteDir, dir)),
|
|
166
|
-
siteDir,
|
|
167
|
-
isMDXPartial: (0, utils_1.createAbsoluteFilePathMatcher)(options.exclude, contentDirs),
|
|
168
|
-
metadataPath: (mdxPath) => {
|
|
169
|
-
// Note that metadataPath must be the same/in-sync as
|
|
170
|
-
// the path from createData for each MDX.
|
|
171
|
-
const aliasedPath = (0, utils_1.aliasedSitePath)(mdxPath, siteDir);
|
|
172
|
-
return path_1.default.join(dataDir, `${(0, utils_1.docuHash)(aliasedPath)}.json`);
|
|
173
|
-
},
|
|
174
|
-
// For blog posts a title in markdown is always removed
|
|
175
|
-
// Blog posts title are rendered separately
|
|
176
|
-
removeContentTitle: true,
|
|
177
|
-
// Assets allow to convert some relative images paths to
|
|
178
|
-
// require() calls
|
|
179
|
-
createAssets: ({ frontMatter, metadata, }) => ({
|
|
180
|
-
image: frontMatter.image,
|
|
181
|
-
authorsImageUrls: metadata.authors.map((author) => author.imageURL),
|
|
182
|
-
}),
|
|
183
|
-
markdownConfig: siteConfig.markdown,
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
loader: path_1.default.resolve(__dirname, './markdownLoader.js'),
|
|
188
|
-
options: markdownLoaderOptions,
|
|
189
|
-
},
|
|
190
|
-
].filter(Boolean),
|
|
255
|
+
use: [createMDXLoader(), createBlogMarkdownLoader()],
|
|
191
256
|
},
|
|
192
257
|
],
|
|
193
258
|
},
|
|
194
259
|
};
|
|
195
260
|
},
|
|
196
261
|
async postBuild({ outDir, content }) {
|
|
197
|
-
if (!
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
const { blogPosts } = content;
|
|
201
|
-
if (!blogPosts.length) {
|
|
262
|
+
if (!content.blogPosts.length ||
|
|
263
|
+
!options.feedOptions.type ||
|
|
264
|
+
isBlogFeedDisabledBecauseOfHashRouter) {
|
|
202
265
|
return;
|
|
203
266
|
}
|
|
204
267
|
await (0, feed_1.createBlogFeedFiles)({
|
|
205
|
-
blogPosts,
|
|
268
|
+
blogPosts: content.blogPosts,
|
|
206
269
|
options,
|
|
207
270
|
outDir,
|
|
208
271
|
siteConfig,
|
|
209
272
|
locale: currentLocale,
|
|
273
|
+
contentPaths,
|
|
210
274
|
});
|
|
211
275
|
},
|
|
212
276
|
injectHtmlTags({ content }) {
|
|
213
|
-
if (!content.blogPosts.length ||
|
|
277
|
+
if (!content.blogPosts.length ||
|
|
278
|
+
!options.feedOptions.type ||
|
|
279
|
+
isBlogFeedDisabledBecauseOfHashRouter) {
|
|
214
280
|
return {};
|
|
215
281
|
}
|
|
216
|
-
|
|
217
|
-
const feedTitle = options.feedOptions.title ?? context.siteConfig.title;
|
|
218
|
-
const feedsConfig = {
|
|
219
|
-
rss: {
|
|
220
|
-
type: 'application/rss+xml',
|
|
221
|
-
path: 'rss.xml',
|
|
222
|
-
title: `${feedTitle} RSS Feed`,
|
|
223
|
-
},
|
|
224
|
-
atom: {
|
|
225
|
-
type: 'application/atom+xml',
|
|
226
|
-
path: 'atom.xml',
|
|
227
|
-
title: `${feedTitle} Atom Feed`,
|
|
228
|
-
},
|
|
229
|
-
json: {
|
|
230
|
-
type: 'application/json',
|
|
231
|
-
path: 'feed.json',
|
|
232
|
-
title: `${feedTitle} JSON Feed`,
|
|
233
|
-
},
|
|
234
|
-
};
|
|
235
|
-
const headTags = [];
|
|
236
|
-
feedTypes.forEach((feedType) => {
|
|
237
|
-
const { type, path: feedConfigPath, title: feedConfigTitle, } = feedsConfig[feedType];
|
|
238
|
-
headTags.push({
|
|
239
|
-
tagName: 'link',
|
|
240
|
-
attributes: {
|
|
241
|
-
rel: 'alternate',
|
|
242
|
-
type,
|
|
243
|
-
href: (0, utils_1.normalizeUrl)([
|
|
244
|
-
baseUrl,
|
|
245
|
-
options.routeBasePath,
|
|
246
|
-
feedConfigPath,
|
|
247
|
-
]),
|
|
248
|
-
title: feedConfigTitle,
|
|
249
|
-
},
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
return {
|
|
253
|
-
headTags,
|
|
254
|
-
};
|
|
282
|
+
return { headTags: (0, feed_1.createFeedHtmlHeadTags)({ context, options }) };
|
|
255
283
|
},
|
|
256
284
|
};
|
|
257
285
|
}
|
|
258
|
-
exports.default = pluginContentBlog;
|
|
259
286
|
var options_1 = require("./options");
|
|
260
287
|
Object.defineProperty(exports, "validateOptions", { enumerable: true, get: function () { return options_1.validateOptions; } });
|
package/lib/markdownLoader.js
CHANGED
|
@@ -6,25 +6,21 @@
|
|
|
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
|
-
const filePath = this.resourcePath;
|
|
12
12
|
const fileString = source;
|
|
13
13
|
const callback = this.async();
|
|
14
14
|
const markdownLoaderOptions = this.getOptions();
|
|
15
15
|
// Linkify blog posts
|
|
16
|
-
let finalContent =
|
|
17
|
-
fileString,
|
|
18
|
-
filePath,
|
|
19
|
-
...markdownLoaderOptions,
|
|
20
|
-
});
|
|
16
|
+
let finalContent = fileString;
|
|
21
17
|
// Truncate content if requested (e.g: file.md?truncated=true).
|
|
22
18
|
const truncated = this.resourceQuery
|
|
23
19
|
? !!new URLSearchParams(this.resourceQuery.slice(1)).get('truncated')
|
|
24
20
|
: undefined;
|
|
21
|
+
// TODO truncate with the AST instead of the string ?
|
|
25
22
|
if (truncated) {
|
|
26
23
|
finalContent = (0, blogUtils_1.truncate)(finalContent, markdownLoaderOptions.truncateMarker);
|
|
27
24
|
}
|
|
28
25
|
return callback(null, finalContent);
|
|
29
26
|
}
|
|
30
|
-
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',
|
|
@@ -42,7 +56,78 @@ exports.DEFAULT_OPTIONS = {
|
|
|
42
56
|
showLastUpdateTime: false,
|
|
43
57
|
showLastUpdateAuthor: false,
|
|
44
58
|
processBlogPosts: async () => undefined,
|
|
59
|
+
onInlineTags: 'warn',
|
|
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'),
|
|
45
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);
|
|
46
131
|
const PluginOptionSchema = utils_validation_1.Joi.object({
|
|
47
132
|
path: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.path),
|
|
48
133
|
archiveBasePath: utils_validation_1.Joi.string()
|
|
@@ -60,6 +145,8 @@ const PluginOptionSchema = utils_validation_1.Joi.object({
|
|
|
60
145
|
blogPostComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogPostComponent),
|
|
61
146
|
blogTagsListComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogTagsListComponent),
|
|
62
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),
|
|
63
150
|
blogArchiveComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogArchiveComponent),
|
|
64
151
|
blogTitle: utils_validation_1.Joi.string().allow('').default(exports.DEFAULT_OPTIONS.blogTitle),
|
|
65
152
|
blogDescription: utils_validation_1.Joi.string()
|
|
@@ -72,35 +159,14 @@ const PluginOptionSchema = utils_validation_1.Joi.object({
|
|
|
72
159
|
showReadingTime: utils_validation_1.Joi.bool().default(exports.DEFAULT_OPTIONS.showReadingTime),
|
|
73
160
|
remarkPlugins: utils_validation_1.RemarkPluginsSchema.default(exports.DEFAULT_OPTIONS.remarkPlugins),
|
|
74
161
|
rehypePlugins: utils_validation_1.RehypePluginsSchema.default(exports.DEFAULT_OPTIONS.rehypePlugins),
|
|
162
|
+
recmaPlugins: utils_validation_1.RecmaPluginsSchema.default(exports.DEFAULT_OPTIONS.recmaPlugins),
|
|
75
163
|
admonitions: utils_validation_1.AdmonitionsSchema.default(exports.DEFAULT_OPTIONS.admonitions),
|
|
76
164
|
editUrl: utils_validation_1.Joi.alternatives().try(utils_validation_1.URISchema, utils_validation_1.Joi.function()),
|
|
77
165
|
editLocalizedFiles: utils_validation_1.Joi.boolean().default(exports.DEFAULT_OPTIONS.editLocalizedFiles),
|
|
78
166
|
truncateMarker: utils_validation_1.Joi.object().default(exports.DEFAULT_OPTIONS.truncateMarker),
|
|
79
167
|
beforeDefaultRemarkPlugins: utils_validation_1.RemarkPluginsSchema.default(exports.DEFAULT_OPTIONS.beforeDefaultRemarkPlugins),
|
|
80
168
|
beforeDefaultRehypePlugins: utils_validation_1.RehypePluginsSchema.default(exports.DEFAULT_OPTIONS.beforeDefaultRehypePlugins),
|
|
81
|
-
feedOptions:
|
|
82
|
-
type: utils_validation_1.Joi.alternatives()
|
|
83
|
-
.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'), {
|
|
84
|
-
then: utils_validation_1.Joi.custom((val) => val === 'all' ? ['rss', 'atom', 'json'] : [val]),
|
|
85
|
-
}))
|
|
86
|
-
.allow(null)
|
|
87
|
-
.default(exports.DEFAULT_OPTIONS.feedOptions.type),
|
|
88
|
-
title: utils_validation_1.Joi.string().allow(''),
|
|
89
|
-
description: utils_validation_1.Joi.string().allow(''),
|
|
90
|
-
// Only add default value when user actually wants a feed (type is not null)
|
|
91
|
-
copyright: utils_validation_1.Joi.when('type', {
|
|
92
|
-
is: utils_validation_1.Joi.any().valid(null),
|
|
93
|
-
then: utils_validation_1.Joi.string().optional(),
|
|
94
|
-
otherwise: utils_validation_1.Joi.string()
|
|
95
|
-
.allow('')
|
|
96
|
-
.default(exports.DEFAULT_OPTIONS.feedOptions.copyright),
|
|
97
|
-
}),
|
|
98
|
-
language: utils_validation_1.Joi.string(),
|
|
99
|
-
createFeedItems: utils_validation_1.Joi.function(),
|
|
100
|
-
limit: utils_validation_1.Joi.alternatives()
|
|
101
|
-
.try(utils_validation_1.Joi.number(), utils_validation_1.Joi.valid(null), utils_validation_1.Joi.valid(false))
|
|
102
|
-
.default(exports.DEFAULT_OPTIONS.feedOptions.limit),
|
|
103
|
-
}).default(exports.DEFAULT_OPTIONS.feedOptions),
|
|
169
|
+
feedOptions: FeedOptionsSchema,
|
|
104
170
|
authorsMapPath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.authorsMapPath),
|
|
105
171
|
readingTime: utils_validation_1.Joi.function().default(() => exports.DEFAULT_OPTIONS.readingTime),
|
|
106
172
|
sortPosts: utils_validation_1.Joi.string()
|
|
@@ -111,9 +177,24 @@ const PluginOptionSchema = utils_validation_1.Joi.object({
|
|
|
111
177
|
processBlogPosts: utils_validation_1.Joi.function()
|
|
112
178
|
.optional()
|
|
113
179
|
.default(() => exports.DEFAULT_OPTIONS.processBlogPosts),
|
|
180
|
+
onInlineTags: utils_validation_1.Joi.string()
|
|
181
|
+
.equal('ignore', 'log', 'warn', 'throw')
|
|
182
|
+
.default(exports.DEFAULT_OPTIONS.onInlineTags),
|
|
183
|
+
tags: utils_validation_1.Joi.string()
|
|
184
|
+
.disallow('')
|
|
185
|
+
.allow(null, false)
|
|
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),
|
|
114
196
|
}).default(exports.DEFAULT_OPTIONS);
|
|
115
197
|
function validateOptions({ validate, options, }) {
|
|
116
198
|
const validatedOptions = validate(PluginOptionSchema, options);
|
|
117
199
|
return validatedOptions;
|
|
118
200
|
}
|
|
119
|
-
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,23 +1,43 @@
|
|
|
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)
|
|
7
10
|
.map((tag) => ({
|
|
8
11
|
label: tag.label,
|
|
9
12
|
permalink: tag.permalink,
|
|
13
|
+
description: tag.description,
|
|
10
14
|
count: tag.items.length,
|
|
11
15
|
}));
|
|
12
16
|
}
|
|
13
|
-
exports.toTagsProp = toTagsProp;
|
|
14
17
|
function toTagProp({ blogTagsListPath, tag, }) {
|
|
15
18
|
return {
|
|
16
19
|
label: tag.label,
|
|
17
20
|
permalink: tag.permalink,
|
|
21
|
+
description: tag.description,
|
|
18
22
|
allTagsPath: blogTagsListPath,
|
|
19
23
|
count: tag.items.length,
|
|
20
24
|
unlisted: tag.unlisted,
|
|
21
25
|
};
|
|
22
26
|
}
|
|
23
|
-
|
|
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 = {
|