@docusaurus/plugin-content-blog 2.0.0-beta.8e9b829d9 → 2.0.0-beta.9
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 -4
- package/lib/blogUtils.js +141 -135
- package/lib/feed.d.ts +20 -0
- package/lib/feed.js +90 -0
- package/lib/index.js +86 -85
- package/lib/markdownLoader.d.ts +3 -6
- package/lib/markdownLoader.js +5 -5
- package/lib/pluginOptionSchema.d.ts +3 -27
- package/lib/pluginOptionSchema.js +21 -7
- package/lib/translations.d.ts +10 -0
- package/lib/translations.js +53 -0
- package/lib/types.d.ts +52 -14
- package/package.json +15 -13
- 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/mdx-require-blog-post.mdx +14 -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__/__fixtures__/website/static/img/docusaurus.png +0 -0
- package/src/__tests__/__snapshots__/{generateBlogFeed.test.ts.snap → feed.test.ts.snap} +55 -7
- 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 → feed.test.ts} +32 -8
- package/src/__tests__/index.test.ts +73 -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 +201 -180
- package/src/feed.ts +129 -0
- package/src/index.ts +105 -88
- package/src/markdownLoader.ts +8 -12
- package/{index.d.ts → src/plugin-content-blog.d.ts} +35 -31
- package/src/pluginOptionSchema.ts +24 -9
- package/src/translations.ts +63 -0
- package/src/types.ts +67 -16
package/lib/index.js
CHANGED
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
exports.validateOptions = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const remark_admonitions_1 = tslib_1.__importDefault(require("remark-admonitions"));
|
|
11
|
+
const path_1 = (0, tslib_1.__importDefault)(require("path"));
|
|
12
|
+
const remark_admonitions_1 = (0, tslib_1.__importDefault)(require("remark-admonitions"));
|
|
14
13
|
const utils_1 = require("@docusaurus/utils");
|
|
15
14
|
const constants_1 = require("@docusaurus/core/lib/constants");
|
|
16
|
-
const
|
|
15
|
+
const translations_1 = require("./translations");
|
|
17
16
|
const pluginOptionSchema_1 = require("./pluginOptionSchema");
|
|
18
17
|
const blogUtils_1 = require("./blogUtils");
|
|
18
|
+
const feed_1 = require("./feed");
|
|
19
19
|
function pluginContentBlog(context, options) {
|
|
20
20
|
var _a;
|
|
21
21
|
if (options.admonitions) {
|
|
@@ -23,10 +23,11 @@ function pluginContentBlog(context, options) {
|
|
|
23
23
|
[remark_admonitions_1.default, options.admonitions],
|
|
24
24
|
]);
|
|
25
25
|
}
|
|
26
|
-
const { siteDir, siteConfig
|
|
26
|
+
const { siteDir, siteConfig, generatedFilesDir, i18n: { currentLocale }, } = context;
|
|
27
|
+
const { onBrokenMarkdownLinks, baseUrl } = siteConfig;
|
|
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,28 @@ 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
|
-
|
|
45
|
-
|
|
46
|
-
})
|
|
44
|
+
const { include, authorsMapPath } = options;
|
|
45
|
+
const contentMarkdownGlobs = (0, blogUtils_1.getContentPathList)(contentPaths).flatMap((contentPath) => include.map((pattern) => `${contentPath}/${pattern}`));
|
|
46
|
+
// TODO: we should read this path in plugin! but plugins do not support async init for now :'(
|
|
47
|
+
// const authorsMapFilePath = await getAuthorsMapFilePath({authorsMapPath,contentPaths,});
|
|
48
|
+
// simplified impl, better than nothing for now:
|
|
49
|
+
const authorsMapFilePath = path_1.default.join(contentPaths.contentPath, authorsMapPath);
|
|
50
|
+
return [authorsMapFilePath, ...contentMarkdownGlobs];
|
|
51
|
+
},
|
|
52
|
+
async getTranslationFiles() {
|
|
53
|
+
return (0, translations_1.getTranslationFiles)(options);
|
|
47
54
|
},
|
|
48
55
|
// Fetches blog contents and returns metadata for the necessary routes.
|
|
49
56
|
async loadContent() {
|
|
50
|
-
const { postsPerPage, routeBasePath } = options;
|
|
51
|
-
const blogPosts = await blogUtils_1.generateBlogPosts(contentPaths, context, options);
|
|
57
|
+
const { postsPerPage: postsPerPageOption, routeBasePath, tagsBasePath, blogDescription, blogTitle, blogSidebarTitle, } = options;
|
|
58
|
+
const blogPosts = await (0, blogUtils_1.generateBlogPosts)(contentPaths, context, options);
|
|
52
59
|
if (!blogPosts.length) {
|
|
53
60
|
return {
|
|
61
|
+
blogSidebarTitle,
|
|
54
62
|
blogPosts: [],
|
|
55
63
|
blogListPaginated: [],
|
|
56
64
|
blogTags: {},
|
|
@@ -77,14 +85,14 @@ function pluginContentBlog(context, options) {
|
|
|
77
85
|
// Blog pagination routes.
|
|
78
86
|
// Example: `/blog`, `/blog/page/1`, `/blog/page/2`
|
|
79
87
|
const totalCount = blogPosts.length;
|
|
88
|
+
const postsPerPage = postsPerPageOption === 'ALL' ? totalCount : postsPerPageOption;
|
|
80
89
|
const numberOfPages = Math.ceil(totalCount / postsPerPage);
|
|
81
|
-
const
|
|
82
|
-
const basePageUrl = utils_1.normalizeUrl([baseUrl, routeBasePath]);
|
|
90
|
+
const baseBlogUrl = (0, utils_1.normalizeUrl)([baseUrl, routeBasePath]);
|
|
83
91
|
const blogListPaginated = [];
|
|
84
92
|
function blogPaginationPermalink(page) {
|
|
85
93
|
return page > 0
|
|
86
|
-
? utils_1.normalizeUrl([
|
|
87
|
-
:
|
|
94
|
+
? (0, utils_1.normalizeUrl)([baseBlogUrl, `page/${page + 1}`])
|
|
95
|
+
: baseBlogUrl;
|
|
88
96
|
}
|
|
89
97
|
for (let page = 0; page < numberOfPages; page += 1) {
|
|
90
98
|
blogListPaginated.push({
|
|
@@ -98,48 +106,19 @@ function pluginContentBlog(context, options) {
|
|
|
98
106
|
nextPage: page < numberOfPages - 1
|
|
99
107
|
? blogPaginationPermalink(page + 1)
|
|
100
108
|
: null,
|
|
101
|
-
blogDescription
|
|
102
|
-
blogTitle
|
|
109
|
+
blogDescription,
|
|
110
|
+
blogTitle,
|
|
103
111
|
},
|
|
104
112
|
items: blogPosts
|
|
105
113
|
.slice(page * postsPerPage, (page + 1) * postsPerPage)
|
|
106
114
|
.map((item) => item.id),
|
|
107
115
|
});
|
|
108
116
|
}
|
|
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
|
-
});
|
|
117
|
+
const blogTags = (0, blogUtils_1.getBlogTags)(blogPosts);
|
|
118
|
+
const tagsPath = (0, utils_1.normalizeUrl)([baseBlogUrl, tagsBasePath]);
|
|
141
119
|
const blogTagsListPath = Object.keys(blogTags).length > 0 ? tagsPath : null;
|
|
142
120
|
return {
|
|
121
|
+
blogSidebarTitle,
|
|
143
122
|
blogPosts,
|
|
144
123
|
blogListPaginated,
|
|
145
124
|
blogTags,
|
|
@@ -150,19 +129,34 @@ function pluginContentBlog(context, options) {
|
|
|
150
129
|
if (!blogContents) {
|
|
151
130
|
return;
|
|
152
131
|
}
|
|
153
|
-
const { blogListComponent, blogPostComponent, blogTagsListComponent, blogTagsPostsComponent, } = options;
|
|
132
|
+
const { blogListComponent, blogPostComponent, blogTagsListComponent, blogTagsPostsComponent, routeBasePath, archiveBasePath, } = options;
|
|
154
133
|
const { addRoute, createData } = actions;
|
|
155
|
-
const { blogPosts, blogListPaginated, blogTags, blogTagsListPath, } = blogContents;
|
|
134
|
+
const { blogSidebarTitle, blogPosts, blogListPaginated, blogTags, blogTagsListPath, } = blogContents;
|
|
156
135
|
const blogItemsToMetadata = {};
|
|
157
136
|
const sidebarBlogPosts = options.blogSidebarCount === 'ALL'
|
|
158
137
|
? blogPosts
|
|
159
|
-
:
|
|
138
|
+
: blogPosts.slice(0, options.blogSidebarCount);
|
|
139
|
+
const archiveUrl = (0, utils_1.normalizeUrl)([
|
|
140
|
+
baseUrl,
|
|
141
|
+
routeBasePath,
|
|
142
|
+
archiveBasePath,
|
|
143
|
+
]);
|
|
144
|
+
// creates a blog archive route
|
|
145
|
+
const archiveProp = await createData(`${(0, utils_1.docuHash)(archiveUrl)}.json`, JSON.stringify({ blogPosts }, null, 2));
|
|
146
|
+
addRoute({
|
|
147
|
+
path: archiveUrl,
|
|
148
|
+
component: '@theme/BlogArchivePage',
|
|
149
|
+
exact: true,
|
|
150
|
+
modules: {
|
|
151
|
+
archive: aliasedSource(archiveProp),
|
|
152
|
+
},
|
|
153
|
+
});
|
|
160
154
|
// This prop is useful to provide the blog list sidebar
|
|
161
155
|
const sidebarProp = await createData(
|
|
162
156
|
// Note that this created data path must be in sync with
|
|
163
157
|
// metadataPath provided to mdx-loader.
|
|
164
158
|
`blog-post-list-prop-${pluginId}.json`, JSON.stringify({
|
|
165
|
-
title:
|
|
159
|
+
title: blogSidebarTitle,
|
|
166
160
|
items: sidebarBlogPosts.map((blogPost) => ({
|
|
167
161
|
title: blogPost.metadata.title,
|
|
168
162
|
permalink: blogPost.metadata.permalink,
|
|
@@ -174,7 +168,7 @@ function pluginContentBlog(context, options) {
|
|
|
174
168
|
await createData(
|
|
175
169
|
// Note that this created data path must be in sync with
|
|
176
170
|
// metadataPath provided to mdx-loader.
|
|
177
|
-
`${utils_1.docuHash(metadata.source)}.json`, JSON.stringify(metadata, null, 2));
|
|
171
|
+
`${(0, utils_1.docuHash)(metadata.source)}.json`, JSON.stringify(metadata, null, 2));
|
|
178
172
|
addRoute({
|
|
179
173
|
path: metadata.permalink,
|
|
180
174
|
component: blogPostComponent,
|
|
@@ -190,7 +184,7 @@ function pluginContentBlog(context, options) {
|
|
|
190
184
|
await Promise.all(blogListPaginated.map(async (listPage) => {
|
|
191
185
|
const { metadata, items } = listPage;
|
|
192
186
|
const { permalink } = metadata;
|
|
193
|
-
const pageMetadataPath = await createData(`${utils_1.docuHash(permalink)}.json`, JSON.stringify(metadata, null, 2));
|
|
187
|
+
const pageMetadataPath = await createData(`${(0, utils_1.docuHash)(permalink)}.json`, JSON.stringify(metadata, null, 2));
|
|
194
188
|
addRoute({
|
|
195
189
|
path: permalink,
|
|
196
190
|
component: blogListComponent,
|
|
@@ -220,6 +214,7 @@ function pluginContentBlog(context, options) {
|
|
|
220
214
|
const tagsModule = {};
|
|
221
215
|
await Promise.all(Object.keys(blogTags).map(async (tag) => {
|
|
222
216
|
const { name, items, permalink } = blogTags[tag];
|
|
217
|
+
// Refactor all this, see docs implementation
|
|
223
218
|
tagsModule[tag] = {
|
|
224
219
|
allTagsPath: blogTagsListPath,
|
|
225
220
|
slug: tag,
|
|
@@ -227,7 +222,7 @@ function pluginContentBlog(context, options) {
|
|
|
227
222
|
count: items.length,
|
|
228
223
|
permalink,
|
|
229
224
|
};
|
|
230
|
-
const tagsMetadataPath = await createData(`${utils_1.docuHash(permalink)}.json`, JSON.stringify(tagsModule[tag], null, 2));
|
|
225
|
+
const tagsMetadataPath = await createData(`${(0, utils_1.docuHash)(permalink)}.json`, JSON.stringify(tagsModule[tag], null, 2));
|
|
231
226
|
addRoute({
|
|
232
227
|
path: permalink,
|
|
233
228
|
component: blogTagsPostsComponent,
|
|
@@ -252,7 +247,7 @@ function pluginContentBlog(context, options) {
|
|
|
252
247
|
}));
|
|
253
248
|
// Only create /tags page if there are tags.
|
|
254
249
|
if (Object.keys(blogTags).length > 0) {
|
|
255
|
-
const tagsListPath = await createData(`${utils_1.docuHash(`${blogTagsListPath}-tags`)}.json`, JSON.stringify(tagsModule, null, 2));
|
|
250
|
+
const tagsListPath = await createData(`${(0, utils_1.docuHash)(`${blogTagsListPath}-tags`)}.json`, JSON.stringify(tagsModule, null, 2));
|
|
256
251
|
addRoute({
|
|
257
252
|
path: blogTagsListPath,
|
|
258
253
|
component: blogTagsListComponent,
|
|
@@ -264,21 +259,24 @@ function pluginContentBlog(context, options) {
|
|
|
264
259
|
});
|
|
265
260
|
}
|
|
266
261
|
},
|
|
262
|
+
translateContent({ content, translationFiles }) {
|
|
263
|
+
return (0, translations_1.translateContent)(content, translationFiles);
|
|
264
|
+
},
|
|
267
265
|
configureWebpack(_config, isServer, { getJSLoader }, content) {
|
|
268
266
|
const { rehypePlugins, remarkPlugins, truncateMarker, beforeDefaultRemarkPlugins, beforeDefaultRehypePlugins, } = options;
|
|
269
267
|
const markdownLoaderOptions = {
|
|
270
268
|
siteDir,
|
|
271
269
|
contentPaths,
|
|
272
270
|
truncateMarker,
|
|
273
|
-
sourceToPermalink: blogUtils_1.getSourceToPermalink(content.blogPosts),
|
|
271
|
+
sourceToPermalink: (0, blogUtils_1.getSourceToPermalink)(content.blogPosts),
|
|
274
272
|
onBrokenMarkdownLink: (brokenMarkdownLink) => {
|
|
275
273
|
if (onBrokenMarkdownLinks === 'ignore') {
|
|
276
274
|
return;
|
|
277
275
|
}
|
|
278
|
-
utils_1.reportMessage(`Blog markdown link couldn't be resolved: (${brokenMarkdownLink.link}) in ${brokenMarkdownLink.filePath}`, onBrokenMarkdownLinks);
|
|
276
|
+
(0, utils_1.reportMessage)(`Blog markdown link couldn't be resolved: (${brokenMarkdownLink.link}) in ${brokenMarkdownLink.filePath}`, onBrokenMarkdownLinks);
|
|
279
277
|
},
|
|
280
278
|
};
|
|
281
|
-
const contentDirs = blogUtils_1.getContentPathList(contentPaths);
|
|
279
|
+
const contentDirs = (0, blogUtils_1.getContentPathList)(contentPaths);
|
|
282
280
|
return {
|
|
283
281
|
resolve: {
|
|
284
282
|
alias: {
|
|
@@ -302,16 +300,23 @@ function pluginContentBlog(context, options) {
|
|
|
302
300
|
beforeDefaultRemarkPlugins,
|
|
303
301
|
beforeDefaultRehypePlugins,
|
|
304
302
|
staticDir: path_1.default.join(siteDir, constants_1.STATIC_DIR_NAME),
|
|
305
|
-
isMDXPartial: utils_1.createAbsoluteFilePathMatcher(options.exclude, contentDirs),
|
|
303
|
+
isMDXPartial: (0, utils_1.createAbsoluteFilePathMatcher)(options.exclude, contentDirs),
|
|
306
304
|
metadataPath: (mdxPath) => {
|
|
307
305
|
// Note that metadataPath must be the same/in-sync as
|
|
308
306
|
// 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`);
|
|
307
|
+
const aliasedPath = (0, utils_1.aliasedSitePath)(mdxPath, siteDir);
|
|
308
|
+
return path_1.default.join(dataDir, `${(0, utils_1.docuHash)(aliasedPath)}.json`);
|
|
311
309
|
},
|
|
312
310
|
// For blog posts a title in markdown is always removed
|
|
313
311
|
// Blog posts title are rendered separately
|
|
314
312
|
removeContentTitle: true,
|
|
313
|
+
// Assets allow to convert some relative images paths to require() calls
|
|
314
|
+
createAssets: ({ frontMatter, metadata, }) => {
|
|
315
|
+
return {
|
|
316
|
+
image: frontMatter.image,
|
|
317
|
+
authorsImageUrls: metadata.authors.map((author) => author.imageURL),
|
|
318
|
+
};
|
|
319
|
+
},
|
|
315
320
|
},
|
|
316
321
|
},
|
|
317
322
|
{
|
|
@@ -325,28 +330,24 @@ function pluginContentBlog(context, options) {
|
|
|
325
330
|
};
|
|
326
331
|
},
|
|
327
332
|
async postBuild({ outDir }) {
|
|
328
|
-
|
|
329
|
-
if (!((_a = options.feedOptions) === null || _a === void 0 ? void 0 : _a.type)) {
|
|
333
|
+
if (!options.feedOptions.type) {
|
|
330
334
|
return;
|
|
331
335
|
}
|
|
332
|
-
|
|
333
|
-
|
|
336
|
+
// TODO: we shouldn't need to re-read the posts here!
|
|
337
|
+
// postBuild should receive loadedContent
|
|
338
|
+
const blogPosts = await (0, blogUtils_1.generateBlogPosts)(contentPaths, context, options);
|
|
339
|
+
if (!blogPosts.length) {
|
|
334
340
|
return;
|
|
335
341
|
}
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
}
|
|
343
|
-
catch (err) {
|
|
344
|
-
throw new Error(`Generating ${feedType} feed failed: ${err}.`);
|
|
345
|
-
}
|
|
346
|
-
}));
|
|
342
|
+
await (0, feed_1.createBlogFeedFiles)({
|
|
343
|
+
blogPosts,
|
|
344
|
+
options,
|
|
345
|
+
outDir,
|
|
346
|
+
siteConfig,
|
|
347
|
+
});
|
|
347
348
|
},
|
|
348
349
|
injectHtmlTags({ content }) {
|
|
349
|
-
var _a;
|
|
350
|
+
var _a, _b;
|
|
350
351
|
if (!content.blogPosts.length) {
|
|
351
352
|
return {};
|
|
352
353
|
}
|
|
@@ -354,17 +355,17 @@ function pluginContentBlog(context, options) {
|
|
|
354
355
|
return {};
|
|
355
356
|
}
|
|
356
357
|
const feedTypes = options.feedOptions.type;
|
|
357
|
-
const
|
|
358
|
+
const feedTitle = (_b = options.feedOptions.title) !== null && _b !== void 0 ? _b : context.siteConfig.title;
|
|
358
359
|
const feedsConfig = {
|
|
359
360
|
rss: {
|
|
360
361
|
type: 'application/rss+xml',
|
|
361
362
|
path: 'rss.xml',
|
|
362
|
-
title: `${
|
|
363
|
+
title: `${feedTitle} RSS Feed`,
|
|
363
364
|
},
|
|
364
365
|
atom: {
|
|
365
366
|
type: 'application/atom+xml',
|
|
366
367
|
path: 'atom.xml',
|
|
367
|
-
title: `${
|
|
368
|
+
title: `${feedTitle} Atom Feed`,
|
|
368
369
|
},
|
|
369
370
|
};
|
|
370
371
|
const headTags = [];
|
|
@@ -379,7 +380,7 @@ function pluginContentBlog(context, options) {
|
|
|
379
380
|
attributes: {
|
|
380
381
|
rel: 'alternate',
|
|
381
382
|
type,
|
|
382
|
-
href: utils_1.normalizeUrl([
|
|
383
|
+
href: (0, utils_1.normalizeUrl)([
|
|
383
384
|
baseUrl,
|
|
384
385
|
options.routeBasePath,
|
|
385
386
|
feedConfigPath,
|
package/lib/markdownLoader.d.ts
CHANGED
|
@@ -4,9 +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
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
declare const markdownLoader: Loader;
|
|
12
|
-
export default markdownLoader;
|
|
7
|
+
import { BlogMarkdownLoaderOptions } from './types';
|
|
8
|
+
import type { LoaderContext } from 'webpack';
|
|
9
|
+
export default function markdownLoader(this: LoaderContext<BlogMarkdownLoaderOptions>, source: string): void;
|
package/lib/markdownLoader.js
CHANGED
|
@@ -8,24 +8,24 @@
|
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
9
|
const blogUtils_1 = require("./blogUtils");
|
|
10
10
|
const loader_utils_1 = require("loader-utils");
|
|
11
|
-
|
|
11
|
+
function markdownLoader(source) {
|
|
12
12
|
const filePath = this.resourcePath;
|
|
13
13
|
const fileString = 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
|
+
}
|
|
31
31
|
exports.default = markdownLoader;
|
|
@@ -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,28 @@ 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',
|
|
38
|
+
readingTime: ({ content, defaultReadingTime }) => defaultReadingTime({ content }),
|
|
35
39
|
};
|
|
36
40
|
exports.PluginOptionSchema = utils_validation_1.Joi.object({
|
|
37
41
|
path: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.path),
|
|
42
|
+
archiveBasePath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.archiveBasePath),
|
|
38
43
|
routeBasePath: utils_validation_1.Joi.string()
|
|
39
44
|
// '' not allowed, see https://github.com/facebook/docusaurus/issues/3374
|
|
40
45
|
// .allow('')
|
|
41
46
|
.default(exports.DEFAULT_OPTIONS.routeBasePath),
|
|
47
|
+
tagsBasePath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.tagsBasePath),
|
|
42
48
|
include: utils_validation_1.Joi.array().items(utils_validation_1.Joi.string()).default(exports.DEFAULT_OPTIONS.include),
|
|
43
49
|
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)
|
|
50
|
+
postsPerPage: utils_validation_1.Joi.alternatives()
|
|
51
|
+
.try(utils_validation_1.Joi.equal('ALL').required(), utils_validation_1.Joi.number().integer().min(1).required())
|
|
47
52
|
.default(exports.DEFAULT_OPTIONS.postsPerPage),
|
|
48
53
|
blogListComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogListComponent),
|
|
49
54
|
blogPostComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogPostComponent),
|
|
@@ -54,7 +59,7 @@ exports.PluginOptionSchema = utils_validation_1.Joi.object({
|
|
|
54
59
|
.allow('')
|
|
55
60
|
.default(exports.DEFAULT_OPTIONS.blogDescription),
|
|
56
61
|
blogSidebarCount: utils_validation_1.Joi.alternatives()
|
|
57
|
-
.try(utils_validation_1.Joi.equal('ALL').required(), utils_validation_1.Joi.number().required())
|
|
62
|
+
.try(utils_validation_1.Joi.equal('ALL').required(), utils_validation_1.Joi.number().integer().min(0).required())
|
|
58
63
|
.default(exports.DEFAULT_OPTIONS.blogSidebarCount),
|
|
59
64
|
blogSidebarTitle: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogSidebarTitle),
|
|
60
65
|
showReadingTime: utils_validation_1.Joi.bool().default(exports.DEFAULT_OPTIONS.showReadingTime),
|
|
@@ -75,7 +80,16 @@ exports.PluginOptionSchema = utils_validation_1.Joi.object({
|
|
|
75
80
|
.default(exports.DEFAULT_OPTIONS.feedOptions.type),
|
|
76
81
|
title: utils_validation_1.Joi.string().allow(''),
|
|
77
82
|
description: utils_validation_1.Joi.string().allow(''),
|
|
78
|
-
|
|
83
|
+
// only add default value when user actually wants a feed (type is not null)
|
|
84
|
+
copyright: utils_validation_1.Joi.when('type', {
|
|
85
|
+
is: utils_validation_1.Joi.any().valid(null),
|
|
86
|
+
then: utils_validation_1.Joi.string().optional(),
|
|
87
|
+
otherwise: utils_validation_1.Joi.string()
|
|
88
|
+
.allow('')
|
|
89
|
+
.default(exports.DEFAULT_OPTIONS.feedOptions.copyright),
|
|
90
|
+
}),
|
|
79
91
|
language: utils_validation_1.Joi.string(),
|
|
80
92
|
}).default(exports.DEFAULT_OPTIONS.feedOptions),
|
|
93
|
+
authorsMapPath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.authorsMapPath),
|
|
94
|
+
readingTime: utils_validation_1.Joi.function().default(() => exports.DEFAULT_OPTIONS.readingTime),
|
|
81
95
|
});
|
|
@@ -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;
|