@docusaurus/plugin-content-blog 2.0.0-beta.fbdeefcac → 2.0.0-rc.1

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.
Files changed (57) hide show
  1. package/lib/authors.d.ts +22 -0
  2. package/lib/authors.js +122 -0
  3. package/lib/blogUtils.d.ts +27 -7
  4. package/lib/blogUtils.js +201 -145
  5. package/lib/feed.d.ts +15 -0
  6. package/lib/feed.js +102 -0
  7. package/lib/frontMatter.d.ts +10 -0
  8. package/lib/{blogFrontMatter.js → frontMatter.js} +31 -19
  9. package/lib/index.d.ts +4 -4
  10. package/lib/index.js +165 -201
  11. package/lib/markdownLoader.d.ts +3 -6
  12. package/lib/markdownLoader.js +6 -7
  13. package/lib/options.d.ts +10 -0
  14. package/lib/{pluginOptionSchema.js → options.js} +44 -14
  15. package/lib/remark/footnoteIDFixer.d.ts +14 -0
  16. package/lib/remark/footnoteIDFixer.js +29 -0
  17. package/lib/translations.d.ts +10 -0
  18. package/lib/translations.js +53 -0
  19. package/lib/types.d.ts +4 -109
  20. package/package.json +23 -19
  21. package/src/authors.ts +168 -0
  22. package/src/blogUtils.ts +306 -204
  23. package/src/feed.ts +171 -0
  24. package/src/frontMatter.ts +81 -0
  25. package/src/index.ts +230 -269
  26. package/src/markdownLoader.ts +11 -16
  27. package/src/{pluginOptionSchema.ts → options.ts} +57 -16
  28. package/src/plugin-content-blog.d.ts +587 -0
  29. package/src/remark/footnoteIDFixer.ts +29 -0
  30. package/src/translations.ts +69 -0
  31. package/src/types.ts +2 -128
  32. package/index.d.ts +0 -138
  33. package/lib/.tsbuildinfo +0 -1
  34. package/lib/blogFrontMatter.d.ts +0 -28
  35. package/lib/pluginOptionSchema.d.ts +0 -33
  36. package/src/__tests__/__fixtures__/website/blog/2018-12-14-Happy-First-Birthday-Slash.md +0 -5
  37. package/src/__tests__/__fixtures__/website/blog/complex-slug.md +0 -7
  38. package/src/__tests__/__fixtures__/website/blog/date-matter.md +0 -5
  39. package/src/__tests__/__fixtures__/website/blog/draft.md +0 -6
  40. package/src/__tests__/__fixtures__/website/blog/heading-as-title.md +0 -5
  41. package/src/__tests__/__fixtures__/website/blog/simple-slug.md +0 -7
  42. package/src/__tests__/__fixtures__/website/blog-with-ref/2018-12-14-Happy-First-Birthday-Slash.md +0 -5
  43. package/src/__tests__/__fixtures__/website/blog-with-ref/post-with-broken-links.md +0 -11
  44. package/src/__tests__/__fixtures__/website/blog-with-ref/post.md +0 -5
  45. package/src/__tests__/__fixtures__/website/i18n/en/docusaurus-plugin-content-blog/2018-12-14-Happy-First-Birthday-Slash.md +0 -5
  46. package/src/__tests__/__fixtures__/website-blog-without-date/blog/no date.md +0 -1
  47. package/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap +0 -76
  48. package/src/__tests__/__snapshots__/linkify.test.ts.snap +0 -24
  49. package/src/__tests__/__snapshots__/pluginOptionSchema.test.ts.snap +0 -5
  50. package/src/__tests__/blogFrontMatter.test.ts +0 -317
  51. package/src/__tests__/generateBlogFeed.test.ts +0 -100
  52. package/src/__tests__/index.test.ts +0 -336
  53. package/src/__tests__/linkify.test.ts +0 -93
  54. package/src/__tests__/pluginOptionSchema.test.ts +0 -150
  55. package/src/blogFrontMatter.ts +0 -88
  56. package/tsconfig.json +0 -9
  57. package/types.d.ts +0 -13
