@docusaurus/plugin-content-blog 0.0.0-4288 → 0.0.0-4297

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.js CHANGED
@@ -9,7 +9,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.getBlogPostAuthors = exports.getAuthorsMap = exports.getAuthorsMapFilePath = exports.readAuthorsMapFile = exports.validateAuthorsMapFile = void 0;
10
10
  const tslib_1 = require("tslib");
11
11
  const fs_extra_1 = (0, tslib_1.__importDefault)(require("fs-extra"));
12
- const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
12
+ const logger_1 = (0, tslib_1.__importDefault)(require("@docusaurus/logger"));
13
13
  const path_1 = (0, tslib_1.__importDefault)(require("path"));
14
14
  const utils_1 = require("@docusaurus/utils");
15
15
  const utils_validation_1 = require("@docusaurus/utils-validation");
@@ -37,7 +37,7 @@ async function readAuthorsMapFile(filePath) {
37
37
  }
38
38
  catch (e) {
39
39
  // TODO replace later by error cause: see https://v8.dev/features/error-cause
40
- console.error(chalk_1.default.red('The author list file looks invalid!'));
40
+ logger_1.default.error('The author list file looks invalid!');
41
41
  throw e;
42
42
  }
43
43
  }
@@ -63,7 +63,7 @@ async function getAuthorsMap(params) {
63
63
  }
64
64
  catch (e) {
65
65
  // TODO replace later by error cause, see https://v8.dev/features/error-cause
66
- console.error(chalk_1.default.red(`Couldn't read blog authors map at path ${filePath}`));
66
+ logger_1.default.error `Couldn't read blog authors map at path=${filePath}`;
67
67
  throw e;
68
68
  }
69
69
  }
package/lib/blogUtils.js CHANGED
@@ -9,13 +9,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.getContentPathList = exports.linkify = exports.generateBlogPosts = exports.parseBlogFileName = exports.getBlogTags = exports.getSourceToPermalink = exports.truncate = void 0;
10
10
  const tslib_1 = require("tslib");
11
11
  const fs_extra_1 = (0, tslib_1.__importDefault)(require("fs-extra"));
12
- const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
13
12
  const path_1 = (0, tslib_1.__importDefault)(require("path"));
14
13
  const reading_time_1 = (0, tslib_1.__importDefault)(require("reading-time"));
15
14
  const lodash_1 = require("lodash");
16
15
  const utils_1 = require("@docusaurus/utils");
17
16
  const blogFrontMatter_1 = require("./blogFrontMatter");
18
17
  const authors_1 = require("./authors");
18
+ const logger_1 = (0, tslib_1.__importDefault)(require("@docusaurus/logger"));
19
19
  function truncate(fileString, truncateMarker) {
20
20
  return fileString.split(truncateMarker, 1).shift();
21
21
  }
@@ -88,7 +88,7 @@ async function processBlogSourceFile(blogSourceRelative, contentPaths, context,
88
88
  return undefined;
89
89
  }
90
90
  if (frontMatter.id) {
91
- console.warn(chalk_1.default.yellow(`"id" header option is deprecated in ${blogSourceRelative} file. Please use "slug" option instead.`));
91
+ logger_1.default.warn `name=${'id'} header option is deprecated in path=${blogSourceRelative} file. Please use name=${'slug'} option instead.`;
92
92
  }
93
93
  const parsedBlogFileName = parseBlogFileName(blogSourceRelative);
94
94
  async function getDate() {
@@ -179,7 +179,7 @@ async function generateBlogPosts(contentPaths, context, options) {
179
179
  return await processBlogSourceFile(blogSourceFile, contentPaths, context, options, authorsMap);
180
180
  }
181
181
  catch (e) {
182
- console.error(chalk_1.default.red(`Processing of blog source file failed for path "${blogSourceFile}"`));
182
+ logger_1.default.error `Processing of blog source file failed for path path=${blogSourceFile}.`;
183
183
  throw e;
184
184
  }
185
185
  }))).filter(Boolean);
package/lib/feed.js CHANGED
@@ -51,23 +51,40 @@ async function generateBlogFeed({ blogPosts, options, siteConfig, }) {
51
51
  }
52
52
  blogPosts.forEach((post) => {
53
53
  const { id, metadata: { title: metadataTitle, permalink, date, description, authors }, } = post;
54
- feed.addItem({
54
+ const feedItem = {
55
55
  title: metadataTitle,
56
56
  id,
57
57
  link: (0, utils_1.normalizeUrl)([siteUrl, permalink]),
58
58
  date,
59
59
  description,
60
60
  content: mdxToFeedContent(post.content),
61
- author: authors.map(toFeedAuthor),
62
- });
61
+ };
62
+ // json1() method takes the first item of authors array
63
+ // it causes an error when authors array is empty
64
+ const feedItemAuthors = authors.map(toFeedAuthor);
65
+ if (feedItemAuthors.length > 0) {
66
+ feedItem.author = feedItemAuthors;
67
+ }
68
+ feed.addItem(feedItem);
63
69
  });
