@docusaurus/plugin-content-blog 0.0.0-5961 → 0.0.0-5963
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/blogUtils.d.ts +0 -3
- package/lib/blogUtils.js +17 -10
- package/lib/index.js +35 -4
- package/lib/options.js +9 -0
- package/lib/props.js +2 -0
- package/package.json +9 -9
- package/src/blogUtils.ts +20 -12
- package/src/index.ts +45 -7
- package/src/options.ts +9 -0
- package/src/plugin-content-blog.d.ts +102 -101
- package/src/props.ts +2 -0
package/lib/blogUtils.d.ts
CHANGED
|
@@ -9,9 +9,6 @@ import type { LoadContext } from '@docusaurus/types';
|
|
|
9
9
|
import type { PluginOptions, BlogPost, BlogTags, BlogPaginated } from '@docusaurus/plugin-content-blog';
|
|
10
10
|
import type { BlogContentPaths } from './types';
|
|
11
11
|
export declare function truncate(fileString: string, truncateMarker: RegExp): string;
|
|
12
|
-
export declare function getSourceToPermalink(blogPosts: BlogPost[]): {
|
|
13
|
-
[aliasedPath: string]: string;
|
|
14
|
-
};
|
|
15
12
|
export declare function paginateBlogPosts({ blogPosts, basePageUrl, blogTitle, blogDescription, postsPerPageOption, pageBasePath, }: {
|
|
16
13
|
blogPosts: BlogPost[];
|
|
17
14
|
basePageUrl: string;
|
package/lib/blogUtils.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* LICENSE file in the root directory of this source tree.
|
|
7
7
|
*/
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.applyProcessBlogPosts = exports.generateBlogPosts = exports.parseBlogFileName = exports.getBlogTags = exports.shouldBeListed = exports.paginateBlogPosts = exports.
|
|
9
|
+
exports.applyProcessBlogPosts = exports.generateBlogPosts = exports.parseBlogFileName = exports.getBlogTags = exports.shouldBeListed = exports.paginateBlogPosts = exports.truncate = void 0;
|
|
10
10
|
const tslib_1 = require("tslib");
|
|
11
11
|
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
|
|
12
12
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
@@ -14,16 +14,13 @@ const lodash_1 = tslib_1.__importDefault(require("lodash"));
|
|
|
14
14
|
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
15
15
|
const reading_time_1 = tslib_1.__importDefault(require("reading-time"));
|
|
16
16
|
const utils_1 = require("@docusaurus/utils");
|
|
17
|
+
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
17
18
|
const frontMatter_1 = require("./frontMatter");
|
|
18
19
|
const authors_1 = require("./authors");
|
|
19
20
|
function truncate(fileString, truncateMarker) {
|
|
20
21
|
return fileString.split(truncateMarker, 1).shift();
|
|
21
22
|
}
|
|
22
23
|
exports.truncate = truncate;
|
|
23
|
-
function getSourceToPermalink(blogPosts) {
|
|
24
|
-
return Object.fromEntries(blogPosts.map(({ metadata: { source, permalink } }) => [source, permalink]));
|
|
25
|
-
}
|
|
26
|
-
exports.getSourceToPermalink = getSourceToPermalink;
|
|
27
24
|
function paginateBlogPosts({ blogPosts, basePageUrl, blogTitle, blogDescription, postsPerPageOption, pageBasePath, }) {
|
|
28
25
|
const totalCount = blogPosts.length;
|
|
29
26
|
const postsPerPage = postsPerPageOption === 'ALL' ? totalCount : postsPerPageOption;
|
|
@@ -67,9 +64,11 @@ function getBlogTags({ blogPosts, ...params }) {
|
|
|
67
64
|
isUnlisted: (item) => item.metadata.unlisted,
|
|
68
65
|
});
|
|
69
66
|
return {
|
|
67
|
+
inline: tag.inline,
|
|
70
68
|
label: tag.label,
|
|
71
|
-
items: tagVisibility.listedItems.map((item) => item.id),
|
|
72
69
|
permalink: tag.permalink,
|
|
70
|
+
description: tag.description,
|
|
71
|
+
items: tagVisibility.listedItems.map((item) => item.id),
|
|
73
72
|
pages: paginateBlogPosts({
|
|
74
73
|
blogPosts: tagVisibility.listedItems,
|
|
75
74
|
basePageUrl: tag.permalink,
|
|
@@ -116,7 +115,7 @@ async function parseBlogPostMarkdownFile({ filePath, parseFrontMatter, }) {
|
|
|
116
115
|
}
|
|
117
116
|
}
|
|
118
117
|
const defaultReadingTime = ({ content, options }) => (0, reading_time_1.default)(content, options).minutes;
|
|
119
|
-
async function processBlogSourceFile(blogSourceRelative, contentPaths, context, options, authorsMap) {
|
|
118
|
+
async function processBlogSourceFile(blogSourceRelative, contentPaths, context, options, tagsFile, authorsMap) {
|
|
120
119
|
const { siteConfig: { baseUrl, markdown: { parseFrontMatter }, }, siteDir, i18n, } = context;
|
|
121
120
|
const { routeBasePath, tagsBasePath: tagsRouteBasePath, truncateMarker, showReadingTime, editUrl, } = options;
|
|
122
121
|
// Lookup in localized folder in priority
|
|
@@ -190,12 +189,19 @@ async function processBlogSourceFile(blogSourceRelative, contentPaths, context,
|
|
|
190
189
|
}
|
|
191
190
|
return undefined;
|
|
192
191
|
}
|
|
193
|
-
const
|
|
192
|
+
const tagsBaseRoutePath = (0, utils_1.normalizeUrl)([
|
|
194
193
|
baseUrl,
|
|
195
194
|
routeBasePath,
|
|
196
195
|
tagsRouteBasePath,
|
|
197
196
|
]);
|
|
198
197
|
const authors = (0, authors_1.getBlogPostAuthors)({ authorsMap, frontMatter, baseUrl });
|
|
198
|
+
const tags = (0, utils_1.normalizeTags)({
|
|
199
|
+
options,
|
|
200
|
+
source: blogSourceRelative,
|
|
201
|
+
frontMatterTags: frontMatter.tags,
|
|
202
|
+
tagsBaseRoutePath,
|
|
203
|
+
tagsFile,
|
|
204
|
+
});
|
|
199
205
|
return {
|
|
200
206
|
id: slug,
|
|
201
207
|
metadata: {
|
|
@@ -205,7 +211,7 @@ async function processBlogSourceFile(blogSourceRelative, contentPaths, context,
|
|
|
205
211
|
title,
|
|
206
212
|
description,
|
|
207
213
|
date,
|
|
208
|
-
tags
|
|
214
|
+
tags,
|
|
209
215
|
readingTime: showReadingTime
|
|
210
216
|
? options.readingTime({
|
|
211
217
|
content,
|
|
@@ -236,9 +242,10 @@ async function generateBlogPosts(contentPaths, context, options) {
|
|
|
236
242
|
contentPaths,
|
|
237
243
|
authorsMapPath: options.authorsMapPath,
|
|
238
244
|
});
|
|
245
|
+
const tagsFile = await (0, utils_validation_1.getTagsFile)({ contentPaths, tags: options.tags });
|
|
239
246
|
async function doProcessBlogSourceFile(blogSourceFile) {
|
|
240
247
|
try {
|
|
241
|
-
return await processBlogSourceFile(blogSourceFile, contentPaths, context, options, authorsMap);
|
|
248
|
+
return await processBlogSourceFile(blogSourceFile, contentPaths, context, options, tagsFile, authorsMap);
|
|
242
249
|
}
|
|
243
250
|
catch (err) {
|
|
244
251
|
throw new Error(`Processing of blog source file path=${blogSourceFile} failed.`, { cause: err });
|
package/lib/index.js
CHANGED
|
@@ -11,12 +11,34 @@ const tslib_1 = require("tslib");
|
|
|
11
11
|
const path_1 = tslib_1.__importDefault(require("path"));
|
|
12
12
|
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
|
|
13
13
|
const utils_1 = require("@docusaurus/utils");
|
|
14
|
+
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
14
15
|
const blogUtils_1 = require("./blogUtils");
|
|
15
16
|
const footnoteIDFixer_1 = tslib_1.__importDefault(require("./remark/footnoteIDFixer"));
|
|
16
17
|
const translations_1 = require("./translations");
|
|
17
18
|
const feed_1 = require("./feed");
|
|
18
19
|
const routes_1 = require("./routes");
|
|
19
20
|
const PluginName = 'docusaurus-plugin-content-blog';
|
|
21
|
+
// TODO this is bad, we should have a better way to do this (new lifecycle?)
|
|
22
|
+
// The source to permalink is currently a mutable map passed to the mdx loader
|
|
23
|
+
// for link resolution
|
|
24
|
+
// see https://github.com/facebook/docusaurus/pull/10185
|
|
25
|
+
function createSourceToPermalinkHelper() {
|
|
26
|
+
const sourceToPermalink = new Map();
|
|
27
|
+
function computeSourceToPermalink(content) {
|
|
28
|
+
return new Map(content.blogPosts.map(({ metadata: { source, permalink } }) => [
|
|
29
|
+
source,
|
|
30
|
+
permalink,
|
|
31
|
+
]));
|
|
32
|
+
}
|
|
33
|
+
// Mutable map update :/
|
|
34
|
+
function update(content) {
|
|
35
|
+
sourceToPermalink.clear();
|
|
36
|
+
computeSourceToPermalink(content).forEach((value, key) => {
|
|
37
|
+
sourceToPermalink.set(key, value);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return { get: () => sourceToPermalink, update };
|
|
41
|
+
}
|
|
20
42
|
async function pluginContentBlog(context, options) {
|
|
21
43
|
const { siteDir, siteConfig, generatedFilesDir, localizationDir, i18n: { currentLocale }, } = context;
|
|
22
44
|
const router = siteConfig.future.experimental_router;
|
|
@@ -44,12 +66,21 @@ async function pluginContentBlog(context, options) {
|
|
|
44
66
|
filePath: options.authorsMapPath,
|
|
45
67
|
contentPaths,
|
|
46
68
|
});
|
|
69
|
+
const sourceToPermalinkHelper = createSourceToPermalinkHelper();
|
|
47
70
|
return {
|
|
48
71
|
name: PluginName,
|
|
49
72
|
getPathsToWatch() {
|
|
50
73
|
const { include } = options;
|
|
51
74
|
const contentMarkdownGlobs = (0, utils_1.getContentPathList)(contentPaths).flatMap((contentPath) => include.map((pattern) => `${contentPath}/${pattern}`));
|
|
52
|
-
|
|
75
|
+
const tagsFilePaths = (0, utils_validation_1.getTagsFilePathsToWatch)({
|
|
76
|
+
contentPaths,
|
|
77
|
+
tags: options.tags,
|
|
78
|
+
});
|
|
79
|
+
return [
|
|
80
|
+
authorsMapFilePath,
|
|
81
|
+
...tagsFilePaths,
|
|
82
|
+
...contentMarkdownGlobs,
|
|
83
|
+
].filter(Boolean);
|
|
53
84
|
},
|
|
54
85
|
getTranslationFiles() {
|
|
55
86
|
return (0, translations_1.getTranslationFiles)(options);
|
|
@@ -117,6 +148,7 @@ async function pluginContentBlog(context, options) {
|
|
|
117
148
|
};
|
|
118
149
|
},
|
|
119
150
|
async contentLoaded({ content, actions }) {
|
|
151
|
+
sourceToPermalinkHelper.update(content);
|
|
120
152
|
await (0, routes_1.createAllRoutes)({
|
|
121
153
|
baseUrl,
|
|
122
154
|
content,
|
|
@@ -128,9 +160,8 @@ async function pluginContentBlog(context, options) {
|
|
|
128
160
|
translateContent({ content, translationFiles }) {
|
|
129
161
|
return (0, translations_1.translateContent)(content, translationFiles);
|
|
130
162
|
},
|
|
131
|
-
configureWebpack(
|
|
163
|
+
configureWebpack() {
|
|
132
164
|
const { admonitions, rehypePlugins, remarkPlugins, truncateMarker, beforeDefaultRemarkPlugins, beforeDefaultRehypePlugins, } = options;
|
|
133
|
-
const sourceToPermalink = (0, blogUtils_1.getSourceToPermalink)(content.blogPosts);
|
|
134
165
|
const contentDirs = (0, utils_1.getContentPathList)(contentPaths);
|
|
135
166
|
function createMDXLoader() {
|
|
136
167
|
const loaderOptions = {
|
|
@@ -165,7 +196,7 @@ async function pluginContentBlog(context, options) {
|
|
|
165
196
|
resolveMarkdownLink: ({ linkPathname, sourceFilePath }) => {
|
|
166
197
|
const permalink = (0, utils_1.resolveMarkdownLinkPathname)(linkPathname, {
|
|
167
198
|
sourceFilePath,
|
|
168
|
-
sourceToPermalink,
|
|
199
|
+
sourceToPermalink: sourceToPermalinkHelper.get(),
|
|
169
200
|
siteDir,
|
|
170
201
|
contentPaths,
|
|
171
202
|
});
|
package/lib/options.js
CHANGED
|
@@ -42,6 +42,8 @@ exports.DEFAULT_OPTIONS = {
|
|
|
42
42
|
showLastUpdateTime: false,
|
|
43
43
|
showLastUpdateAuthor: false,
|
|
44
44
|
processBlogPosts: async () => undefined,
|
|
45
|
+
onInlineTags: 'warn',
|
|
46
|
+
tags: undefined,
|
|
45
47
|
};
|
|
46
48
|
const PluginOptionSchema = utils_validation_1.Joi.object({
|
|
47
49
|
path: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.path),
|
|
@@ -111,6 +113,13 @@ const PluginOptionSchema = utils_validation_1.Joi.object({
|
|
|
111
113
|
processBlogPosts: utils_validation_1.Joi.function()
|
|
112
114
|
.optional()
|
|
113
115
|
.default(() => exports.DEFAULT_OPTIONS.processBlogPosts),
|
|
116
|
+
onInlineTags: utils_validation_1.Joi.string()
|
|
117
|
+
.equal('ignore', 'log', 'warn', 'throw')
|
|
118
|
+
.default(exports.DEFAULT_OPTIONS.onInlineTags),
|
|
119
|
+
tags: utils_validation_1.Joi.string()
|
|
120
|
+
.disallow('')
|
|
121
|
+
.allow(null, false)
|
|
122
|
+
.default(() => exports.DEFAULT_OPTIONS.tags),
|
|
114
123
|
}).default(exports.DEFAULT_OPTIONS);
|
|
115
124
|
function validateOptions({ validate, options, }) {
|
|
116
125
|
const validatedOptions = validate(PluginOptionSchema, options);
|
package/lib/props.js
CHANGED
|
@@ -7,6 +7,7 @@ function toTagsProp({ blogTags }) {
|
|
|
7
7
|
.map((tag) => ({
|
|
8
8
|
label: tag.label,
|
|
9
9
|
permalink: tag.permalink,
|
|
10
|
+
description: tag.description,
|
|
10
11
|
count: tag.items.length,
|
|
11
12
|
}));
|
|
12
13
|
}
|
|
@@ -15,6 +16,7 @@ function toTagProp({ blogTagsListPath, tag, }) {
|
|
|
15
16
|
return {
|
|
16
17
|
label: tag.label,
|
|
17
18
|
permalink: tag.permalink,
|
|
19
|
+
description: tag.description,
|
|
18
20
|
allTagsPath: blogTagsListPath,
|
|
19
21
|
count: tag.items.length,
|
|
20
22
|
unlisted: tag.unlisted,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@docusaurus/plugin-content-blog",
|
|
3
|
-
"version": "0.0.0-
|
|
3
|
+
"version": "0.0.0-5963",
|
|
4
4
|
"description": "Blog plugin for Docusaurus.",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "src/plugin-content-blog.d.ts",
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
},
|
|
32
32
|
"license": "MIT",
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@docusaurus/core": "0.0.0-
|
|
35
|
-
"@docusaurus/logger": "0.0.0-
|
|
36
|
-
"@docusaurus/mdx-loader": "0.0.0-
|
|
37
|
-
"@docusaurus/types": "0.0.0-
|
|
38
|
-
"@docusaurus/utils": "0.0.0-
|
|
39
|
-
"@docusaurus/utils-common": "0.0.0-
|
|
40
|
-
"@docusaurus/utils-validation": "0.0.0-
|
|
34
|
+
"@docusaurus/core": "0.0.0-5963",
|
|
35
|
+
"@docusaurus/logger": "0.0.0-5963",
|
|
36
|
+
"@docusaurus/mdx-loader": "0.0.0-5963",
|
|
37
|
+
"@docusaurus/types": "0.0.0-5963",
|
|
38
|
+
"@docusaurus/utils": "0.0.0-5963",
|
|
39
|
+
"@docusaurus/utils-common": "0.0.0-5963",
|
|
40
|
+
"@docusaurus/utils-validation": "0.0.0-5963",
|
|
41
41
|
"cheerio": "^1.0.0-rc.12",
|
|
42
42
|
"feed": "^4.2.2",
|
|
43
43
|
"fs-extra": "^11.1.1",
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"devDependencies": {
|
|
60
60
|
"@total-typescript/shoehorn": "^0.1.2"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "e9090dc8a38a21043b0849887aa7d54d04c4af9f"
|
|
63
63
|
}
|
package/src/blogUtils.ts
CHANGED
|
@@ -18,7 +18,6 @@ import {
|
|
|
18
18
|
getFolderContainingFile,
|
|
19
19
|
posixPath,
|
|
20
20
|
Globby,
|
|
21
|
-
normalizeFrontMatterTags,
|
|
22
21
|
groupTaggedItems,
|
|
23
22
|
getTagVisibility,
|
|
24
23
|
getFileCommitDate,
|
|
@@ -26,9 +25,12 @@ import {
|
|
|
26
25
|
isUnlisted,
|
|
27
26
|
isDraft,
|
|
28
27
|
readLastUpdateData,
|
|
28
|
+
normalizeTags,
|
|
29
29
|
} from '@docusaurus/utils';
|
|
30
|
+
import {getTagsFile} from '@docusaurus/utils-validation';
|
|
30
31
|
import {validateBlogPostFrontMatter} from './frontMatter';
|
|
31
32
|
import {type AuthorsMap, getAuthorsMap, getBlogPostAuthors} from './authors';
|
|
33
|
+
import type {TagsFile} from '@docusaurus/utils';
|
|
32
34
|
import type {LoadContext, ParseFrontMatter} from '@docusaurus/types';
|
|
33
35
|
import type {
|
|
34
36
|
PluginOptions,
|
|
@@ -43,14 +45,6 @@ export function truncate(fileString: string, truncateMarker: RegExp): string {
|
|
|
43
45
|
return fileString.split(truncateMarker, 1).shift()!;
|
|
44
46
|
}
|
|
45
47
|
|
|
46
|
-
export function getSourceToPermalink(blogPosts: BlogPost[]): {
|
|
47
|
-
[aliasedPath: string]: string;
|
|
48
|
-
} {
|
|
49
|
-
return Object.fromEntries(
|
|
50
|
-
blogPosts.map(({metadata: {source, permalink}}) => [source, permalink]),
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
48
|
export function paginateBlogPosts({
|
|
55
49
|
blogPosts,
|
|
56
50
|
basePageUrl,
|
|
@@ -125,9 +119,11 @@ export function getBlogTags({
|
|
|
125
119
|
isUnlisted: (item) => item.metadata.unlisted,
|
|
126
120
|
});
|
|
127
121
|
return {
|
|
122
|
+
inline: tag.inline,
|
|
128
123
|
label: tag.label,
|
|
129
|
-
items: tagVisibility.listedItems.map((item) => item.id),
|
|
130
124
|
permalink: tag.permalink,
|
|
125
|
+
description: tag.description,
|
|
126
|
+
items: tagVisibility.listedItems.map((item) => item.id),
|
|
131
127
|
pages: paginateBlogPosts({
|
|
132
128
|
blogPosts: tagVisibility.listedItems,
|
|
133
129
|
basePageUrl: tag.permalink,
|
|
@@ -197,6 +193,7 @@ async function processBlogSourceFile(
|
|
|
197
193
|
contentPaths: BlogContentPaths,
|
|
198
194
|
context: LoadContext,
|
|
199
195
|
options: PluginOptions,
|
|
196
|
+
tagsFile: TagsFile | null,
|
|
200
197
|
authorsMap?: AuthorsMap,
|
|
201
198
|
): Promise<BlogPost | undefined> {
|
|
202
199
|
const {
|
|
@@ -315,13 +312,21 @@ async function processBlogSourceFile(
|
|
|
315
312
|
return undefined;
|
|
316
313
|
}
|
|
317
314
|
|
|
318
|
-
const
|
|
315
|
+
const tagsBaseRoutePath = normalizeUrl([
|
|
319
316
|
baseUrl,
|
|
320
317
|
routeBasePath,
|
|
321
318
|
tagsRouteBasePath,
|
|
322
319
|
]);
|
|
323
320
|
const authors = getBlogPostAuthors({authorsMap, frontMatter, baseUrl});
|
|
324
321
|
|
|
322
|
+
const tags = normalizeTags({
|
|
323
|
+
options,
|
|
324
|
+
source: blogSourceRelative,
|
|
325
|
+
frontMatterTags: frontMatter.tags,
|
|
326
|
+
tagsBaseRoutePath,
|
|
327
|
+
tagsFile,
|
|
328
|
+
});
|
|
329
|
+
|
|
325
330
|
return {
|
|
326
331
|
id: slug,
|
|
327
332
|
metadata: {
|
|
@@ -331,7 +336,7 @@ async function processBlogSourceFile(
|
|
|
331
336
|
title,
|
|
332
337
|
description,
|
|
333
338
|
date,
|
|
334
|
-
tags
|
|
339
|
+
tags,
|
|
335
340
|
readingTime: showReadingTime
|
|
336
341
|
? options.readingTime({
|
|
337
342
|
content,
|
|
@@ -371,6 +376,8 @@ export async function generateBlogPosts(
|
|
|
371
376
|
authorsMapPath: options.authorsMapPath,
|
|
372
377
|
});
|
|
373
378
|
|
|
379
|
+
const tagsFile = await getTagsFile({contentPaths, tags: options.tags});
|
|
380
|
+
|
|
374
381
|
async function doProcessBlogSourceFile(blogSourceFile: string) {
|
|
375
382
|
try {
|
|
376
383
|
return await processBlogSourceFile(
|
|
@@ -378,6 +385,7 @@ export async function generateBlogPosts(
|
|
|
378
385
|
contentPaths,
|
|
379
386
|
context,
|
|
380
387
|
options,
|
|
388
|
+
tagsFile,
|
|
381
389
|
authorsMap,
|
|
382
390
|
);
|
|
383
391
|
} catch (err) {
|
package/src/index.ts
CHANGED
|
@@ -19,9 +19,10 @@ import {
|
|
|
19
19
|
getDataFilePath,
|
|
20
20
|
DEFAULT_PLUGIN_ID,
|
|
21
21
|
resolveMarkdownLinkPathname,
|
|
22
|
+
type SourceToPermalink,
|
|
22
23
|
} from '@docusaurus/utils';
|
|
24
|
+
import {getTagsFilePathsToWatch} from '@docusaurus/utils-validation';
|
|
23
25
|
import {
|
|
24
|
-
getSourceToPermalink,
|
|
25
26
|
getBlogTags,
|
|
26
27
|
paginateBlogPosts,
|
|
27
28
|
shouldBeListed,
|
|
@@ -49,6 +50,33 @@ import type {RuleSetUseItem} from 'webpack';
|
|
|
49
50
|
|
|
50
51
|
const PluginName = 'docusaurus-plugin-content-blog';
|
|
51
52
|
|
|
53
|
+
// TODO this is bad, we should have a better way to do this (new lifecycle?)
|
|
54
|
+
// The source to permalink is currently a mutable map passed to the mdx loader
|
|
55
|
+
// for link resolution
|
|
56
|
+
// see https://github.com/facebook/docusaurus/pull/10185
|
|
57
|
+
function createSourceToPermalinkHelper() {
|
|
58
|
+
const sourceToPermalink: SourceToPermalink = new Map();
|
|
59
|
+
|
|
60
|
+
function computeSourceToPermalink(content: BlogContent): SourceToPermalink {
|
|
61
|
+
return new Map(
|
|
62
|
+
content.blogPosts.map(({metadata: {source, permalink}}) => [
|
|
63
|
+
source,
|
|
64
|
+
permalink,
|
|
65
|
+
]),
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Mutable map update :/
|
|
70
|
+
function update(content: BlogContent): void {
|
|
71
|
+
sourceToPermalink.clear();
|
|
72
|
+
computeSourceToPermalink(content).forEach((value, key) => {
|
|
73
|
+
sourceToPermalink.set(key, value);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return {get: () => sourceToPermalink, update};
|
|
78
|
+
}
|
|
79
|
+
|
|
52
80
|
export default async function pluginContentBlog(
|
|
53
81
|
context: LoadContext,
|
|
54
82
|
options: PluginOptions,
|
|
@@ -95,6 +123,8 @@ export default async function pluginContentBlog(
|
|
|
95
123
|
contentPaths,
|
|
96
124
|
});
|
|
97
125
|
|
|
126
|
+
const sourceToPermalinkHelper = createSourceToPermalinkHelper();
|
|
127
|
+
|
|
98
128
|
return {
|
|
99
129
|
name: PluginName,
|
|
100
130
|
|
|
@@ -104,9 +134,16 @@ export default async function pluginContentBlog(
|
|
|
104
134
|
(contentPath) => include.map((pattern) => `${contentPath}/${pattern}`),
|
|
105
135
|
);
|
|
106
136
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
137
|
+
const tagsFilePaths = getTagsFilePathsToWatch({
|
|
138
|
+
contentPaths,
|
|
139
|
+
tags: options.tags,
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
return [
|
|
143
|
+
authorsMapFilePath,
|
|
144
|
+
...tagsFilePaths,
|
|
145
|
+
...contentMarkdownGlobs,
|
|
146
|
+
].filter(Boolean) as string[];
|
|
110
147
|
},
|
|
111
148
|
|
|
112
149
|
getTranslationFiles() {
|
|
@@ -193,6 +230,8 @@ export default async function pluginContentBlog(
|
|
|
193
230
|
},
|
|
194
231
|
|
|
195
232
|
async contentLoaded({content, actions}) {
|
|
233
|
+
sourceToPermalinkHelper.update(content);
|
|
234
|
+
|
|
196
235
|
await createAllRoutes({
|
|
197
236
|
baseUrl,
|
|
198
237
|
content,
|
|
@@ -206,7 +245,7 @@ export default async function pluginContentBlog(
|
|
|
206
245
|
return translateContent(content, translationFiles);
|
|
207
246
|
},
|
|
208
247
|
|
|
209
|
-
configureWebpack(
|
|
248
|
+
configureWebpack() {
|
|
210
249
|
const {
|
|
211
250
|
admonitions,
|
|
212
251
|
rehypePlugins,
|
|
@@ -216,7 +255,6 @@ export default async function pluginContentBlog(
|
|
|
216
255
|
beforeDefaultRehypePlugins,
|
|
217
256
|
} = options;
|
|
218
257
|
|
|
219
|
-
const sourceToPermalink = getSourceToPermalink(content.blogPosts);
|
|
220
258
|
const contentDirs = getContentPathList(contentPaths);
|
|
221
259
|
|
|
222
260
|
function createMDXLoader(): RuleSetUseItem {
|
|
@@ -263,7 +301,7 @@ export default async function pluginContentBlog(
|
|
|
263
301
|
resolveMarkdownLink: ({linkPathname, sourceFilePath}) => {
|
|
264
302
|
const permalink = resolveMarkdownLinkPathname(linkPathname, {
|
|
265
303
|
sourceFilePath,
|
|
266
|
-
sourceToPermalink,
|
|
304
|
+
sourceToPermalink: sourceToPermalinkHelper.get(),
|
|
267
305
|
siteDir,
|
|
268
306
|
contentPaths,
|
|
269
307
|
});
|
package/src/options.ts
CHANGED
|
@@ -54,6 +54,8 @@ export const DEFAULT_OPTIONS: PluginOptions = {
|
|
|
54
54
|
showLastUpdateTime: false,
|
|
55
55
|
showLastUpdateAuthor: false,
|
|
56
56
|
processBlogPosts: async () => undefined,
|
|
57
|
+
onInlineTags: 'warn',
|
|
58
|
+
tags: undefined,
|
|
57
59
|
};
|
|
58
60
|
|
|
59
61
|
const PluginOptionSchema = Joi.object<PluginOptions>({
|
|
@@ -144,6 +146,13 @@ const PluginOptionSchema = Joi.object<PluginOptions>({
|
|
|
144
146
|
processBlogPosts: Joi.function()
|
|
145
147
|
.optional()
|
|
146
148
|
.default(() => DEFAULT_OPTIONS.processBlogPosts),
|
|
149
|
+
onInlineTags: Joi.string()
|
|
150
|
+
.equal('ignore', 'log', 'warn', 'throw')
|
|
151
|
+
.default(DEFAULT_OPTIONS.onInlineTags),
|
|
152
|
+
tags: Joi.string()
|
|
153
|
+
.disallow('')
|
|
154
|
+
.allow(null, false)
|
|
155
|
+
.default(() => DEFAULT_OPTIONS.tags),
|
|
147
156
|
}).default(DEFAULT_OPTIONS);
|
|
148
157
|
|
|
149
158
|
export function validateOptions({
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
|
-
|
|
8
7
|
/// <reference types="@docusaurus/module-type-aliases" />
|
|
9
8
|
|
|
10
9
|
declare module '@docusaurus/plugin-content-blog' {
|
|
@@ -12,9 +11,10 @@ declare module '@docusaurus/plugin-content-blog' {
|
|
|
12
11
|
import type {MDXOptions} from '@docusaurus/mdx-loader';
|
|
13
12
|
import type {
|
|
14
13
|
FrontMatterTag,
|
|
15
|
-
|
|
14
|
+
TagMetadata,
|
|
16
15
|
LastUpdateData,
|
|
17
16
|
FrontMatterLastUpdate,
|
|
17
|
+
TagsPluginOptions,
|
|
18
18
|
} from '@docusaurus/utils';
|
|
19
19
|
import type {DocusaurusConfig, Plugin, LoadContext} from '@docusaurus/types';
|
|
20
20
|
import type {Item as FeedItem} from 'feed';
|
|
@@ -236,7 +236,7 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the
|
|
|
236
236
|
/** Front matter, as-is. */
|
|
237
237
|
readonly frontMatter: BlogPostFrontMatter & {[key: string]: unknown};
|
|
238
238
|
/** Tags, normalized. */
|
|
239
|
-
readonly tags:
|
|
239
|
+
readonly tags: TagMetadata[];
|
|
240
240
|
/**
|
|
241
241
|
* Marks the post as unlisted and visibly hides it unless directly accessed.
|
|
242
242
|
*/
|
|
@@ -345,103 +345,104 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the
|
|
|
345
345
|
/**
|
|
346
346
|
* Plugin options after normalization.
|
|
347
347
|
*/
|
|
348
|
-
export type PluginOptions = MDXOptions &
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
348
|
+
export type PluginOptions = MDXOptions &
|
|
349
|
+
TagsPluginOptions & {
|
|
350
|
+
/** Plugin ID. */
|
|
351
|
+
id?: string;
|
|
352
|
+
/**
|
|
353
|
+
* Path to the blog content directory on the file system, relative to site
|
|
354
|
+
* directory.
|
|
355
|
+
*/
|
|
356
|
+
path: string;
|
|
357
|
+
/**
|
|
358
|
+
* URL route for the blog section of your site. **DO NOT** include a
|
|
359
|
+
* trailing slash. Use `/` to put the blog at root path.
|
|
360
|
+
*/
|
|
361
|
+
routeBasePath: string;
|
|
362
|
+
/**
|
|
363
|
+
* URL route for the tags section of your blog. Will be appended to
|
|
364
|
+
* `routeBasePath`.
|
|
365
|
+
*/
|
|
366
|
+
tagsBasePath: string;
|
|
367
|
+
/**
|
|
368
|
+
* URL route for the pages section of your blog. Will be appended to
|
|
369
|
+
* `routeBasePath`.
|
|
370
|
+
*/
|
|
371
|
+
pageBasePath: string;
|
|
372
|
+
/**
|
|
373
|
+
* URL route for the archive section of your blog. Will be appended to
|
|
374
|
+
* `routeBasePath`. **DO NOT** include a trailing slash. Use `null` to
|
|
375
|
+
* disable generation of archive.
|
|
376
|
+
*/
|
|
377
|
+
archiveBasePath: string | null;
|
|
378
|
+
/**
|
|
379
|
+
* Array of glob patterns matching Markdown files to be built, relative to
|
|
380
|
+
* the content path.
|
|
381
|
+
*/
|
|
382
|
+
include: string[];
|
|
383
|
+
/**
|
|
384
|
+
* Array of glob patterns matching Markdown files to be excluded. Serves as
|
|
385
|
+
* refinement based on the `include` option.
|
|
386
|
+
*/
|
|
387
|
+
exclude: string[];
|
|
388
|
+
/**
|
|
389
|
+
* Number of posts to show per page in the listing page. Use `'ALL'` to
|
|
390
|
+
* display all posts on one listing page.
|
|
391
|
+
*/
|
|
392
|
+
postsPerPage: number | 'ALL';
|
|
393
|
+
/** Root component of the blog listing page. */
|
|
394
|
+
blogListComponent: string;
|
|
395
|
+
/** Root component of each blog post page. */
|
|
396
|
+
blogPostComponent: string;
|
|
397
|
+
/** Root component of the tags list page. */
|
|
398
|
+
blogTagsListComponent: string;
|
|
399
|
+
/** Root component of the "posts containing tag" page. */
|
|
400
|
+
blogTagsPostsComponent: string;
|
|
401
|
+
/** Root component of the blog archive page. */
|
|
402
|
+
blogArchiveComponent: string;
|
|
403
|
+
/** Blog page title for better SEO. */
|
|
404
|
+
blogTitle: string;
|
|
405
|
+
/** Blog page meta description for better SEO. */
|
|
406
|
+
blogDescription: string;
|
|
407
|
+
/**
|
|
408
|
+
* Number of blog post elements to show in the blog sidebar. `'ALL'` to show
|
|
409
|
+
* all blog posts; `0` to disable.
|
|
410
|
+
*/
|
|
411
|
+
blogSidebarCount: number | 'ALL';
|
|
412
|
+
/** Title of the blog sidebar. */
|
|
413
|
+
blogSidebarTitle: string;
|
|
414
|
+
/** Truncate marker marking where the summary ends. */
|
|
415
|
+
truncateMarker: RegExp;
|
|
416
|
+
/** Show estimated reading time for the blog post. */
|
|
417
|
+
showReadingTime: boolean;
|
|
418
|
+
/** Blog feed. */
|
|
419
|
+
feedOptions: FeedOptions;
|
|
420
|
+
/**
|
|
421
|
+
* Base URL to edit your site. The final URL is computed by `editUrl +
|
|
422
|
+
* relativePostPath`. Using a function allows more nuanced control for each
|
|
423
|
+
* file. Omitting this variable entirely will disable edit links.
|
|
424
|
+
*/
|
|
425
|
+
editUrl?: string | EditUrlFunction;
|
|
426
|
+
/**
|
|
427
|
+
* The edit URL will target the localized file, instead of the original
|
|
428
|
+
* unlocalized file. Ignored when `editUrl` is a function.
|
|
429
|
+
*/
|
|
430
|
+
editLocalizedFiles?: boolean;
|
|
431
|
+
/** Path to the authors map file, relative to the blog content directory. */
|
|
432
|
+
authorsMapPath: string;
|
|
433
|
+
/** A callback to customize the reading time number displayed. */
|
|
434
|
+
readingTime: ReadingTimeFunctionOption;
|
|
435
|
+
/** Governs the direction of blog post sorting. */
|
|
436
|
+
sortPosts: 'ascending' | 'descending';
|
|
437
|
+
/** Whether to display the last date the doc was updated. */
|
|
438
|
+
showLastUpdateTime: boolean;
|
|
439
|
+
/** Whether to display the author who last updated the doc. */
|
|
440
|
+
showLastUpdateAuthor: boolean;
|
|
441
|
+
/** An optional function which can be used to transform blog posts
|
|
442
|
+
* (filter, modify, delete, etc...).
|
|
443
|
+
*/
|
|
444
|
+
processBlogPosts: ProcessBlogPostsFn;
|
|
445
|
+
};
|
|
445
446
|
|
|
446
447
|
/**
|
|
447
448
|
* Feed options, as provided by user config. `type` accepts `all` as shortcut
|
|
@@ -494,7 +495,7 @@ yarn workspace v1.22.19image` is a collocated image path, this entry will be the
|
|
|
494
495
|
[permalink: string]: BlogTag;
|
|
495
496
|
};
|
|
496
497
|
|
|
497
|
-
export type BlogTag =
|
|
498
|
+
export type BlogTag = TagMetadata & {
|
|
498
499
|
/** Blog post permalinks. */
|
|
499
500
|
items: string[];
|
|
500
501
|
pages: BlogPaginated[];
|
package/src/props.ts
CHANGED
|
@@ -13,6 +13,7 @@ export function toTagsProp({blogTags}: {blogTags: BlogTags}): TagsListItem[] {
|
|
|
13
13
|
.map((tag) => ({
|
|
14
14
|
label: tag.label,
|
|
15
15
|
permalink: tag.permalink,
|
|
16
|
+
description: tag.description,
|
|
16
17
|
count: tag.items.length,
|
|
17
18
|
}));
|
|
18
19
|
}
|
|
@@ -27,6 +28,7 @@ export function toTagProp({
|
|
|
27
28
|
return {
|
|
28
29
|
label: tag.label,
|
|
29
30
|
permalink: tag.permalink,
|
|
31
|
+
description: tag.description,
|
|
30
32
|
allTagsPath: blogTagsListPath,
|
|
31
33
|
count: tag.items.length,
|
|
32
34
|
unlisted: tag.unlisted,
|