@@ -1,76 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`blogFeed atom should not show feed without posts 1`] = `null`;
4
-
5
- exports[`blogFeed atom shows feed item for each post 1`] = `
6
- "<?xml version=\\"1.0\\" encoding=\\"utf-8\\"?>
7
- <feed xmlns=\\"http://www.w3.org/2005/Atom\\">
8
- <id>https://docusaurus.io/myBaseUrl/blog</id>
9
- <title>Hello Blog</title>
10
- <updated>2020-02-27T00:00:00.000Z</updated>
11
- <generator>https://github.com/jpmonette/feed</generator>
12
- <link rel=\\"alternate\\" href=\\"https://docusaurus.io/myBaseUrl/blog\\"/>
13
- <subtitle>Hello Blog</subtitle>
14
- <icon>https://docusaurus.io/myBaseUrl/image/favicon.ico</icon>
15
- <rights>Copyright</rights>
16
- <entry>
17
- <title type=\\"html\\"><![CDATA[draft]]></title>
18
- <id>draft</id>
19
- <link href=\\"https://docusaurus.io/myBaseUrl/blog/draft\\"/>
20
- <updated>2020-02-27T00:00:00.000Z</updated>
21
- <summary type=\\"html\\"><![CDATA[this post should not be published yet]]></summary>
22
- </entry>
23
- <entry>
24
- <title type=\\"html\\"><![CDATA[date-matter]]></title>
25
- <id>date-matter</id>
26
- <link href=\\"https://docusaurus.io/myBaseUrl/blog/date-matter\\"/>
27
- <updated>2019-01-01T00:00:00.000Z</updated>
28
- <summary type=\\"html\\"><![CDATA[date inside front matter]]></summary>
29
- </entry>
30
- <entry>
31
- <title type=\\"html\\"><![CDATA[Happy 1st Birthday Slash! (translated)]]></title>
32
- <id>Happy 1st Birthday Slash! (translated)</id>
33
- <link href=\\"https://docusaurus.io/myBaseUrl/blog/2018/12/14/Happy-First-Birthday-Slash\\"/>
34
- <updated>2018-12-14T00:00:00.000Z</updated>
35
- <summary type=\\"html\\"><![CDATA[Happy birthday! (translated)]]></summary>
36
- </entry>
37
- </feed>"
38
- `;
39
-
40
- exports[`blogFeed rss should not show feed without posts 1`] = `null`;
41
-
42
- exports[`blogFeed rss shows feed item for each post 1`] = `
43
- "<?xml version=\\"1.0\\" encoding=\\"utf-8\\"?>
44
- <rss version=\\"2.0\\">
45
- <channel>
46
- <title>Hello Blog</title>
47
- <link>https://docusaurus.io/myBaseUrl/blog</link>
48
- <description>Hello Blog</description>
49
- <lastBuildDate>Thu, 27 Feb 2020 00:00:00 GMT</lastBuildDate>
50
- <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
51
- <generator>https://github.com/jpmonette/feed</generator>
52
- <copyright>Copyright</copyright>
53
- <item>
54
- <title><![CDATA[draft]]></title>
55
- <link>https://docusaurus.io/myBaseUrl/blog/draft</link>
56
- <guid>draft</guid>
57
- <pubDate>Thu, 27 Feb 2020 00:00:00 GMT</pubDate>
58
- <description><![CDATA[this post should not be published yet]]></description>
59
- </item>
60
- <item>
61
- <title><![CDATA[date-matter]]></title>
62
- <link>https://docusaurus.io/myBaseUrl/blog/date-matter</link>
63
- <guid>date-matter</guid>
64
- <pubDate>Tue, 01 Jan 2019 00:00:00 GMT</pubDate>
65
- <description><![CDATA[date inside front matter]]></description>
66
- </item>
67
- <item>
68
- <title><![CDATA[Happy 1st Birthday Slash! (translated)]]></title>
69
- <link>https://docusaurus.io/myBaseUrl/blog/2018/12/14/Happy-First-Birthday-Slash</link>
70
- <guid>Happy 1st Birthday Slash! (translated)</guid>
71
- <pubDate>Fri, 14 Dec 2018 00:00:00 GMT</pubDate>
72
- <description><![CDATA[Happy birthday! (translated)]]></description>
73
- </item>
74
- </channel>
75
- </rss>"
76
- `;
@@ -1,24 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`report broken markdown links 1`] = `
4
- "---
5
- title: This post links to another one!
6
- ---
7
-
8
- [Good link 1](/blog/2018/12/14/Happy-First-Birthday-Slash)
9
-
10
- [Good link 2](/blog/2018/12/14/Happy-First-Birthday-Slash)
11
-
12
- [Bad link 1](postNotExist1.md)
13
-
14
- [Bad link 1](./postNotExist2.mdx)
15
- "
16
- `;
17
-
18
- exports[`transform to correct link 1`] = `
19
- "---
20
- title: This post links to another one!
21
- ---
22
-
23
- [Linked post](/blog/2018/12/14/Happy-First-Birthday-Slash)"
24
- `;
@@ -1,5 +0,0 @@
1
- // Jest Snapshot v1, https://goo.gl/fbAQLP
2
-
3
- exports[`should throw Error in case of invalid feedtype 1`] = `[ValidationError: "feedOptions.type" does not match any of the allowed types]`;
4
-
5
- exports[`should throw Error in case of invalid options 1`] = `[ValidationError: "postsPerPage" must be greater than or equal to 1]`;
@@ -1,317 +0,0 @@
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
-
8
- import {
9
- BlogPostFrontMatter,
10
- validateBlogPostFrontMatter,
11
- } from '../blogFrontMatter';
12
- import escapeStringRegexp from 'escape-string-regexp';
13
-
14
- function testField(params: {
15
- fieldName: keyof BlogPostFrontMatter;
16
- validFrontMatters: BlogPostFrontMatter[];
17
- convertibleFrontMatter?: [
18
- ConvertableFrontMatter: Record<string, unknown>,
19
- ConvertedFrontMatter: BlogPostFrontMatter,
20
- ][];
21
- invalidFrontMatters?: [
22
- InvalidFrontMatter: Record<string, unknown>,
23
- ErrorMessage: string,
24
- ][];
25
- }) {
26
- describe(`"${params.fieldName}" field`, () => {
27
- test('accept valid values', () => {
28
- params.validFrontMatters.forEach((frontMatter) => {
29
- expect(validateBlogPostFrontMatter(frontMatter)).toEqual(frontMatter);
30
- });
31
- });
32
-
33
- test('convert valid values', () => {
34
- params.convertibleFrontMatter?.forEach(
35
- ([convertibleFrontMatter, convertedFrontMatter]) => {
36
- expect(validateBlogPostFrontMatter(convertibleFrontMatter)).toEqual(
37
- convertedFrontMatter,
38
- );
39
- },
40
- );
41
- });
42
-
43
- test('throw error for values', () => {
44
- params.invalidFrontMatters?.forEach(([frontMatter, message]) => {
45
- try {
46
- validateBlogPostFrontMatter(frontMatter);
47
- fail(
48
- new Error(
49
- `Blog frontmatter is expected to be rejected, but was accepted successfully:\n ${JSON.stringify(
50
- frontMatter,
51
- null,
52
- 2,
53
- )}`,
54
- ),
55
- );
56
- } catch (e) {
57
- expect(e.message).toMatch(new RegExp(escapeStringRegexp(message)));
58
- }
59
- });
60
- });
61
- });
62
- }
63
-
64
- describe('validateBlogPostFrontMatter', () => {
65
- test('accept empty object', () => {
66
- const frontMatter = {};
67
- expect(validateBlogPostFrontMatter(frontMatter)).toEqual(frontMatter);
68
- });
69
-
70
- test('accept unknown field', () => {
71
- const frontMatter = {abc: '1'};
72
- expect(validateBlogPostFrontMatter(frontMatter)).toEqual(frontMatter);
73
- });
74
- });
75
-
76
- describe('validateBlogPostFrontMatter description', () => {
77
- testField({
78
- fieldName: 'description',
79
- validFrontMatters: [
80
- // See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
81
- {description: ''},
82
- {description: 'description'},
83
- ],
84
- });
85
- });
86
-
87
- describe('validateBlogPostFrontMatter title', () => {
88
- testField({
89
- fieldName: 'title',
90
- validFrontMatters: [
91
- // See https://github.com/facebook/docusaurus/issues/4591#issuecomment-822372398
92
- {title: ''},
93
- {title: 'title'},
94
- ],
95
- });
96
- });
97
-
98
- describe('validateBlogPostFrontMatter id', () => {
99
- testField({
100
- fieldName: 'id',
101
- validFrontMatters: [{id: '123'}, {id: 'id'}],
102
- invalidFrontMatters: [[{id: ''}, 'is not allowed to be empty']],
103
- });
104
- });
105
-
106
- describe('validateBlogPostFrontMatter author', () => {
107
- testField({
108
- fieldName: 'author',
109
- validFrontMatters: [{author: '123'}, {author: 'author'}],
110
- invalidFrontMatters: [[{author: ''}, 'is not allowed to be empty']],
111
- });
112
- });
113
-
114
- describe('validateBlogPostFrontMatter author_title', () => {
115
- testField({
116
- fieldName: 'author_title',
117
- validFrontMatters: [{author_title: '123'}, {author_title: 'author_title'}],
118
- invalidFrontMatters: [[{author_title: ''}, 'is not allowed to be empty']],
119
- });
120
-
121
- testField({
122
- fieldName: 'authorTitle',
123
- validFrontMatters: [{authorTitle: '123'}, {authorTitle: 'authorTitle'}],
124
- invalidFrontMatters: [[{authorTitle: ''}, 'is not allowed to be empty']],
125
- });
126
- });
127
-
128
- describe('validateBlogPostFrontMatter author_url', () => {
129
- testField({
130
- fieldName: 'author_url',
131
- validFrontMatters: [
132
- {author_url: 'https://docusaurus.io'},
133
- {author_url: '../../relative'},
134
- {author_url: '/absolute'},
135
- ],
136
- invalidFrontMatters: [
137
- [
138
- {author_url: ''},
139
- '"author_url" does not match any of the allowed types',
140
- ],
141
- ],
142
- });
143
-
144
- testField({
145
- fieldName: 'authorURL',
146
- validFrontMatters: [
147
- {authorURL: 'https://docusaurus.io'},
148
- {authorURL: '../../relative'},
149
- {authorURL: '/absolute'},
150
- ],
151
-
152
- invalidFrontMatters: [
153
- [{authorURL: ''}, '"authorURL" does not match any of the allowed types'],
154
- ],
155
- });
156
- });
157
-
158
- describe('validateBlogPostFrontMatter author_image_url', () => {
159
- testField({
160
- fieldName: 'author_image_url',
161
- validFrontMatters: [
162
- {author_image_url: 'https://docusaurus.io/asset/image.png'},
163
- {author_image_url: '../../relative'},
164
- {author_image_url: '/absolute'},
165
- ],
166
- invalidFrontMatters: [
167
- [
168
- {author_image_url: ''},
169
- '"author_image_url" does not match any of the allowed types',
170
- ],
171
- ],
172
- });
173
-
174
- testField({
175
- fieldName: 'authorImageURL',
176
- validFrontMatters: [
177
- {authorImageURL: 'https://docusaurus.io/asset/image.png'},
178
- {authorImageURL: '../../relative'},
179
- {authorImageURL: '/absolute'},
180
- ],
181
- invalidFrontMatters: [
182
- [
183
- {authorImageURL: ''},
184
- '"authorImageURL" does not match any of the allowed types',
185
- ],
186
- ],
187
- });
188
- });
189
-
190
- describe('validateBlogPostFrontMatter slug', () => {
191
- testField({
192
- fieldName: 'slug',
193
- validFrontMatters: [
194
- {slug: 'blog/'},
195
- {slug: '/blog'},
196
- {slug: '/blog/'},
197
- {slug: './blog'},
198
- {slug: '../blog'},
199
- {slug: '../../blog'},
200
- {slug: '/api/plugins/@docusaurus/plugin-debug'},
201
- {slug: '@site/api/asset/image.png'},
202
- ],
203
- invalidFrontMatters: [[{slug: ''}, 'is not allowed to be empty']],
204
- });
205
- });
206
-
207
- describe('validateBlogPostFrontMatter image', () => {
208
- testField({
209
- fieldName: 'image',
210
- validFrontMatters: [
211
- {image: 'https://docusaurus.io/image.png'},
212
- {image: 'blog/'},
213
- {image: '/blog'},
214
- {image: '/blog/'},
215
- {image: './blog'},
216
- {image: '../blog'},
217
- {image: '../../blog'},
218
- {image: '/api/plugins/@docusaurus/plugin-debug'},
219
- {image: '@site/api/asset/image.png'},
220
- ],
221
- invalidFrontMatters: [
222
- [{image: ''}, '"image" does not match any of the allowed types'],
223
- ],
224
- });
225
- });
226
-
227
- describe('validateBlogPostFrontMatter tags', () => {
228
- testField({
229
- fieldName: 'tags',
230
- validFrontMatters: [
231
- {tags: []},
232
- {tags: ['hello']},
233
- {tags: ['hello', 'world']},
234
- {tags: ['hello', 'world']},
235
- {tags: ['hello', {label: 'tagLabel', permalink: '/tagPermalink'}]},
236
- ],
237
- invalidFrontMatters: [
238
- [{tags: ''}, 'must be an array'],
239
- [{tags: ['']}, 'is not allowed to be empty'],
240
- ],
241
- // See https://github.com/facebook/docusaurus/issues/4642
242
- convertibleFrontMatter: [
243
- [{tags: [42]}, {tags: ['42']}],
244
- [
245
- {tags: [{label: 84, permalink: '/tagPermalink'}]},
246
- {tags: [{label: '84', permalink: '/tagPermalink'}]},
247
- ],
248
- ],
249
- });
250
- });
251
-
252
- describe('validateBlogPostFrontMatter keywords', () => {
253
- testField({
254
- fieldName: 'keywords',
255
- validFrontMatters: [
256
- {keywords: ['hello']},
257
- {keywords: ['hello', 'world']},
258
- {keywords: ['hello', 'world']},
259
- {keywords: ['hello']},
260
- ],
261
- invalidFrontMatters: [
262
- [{keywords: ''}, 'must be an array'],
263
- [{keywords: ['']}, 'is not allowed to be empty'],
264
- [{keywords: []}, 'does not contain 1 required value(s)'],
265
- ],
266
- });
267
- });
268
-
269
- describe('validateBlogPostFrontMatter draft', () => {
270
- testField({
271
- fieldName: 'draft',
272
- validFrontMatters: [{draft: true}, {draft: false}],
273
- convertibleFrontMatter: [
274
- [{draft: 'true'}, {draft: true}],
275
- [{draft: 'false'}, {draft: false}],
276
- ],
277
- invalidFrontMatters: [
278
- [{draft: 'yes'}, 'must be a boolean'],
279
- [{draft: 'no'}, 'must be a boolean'],
280
- ],
281
- });
282
- });
283
-
284
- describe('validateBlogPostFrontMatter hide_table_of_contents', () => {
285
- testField({
286
- fieldName: 'hide_table_of_contents',
287
- validFrontMatters: [
288
- {hide_table_of_contents: true},
289
- {hide_table_of_contents: false},
290
- ],
291
- convertibleFrontMatter: [
292
- [{hide_table_of_contents: 'true'}, {hide_table_of_contents: true}],
293
- [{hide_table_of_contents: 'false'}, {hide_table_of_contents: false}],
294
- ],
295
- invalidFrontMatters: [
296
- [{hide_table_of_contents: 'yes'}, 'must be a boolean'],
297
- [{hide_table_of_contents: 'no'}, 'must be a boolean'],
298
- ],
299
- });
300
- });
301
-
302
- describe('validateBlogPostFrontMatter date', () => {
303
- testField({
304
- fieldName: 'date',
305
- validFrontMatters: [
306
- {date: new Date('2020-01-01')},
307
- // @ts-expect-error: string for test
308
- {date: '2020-01-01'},
309
- // @ts-expect-error: string for test
310
- {date: '2020'},
311
- ],
312
- invalidFrontMatters: [
313
- [{date: 'abc'}, 'must be a valid date'],
314
- [{date: ''}, 'must be a valid date'],
315
- ],
316
- });
317
- });
@@ -1,100 +0,0 @@
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
-
8
- import path from 'path';
9
- import {generateBlogFeed} from '../blogUtils';
10
- import {LoadContext, I18n} from '@docusaurus/types';
11
- import {PluginOptions, BlogContentPaths} from '../types';
12
-
13
- const DefaultI18N: I18n = {
14
- currentLocale: 'en',
15
- locales: ['en'],
16
- defaultLocale: 'en',
17
- localeConfigs: {},
18
- };
19
-
20
- function getBlogContentPaths(siteDir: string): BlogContentPaths {
21
- return {
22
- contentPath: path.resolve(siteDir, 'blog'),
23
- contentPathLocalized: path.resolve(
24
- siteDir,
25
- 'i18n',
26
- 'en',
27
- 'docusaurus-plugin-content-blog',
28
- ),
29
- };
30
- }
31
-
32
- describe('blogFeed', () => {
33
- (['atom', 'rss'] as const).forEach((feedType) => {
34
- describe(`${feedType}`, () => {
35
- test('should not show feed without posts', async () => {
36
- const siteDir = __dirname;
37
- const siteConfig = {
38
- title: 'Hello',
39
- baseUrl: '/',
40
- url: 'https://docusaurus.io',
41
- favicon: 'image/favicon.ico',
42
- };
43
-
44
- const feed = await generateBlogFeed(
45
- getBlogContentPaths(siteDir),
46
- {
47
- siteDir,
48
- siteConfig,
49
- i18n: DefaultI18N,
50
- } as LoadContext,
51
- {
52
- path: 'invalid-blog-path',
53
- routeBasePath: 'blog',
54
- include: ['*.md', '*.mdx'],
55
- feedOptions: {
56
- type: [feedType],
57
- copyright: 'Copyright',
58
- },
59
- } as PluginOptions,
60
- );
61
- const feedContent =
62
- feed && (feedType === 'rss' ? feed.rss2() : feed.atom1());
63
- expect(feedContent).toMatchSnapshot();
64
- });
65
-
66
- test('shows feed item for each post', async () => {
67
- const siteDir = path.join(__dirname, '__fixtures__', 'website');
68
- const generatedFilesDir = path.resolve(siteDir, '.docusaurus');
69
- const siteConfig = {
70
- title: 'Hello',
71
- baseUrl: '/myBaseUrl/',
72
- url: 'https://docusaurus.io',
73
- favicon: 'image/favicon.ico',
74
- };
75
-
76
- const feed = await generateBlogFeed(
77
- getBlogContentPaths(siteDir),
78
- {
79
- siteDir,
80
- siteConfig,
81
- generatedFilesDir,
82
- i18n: DefaultI18N,
83
- } as LoadContext,
84
- {
85
- path: 'blog',
86
- routeBasePath: 'blog',
87
- include: ['*r*.md', '*.mdx'], // skip no-date.md - it won't play nice with snapshots
88
- feedOptions: {
89
- type: [feedType],
90
- copyright: 'Copyright',
91
- },
92
- } as PluginOptions,
93
- );
94
- const feedContent =
95
- feed && (feedType === 'rss' ? feed.rss2() : feed.atom1());
96
- expect(feedContent).toMatchSnapshot();
97
- });
98
- });
99
- });
100
- });