@docusaurus/plugin-content-blog 2.0.0-beta.16 → 2.0.0-beta.19
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/authors.d.ts +3 -1
- package/lib/authors.js +14 -6
- package/lib/blogUtils.d.ts +5 -3
- package/lib/blogUtils.js +21 -19
- package/lib/feed.d.ts +3 -3
- package/lib/feed.js +16 -17
- package/lib/{blogFrontMatter.d.ts → frontMatter.d.ts} +3 -1
- package/lib/{blogFrontMatter.js → frontMatter.js} +0 -0
- package/lib/index.d.ts +3 -4
- package/lib/index.js +50 -58
- package/lib/markdownLoader.js +1 -1
- package/lib/options.d.ts +10 -0
- package/lib/{pluginOptionSchema.js → options.js} +9 -4
- package/lib/remark/footnoteIDFixer.d.ts +14 -0
- package/lib/remark/footnoteIDFixer.js +29 -0
- package/lib/translations.d.ts +4 -5
- package/lib/translations.js +4 -4
- package/lib/types.d.ts +4 -73
- package/package.json +13 -12
- package/src/authors.ts +29 -17
- package/src/blogUtils.ts +30 -22
- package/src/deps.d.ts +1 -1
- package/src/feed.ts +53 -56
- package/src/{blogFrontMatter.ts → frontMatter.ts} +3 -3
- package/src/index.ts +74 -98
- package/src/markdownLoader.ts +1 -1
- package/src/{pluginOptionSchema.ts → options.ts} +16 -4
- package/src/plugin-content-blog.d.ts +408 -97
- package/src/remark/footnoteIDFixer.ts +29 -0
- package/src/translations.ts +14 -9
- package/src/types.ts +2 -94
- package/lib/pluginOptionSchema.d.ts +0 -10
package/src/index.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import path from 'path';
|
|
9
9
|
import admonitions from 'remark-admonitions';
|
|
10
|
+
import footnoteIDFixer from './remark/footnoteIDFixer';
|
|
10
11
|
import {
|
|
11
12
|
normalizeUrl,
|
|
12
13
|
docuHash,
|
|
@@ -19,29 +20,13 @@ import {
|
|
|
19
20
|
getContentPathList,
|
|
20
21
|
getDataFilePath,
|
|
21
22
|
DEFAULT_PLUGIN_ID,
|
|
23
|
+
type TagsListItem,
|
|
24
|
+
type TagModule,
|
|
22
25
|
} from '@docusaurus/utils';
|
|
23
26
|
import {translateContent, getTranslationFiles} from './translations';
|
|
24
27
|
|
|
25
|
-
import type {
|
|
26
|
-
|
|
27
|
-
BlogTags,
|
|
28
|
-
BlogContent,
|
|
29
|
-
BlogItemsToMetadata,
|
|
30
|
-
TagsModule,
|
|
31
|
-
BlogPaginated,
|
|
32
|
-
BlogContentPaths,
|
|
33
|
-
BlogMarkdownLoaderOptions,
|
|
34
|
-
MetaData,
|
|
35
|
-
TagModule,
|
|
36
|
-
} from './types';
|
|
37
|
-
import {PluginOptionSchema} from './pluginOptionSchema';
|
|
38
|
-
import type {
|
|
39
|
-
LoadContext,
|
|
40
|
-
Plugin,
|
|
41
|
-
HtmlTags,
|
|
42
|
-
OptionValidationContext,
|
|
43
|
-
ValidationResult,
|
|
44
|
-
} from '@docusaurus/types';
|
|
28
|
+
import type {BlogContentPaths, BlogMarkdownLoaderOptions} from './types';
|
|
29
|
+
import type {LoadContext, Plugin, HtmlTags} from '@docusaurus/types';
|
|
45
30
|
import {
|
|
46
31
|
generateBlogPosts,
|
|
47
32
|
getSourceToPermalink,
|
|
@@ -52,7 +37,12 @@ import {createBlogFeedFiles} from './feed';
|
|
|
52
37
|
import type {
|
|
53
38
|
PluginOptions,
|
|
54
39
|
BlogPostFrontMatter,
|
|
40
|
+
BlogPostMetadata,
|
|
55
41
|
Assets,
|
|
42
|
+
BlogTag,
|
|
43
|
+
BlogTags,
|
|
44
|
+
BlogContent,
|
|
45
|
+
BlogPaginated,
|
|
56
46
|
} from '@docusaurus/plugin-content-blog';
|
|
57
47
|
|
|
58
48
|
export default async function pluginContentBlog(
|
|
@@ -111,7 +101,7 @@ export default async function pluginContentBlog(
|
|
|
111
101
|
) as string[];
|
|
112
102
|
},
|
|
113
103
|
|
|
114
|
-
|
|
104
|
+
getTranslationFiles() {
|
|
115
105
|
return getTranslationFiles(options);
|
|
116
106
|
},
|
|
117
107
|
|
|
@@ -126,6 +116,8 @@ export default async function pluginContentBlog(
|
|
|
126
116
|
blogSidebarTitle,
|
|
127
117
|
} = options;
|
|
128
118
|
|
|
119
|
+
const baseBlogUrl = normalizeUrl([baseUrl, routeBasePath]);
|
|
120
|
+
const blogTagsListPath = normalizeUrl([baseBlogUrl, tagsBasePath]);
|
|
129
121
|
const blogPosts = await generateBlogPosts(contentPaths, context, options);
|
|
130
122
|
|
|
131
123
|
if (!blogPosts.length) {
|
|
@@ -134,7 +126,7 @@ export default async function pluginContentBlog(
|
|
|
134
126
|
blogPosts: [],
|
|
135
127
|
blogListPaginated: [],
|
|
136
128
|
blogTags: {},
|
|
137
|
-
blogTagsListPath
|
|
129
|
+
blogTagsListPath,
|
|
138
130
|
blogTagsPaginated: [],
|
|
139
131
|
};
|
|
140
132
|
}
|
|
@@ -159,8 +151,6 @@ export default async function pluginContentBlog(
|
|
|
159
151
|
}
|
|
160
152
|
});
|
|
161
153
|
|
|
162
|
-
const baseBlogUrl = normalizeUrl([baseUrl, routeBasePath]);
|
|
163
|
-
|
|
164
154
|
const blogListPaginated: BlogPaginated[] = paginateBlogPosts({
|
|
165
155
|
blogPosts,
|
|
166
156
|
blogTitle,
|
|
@@ -176,11 +166,6 @@ export default async function pluginContentBlog(
|
|
|
176
166
|
blogTitle,
|
|
177
167
|
});
|
|
178
168
|
|
|
179
|
-
const tagsPath = normalizeUrl([baseBlogUrl, tagsBasePath]);
|
|
180
|
-
|
|
181
|
-
const blogTagsListPath =
|
|
182
|
-
Object.keys(blogTags).length > 0 ? tagsPath : null;
|
|
183
|
-
|
|
184
169
|
return {
|
|
185
170
|
blogSidebarTitle,
|
|
186
171
|
blogPosts,
|
|
@@ -214,20 +199,20 @@ export default async function pluginContentBlog(
|
|
|
214
199
|
blogTagsListPath,
|
|
215
200
|
} = blogContents;
|
|
216
201
|
|
|
217
|
-
const blogItemsToMetadata:
|
|
202
|
+
const blogItemsToMetadata: {[postId: string]: BlogPostMetadata} = {};
|
|
218
203
|
|
|
219
204
|
const sidebarBlogPosts =
|
|
220
205
|
options.blogSidebarCount === 'ALL'
|
|
221
206
|
? blogPosts
|
|
222
207
|
: blogPosts.slice(0, options.blogSidebarCount);
|
|
223
208
|
|
|
224
|
-
if (archiveBasePath) {
|
|
209
|
+
if (archiveBasePath && blogPosts.length) {
|
|
225
210
|
const archiveUrl = normalizeUrl([
|
|
226
211
|
baseUrl,
|
|
227
212
|
routeBasePath,
|
|
228
213
|
archiveBasePath,
|
|
229
214
|
]);
|
|
230
|
-
//
|
|
215
|
+
// Create a blog archive route
|
|
231
216
|
const archiveProp = await createData(
|
|
232
217
|
`${docuHash(archiveUrl)}.json`,
|
|
233
218
|
JSON.stringify({blogPosts}, null, 2),
|
|
@@ -301,50 +286,62 @@ export default async function pluginContentBlog(
|
|
|
301
286
|
exact: true,
|
|
302
287
|
modules: {
|
|
303
288
|
sidebar: aliasedSource(sidebarProp),
|
|
304
|
-
items: items.map((postID) =>
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
path: blogItemsToMetadata[postID].source,
|
|
311
|
-
query: {
|
|
312
|
-
truncated: true,
|
|
313
|
-
},
|
|
289
|
+
items: items.map((postID) => ({
|
|
290
|
+
content: {
|
|
291
|
+
__import: true,
|
|
292
|
+
path: blogItemsToMetadata[postID]!.source,
|
|
293
|
+
query: {
|
|
294
|
+
truncated: true,
|
|
314
295
|
},
|
|
315
|
-
}
|
|
316
|
-
),
|
|
296
|
+
},
|
|
297
|
+
})),
|
|
317
298
|
metadata: aliasedSource(pageMetadataPath),
|
|
318
299
|
},
|
|
319
300
|
});
|
|
320
301
|
}),
|
|
321
302
|
);
|
|
322
303
|
|
|
323
|
-
// Tags.
|
|
324
|
-
if (
|
|
304
|
+
// Tags. This is the last part so we early-return if there are no tags.
|
|
305
|
+
if (Object.keys(blogTags).length === 0) {
|
|
325
306
|
return;
|
|
326
307
|
}
|
|
327
308
|
|
|
328
|
-
|
|
329
|
-
Object.
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
);
|
|
309
|
+
async function createTagsListPage() {
|
|
310
|
+
const tagsProp: TagsListItem[] = Object.values(blogTags).map((tag) => ({
|
|
311
|
+
label: tag.label,
|
|
312
|
+
permalink: tag.permalink,
|
|
313
|
+
count: tag.items.length,
|
|
314
|
+
}));
|
|
315
|
+
|
|
316
|
+
const tagsPropPath = await createData(
|
|
317
|
+
`${docuHash(`${blogTagsListPath}-tags`)}.json`,
|
|
318
|
+
JSON.stringify(tagsProp, null, 2),
|
|
319
|
+
);
|
|
340
320
|
|
|
341
|
-
|
|
321
|
+
addRoute({
|
|
322
|
+
path: blogTagsListPath,
|
|
323
|
+
component: blogTagsListComponent,
|
|
324
|
+
exact: true,
|
|
325
|
+
modules: {
|
|
326
|
+
sidebar: aliasedSource(sidebarProp),
|
|
327
|
+
tags: aliasedSource(tagsPropPath),
|
|
328
|
+
},
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
async function createTagPostsListPage(tag: BlogTag): Promise<void> {
|
|
342
333
|
await Promise.all(
|
|
343
334
|
tag.pages.map(async (blogPaginated) => {
|
|
344
335
|
const {metadata, items} = blogPaginated;
|
|
345
|
-
const
|
|
336
|
+
const tagProp: TagModule = {
|
|
337
|
+
label: tag.label,
|
|
338
|
+
permalink: tag.permalink,
|
|
339
|
+
allTagsPath: blogTagsListPath,
|
|
340
|
+
count: tag.items.length,
|
|
341
|
+
};
|
|
342
|
+
const tagPropPath = await createData(
|
|
346
343
|
`${docuHash(metadata.permalink)}.json`,
|
|
347
|
-
JSON.stringify(
|
|
344
|
+
JSON.stringify(tagProp, null, 2),
|
|
348
345
|
);
|
|
349
346
|
|
|
350
347
|
const listMetadataPath = await createData(
|
|
@@ -359,7 +356,7 @@ export default async function pluginContentBlog(
|
|
|
359
356
|
modules: {
|
|
360
357
|
sidebar: aliasedSource(sidebarProp),
|
|
361
358
|
items: items.map((postID) => {
|
|
362
|
-
const blogPostMetadata = blogItemsToMetadata[postID]
|
|
359
|
+
const blogPostMetadata = blogItemsToMetadata[postID]!;
|
|
363
360
|
return {
|
|
364
361
|
content: {
|
|
365
362
|
__import: true,
|
|
@@ -370,7 +367,7 @@ export default async function pluginContentBlog(
|
|
|
370
367
|
},
|
|
371
368
|
};
|
|
372
369
|
}),
|
|
373
|
-
|
|
370
|
+
tag: aliasedSource(tagPropPath),
|
|
374
371
|
listMetadata: aliasedSource(listMetadataPath),
|
|
375
372
|
},
|
|
376
373
|
});
|
|
@@ -378,25 +375,8 @@ export default async function pluginContentBlog(
|
|
|
378
375
|
);
|
|
379
376
|
}
|
|
380
377
|
|
|
381
|
-
await
|
|
382
|
-
|
|
383
|
-
// Only create /tags page if there are tags.
|
|
384
|
-
if (Object.keys(blogTags).length > 0) {
|
|
385
|
-
const tagsListPath = await createData(
|
|
386
|
-
`${docuHash(`${blogTagsListPath}-tags`)}.json`,
|
|
387
|
-
JSON.stringify(tagsModule, null, 2),
|
|
388
|
-
);
|
|
389
|
-
|
|
390
|
-
addRoute({
|
|
391
|
-
path: blogTagsListPath,
|
|
392
|
-
component: blogTagsListComponent,
|
|
393
|
-
exact: true,
|
|
394
|
-
modules: {
|
|
395
|
-
sidebar: aliasedSource(sidebarProp),
|
|
396
|
-
tags: aliasedSource(tagsListPath),
|
|
397
|
-
},
|
|
398
|
-
});
|
|
399
|
-
}
|
|
378
|
+
await createTagsListPage();
|
|
379
|
+
await Promise.all(Object.values(blogTags).map(createTagPostsListPage));
|
|
400
380
|
},
|
|
401
381
|
|
|
402
382
|
translateContent({content, translationFiles}) {
|
|
@@ -449,7 +429,10 @@ export default async function pluginContentBlog(
|
|
|
449
429
|
options: {
|
|
450
430
|
remarkPlugins,
|
|
451
431
|
rehypePlugins,
|
|
452
|
-
beforeDefaultRemarkPlugins
|
|
432
|
+
beforeDefaultRemarkPlugins: [
|
|
433
|
+
footnoteIDFixer,
|
|
434
|
+
...beforeDefaultRemarkPlugins,
|
|
435
|
+
],
|
|
453
436
|
beforeDefaultRehypePlugins,
|
|
454
437
|
staticDirs: siteConfig.staticDirectories.map((dir) =>
|
|
455
438
|
path.resolve(siteDir, dir),
|
|
@@ -479,7 +462,7 @@ export default async function pluginContentBlog(
|
|
|
479
462
|
metadata,
|
|
480
463
|
}: {
|
|
481
464
|
frontMatter: BlogPostFrontMatter;
|
|
482
|
-
metadata:
|
|
465
|
+
metadata: BlogPostMetadata;
|
|
483
466
|
}): Assets => ({
|
|
484
467
|
image: frontMatter.image,
|
|
485
468
|
authorsImageUrls: metadata.authors.map(
|
|
@@ -512,6 +495,7 @@ export default async function pluginContentBlog(
|
|
|
512
495
|
options,
|
|
513
496
|
outDir,
|
|
514
497
|
siteConfig,
|
|
498
|
+
locale: currentLocale,
|
|
515
499
|
});
|
|
516
500
|
},
|
|
517
501
|
|
|
@@ -546,13 +530,11 @@ export default async function pluginContentBlog(
|
|
|
546
530
|
const headTags: HtmlTags = [];
|
|
547
531
|
|
|
548
532
|
feedTypes.forEach((feedType) => {
|
|
549
|
-
const
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
const {type, path: feedConfigPath, title: feedConfigTitle} = feedConfig;
|
|
533
|
+
const {
|
|
534
|
+
type,
|
|
535
|
+
path: feedConfigPath,
|
|
536
|
+
title: feedConfigTitle,
|
|
537
|
+
} = feedsConfig[feedType];
|
|
556
538
|
|
|
557
539
|
headTags.push({
|
|
558
540
|
tagName: 'link',
|
|
@@ -576,10 +558,4 @@ export default async function pluginContentBlog(
|
|
|
576
558
|
};
|
|
577
559
|
}
|
|
578
560
|
|
|
579
|
-
export
|
|
580
|
-
validate,
|
|
581
|
-
options,
|
|
582
|
-
}: OptionValidationContext<PluginOptions>): ValidationResult<PluginOptions> {
|
|
583
|
-
const validatedOptions = validate(PluginOptionSchema, options);
|
|
584
|
-
return validatedOptions;
|
|
585
|
-
}
|
|
561
|
+
export {validateOptions} from './options';
|
package/src/markdownLoader.ts
CHANGED
|
@@ -13,7 +13,8 @@ import {
|
|
|
13
13
|
URISchema,
|
|
14
14
|
} from '@docusaurus/utils-validation';
|
|
15
15
|
import {GlobExcludeDefault} from '@docusaurus/utils';
|
|
16
|
-
import type {PluginOptions} from '@docusaurus/plugin-content-blog';
|
|
16
|
+
import type {PluginOptions, Options} from '@docusaurus/plugin-content-blog';
|
|
17
|
+
import type {OptionValidationContext} from '@docusaurus/types';
|
|
17
18
|
|
|
18
19
|
export const DEFAULT_OPTIONS: PluginOptions = {
|
|
19
20
|
feedOptions: {type: ['rss', 'atom'], copyright: ''},
|
|
@@ -46,7 +47,7 @@ export const DEFAULT_OPTIONS: PluginOptions = {
|
|
|
46
47
|
sortPosts: 'descending',
|
|
47
48
|
};
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
const PluginOptionSchema = Joi.object<PluginOptions>({
|
|
50
51
|
path: Joi.string().default(DEFAULT_OPTIONS.path),
|
|
51
52
|
archiveBasePath: Joi.string()
|
|
52
53
|
.default(DEFAULT_OPTIONS.archiveBasePath)
|
|
@@ -110,7 +111,7 @@ export const PluginOptionSchema = Joi.object<PluginOptions>({
|
|
|
110
111
|
.default(DEFAULT_OPTIONS.feedOptions.type),
|
|
111
112
|
title: Joi.string().allow(''),
|
|
112
113
|
description: Joi.string().allow(''),
|
|
113
|
-
//
|
|
114
|
+
// Only add default value when user actually wants a feed (type is not null)
|
|
114
115
|
copyright: Joi.when('type', {
|
|
115
116
|
is: Joi.any().valid(null),
|
|
116
117
|
then: Joi.string().optional(),
|
|
@@ -125,4 +126,15 @@ export const PluginOptionSchema = Joi.object<PluginOptions>({
|
|
|
125
126
|
sortPosts: Joi.string()
|
|
126
127
|
.valid('descending', 'ascending')
|
|
127
128
|
.default(DEFAULT_OPTIONS.sortPosts),
|
|
128
|
-
});
|
|
129
|
+
}).default(DEFAULT_OPTIONS);
|
|
130
|
+
|
|
131
|
+
export function validateOptions({
|
|
132
|
+
validate,
|
|
133
|
+
options,
|
|
134
|
+
}: OptionValidationContext<Options, PluginOptions>): PluginOptions {
|
|
135
|
+
const validatedOptions = validate(
|
|
136
|
+
PluginOptionSchema,
|
|
137
|
+
options,
|
|
138
|
+
) as PluginOptions;
|
|
139
|
+
return validatedOptions;
|
|
140
|
+
}
|