@docusaurus/plugin-content-blog 2.0.0-beta.6f366f4b4 → 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 +76 -70
- package/lib/markdownLoader.js +3 -3
- package/lib/pluginOptionSchema.d.ts +3 -27
- package/lib/pluginOptionSchema.js +19 -7
- package/lib/translations.d.ts +10 -0
- package/lib/translations.js +53 -0
- package/lib/types.d.ts +37 -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/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 +41 -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 +4 -0
- 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 +205 -132
- package/src/index.ts +92 -61
- package/{index.d.ts → src/plugin-content-blog.d.ts} +35 -31
- package/src/pluginOptionSchema.ts +22 -9
- package/src/translations.ts +63 -0
- package/src/types.ts +47 -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,21 +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];
|
|
53
|
+
},
|
|
54
|
+
async getTranslationFiles() {
|
|
55
|
+
return (0, translations_1.getTranslationFiles)(options);
|
|
47
56
|
},
|
|
48
57
|
// Fetches blog contents and returns metadata for the necessary routes.
|
|
49
58
|
async loadContent() {
|
|
50
|
-
const { postsPerPage, routeBasePath } = options;
|
|
51
|
-
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);
|
|
52
61
|
if (!blogPosts.length) {
|
|
53
62
|
return {
|
|
63
|
+
blogSidebarTitle,
|
|
54
64
|
blogPosts: [],
|
|
55
65
|
blogListPaginated: [],
|
|
56
66
|
blogTags: {},
|
|
@@ -77,14 +87,14 @@ function pluginContentBlog(context, options) {
|
|
|
77
87
|
// Blog pagination routes.
|
|
78
88
|
// Example: `/blog`, `/blog/page/1`, `/blog/page/2`
|
|
79
89
|
const totalCount = blogPosts.length;
|
|
90
|
+
const postsPerPage = postsPerPageOption === 'ALL' ? totalCount : postsPerPageOption;
|
|
80
91
|
const numberOfPages = Math.ceil(totalCount / postsPerPage);
|
|
81
|
-
const
|
|
82
|
-
const basePageUrl = utils_1.normalizeUrl([baseUrl, routeBasePath]);
|
|
92
|
+
const baseBlogUrl = (0, utils_1.normalizeUrl)([baseUrl, routeBasePath]);
|
|
83
93
|
const blogListPaginated = [];
|
|
84
94
|
function blogPaginationPermalink(page) {
|
|
85
95
|
return page > 0
|
|
86
|
-
? utils_1.normalizeUrl([
|
|
87
|
-
:
|
|
96
|
+
? (0, utils_1.normalizeUrl)([baseBlogUrl, `page/${page + 1}`])
|
|
97
|
+
: baseBlogUrl;
|
|
88
98
|
}
|
|
89
99
|
for (let page = 0; page < numberOfPages; page += 1) {
|
|
90
100
|
blogListPaginated.push({
|
|
@@ -98,48 +108,19 @@ function pluginContentBlog(context, options) {
|
|
|
98
108
|
nextPage: page < numberOfPages - 1
|
|
99
109
|
? blogPaginationPermalink(page + 1)
|
|
100
110
|
: null,
|
|
101
|
-
blogDescription
|
|
102
|
-
blogTitle
|
|
111
|
+
blogDescription,
|
|
112
|
+
blogTitle,
|
|
103
113
|
},
|
|
104
114
|
items: blogPosts
|
|
105
115
|
.slice(page * postsPerPage, (page + 1) * postsPerPage)
|
|
106
116
|
.map((item) => item.id),
|
|
107
117
|
});
|
|
108
118
|
}
|
|
109
|
-
const blogTags =
|
|
110
|
-
const tagsPath = utils_1.normalizeUrl([
|
|
111
|
-
blogPosts.forEach((blogPost) => {
|
|
112
|
-
const { tags } = blogPost.metadata;
|
|
113
|
-
if (!tags || tags.length === 0) {
|
|
114
|
-
// TODO: Extract tags out into a separate plugin.
|
|
115
|
-
// eslint-disable-next-line no-param-reassign
|
|
116
|
-
blogPost.metadata.tags = [];
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
// eslint-disable-next-line no-param-reassign
|
|
120
|
-
blogPost.metadata.tags = tags.map((tag) => {
|
|
121
|
-
if (typeof tag === 'string') {
|
|
122
|
-
const normalizedTag = lodash_1.kebabCase(tag);
|
|
123
|
-
const permalink = utils_1.normalizeUrl([tagsPath, normalizedTag]);
|
|
124
|
-
if (!blogTags[normalizedTag]) {
|
|
125
|
-
blogTags[normalizedTag] = {
|
|
126
|
-
// Will only use the name of the first occurrence of the tag.
|
|
127
|
-
name: tag.toLowerCase(),
|
|
128
|
-
items: [],
|
|
129
|
-
permalink,
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
blogTags[normalizedTag].items.push(blogPost.id);
|
|
133
|
-
return {
|
|
134
|
-
label: tag,
|
|
135
|
-
permalink,
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
return tag;
|
|
139
|
-
});
|
|
140
|
-
});
|
|
119
|
+
const blogTags = (0, blogUtils_1.getBlogTags)(blogPosts);
|
|
120
|
+
const tagsPath = (0, utils_1.normalizeUrl)([baseBlogUrl, tagsBasePath]);
|
|
141
121
|
const blogTagsListPath = Object.keys(blogTags).length > 0 ? tagsPath : null;
|
|
142
122
|
return {
|
|
123
|
+
blogSidebarTitle,
|
|
143
124
|
blogPosts,
|
|
144
125
|
blogListPaginated,
|
|
145
126
|
blogTags,
|
|
@@ -150,19 +131,34 @@ function pluginContentBlog(context, options) {
|
|
|
150
131
|
if (!blogContents) {
|
|
151
132
|
return;
|
|
152
133
|
}
|
|
153
|
-
const { blogListComponent, blogPostComponent, blogTagsListComponent, blogTagsPostsComponent, } = options;
|
|
134
|
+
const { blogListComponent, blogPostComponent, blogTagsListComponent, blogTagsPostsComponent, routeBasePath, archiveBasePath, } = options;
|
|
154
135
|
const { addRoute, createData } = actions;
|
|
155
|
-
const { blogPosts, blogListPaginated, blogTags, blogTagsListPath, } = blogContents;
|
|
136
|
+
const { blogSidebarTitle, blogPosts, blogListPaginated, blogTags, blogTagsListPath, } = blogContents;
|
|
156
137
|
const blogItemsToMetadata = {};
|
|
157
138
|
const sidebarBlogPosts = options.blogSidebarCount === 'ALL'
|
|
158
139
|
? blogPosts
|
|
159
|
-
: 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
|
+
});
|
|
160
156
|
// This prop is useful to provide the blog list sidebar
|
|
161
157
|
const sidebarProp = await createData(
|
|
162
158
|
// Note that this created data path must be in sync with
|
|
163
159
|
// metadataPath provided to mdx-loader.
|
|
164
160
|
`blog-post-list-prop-${pluginId}.json`, JSON.stringify({
|
|
165
|
-
title:
|
|
161
|
+
title: blogSidebarTitle,
|
|
166
162
|
items: sidebarBlogPosts.map((blogPost) => ({
|
|
167
163
|
title: blogPost.metadata.title,
|
|
168
164
|
permalink: blogPost.metadata.permalink,
|
|
@@ -174,7 +170,7 @@ function pluginContentBlog(context, options) {
|
|
|
174
170
|
await createData(
|
|
175
171
|
// Note that this created data path must be in sync with
|
|
176
172
|
// metadataPath provided to mdx-loader.
|
|
177
|
-
`${utils_1.docuHash(metadata.source)}.json`, JSON.stringify(metadata, null, 2));
|
|
173
|
+
`${(0, utils_1.docuHash)(metadata.source)}.json`, JSON.stringify(metadata, null, 2));
|
|
178
174
|
addRoute({
|
|
179
175
|
path: metadata.permalink,
|
|
180
176
|
component: blogPostComponent,
|
|
@@ -190,7 +186,7 @@ function pluginContentBlog(context, options) {
|
|
|
190
186
|
await Promise.all(blogListPaginated.map(async (listPage) => {
|
|
191
187
|
const { metadata, items } = listPage;
|
|
192
188
|
const { permalink } = metadata;
|
|
193
|
-
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));
|
|
194
190
|
addRoute({
|
|
195
191
|
path: permalink,
|
|
196
192
|
component: blogListComponent,
|
|
@@ -220,6 +216,7 @@ function pluginContentBlog(context, options) {
|
|
|
220
216
|
const tagsModule = {};
|
|
221
217
|
await Promise.all(Object.keys(blogTags).map(async (tag) => {
|
|
222
218
|
const { name, items, permalink } = blogTags[tag];
|
|
219
|
+
// Refactor all this, see docs implementation
|
|
223
220
|
tagsModule[tag] = {
|
|
224
221
|
allTagsPath: blogTagsListPath,
|
|
225
222
|
slug: tag,
|
|
@@ -227,7 +224,7 @@ function pluginContentBlog(context, options) {
|
|
|
227
224
|
count: items.length,
|
|
228
225
|
permalink,
|
|
229
226
|
};
|
|
230
|
-
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));
|
|
231
228
|
addRoute({
|
|
232
229
|
path: permalink,
|
|
233
230
|
component: blogTagsPostsComponent,
|
|
@@ -252,7 +249,7 @@ function pluginContentBlog(context, options) {
|
|
|
252
249
|
}));
|
|
253
250
|
// Only create /tags page if there are tags.
|
|
254
251
|
if (Object.keys(blogTags).length > 0) {
|
|
255
|
-
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));
|
|
256
253
|
addRoute({
|
|
257
254
|
path: blogTagsListPath,
|
|
258
255
|
component: blogTagsListComponent,
|
|
@@ -264,21 +261,24 @@ function pluginContentBlog(context, options) {
|
|
|
264
261
|
});
|
|
265
262
|
}
|
|
266
263
|
},
|
|
264
|
+
translateContent({ content, translationFiles }) {
|
|
265
|
+
return (0, translations_1.translateContent)(content, translationFiles);
|
|
266
|
+
},
|
|
267
267
|
configureWebpack(_config, isServer, { getJSLoader }, content) {
|
|
268
268
|
const { rehypePlugins, remarkPlugins, truncateMarker, beforeDefaultRemarkPlugins, beforeDefaultRehypePlugins, } = options;
|
|
269
269
|
const markdownLoaderOptions = {
|
|
270
270
|
siteDir,
|
|
271
271
|
contentPaths,
|
|
272
272
|
truncateMarker,
|
|
273
|
-
sourceToPermalink: blogUtils_1.getSourceToPermalink(content.blogPosts),
|
|
273
|
+
sourceToPermalink: (0, blogUtils_1.getSourceToPermalink)(content.blogPosts),
|
|
274
274
|
onBrokenMarkdownLink: (brokenMarkdownLink) => {
|
|
275
275
|
if (onBrokenMarkdownLinks === 'ignore') {
|
|
276
276
|
return;
|
|
277
277
|
}
|
|
278
|
-
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);
|
|
279
279
|
},
|
|
280
280
|
};
|
|
281
|
-
const contentDirs = blogUtils_1.getContentPathList(contentPaths);
|
|
281
|
+
const contentDirs = (0, blogUtils_1.getContentPathList)(contentPaths);
|
|
282
282
|
return {
|
|
283
283
|
resolve: {
|
|
284
284
|
alias: {
|
|
@@ -302,16 +302,23 @@ function pluginContentBlog(context, options) {
|
|
|
302
302
|
beforeDefaultRemarkPlugins,
|
|
303
303
|
beforeDefaultRehypePlugins,
|
|
304
304
|
staticDir: path_1.default.join(siteDir, constants_1.STATIC_DIR_NAME),
|
|
305
|
-
isMDXPartial: utils_1.createAbsoluteFilePathMatcher(options.exclude, contentDirs),
|
|
305
|
+
isMDXPartial: (0, utils_1.createAbsoluteFilePathMatcher)(options.exclude, contentDirs),
|
|
306
306
|
metadataPath: (mdxPath) => {
|
|
307
307
|
// Note that metadataPath must be the same/in-sync as
|
|
308
308
|
// the path from createData for each MDX.
|
|
309
|
-
const aliasedPath = utils_1.aliasedSitePath(mdxPath, siteDir);
|
|
310
|
-
return path_1.default.join(dataDir, `${utils_1.docuHash(aliasedPath)}.json`);
|
|
309
|
+
const aliasedPath = (0, utils_1.aliasedSitePath)(mdxPath, siteDir);
|
|
310
|
+
return path_1.default.join(dataDir, `${(0, utils_1.docuHash)(aliasedPath)}.json`);
|
|
311
311
|
},
|
|
312
312
|
// For blog posts a title in markdown is always removed
|
|
313
313
|
// Blog posts title are rendered separately
|
|
314
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
|
+
},
|
|
315
322
|
},
|
|
316
323
|
},
|
|
317
324
|
{
|
|
@@ -325,11 +332,10 @@ function pluginContentBlog(context, options) {
|
|
|
325
332
|
};
|
|
326
333
|
},
|
|
327
334
|
async postBuild({ outDir }) {
|
|
328
|
-
|
|
329
|
-
if (!((_a = options.feedOptions) === null || _a === void 0 ? void 0 : _a.type)) {
|
|
335
|
+
if (!options.feedOptions.type) {
|
|
330
336
|
return;
|
|
331
337
|
}
|
|
332
|
-
const feed = await blogUtils_1.generateBlogFeed(contentPaths, context, options);
|
|
338
|
+
const feed = await (0, blogUtils_1.generateBlogFeed)(contentPaths, context, options);
|
|
333
339
|
if (!feed) {
|
|
334
340
|
return;
|
|
335
341
|
}
|
|
@@ -346,7 +352,7 @@ function pluginContentBlog(context, options) {
|
|
|
346
352
|
}));
|
|
347
353
|
},
|
|
348
354
|
injectHtmlTags({ content }) {
|
|
349
|
-
var _a;
|
|
355
|
+
var _a, _b;
|
|
350
356
|
if (!content.blogPosts.length) {
|
|
351
357
|
return {};
|
|
352
358
|
}
|
|
@@ -354,17 +360,17 @@ function pluginContentBlog(context, options) {
|
|
|
354
360
|
return {};
|
|
355
361
|
}
|
|
356
362
|
const feedTypes = options.feedOptions.type;
|
|
357
|
-
const
|
|
363
|
+
const feedTitle = (_b = options.feedOptions.title) !== null && _b !== void 0 ? _b : context.siteConfig.title;
|
|
358
364
|
const feedsConfig = {
|
|
359
365
|
rss: {
|
|
360
366
|
type: 'application/rss+xml',
|
|
361
367
|
path: 'rss.xml',
|
|
362
|
-
title: `${
|
|
368
|
+
title: `${feedTitle} RSS Feed`,
|
|
363
369
|
},
|
|
364
370
|
atom: {
|
|
365
371
|
type: 'application/atom+xml',
|
|
366
372
|
path: 'atom.xml',
|
|
367
|
-
title: `${
|
|
373
|
+
title: `${feedTitle} Atom Feed`,
|
|
368
374
|
},
|
|
369
375
|
};
|
|
370
376
|
const headTags = [];
|
|
@@ -379,7 +385,7 @@ function pluginContentBlog(context, options) {
|
|
|
379
385
|
attributes: {
|
|
380
386
|
rel: 'alternate',
|
|
381
387
|
type,
|
|
382
|
-
href: utils_1.normalizeUrl([
|
|
388
|
+
href: (0, utils_1.normalizeUrl)([
|
|
383
389
|
baseUrl,
|
|
384
390
|
options.routeBasePath,
|
|
385
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,30 +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
|
-
exclude: string[];
|
|
30
|
-
routeBasePath: string;
|
|
31
|
-
path: string;
|
|
32
|
-
editLocalizedFiles: boolean;
|
|
33
|
-
};
|
|
34
|
-
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>;
|
|
@@ -10,7 +10,7 @@ exports.PluginOptionSchema = exports.DEFAULT_OPTIONS = void 0;
|
|
|
10
10
|
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
11
11
|
const utils_1 = require("@docusaurus/utils");
|
|
12
12
|
exports.DEFAULT_OPTIONS = {
|
|
13
|
-
feedOptions: { type: ['rss', 'atom'] },
|
|
13
|
+
feedOptions: { type: ['rss', 'atom'], copyright: '' },
|
|
14
14
|
beforeDefaultRehypePlugins: [],
|
|
15
15
|
beforeDefaultRemarkPlugins: [],
|
|
16
16
|
admonitions: {},
|
|
@@ -27,23 +27,27 @@ exports.DEFAULT_OPTIONS = {
|
|
|
27
27
|
blogSidebarCount: 5,
|
|
28
28
|
blogSidebarTitle: 'Recent posts',
|
|
29
29
|
postsPerPage: 10,
|
|
30
|
-
include: ['
|
|
30
|
+
include: ['**/*.{md,mdx}'],
|
|
31
31
|
exclude: utils_1.GlobExcludeDefault,
|
|
32
32
|
routeBasePath: 'blog',
|
|
33
|
+
tagsBasePath: 'tags',
|
|
34
|
+
archiveBasePath: 'archive',
|
|
33
35
|
path: 'blog',
|
|
34
36
|
editLocalizedFiles: false,
|
|
37
|
+
authorsMapPath: 'authors.yml',
|
|
35
38
|
};
|
|
36
39
|
exports.PluginOptionSchema = utils_validation_1.Joi.object({
|
|
37
40
|
path: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.path),
|
|
41
|
+
archiveBasePath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.archiveBasePath),
|
|
38
42
|
routeBasePath: utils_validation_1.Joi.string()
|
|
39
43
|
// '' not allowed, see https://github.com/facebook/docusaurus/issues/3374
|
|
40
44
|
// .allow('')
|
|
41
45
|
.default(exports.DEFAULT_OPTIONS.routeBasePath),
|
|
46
|
+
tagsBasePath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.tagsBasePath),
|
|
42
47
|
include: utils_validation_1.Joi.array().items(utils_validation_1.Joi.string()).default(exports.DEFAULT_OPTIONS.include),
|
|
43
48
|
exclude: utils_validation_1.Joi.array().items(utils_validation_1.Joi.string()).default(exports.DEFAULT_OPTIONS.exclude),
|
|
44
|
-
postsPerPage: utils_validation_1.Joi.
|
|
45
|
-
.integer()
|
|
46
|
-
.min(1)
|
|
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())
|
|
47
51
|
.default(exports.DEFAULT_OPTIONS.postsPerPage),
|
|
48
52
|
blogListComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogListComponent),
|
|
49
53
|
blogPostComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogPostComponent),
|
|
@@ -54,7 +58,7 @@ exports.PluginOptionSchema = utils_validation_1.Joi.object({
|
|
|
54
58
|
.allow('')
|
|
55
59
|
.default(exports.DEFAULT_OPTIONS.blogDescription),
|
|
56
60
|
blogSidebarCount: utils_validation_1.Joi.alternatives()
|
|
57
|
-
.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())
|
|
58
62
|
.default(exports.DEFAULT_OPTIONS.blogSidebarCount),
|
|
59
63
|
blogSidebarTitle: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogSidebarTitle),
|
|
60
64
|
showReadingTime: utils_validation_1.Joi.bool().default(exports.DEFAULT_OPTIONS.showReadingTime),
|
|
@@ -75,7 +79,15 @@ exports.PluginOptionSchema = utils_validation_1.Joi.object({
|
|
|
75
79
|
.default(exports.DEFAULT_OPTIONS.feedOptions.type),
|
|
76
80
|
title: utils_validation_1.Joi.string().allow(''),
|
|
77
81
|
description: utils_validation_1.Joi.string().allow(''),
|
|
78
|
-
|
|
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
|
+
}),
|
|
79
90
|
language: utils_validation_1.Joi.string(),
|
|
80
91
|
}).default(exports.DEFAULT_OPTIONS.feedOptions),
|
|
92
|
+
authorsMapPath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.authorsMapPath),
|
|
81
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,32 +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[];
|
|
33
|
-
postsPerPage: number;
|
|
44
|
+
postsPerPage: number | 'ALL';
|
|
34
45
|
blogListComponent: string;
|
|
35
46
|
blogPostComponent: string;
|
|
36
47
|
blogTagsListComponent: string;
|
|
@@ -42,7 +53,7 @@ export interface PluginOptions extends RemarkAndRehypePluginOptions {
|
|
|
42
53
|
truncateMarker: RegExp;
|
|
43
54
|
showReadingTime: boolean;
|
|
44
55
|
feedOptions: {
|
|
45
|
-
type?: [
|
|
56
|
+
type?: FeedType[] | null;
|
|
46
57
|
title?: string;
|
|
47
58
|
description?: string;
|
|
48
59
|
copyright: string;
|
|
@@ -51,7 +62,11 @@ export interface PluginOptions extends RemarkAndRehypePluginOptions {
|
|
|
51
62
|
editUrl?: string | EditUrlFunction;
|
|
52
63
|
editLocalizedFiles?: boolean;
|
|
53
64
|
admonitions: Record<string, unknown>;
|
|
54
|
-
|
|
65
|
+
authorsMapPath: string;
|
|
66
|
+
};
|
|
67
|
+
export declare type UserPluginOptions = Overwrite<Partial<PluginOptions>, {
|
|
68
|
+
feedOptions?: UserFeedOptions;
|
|
69
|
+
}>;
|
|
55
70
|
export interface BlogTags {
|
|
56
71
|
[key: string]: BlogTag;
|
|
57
72
|
}
|
|
@@ -63,6 +78,7 @@ export interface BlogTag {
|
|
|
63
78
|
export interface BlogPost {
|
|
64
79
|
id: string;
|
|
65
80
|
metadata: MetaData;
|
|
81
|
+
content: string;
|
|
66
82
|
}
|
|
67
83
|
export interface BlogPaginatedMetadata {
|
|
68
84
|
permalink: string;
|
|
@@ -79,28 +95,35 @@ export interface BlogPaginated {
|
|
|
79
95
|
metadata: BlogPaginatedMetadata;
|
|
80
96
|
items: string[];
|
|
81
97
|
}
|
|
98
|
+
export interface Author extends Record<string, unknown> {
|
|
99
|
+
name?: string;
|
|
100
|
+
imageURL?: string;
|
|
101
|
+
url?: string;
|
|
102
|
+
title?: string;
|
|
103
|
+
}
|
|
82
104
|
export interface MetaData {
|
|
83
105
|
permalink: string;
|
|
84
106
|
source: string;
|
|
85
107
|
description: string;
|
|
86
108
|
date: Date;
|
|
87
109
|
formattedDate: string;
|
|
88
|
-
tags:
|
|
110
|
+
tags: Tag[];
|
|
89
111
|
title: string;
|
|
90
112
|
readingTime?: number;
|
|
91
113
|
prevItem?: Paginator;
|
|
92
114
|
nextItem?: Paginator;
|
|
93
115
|
truncated: boolean;
|
|
94
116
|
editUrl?: string;
|
|
117
|
+
authors: Author[];
|
|
118
|
+
}
|
|
119
|
+
export interface Assets {
|
|
120
|
+
image?: string;
|
|
121
|
+
authorsImageUrls: (string | undefined)[];
|
|
95
122
|
}
|
|
96
123
|
export interface Paginator {
|
|
97
124
|
title: string;
|
|
98
125
|
permalink: string;
|
|
99
126
|
}
|
|
100
|
-
export interface Tag {
|
|
101
|
-
label: string;
|
|
102
|
-
permalink: string;
|
|
103
|
-
}
|
|
104
127
|
export interface BlogItemsToMetadata {
|
|
105
128
|
[key: string]: MetaData;
|
|
106
129
|
}
|