@docusaurus/plugin-content-blog 2.0.0-beta.677e53d4d → 2.0.0-beta.7
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/.tsbuildinfo +1 -1
- package/lib/authors.d.ts +23 -0
- package/lib/authors.js +150 -0
- package/lib/blogFrontMatter.d.ts +19 -6
- package/lib/blogFrontMatter.js +31 -19
- package/lib/blogUtils.d.ts +10 -2
- package/lib/blogUtils.js +146 -104
- package/lib/index.js +78 -77
- package/lib/markdownLoader.js +3 -3
- package/lib/pluginOptionSchema.d.ts +3 -26
- package/lib/pluginOptionSchema.js +22 -7
- package/lib/translations.d.ts +10 -0
- package/lib/translations.js +53 -0
- package/lib/types.d.ts +38 -14
- package/package.json +13 -11
- package/src/__tests__/__fixtures__/authorsMapFiles/authors.json +29 -0
- package/src/__tests__/__fixtures__/authorsMapFiles/authors.yml +27 -0
- package/src/__tests__/__fixtures__/authorsMapFiles/authorsBad1.json +5 -0
- package/src/__tests__/__fixtures__/authorsMapFiles/authorsBad1.yml +3 -0
- package/src/__tests__/__fixtures__/authorsMapFiles/authorsBad2.json +3 -0
- package/src/__tests__/__fixtures__/authorsMapFiles/authorsBad2.yml +2 -0
- package/src/__tests__/__fixtures__/authorsMapFiles/authorsBad3.json +8 -0
- package/src/__tests__/__fixtures__/authorsMapFiles/authorsBad3.yml +3 -0
- package/src/__tests__/__fixtures__/component/Typography.tsx +6 -0
- package/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathEmpty/empty +0 -0
- package/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathJson1/authors.json +0 -0
- package/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathJson2/authors.json +0 -0
- package/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathNestedYml/sub/folder/authors.yml +0 -0
- package/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathYml1/authors.yml +0 -0
- package/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathYml2/authors.yml +0 -0
- package/src/__tests__/__fixtures__/website/blog/2018-12-14-Happy-First-Birthday-Slash.md +3 -0
- package/src/__tests__/__fixtures__/website/blog/_partials/somePartial.md +3 -0
- package/src/__tests__/__fixtures__/website/blog/_partials/subfolder/somePartial.md +3 -0
- package/src/__tests__/__fixtures__/website/blog/_somePartial.md +3 -0
- package/src/__tests__/__fixtures__/website/blog/authors.yml +4 -0
- package/src/__tests__/__fixtures__/website/blog/mdx-blog-post.mdx +36 -0
- package/src/__tests__/__fixtures__/website/blog/simple-slug.md +4 -0
- package/src/__tests__/__fixtures__/website/i18n/en/docusaurus-plugin-content-blog/2018-12-14-Happy-First-Birthday-Slash.md +3 -0
- package/src/__tests__/__fixtures__/website/i18n/en/docusaurus-plugin-content-blog/authors.yml +5 -0
- package/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap +81 -3
- package/src/__tests__/__snapshots__/translations.test.ts.snap +64 -0
- package/src/__tests__/authors.test.ts +608 -0
- package/src/__tests__/blogFrontMatter.test.ts +93 -16
- package/src/__tests__/blogUtils.test.ts +94 -0
- package/src/__tests__/generateBlogFeed.test.ts +7 -1
- package/src/__tests__/index.test.ts +63 -12
- package/src/__tests__/pluginOptionSchema.test.ts +3 -3
- package/src/__tests__/translations.test.ts +92 -0
- package/src/authors.ts +202 -0
- package/src/blogFrontMatter.ts +73 -33
- package/src/blogUtils.ts +206 -131
- package/src/index.ts +98 -71
- package/{index.d.ts → src/plugin-content-blog.d.ts} +35 -31
- package/src/pluginOptionSchema.ts +25 -9
- package/src/translations.ts +63 -0
- package/src/types.ts +48 -16
package/lib/index.js
CHANGED
|
@@ -8,11 +8,12 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.validateOptions = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
|
-
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
12
|
-
const path_1 = tslib_1.__importDefault(require("path"));
|
|
13
|
-
const remark_admonitions_1 = tslib_1.__importDefault(require("remark-admonitions"));
|
|
11
|
+
const fs_extra_1 = (0, tslib_1.__importDefault)(require("fs-extra"));
|
|
12
|
+
const path_1 = (0, tslib_1.__importDefault)(require("path"));
|
|
13
|
+
const remark_admonitions_1 = (0, tslib_1.__importDefault)(require("remark-admonitions"));
|
|
14
14
|
const utils_1 = require("@docusaurus/utils");
|
|
15
15
|
const constants_1 = require("@docusaurus/core/lib/constants");
|
|
16
|
+
const translations_1 = require("./translations");
|
|
16
17
|
const lodash_1 = require("lodash");
|
|
17
18
|
const pluginOptionSchema_1 = require("./pluginOptionSchema");
|
|
18
19
|
const blogUtils_1 = require("./blogUtils");
|
|
@@ -23,10 +24,10 @@ function pluginContentBlog(context, options) {
|
|
|
23
24
|
[remark_admonitions_1.default, options.admonitions],
|
|
24
25
|
]);
|
|
25
26
|
}
|
|
26
|
-
const { siteDir, siteConfig: { onBrokenMarkdownLinks }, generatedFilesDir, i18n: { currentLocale }, } = context;
|
|
27
|
+
const { siteDir, siteConfig: { onBrokenMarkdownLinks, baseUrl }, generatedFilesDir, i18n: { currentLocale }, } = context;
|
|
27
28
|
const contentPaths = {
|
|
28
29
|
contentPath: path_1.default.resolve(siteDir, options.path),
|
|
29
|
-
contentPathLocalized: utils_1.getPluginI18nPath({
|
|
30
|
+
contentPathLocalized: (0, utils_1.getPluginI18nPath)({
|
|
30
31
|
siteDir,
|
|
31
32
|
locale: currentLocale,
|
|
32
33
|
pluginName: 'docusaurus-plugin-content-blog',
|
|
@@ -36,28 +37,30 @@ function pluginContentBlog(context, options) {
|
|
|
36
37
|
const pluginId = (_a = options.id) !== null && _a !== void 0 ? _a : constants_1.DEFAULT_PLUGIN_ID;
|
|
37
38
|
const pluginDataDirRoot = path_1.default.join(generatedFilesDir, 'docusaurus-plugin-content-blog');
|
|
38
39
|
const dataDir = path_1.default.join(pluginDataDirRoot, pluginId);
|
|
39
|
-
const aliasedSource = (source) => `~blog/${utils_1.posixPath(path_1.default.relative(pluginDataDirRoot, source))}`;
|
|
40
|
+
const aliasedSource = (source) => `~blog/${(0, utils_1.posixPath)(path_1.default.relative(pluginDataDirRoot, source))}`;
|
|
40
41
|
return {
|
|
41
42
|
name: 'docusaurus-plugin-content-blog',
|
|
42
43
|
getPathsToWatch() {
|
|
43
|
-
const { include
|
|
44
|
-
|
|
44
|
+
const { include, authorsMapPath } = options;
|
|
45
|
+
const contentMarkdownGlobs = (0, lodash_1.flatten)((0, blogUtils_1.getContentPathList)(contentPaths).map((contentPath) => {
|
|
45
46
|
return include.map((pattern) => `${contentPath}/${pattern}`);
|
|
46
47
|
}));
|
|
48
|
+
// TODO: we should read this path in plugin! but plugins do not support async init for now :'(
|
|
49
|
+
// const authorsMapFilePath = await getAuthorsMapFilePath({authorsMapPath,contentPaths,});
|
|
50
|
+
// simplified impl, better than nothing for now:
|
|
51
|
+
const authorsMapFilePath = path_1.default.join(contentPaths.contentPath, authorsMapPath);
|
|
52
|
+
return [authorsMapFilePath, ...contentMarkdownGlobs];
|
|
47
53
|
},
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if (options.admonitions) {
|
|
51
|
-
modules.push(require.resolve('remark-admonitions/styles/infima.css'));
|
|
52
|
-
}
|
|
53
|
-
return modules;
|
|
54
|
+
async getTranslationFiles() {
|
|
55
|
+
return (0, translations_1.getTranslationFiles)(options);
|
|
54
56
|
},
|
|
55
57
|
// Fetches blog contents and returns metadata for the necessary routes.
|
|
56
58
|
async loadContent() {
|
|
57
|
-
const { postsPerPage, routeBasePath } = options;
|
|
58
|
-
const blogPosts = await blogUtils_1.generateBlogPosts(contentPaths, context, options);
|
|
59
|
+
const { postsPerPage: postsPerPageOption, routeBasePath, tagsBasePath, blogDescription, blogTitle, blogSidebarTitle, } = options;
|
|
60
|
+
const blogPosts = await (0, blogUtils_1.generateBlogPosts)(contentPaths, context, options);
|
|
59
61
|
if (!blogPosts.length) {
|
|
60
62
|
return {
|
|
63
|
+
blogSidebarTitle,
|
|
61
64
|
blogPosts: [],
|
|
62
65
|
blogListPaginated: [],
|
|
63
66
|
blogTags: {},
|
|
@@ -84,14 +87,14 @@ function pluginContentBlog(context, options) {
|
|
|
84
87
|
// Blog pagination routes.
|
|
85
88
|
// Example: `/blog`, `/blog/page/1`, `/blog/page/2`
|
|
86
89
|
const totalCount = blogPosts.length;
|
|
90
|
+
const postsPerPage = postsPerPageOption === 'ALL' ? totalCount : postsPerPageOption;
|
|
87
91
|
const numberOfPages = Math.ceil(totalCount / postsPerPage);
|
|
88
|
-
const
|
|
89
|
-
const basePageUrl = utils_1.normalizeUrl([baseUrl, routeBasePath]);
|
|
92
|
+
const baseBlogUrl = (0, utils_1.normalizeUrl)([baseUrl, routeBasePath]);
|
|
90
93
|
const blogListPaginated = [];
|
|
91
94
|
function blogPaginationPermalink(page) {
|
|
92
95
|
return page > 0
|
|
93
|
-
? utils_1.normalizeUrl([
|
|
94
|
-
:
|
|
96
|
+
? (0, utils_1.normalizeUrl)([baseBlogUrl, `page/${page + 1}`])
|
|
97
|
+
: baseBlogUrl;
|
|
95
98
|
}
|
|
96
99
|
for (let page = 0; page < numberOfPages; page += 1) {
|
|
97
100
|
blogListPaginated.push({
|
|
@@ -105,48 +108,19 @@ function pluginContentBlog(context, options) {
|
|
|
105
108
|
nextPage: page < numberOfPages - 1
|
|
106
109
|
? blogPaginationPermalink(page + 1)
|
|
107
110
|
: null,
|
|
108
|
-
blogDescription
|
|
109
|
-
blogTitle
|
|
111
|
+
blogDescription,
|
|
112
|
+
blogTitle,
|
|
110
113
|
},
|
|
111
114
|
items: blogPosts
|
|
112
115
|
.slice(page * postsPerPage, (page + 1) * postsPerPage)
|
|
113
116
|
.map((item) => item.id),
|
|
114
117
|
});
|
|
115
118
|
}
|
|
116
|
-
const blogTags =
|
|
117
|
-
const tagsPath = utils_1.normalizeUrl([
|
|
118
|
-
blogPosts.forEach((blogPost) => {
|
|
119
|
-
const { tags } = blogPost.metadata;
|
|
120
|
-
if (!tags || tags.length === 0) {
|
|
121
|
-
// TODO: Extract tags out into a separate plugin.
|
|
122
|
-
// eslint-disable-next-line no-param-reassign
|
|
123
|
-
blogPost.metadata.tags = [];
|
|
124
|
-
return;
|
|
125
|
-
}
|
|
126
|
-
// eslint-disable-next-line no-param-reassign
|
|
127
|
-
blogPost.metadata.tags = tags.map((tag) => {
|
|
128
|
-
if (typeof tag === 'string') {
|
|
129
|
-
const normalizedTag = lodash_1.kebabCase(tag);
|
|
130
|
-
const permalink = utils_1.normalizeUrl([tagsPath, normalizedTag]);
|
|
131
|
-
if (!blogTags[normalizedTag]) {
|
|
132
|
-
blogTags[normalizedTag] = {
|
|
133
|
-
// Will only use the name of the first occurrence of the tag.
|
|
134
|
-
name: tag.toLowerCase(),
|
|
135
|
-
items: [],
|
|
136
|
-
permalink,
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
blogTags[normalizedTag].items.push(blogPost.id);
|
|
140
|
-
return {
|
|
141
|
-
label: tag,
|
|
142
|
-
permalink,
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
return tag;
|
|
146
|
-
});
|
|
147
|
-
});
|
|
119
|
+
const blogTags = (0, blogUtils_1.getBlogTags)(blogPosts);
|
|
120
|
+
const tagsPath = (0, utils_1.normalizeUrl)([baseBlogUrl, tagsBasePath]);
|
|
148
121
|
const blogTagsListPath = Object.keys(blogTags).length > 0 ? tagsPath : null;
|
|
149
122
|
return {
|
|
123
|
+
blogSidebarTitle,
|
|
150
124
|
blogPosts,
|
|
151
125
|
blogListPaginated,
|
|
152
126
|
blogTags,
|
|
@@ -157,19 +131,34 @@ function pluginContentBlog(context, options) {
|
|
|
157
131
|
if (!blogContents) {
|
|
158
132
|
return;
|
|
159
133
|
}
|
|
160
|
-
const { blogListComponent, blogPostComponent, blogTagsListComponent, blogTagsPostsComponent, } = options;
|
|
134
|
+
const { blogListComponent, blogPostComponent, blogTagsListComponent, blogTagsPostsComponent, routeBasePath, archiveBasePath, } = options;
|
|
161
135
|
const { addRoute, createData } = actions;
|
|
162
|
-
const { blogPosts, blogListPaginated, blogTags, blogTagsListPath, } = blogContents;
|
|
136
|
+
const { blogSidebarTitle, blogPosts, blogListPaginated, blogTags, blogTagsListPath, } = blogContents;
|
|
163
137
|
const blogItemsToMetadata = {};
|
|
164
138
|
const sidebarBlogPosts = options.blogSidebarCount === 'ALL'
|
|
165
139
|
? blogPosts
|
|
166
|
-
: lodash_1.take(blogPosts, options.blogSidebarCount);
|
|
140
|
+
: (0, lodash_1.take)(blogPosts, options.blogSidebarCount);
|
|
141
|
+
const archiveUrl = (0, utils_1.normalizeUrl)([
|
|
142
|
+
baseUrl,
|
|
143
|
+
routeBasePath,
|
|
144
|
+
archiveBasePath,
|
|
145
|
+
]);
|
|
146
|
+
// creates a blog archive route
|
|
147
|
+
const archiveProp = await createData(`${(0, utils_1.docuHash)(archiveUrl)}.json`, JSON.stringify({ blogPosts }, null, 2));
|
|
148
|
+
addRoute({
|
|
149
|
+
path: archiveUrl,
|
|
150
|
+
component: '@theme/BlogArchivePage',
|
|
151
|
+
exact: true,
|
|
152
|
+
modules: {
|
|
153
|
+
archive: aliasedSource(archiveProp),
|
|
154
|
+
},
|
|
155
|
+
});
|
|
167
156
|
// This prop is useful to provide the blog list sidebar
|
|
168
157
|
const sidebarProp = await createData(
|
|
169
158
|
// Note that this created data path must be in sync with
|
|
170
159
|
// metadataPath provided to mdx-loader.
|
|
171
160
|
`blog-post-list-prop-${pluginId}.json`, JSON.stringify({
|
|
172
|
-
title:
|
|
161
|
+
title: blogSidebarTitle,
|
|
173
162
|
items: sidebarBlogPosts.map((blogPost) => ({
|
|
174
163
|
title: blogPost.metadata.title,
|
|
175
164
|
permalink: blogPost.metadata.permalink,
|
|
@@ -181,7 +170,7 @@ function pluginContentBlog(context, options) {
|
|
|
181
170
|
await createData(
|
|
182
171
|
// Note that this created data path must be in sync with
|
|
183
172
|
// metadataPath provided to mdx-loader.
|
|
184
|
-
`${utils_1.docuHash(metadata.source)}.json`, JSON.stringify(metadata, null, 2));
|
|
173
|
+
`${(0, utils_1.docuHash)(metadata.source)}.json`, JSON.stringify(metadata, null, 2));
|
|
185
174
|
addRoute({
|
|
186
175
|
path: metadata.permalink,
|
|
187
176
|
component: blogPostComponent,
|
|
@@ -197,7 +186,7 @@ function pluginContentBlog(context, options) {
|
|
|
197
186
|
await Promise.all(blogListPaginated.map(async (listPage) => {
|
|
198
187
|
const { metadata, items } = listPage;
|
|
199
188
|
const { permalink } = metadata;
|
|
200
|
-
const pageMetadataPath = await createData(`${utils_1.docuHash(permalink)}.json`, JSON.stringify(metadata, null, 2));
|
|
189
|
+
const pageMetadataPath = await createData(`${(0, utils_1.docuHash)(permalink)}.json`, JSON.stringify(metadata, null, 2));
|
|
201
190
|
addRoute({
|
|
202
191
|
path: permalink,
|
|
203
192
|
component: blogListComponent,
|
|
@@ -227,6 +216,7 @@ function pluginContentBlog(context, options) {
|
|
|
227
216
|
const tagsModule = {};
|
|
228
217
|
await Promise.all(Object.keys(blogTags).map(async (tag) => {
|
|
229
218
|
const { name, items, permalink } = blogTags[tag];
|
|
219
|
+
// Refactor all this, see docs implementation
|
|
230
220
|
tagsModule[tag] = {
|
|
231
221
|
allTagsPath: blogTagsListPath,
|
|
232
222
|
slug: tag,
|
|
@@ -234,7 +224,7 @@ function pluginContentBlog(context, options) {
|
|
|
234
224
|
count: items.length,
|
|
235
225
|
permalink,
|
|
236
226
|
};
|
|
237
|
-
const tagsMetadataPath = await createData(`${utils_1.docuHash(permalink)}.json`, JSON.stringify(tagsModule[tag], null, 2));
|
|
227
|
+
const tagsMetadataPath = await createData(`${(0, utils_1.docuHash)(permalink)}.json`, JSON.stringify(tagsModule[tag], null, 2));
|
|
238
228
|
addRoute({
|
|
239
229
|
path: permalink,
|
|
240
230
|
component: blogTagsPostsComponent,
|
|
@@ -259,7 +249,7 @@ function pluginContentBlog(context, options) {
|
|
|
259
249
|
}));
|
|
260
250
|
// Only create /tags page if there are tags.
|
|
261
251
|
if (Object.keys(blogTags).length > 0) {
|
|
262
|
-
const tagsListPath = await createData(`${utils_1.docuHash(`${blogTagsListPath}-tags`)}.json`, JSON.stringify(tagsModule, null, 2));
|
|
252
|
+
const tagsListPath = await createData(`${(0, utils_1.docuHash)(`${blogTagsListPath}-tags`)}.json`, JSON.stringify(tagsModule, null, 2));
|
|
263
253
|
addRoute({
|
|
264
254
|
path: blogTagsListPath,
|
|
265
255
|
component: blogTagsListComponent,
|
|
@@ -271,20 +261,24 @@ function pluginContentBlog(context, options) {
|
|
|
271
261
|
});
|
|
272
262
|
}
|
|
273
263
|
},
|
|
264
|
+
translateContent({ content, translationFiles }) {
|
|
265
|
+
return (0, translations_1.translateContent)(content, translationFiles);
|
|
266
|
+
},
|
|
274
267
|
configureWebpack(_config, isServer, { getJSLoader }, content) {
|
|
275
268
|
const { rehypePlugins, remarkPlugins, truncateMarker, beforeDefaultRemarkPlugins, beforeDefaultRehypePlugins, } = options;
|
|
276
269
|
const markdownLoaderOptions = {
|
|
277
270
|
siteDir,
|
|
278
271
|
contentPaths,
|
|
279
272
|
truncateMarker,
|
|
280
|
-
sourceToPermalink: blogUtils_1.getSourceToPermalink(content.blogPosts),
|
|
273
|
+
sourceToPermalink: (0, blogUtils_1.getSourceToPermalink)(content.blogPosts),
|
|
281
274
|
onBrokenMarkdownLink: (brokenMarkdownLink) => {
|
|
282
275
|
if (onBrokenMarkdownLinks === 'ignore') {
|
|
283
276
|
return;
|
|
284
277
|
}
|
|
285
|
-
utils_1.reportMessage(`Blog markdown link couldn't be resolved: (${brokenMarkdownLink.link}) in ${brokenMarkdownLink.filePath}`, onBrokenMarkdownLinks);
|
|
278
|
+
(0, utils_1.reportMessage)(`Blog markdown link couldn't be resolved: (${brokenMarkdownLink.link}) in ${brokenMarkdownLink.filePath}`, onBrokenMarkdownLinks);
|
|
286
279
|
},
|
|
287
280
|
};
|
|
281
|
+
const contentDirs = (0, blogUtils_1.getContentPathList)(contentPaths);
|
|
288
282
|
return {
|
|
289
283
|
resolve: {
|
|
290
284
|
alias: {
|
|
@@ -295,7 +289,7 @@ function pluginContentBlog(context, options) {
|
|
|
295
289
|
rules: [
|
|
296
290
|
{
|
|
297
291
|
test: /(\.mdx?)$/,
|
|
298
|
-
include:
|
|
292
|
+
include: contentDirs
|
|
299
293
|
// Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
|
|
300
294
|
.map(utils_1.addTrailingPathSeparator),
|
|
301
295
|
use: [
|
|
@@ -308,15 +302,23 @@ function pluginContentBlog(context, options) {
|
|
|
308
302
|
beforeDefaultRemarkPlugins,
|
|
309
303
|
beforeDefaultRehypePlugins,
|
|
310
304
|
staticDir: path_1.default.join(siteDir, constants_1.STATIC_DIR_NAME),
|
|
311
|
-
|
|
312
|
-
// the path from createData for each MDX.
|
|
305
|
+
isMDXPartial: (0, utils_1.createAbsoluteFilePathMatcher)(options.exclude, contentDirs),
|
|
313
306
|
metadataPath: (mdxPath) => {
|
|
314
|
-
|
|
315
|
-
|
|
307
|
+
// Note that metadataPath must be the same/in-sync as
|
|
308
|
+
// the path from createData for each MDX.
|
|
309
|
+
const aliasedPath = (0, utils_1.aliasedSitePath)(mdxPath, siteDir);
|
|
310
|
+
return path_1.default.join(dataDir, `${(0, utils_1.docuHash)(aliasedPath)}.json`);
|
|
316
311
|
},
|
|
317
312
|
// For blog posts a title in markdown is always removed
|
|
318
313
|
// Blog posts title are rendered separately
|
|
319
314
|
removeContentTitle: true,
|
|
315
|
+
// Assets allow to convert some relative images paths to require() calls
|
|
316
|
+
createAssets: ({ frontMatter, metadata, }) => {
|
|
317
|
+
return {
|
|
318
|
+
image: frontMatter.image,
|
|
319
|
+
authorsImageUrls: metadata.authors.map((author) => author.imageURL),
|
|
320
|
+
};
|
|
321
|
+
},
|
|
320
322
|
},
|
|
321
323
|
},
|
|
322
324
|
{
|
|
@@ -330,11 +332,10 @@ function pluginContentBlog(context, options) {
|
|
|
330
332
|
};
|
|
331
333
|
},
|
|
332
334
|
async postBuild({ outDir }) {
|
|
333
|
-
|
|
334
|
-
if (!((_a = options.feedOptions) === null || _a === void 0 ? void 0 : _a.type)) {
|
|
335
|
+
if (!options.feedOptions.type) {
|
|
335
336
|
return;
|
|
336
337
|
}
|
|
337
|
-
const feed = await blogUtils_1.generateBlogFeed(contentPaths, context, options);
|
|
338
|
+
const feed = await (0, blogUtils_1.generateBlogFeed)(contentPaths, context, options);
|
|
338
339
|
if (!feed) {
|
|
339
340
|
return;
|
|
340
341
|
}
|
|
@@ -351,7 +352,7 @@ function pluginContentBlog(context, options) {
|
|
|
351
352
|
}));
|
|
352
353
|
},
|
|
353
354
|
injectHtmlTags({ content }) {
|
|
354
|
-
var _a;
|
|
355
|
+
var _a, _b;
|
|
355
356
|
if (!content.blogPosts.length) {
|
|
356
357
|
return {};
|
|
357
358
|
}
|
|
@@ -359,17 +360,17 @@ function pluginContentBlog(context, options) {
|
|
|
359
360
|
return {};
|
|
360
361
|
}
|
|
361
362
|
const feedTypes = options.feedOptions.type;
|
|
362
|
-
const
|
|
363
|
+
const feedTitle = (_b = options.feedOptions.title) !== null && _b !== void 0 ? _b : context.siteConfig.title;
|
|
363
364
|
const feedsConfig = {
|
|
364
365
|
rss: {
|
|
365
366
|
type: 'application/rss+xml',
|
|
366
367
|
path: 'rss.xml',
|
|
367
|
-
title: `${
|
|
368
|
+
title: `${feedTitle} RSS Feed`,
|
|
368
369
|
},
|
|
369
370
|
atom: {
|
|
370
371
|
type: 'application/atom+xml',
|
|
371
372
|
path: 'atom.xml',
|
|
372
|
-
title: `${
|
|
373
|
+
title: `${feedTitle} Atom Feed`,
|
|
373
374
|
},
|
|
374
375
|
};
|
|
375
376
|
const headTags = [];
|
|
@@ -384,7 +385,7 @@ function pluginContentBlog(context, options) {
|
|
|
384
385
|
attributes: {
|
|
385
386
|
rel: 'alternate',
|
|
386
387
|
type,
|
|
387
|
-
href: utils_1.normalizeUrl([
|
|
388
|
+
href: (0, utils_1.normalizeUrl)([
|
|
388
389
|
baseUrl,
|
|
389
390
|
options.routeBasePath,
|
|
390
391
|
feedConfigPath,
|
package/lib/markdownLoader.js
CHANGED
|
@@ -14,17 +14,17 @@ const markdownLoader = function (source) {
|
|
|
14
14
|
const callback = this.async();
|
|
15
15
|
const markdownLoaderOptions = this.getOptions();
|
|
16
16
|
// Linkify blog posts
|
|
17
|
-
let finalContent = blogUtils_1.linkify({
|
|
17
|
+
let finalContent = (0, blogUtils_1.linkify)({
|
|
18
18
|
fileString,
|
|
19
19
|
filePath,
|
|
20
20
|
...markdownLoaderOptions,
|
|
21
21
|
});
|
|
22
22
|
// Truncate content if requested (e.g: file.md?truncated=true).
|
|
23
23
|
const truncated = this.resourceQuery
|
|
24
|
-
? !!loader_utils_1.parseQuery(this.resourceQuery).truncated
|
|
24
|
+
? !!(0, loader_utils_1.parseQuery)(this.resourceQuery).truncated
|
|
25
25
|
: undefined;
|
|
26
26
|
if (truncated) {
|
|
27
|
-
finalContent = blogUtils_1.truncate(finalContent, markdownLoaderOptions.truncateMarker);
|
|
27
|
+
finalContent = (0, blogUtils_1.truncate)(finalContent, markdownLoaderOptions.truncateMarker);
|
|
28
28
|
}
|
|
29
29
|
return callback && callback(null, finalContent);
|
|
30
30
|
};
|
|
@@ -5,29 +5,6 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import { Joi } from '@docusaurus/utils-validation';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
};
|
|
12
|
-
beforeDefaultRehypePlugins: never[];
|
|
13
|
-
beforeDefaultRemarkPlugins: never[];
|
|
14
|
-
admonitions: {};
|
|
15
|
-
truncateMarker: RegExp;
|
|
16
|
-
rehypePlugins: never[];
|
|
17
|
-
remarkPlugins: never[];
|
|
18
|
-
showReadingTime: boolean;
|
|
19
|
-
blogTagsPostsComponent: string;
|
|
20
|
-
blogTagsListComponent: string;
|
|
21
|
-
blogPostComponent: string;
|
|
22
|
-
blogListComponent: string;
|
|
23
|
-
blogDescription: string;
|
|
24
|
-
blogTitle: string;
|
|
25
|
-
blogSidebarCount: number;
|
|
26
|
-
blogSidebarTitle: string;
|
|
27
|
-
postsPerPage: number;
|
|
28
|
-
include: string[];
|
|
29
|
-
routeBasePath: string;
|
|
30
|
-
path: string;
|
|
31
|
-
editLocalizedFiles: boolean;
|
|
32
|
-
};
|
|
33
|
-
export declare const PluginOptionSchema: Joi.ObjectSchema<any>;
|
|
8
|
+
import { PluginOptions } from './types';
|
|
9
|
+
export declare const DEFAULT_OPTIONS: PluginOptions;
|
|
10
|
+
export declare const PluginOptionSchema: Joi.ObjectSchema<PluginOptions>;
|
|
@@ -8,8 +8,9 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.PluginOptionSchema = exports.DEFAULT_OPTIONS = void 0;
|
|
10
10
|
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
11
|
+
const utils_1 = require("@docusaurus/utils");
|
|
11
12
|
exports.DEFAULT_OPTIONS = {
|
|
12
|
-
feedOptions: { type: ['rss', 'atom'] },
|
|
13
|
+
feedOptions: { type: ['rss', 'atom'], copyright: '' },
|
|
13
14
|
beforeDefaultRehypePlugins: [],
|
|
14
15
|
beforeDefaultRemarkPlugins: [],
|
|
15
16
|
admonitions: {},
|
|
@@ -26,21 +27,27 @@ exports.DEFAULT_OPTIONS = {
|
|
|
26
27
|
blogSidebarCount: 5,
|
|
27
28
|
blogSidebarTitle: 'Recent posts',
|
|
28
29
|
postsPerPage: 10,
|
|
29
|
-
include: ['
|
|
30
|
+
include: ['**/*.{md,mdx}'],
|
|
31
|
+
exclude: utils_1.GlobExcludeDefault,
|
|
30
32
|
routeBasePath: 'blog',
|
|
33
|
+
tagsBasePath: 'tags',
|
|
34
|
+
archiveBasePath: 'archive',
|
|
31
35
|
path: 'blog',
|
|
32
36
|
editLocalizedFiles: false,
|
|
37
|
+
authorsMapPath: 'authors.yml',
|
|
33
38
|
};
|
|
34
39
|
exports.PluginOptionSchema = utils_validation_1.Joi.object({
|
|
35
40
|
path: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.path),
|
|
41
|
+
archiveBasePath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.archiveBasePath),
|
|
36
42
|
routeBasePath: utils_validation_1.Joi.string()
|
|
37
43
|
// '' not allowed, see https://github.com/facebook/docusaurus/issues/3374
|
|
38
44
|
// .allow('')
|
|
39
45
|
.default(exports.DEFAULT_OPTIONS.routeBasePath),
|
|
46
|
+
tagsBasePath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.tagsBasePath),
|
|
40
47
|
include: utils_validation_1.Joi.array().items(utils_validation_1.Joi.string()).default(exports.DEFAULT_OPTIONS.include),
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
.min(1)
|
|
48
|
+
exclude: utils_validation_1.Joi.array().items(utils_validation_1.Joi.string()).default(exports.DEFAULT_OPTIONS.exclude),
|
|
49
|
+
postsPerPage: utils_validation_1.Joi.alternatives()
|
|
50
|
+
.try(utils_validation_1.Joi.equal('ALL').required(), utils_validation_1.Joi.number().integer().min(1).required())
|
|
44
51
|
.default(exports.DEFAULT_OPTIONS.postsPerPage),
|
|
45
52
|
blogListComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogListComponent),
|
|
46
53
|
blogPostComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogPostComponent),
|
|
@@ -51,7 +58,7 @@ exports.PluginOptionSchema = utils_validation_1.Joi.object({
|
|
|
51
58
|
.allow('')
|
|
52
59
|
.default(exports.DEFAULT_OPTIONS.blogDescription),
|
|
53
60
|
blogSidebarCount: utils_validation_1.Joi.alternatives()
|
|
54
|
-
.try(utils_validation_1.Joi.equal('ALL').required(), utils_validation_1.Joi.number().required())
|
|
61
|
+
.try(utils_validation_1.Joi.equal('ALL').required(), utils_validation_1.Joi.number().integer().min(0).required())
|
|
55
62
|
.default(exports.DEFAULT_OPTIONS.blogSidebarCount),
|
|
56
63
|
blogSidebarTitle: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogSidebarTitle),
|
|
57
64
|
showReadingTime: utils_validation_1.Joi.bool().default(exports.DEFAULT_OPTIONS.showReadingTime),
|
|
@@ -72,7 +79,15 @@ exports.PluginOptionSchema = utils_validation_1.Joi.object({
|
|
|
72
79
|
.default(exports.DEFAULT_OPTIONS.feedOptions.type),
|
|
73
80
|
title: utils_validation_1.Joi.string().allow(''),
|
|
74
81
|
description: utils_validation_1.Joi.string().allow(''),
|
|
75
|
-
|
|
82
|
+
// only add default value when user actually wants a feed (type is not null)
|
|
83
|
+
copyright: utils_validation_1.Joi.when('type', {
|
|
84
|
+
is: utils_validation_1.Joi.any().valid(null),
|
|
85
|
+
then: utils_validation_1.Joi.string().optional(),
|
|
86
|
+
otherwise: utils_validation_1.Joi.string()
|
|
87
|
+
.allow('')
|
|
88
|
+
.default(exports.DEFAULT_OPTIONS.feedOptions.copyright),
|
|
89
|
+
}),
|
|
76
90
|
language: utils_validation_1.Joi.string(),
|
|
77
91
|
}).default(exports.DEFAULT_OPTIONS.feedOptions),
|
|
92
|
+
authorsMapPath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.authorsMapPath),
|
|
78
93
|
});
|
|
@@ -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 { BlogContent, PluginOptions } from './types';
|
|
8
|
+
import type { TranslationFiles } from '@docusaurus/types';
|
|
9
|
+
export declare function getTranslationFiles(options: PluginOptions): TranslationFiles;
|
|
10
|
+
export declare function translateContent(content: BlogContent, translationFiles: TranslationFiles): BlogContent;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.translateContent = exports.getTranslationFiles = void 0;
|
|
10
|
+
function translateListPage(blogListPaginated, translations) {
|
|
11
|
+
return blogListPaginated.map((page) => {
|
|
12
|
+
const { items, metadata } = page;
|
|
13
|
+
return {
|
|
14
|
+
items,
|
|
15
|
+
metadata: {
|
|
16
|
+
...metadata,
|
|
17
|
+
blogTitle: translations.title.message,
|
|
18
|
+
blogDescription: translations.description.message,
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
function getTranslationFiles(options) {
|
|
24
|
+
return [
|
|
25
|
+
{
|
|
26
|
+
path: 'options',
|
|
27
|
+
content: {
|
|
28
|
+
title: {
|
|
29
|
+
message: options.blogTitle,
|
|
30
|
+
description: 'The title for the blog used in SEO',
|
|
31
|
+
},
|
|
32
|
+
description: {
|
|
33
|
+
message: options.blogDescription,
|
|
34
|
+
description: 'The description for the blog used in SEO',
|
|
35
|
+
},
|
|
36
|
+
'sidebar.title': {
|
|
37
|
+
message: options.blogSidebarTitle,
|
|
38
|
+
description: 'The label for the left sidebar',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
];
|
|
43
|
+
}
|
|
44
|
+
exports.getTranslationFiles = getTranslationFiles;
|
|
45
|
+
function translateContent(content, translationFiles) {
|
|
46
|
+
const [{ content: optonsTranslations }] = translationFiles;
|
|
47
|
+
return {
|
|
48
|
+
...content,
|
|
49
|
+
blogSidebarTitle: optonsTranslations['sidebar.title'].message,
|
|
50
|
+
blogListPaginated: translateListPage(content.blogListPaginated, optonsTranslations),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
exports.translateContent = translateContent;
|
package/lib/types.d.ts
CHANGED
|
@@ -5,31 +5,43 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import type { RemarkAndRehypePluginOptions } from '@docusaurus/mdx-loader';
|
|
8
|
-
import {
|
|
8
|
+
import type { Tag } from '@docusaurus/utils';
|
|
9
|
+
import type { BrokenMarkdownLink, ContentPaths } from '@docusaurus/utils/lib/markdownLinks';
|
|
10
|
+
import { Overwrite } from 'utility-types';
|
|
9
11
|
export declare type BlogContentPaths = ContentPaths;
|
|
10
12
|
export interface BlogContent {
|
|
13
|
+
blogSidebarTitle: string;
|
|
11
14
|
blogPosts: BlogPost[];
|
|
12
15
|
blogListPaginated: BlogPaginated[];
|
|
13
16
|
blogTags: BlogTags;
|
|
14
17
|
blogTagsListPath: string | null;
|
|
15
18
|
}
|
|
16
|
-
export interface DateLink {
|
|
17
|
-
date: Date;
|
|
18
|
-
link: string;
|
|
19
|
-
}
|
|
20
19
|
export declare type FeedType = 'rss' | 'atom';
|
|
20
|
+
export declare type FeedOptions = {
|
|
21
|
+
type?: FeedType[] | null;
|
|
22
|
+
title?: string;
|
|
23
|
+
description?: string;
|
|
24
|
+
copyright: string;
|
|
25
|
+
language?: string;
|
|
26
|
+
};
|
|
27
|
+
export declare type UserFeedOptions = Overwrite<Partial<FeedOptions>, {
|
|
28
|
+
type?: FeedOptions['type'] | 'all';
|
|
29
|
+
}>;
|
|
21
30
|
export declare type EditUrlFunction = (editUrlParams: {
|
|
22
31
|
blogDirPath: string;
|
|
23
32
|
blogPath: string;
|
|
24
33
|
permalink: string;
|
|
25
34
|
locale: string;
|
|
26
35
|
}) => string | undefined;
|
|
27
|
-
export
|
|
36
|
+
export declare type PluginOptions = RemarkAndRehypePluginOptions & {
|
|
28
37
|
id?: string;
|
|
29
38
|
path: string;
|
|
30
39
|
routeBasePath: string;
|
|
40
|
+
tagsBasePath: string;
|
|
41
|
+
archiveBasePath: string;
|
|
31
42
|
include: string[];
|
|
32
|
-
|
|
43
|
+
exclude: string[];
|
|
44
|
+
postsPerPage: number | 'ALL';
|
|
33
45
|
blogListComponent: string;
|
|
34
46
|
blogPostComponent: string;
|
|
35
47
|
blogTagsListComponent: string;
|
|
@@ -41,7 +53,7 @@ export interface PluginOptions extends RemarkAndRehypePluginOptions {
|
|
|
41
53
|
truncateMarker: RegExp;
|
|
42
54
|
showReadingTime: boolean;
|
|
43
55
|
feedOptions: {
|
|
44
|
-
type?: [
|
|
56
|
+
type?: FeedType[] | null;
|
|
45
57
|
title?: string;
|
|
46
58
|
description?: string;
|
|
47
59
|
copyright: string;
|
|
@@ -50,7 +62,11 @@ export interface PluginOptions extends RemarkAndRehypePluginOptions {
|
|
|
50
62
|
editUrl?: string | EditUrlFunction;
|
|
51
63
|
editLocalizedFiles?: boolean;
|
|
52
64
|
admonitions: Record<string, unknown>;
|
|
53
|
-
|
|
65
|
+
authorsMapPath: string;
|
|
66
|
+
};
|
|
67
|
+
export declare type UserPluginOptions = Overwrite<Partial<PluginOptions>, {
|
|
68
|
+
feedOptions?: UserFeedOptions;
|
|
69
|
+
}>;
|
|
54
70
|
export interface BlogTags {
|
|
55
71
|
[key: string]: BlogTag;
|
|
56
72
|
}
|
|
@@ -62,6 +78,7 @@ export interface BlogTag {
|
|
|
62
78
|
export interface BlogPost {
|
|
63
79
|
id: string;
|
|
64
80
|
metadata: MetaData;
|
|
81
|
+
content: string;
|
|
65
82
|
}
|
|
66
83
|
export interface BlogPaginatedMetadata {
|
|
67
84
|
permalink: string;
|
|
@@ -78,28 +95,35 @@ export interface BlogPaginated {
|
|
|
78
95
|
metadata: BlogPaginatedMetadata;
|
|
79
96
|
items: string[];
|
|
80
97
|
}
|
|
98
|
+
export interface Author extends Record<string, unknown> {
|
|
99
|
+
name?: string;
|
|
100
|
+
imageURL?: string;
|
|
101
|
+
url?: string;
|
|
102
|
+
title?: string;
|
|
103
|
+
}
|
|
81
104
|
export interface MetaData {
|
|
82
105
|
permalink: string;
|
|
83
106
|
source: string;
|
|
84
107
|
description: string;
|
|
85
108
|
date: Date;
|
|
86
109
|
formattedDate: string;
|
|
87
|
-
tags:
|
|
110
|
+
tags: Tag[];
|
|
88
111
|
title: string;
|
|
89
112
|
readingTime?: number;
|
|
90
113
|
prevItem?: Paginator;
|
|
91
114
|
nextItem?: Paginator;
|
|
92
115
|
truncated: boolean;
|
|
93
116
|
editUrl?: string;
|
|
117
|
+
authors: Author[];
|
|
118
|
+
}
|
|
119
|
+
export interface Assets {
|
|
120
|
+
image?: string;
|
|
121
|
+
authorsImageUrls: (string | undefined)[];
|
|
94
122
|
}
|
|
95
123
|
export interface Paginator {
|
|
96
124
|
title: string;
|
|
97
125
|
permalink: string;
|
|
98
126
|
}
|
|
99
|
-
export interface Tag {
|
|
100
|
-
label: string;
|
|
101
|
-
permalink: string;
|
|
102
|
-
}
|
|
103
127
|
export interface BlogItemsToMetadata {
|
|
104
128
|
[key: string]: MetaData;
|
|
105
129
|
}
|