64
70
  return feed;
65
71
  }
66
72
  exports.generateBlogFeed = generateBlogFeed;
67
- async function createBlogFeedFile({ feed, feedType, filePath, }) {
68
- const feedContent = feedType === 'rss' ? feed.rss2() : feed.atom1();
73
+ async function createBlogFeedFile({ feed, feedType, generatePath, }) {
74
+ const [feedContent, feedPath] = (() => {
75
+ switch (feedType) {
76
+ case 'rss':
77
+ return [feed.rss2(), 'rss.xml'];
78
+ case 'json':
79
+ return [feed.json1(), 'feed.json'];
80
+ case 'atom':
81
+ return [feed.atom1(), 'atom.xml'];
82
+ default:
83
+ throw new Error(`Feed type ${feedType} not supported.`);
84
+ }
85
+ })();
69
86
  try {
70
- await fs_extra_1.default.outputFile(filePath, feedContent);
87
+ await fs_extra_1.default.outputFile(path_1.default.join(generatePath, feedPath), feedContent);
71
88
  }
72
89
  catch (err) {
73
90
  throw new Error(`Generating ${feedType} feed failed: ${err}.`);
@@ -79,12 +96,10 @@ async function createBlogFeedFiles({ blogPosts, options, siteConfig, outDir, })
79
96
  if (!feed || !feedTypes) {
80
97
  return;
81
98
  }
82
- await Promise.all(feedTypes.map(async (feedType) => {
83
- await createBlogFeedFile({
84
- feed,
85
- feedType,
86
- filePath: path_1.default.join(outDir, options.routeBasePath, `${feedType}.xml`),
87
- });
88
- }));
99
+ await Promise.all(feedTypes.map((feedType) => createBlogFeedFile({
100
+ feed,
101
+ feedType,
102
+ generatePath: path_1.default.join(outDir, options.routeBasePath),
103
+ })));
89
104
  }
90
105
  exports.createBlogFeedFiles = createBlogFeedFiles;
package/lib/index.js CHANGED
@@ -364,6 +364,11 @@ function pluginContentBlog(context, options) {
364
364
  path: 'atom.xml',
365
365
  title: `${feedTitle} Atom Feed`,
366
366
  },
367
+ json: {
368
+ type: 'application/json',
369
+ path: 'feed.json',
370
+ title: `${feedTitle} JSON Feed`,
371
+ },
367
372
  };
368
373
  const headTags = [];
369
374
  feedTypes.forEach((feedType) => {
@@ -74,8 +74,8 @@ exports.PluginOptionSchema = utils_validation_1.Joi.object({
74
74
  beforeDefaultRehypePlugins: utils_validation_1.RehypePluginsSchema.default(exports.DEFAULT_OPTIONS.beforeDefaultRehypePlugins),
75
75
  feedOptions: utils_validation_1.Joi.object({
76
76
  type: utils_validation_1.Joi.alternatives()
77
- .try(utils_validation_1.Joi.array().items(utils_validation_1.Joi.string()), utils_validation_1.Joi.alternatives().conditional(utils_validation_1.Joi.string().equal('all', 'rss', 'atom'), {
78
- then: utils_validation_1.Joi.custom((val) => val === 'all' ? ['rss', 'atom'] : [val]),
77
+ .try(utils_validation_1.Joi.array().items(utils_validation_1.Joi.string().equal('rss', 'atom', 'json')), utils_validation_1.Joi.alternatives().conditional(utils_validation_1.Joi.string().equal('all', 'rss', 'atom', 'json'), {
78
+ then: utils_validation_1.Joi.custom((val) => val === 'all' ? ['rss', 'atom', 'json'] : [val]),
79
79
  }))
80
80
  .allow(null)
81
81
  .default(exports.DEFAULT_OPTIONS.feedOptions.type),
package/lib/types.d.ts CHANGED
@@ -17,7 +17,7 @@ export interface BlogContent {
17
17
  blogTags: BlogTags;
18
18
  blogTagsListPath: string | null;
19
19
  }
20
- export declare type FeedType = 'rss' | 'atom';
20
+ export declare type FeedType = 'rss' | 'atom' | 'json';
21
21
  export declare type FeedOptions = {
22
22
  type?: FeedType[] | null;
23
23
  title?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docusaurus/plugin-content-blog",
3
- "version": "0.0.0-4288",
3
+ "version": "0.0.0-4297",
4
4
  "description": "Blog plugin for Docusaurus.",
5
5
  "main": "lib/index.js",
6
6
  "types": "src/plugin-content-blog.d.ts",
@@ -18,11 +18,11 @@
18
18
  },
19
19
  "license": "MIT",
20
20
  "dependencies": {
21
- "@docusaurus/core": "0.0.0-4288",
22
- "@docusaurus/mdx-loader": "0.0.0-4288",
23
- "@docusaurus/utils": "0.0.0-4288",
24
- "@docusaurus/utils-validation": "0.0.0-4288",
25
- "chalk": "^4.1.2",
21
+ "@docusaurus/core": "0.0.0-4297",
22
+ "@docusaurus/logger": "0.0.0-4297",
23
+ "@docusaurus/mdx-loader": "0.0.0-4297",
24
+ "@docusaurus/utils": "0.0.0-4297",
25
+ "@docusaurus/utils-validation": "0.0.0-4297",
26
26
  "escape-string-regexp": "^4.0.0",
27
27
  "feed": "^4.2.2",
28
28
  "fs-extra": "^10.0.0",
@@ -37,7 +37,7 @@
37
37
  "webpack": "^5.61.0"
38
38
  },
39
39
  "devDependencies": {
40
- "@docusaurus/types": "0.0.0-4288"
40
+ "@docusaurus/types": "0.0.0-4297"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "react": "^16.8.4 || ^17.0.0",
@@ -46,5 +46,5 @@
46
46
  "engines": {
47
47
  "node": ">=14"
48
48
  },
49
- "gitHead": "7c22eff7031a837b8ed4810c896508e3a1756f2e"
49
+ "gitHead": "84ae34c33c664bf856f3a92047919a074e087d77"
50
50
  }
package/src/authors.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  import fs from 'fs-extra';
9
- import chalk from 'chalk';
9
+ import logger from '@docusaurus/logger';
10
10
  import path from 'path';
11
11
  import {Author, BlogContentPaths} from './types';
12
12
  import {findFolderContainingFile} from '@docusaurus/utils';
@@ -48,7 +48,7 @@ export async function readAuthorsMapFile(
48
48
  return validateAuthorsMapFile(unsafeContent);
49
49
  } catch (e) {
50
50
  // TODO replace later by error cause: see https://v8.dev/features/error-cause
51
- console.error(chalk.red('The author list file looks invalid!'));
51
+ logger.error('The author list file looks invalid!');
52
52
  throw e;
53
53
  }
54
54
  }
@@ -88,9 +88,7 @@ export async function getAuthorsMap(
88
88
  return await readAuthorsMapFile(filePath);
89
89
  } catch (e) {
90
90
  // TODO replace later by error cause, see https://v8.dev/features/error-cause
91
- console.error(
92
- chalk.red(`Couldn't read blog authors map at path ${filePath}`),
93
- );
91
+ logger.error`Couldn't read blog authors map at path=${filePath}`;
94
92
  throw e;
95
93
  }
96
94
  }
package/src/blogUtils.ts CHANGED
@@ -6,7 +6,6 @@
6
6
  */
7
7
 
8
8
  import fs from 'fs-extra';
9
- import chalk from 'chalk';
10
9
  import path from 'path';
11
10
  import readingTime from 'reading-time';
12
11
  import {keyBy, mapValues} from 'lodash';
@@ -33,6 +32,7 @@ import {
33
32
  import {LoadContext} from '@docusaurus/types';
34
33
  import {validateBlogPostFrontMatter} from './blogFrontMatter';
35
34
  import {AuthorsMap, getAuthorsMap, getBlogPostAuthors} from './authors';
35
+ import logger from '@docusaurus/logger';
36
36
 
37
37
  export function truncate(fileString: string, truncateMarker: RegExp): string {
38
38
  return fileString.split(truncateMarker, 1).shift()!;
@@ -151,11 +151,7 @@ async function processBlogSourceFile(
151
151
  }
152
152
 
153
153
  if (frontMatter.id) {
154
- console.warn(
155
- chalk.yellow(
156
- `"id" header option is deprecated in ${blogSourceRelative} file. Please use "slug" option instead.`,
157
- ),
158
- );
154
+ logger.warn`name=${'id'} header option is deprecated in path=${blogSourceRelative} file. Please use name=${'slug'} option instead.`;
159
155
  }
160
156
 
161
157
  const parsedBlogFileName = parseBlogFileName(blogSourceRelative);
@@ -276,11 +272,7 @@ export async function generateBlogPosts(
276
272
  authorsMap,
277
273
  );
278
274
  } catch (e) {
279
- console.error(
280
- chalk.red(
281
- `Processing of blog source file failed for path "${blogSourceFile}"`,
282
- ),
283
- );
275
+ logger.error`Processing of blog source file failed for path path=${blogSourceFile}.`;
284
276
  throw e;
285
277
  }
286
278
  }),
package/src/feed.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
 
8
- import {Feed, Author as FeedAuthor} from 'feed';
8
+ import {Feed, Author as FeedAuthor, Item as FeedItem} from 'feed';
9
9
  import {PluginOptions, Author, BlogPost, FeedType} from './types';
10
10
  import {normalizeUrl, mdxToHtml} from '@docusaurus/utils';
11
11
  import {DocusaurusConfig} from '@docusaurus/types';
@@ -68,15 +68,24 @@ export async function generateBlogFeed({
68
68
  id,
69
69
  metadata: {title: metadataTitle, permalink, date, description, authors},
70
70
  } = post;
71
- feed.addItem({
71
+
72
+ const feedItem: FeedItem = {
72
73
  title: metadataTitle,
73
74
  id,
74
75
  link: normalizeUrl([siteUrl, permalink]),
75
76
  date,
76
77
  description,
77
78
  content: mdxToFeedContent(post.content),
78
- author: authors.map(toFeedAuthor),
79
- });
79
+ };
80
+
81
+ // json1() method takes the first item of authors array
82
+ // it causes an error when authors array is empty
83
+ const feedItemAuthors = authors.map(toFeedAuthor);
84
+ if (feedItemAuthors.length > 0) {
85
+ feedItem.author = feedItemAuthors;
86
+ }
87
+
88
+ feed.addItem(feedItem);
80
89
  });
81
90
 
82
91
  return feed;
@@ -85,15 +94,26 @@ export async function generateBlogFeed({
85
94
  async function createBlogFeedFile({
86
95
  feed,
87
96
  feedType,
88
- filePath,
97
+ generatePath,
89
98
  }: {
90
99
  feed: Feed;
91
100
  feedType: FeedType;
92
- filePath: string;
101
+ generatePath: string;
93
102
  }) {
94
- const feedContent = feedType === 'rss' ? feed.rss2() : feed.atom1();
103
+ const [feedContent, feedPath] = (() => {
104
+ switch (feedType) {
105
+ case 'rss':
106
+ return [feed.rss2(), 'rss.xml'];
107
+ case 'json':
108
+ return [feed.json1(), 'feed.json'];
109
+ case 'atom':
110
+ return [feed.atom1(), 'atom.xml'];
111
+ default:
112
+ throw new Error(`Feed type ${feedType} not supported.`);
113
+ }
114
+ })();
95
115
  try {
96
- await fs.outputFile(filePath, feedContent);
116
+ await fs.outputFile(path.join(generatePath, feedPath), feedContent);
97
117
  } catch (err) {
98
118
  throw new Error(`Generating ${feedType} feed failed: ${err}.`);
99
119
  }
@@ -118,12 +138,12 @@ export async function createBlogFeedFiles({
118
138
  }
119
139
 
120
140
  await Promise.all(
121
- feedTypes.map(async (feedType) => {
122
- await createBlogFeedFile({
141
+ feedTypes.map((feedType) =>
142
+ createBlogFeedFile({
123
143
  feed,
124
144
  feedType,
125
- filePath: path.join(outDir, options.routeBasePath, `${feedType}.xml`),
126
- });
127
- }),
145
+ generatePath: path.join(outDir, options.routeBasePath),
146
+ }),
147
+ ),
128
148
  );
129
149
  }
package/src/index.ts CHANGED
@@ -550,6 +550,11 @@ export default function pluginContentBlog(
550
550
  path: 'atom.xml',
551
551
  title: `${feedTitle} Atom Feed`,
552
552
  },
553
+ json: {
554
+ type: 'application/json',
555
+ path: 'feed.json',
556
+ title: `${feedTitle} JSON Feed`,
557
+ },
553
558
  };
554
559
  const headTags: HtmlTags = [];
555
560
 
@@ -90,12 +90,12 @@ export const PluginOptionSchema = Joi.object<PluginOptions>({
90
90
  feedOptions: Joi.object({
91
91
  type: Joi.alternatives()
92
92
  .try(
93
- Joi.array().items(Joi.string()),
93
+ Joi.array().items(Joi.string().equal('rss', 'atom', 'json')),
94
94
  Joi.alternatives().conditional(
95
- Joi.string().equal('all', 'rss', 'atom'),
95
+ Joi.string().equal('all', 'rss', 'atom', 'json'),
96
96
  {
97
97
  then: Joi.custom((val) =>
98
- val === 'all' ? ['rss', 'atom'] : [val],
98
+ val === 'all' ? ['rss', 'atom', 'json'] : [val],
99
99
  ),
100
100
  },
101
101
  ),
package/src/types.ts CHANGED
@@ -24,7 +24,7 @@ export interface BlogContent {
24
24
  blogTagsListPath: string | null;
25
25
  }
26
26
 
27
- export type FeedType = 'rss' | 'atom';
27
+ export type FeedType = 'rss' | 'atom' | 'json';
28
28
 
29
29
  export type FeedOptions = {
30
30
  type?: FeedType[] | null;