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