@docusaurus/plugin-content-blog 2.0.0-beta.6f366f4b4 → 2.0.0-beta.7

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 (53) hide show
  1. package/lib/.tsbuildinfo +1 -1
  2. package/lib/authors.d.ts +23 -0
  3. package/lib/authors.js +150 -0
  4. package/lib/blogFrontMatter.d.ts +19 -6
  5. package/lib/blogFrontMatter.js +31 -19
  6. package/lib/blogUtils.d.ts +10 -2
  7. package/lib/blogUtils.js +146 -104
  8. package/lib/index.js +76 -70
  9. package/lib/markdownLoader.js +3 -3
  10. package/lib/pluginOptionSchema.d.ts +3 -27
  11. package/lib/pluginOptionSchema.js +19 -7
  12. package/lib/translations.d.ts +10 -0
  13. package/lib/translations.js +53 -0
  14. package/lib/types.d.ts +37 -14
  15. package/package.json +13 -11
  16. package/src/__tests__/__fixtures__/authorsMapFiles/authors.json +29 -0
  17. package/src/__tests__/__fixtures__/authorsMapFiles/authors.yml +27 -0
  18. package/src/__tests__/__fixtures__/authorsMapFiles/authorsBad1.json +5 -0
  19. package/src/__tests__/__fixtures__/authorsMapFiles/authorsBad1.yml +3 -0
  20. package/src/__tests__/__fixtures__/authorsMapFiles/authorsBad2.json +3 -0
  21. package/src/__tests__/__fixtures__/authorsMapFiles/authorsBad2.yml +2 -0
  22. package/src/__tests__/__fixtures__/authorsMapFiles/authorsBad3.json +8 -0
  23. package/src/__tests__/__fixtures__/authorsMapFiles/authorsBad3.yml +3 -0
  24. package/src/__tests__/__fixtures__/component/Typography.tsx +6 -0
  25. package/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathEmpty/empty +0 -0
  26. package/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathJson1/authors.json +0 -0
  27. package/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathJson2/authors.json +0 -0
  28. package/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathNestedYml/sub/folder/authors.yml +0 -0
  29. package/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathYml1/authors.yml +0 -0
  30. package/src/__tests__/__fixtures__/getAuthorsMapFilePath/contentPathYml2/authors.yml +0 -0
  31. package/src/__tests__/__fixtures__/website/blog/2018-12-14-Happy-First-Birthday-Slash.md +3 -0
  32. package/src/__tests__/__fixtures__/website/blog/authors.yml +4 -0
  33. package/src/__tests__/__fixtures__/website/blog/mdx-blog-post.mdx +36 -0
  34. package/src/__tests__/__fixtures__/website/blog/simple-slug.md +4 -0
  35. package/src/__tests__/__fixtures__/website/i18n/en/docusaurus-plugin-content-blog/2018-12-14-Happy-First-Birthday-Slash.md +3 -0
  36. package/src/__tests__/__fixtures__/website/i18n/en/docusaurus-plugin-content-blog/authors.yml +5 -0
  37. package/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap +41 -3
  38. package/src/__tests__/__snapshots__/translations.test.ts.snap +64 -0
  39. package/src/__tests__/authors.test.ts +608 -0
  40. package/src/__tests__/blogFrontMatter.test.ts +93 -16
  41. package/src/__tests__/blogUtils.test.ts +94 -0
  42. package/src/__tests__/generateBlogFeed.test.ts +4 -0
  43. package/src/__tests__/index.test.ts +63 -12
  44. package/src/__tests__/pluginOptionSchema.test.ts +3 -3
  45. package/src/__tests__/translations.test.ts +92 -0
  46. package/src/authors.ts +202 -0
  47. package/src/blogFrontMatter.ts +73 -33
  48. package/src/blogUtils.ts +205 -132
  49. package/src/index.ts +92 -61
  50. package/{index.d.ts → src/plugin-content-blog.d.ts} +35 -31
  51. package/src/pluginOptionSchema.ts +22 -9
  52. package/src/translations.ts +63 -0
  53. package/src/types.ts +47 -16
package/lib/index.js CHANGED
@@ -8,11 +8,12 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.validateOptions = void 0;
10
10
  const tslib_1 = require("tslib");
11
- const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
12
- const path_1 = tslib_1.__importDefault(require("path"));
13
- const remark_admonitions_1 = tslib_1.__importDefault(require("remark-admonitions"));
11
+ const fs_extra_1 = (0, tslib_1.__importDefault)(require("fs-extra"));
12
+ const path_1 = (0, tslib_1.__importDefault)(require("path"));
13
+ const remark_admonitions_1 = (0, tslib_1.__importDefault)(require("remark-admonitions"));
14
14
  const utils_1 = require("@docusaurus/utils");
15
15
  const constants_1 = require("@docusaurus/core/lib/constants");
16
+ const translations_1 = require("./translations");
16
17
  const lodash_1 = require("lodash");
17
18
  const pluginOptionSchema_1 = require("./pluginOptionSchema");
18
19
  const blogUtils_1 = require("./blogUtils");
@@ -23,10 +24,10 @@ function pluginContentBlog(context, options) {
23
24
  [remark_admonitions_1.default, options.admonitions],
24
25
  ]);
25
26
  }
26
- const { siteDir, siteConfig: { onBrokenMarkdownLinks }, generatedFilesDir, i18n: { currentLocale }, } = context;
27
+ const { siteDir, siteConfig: { onBrokenMarkdownLinks, baseUrl }, generatedFilesDir, i18n: { currentLocale }, } = context;
27
28
  const contentPaths = {
28
29
  contentPath: path_1.default.resolve(siteDir, options.path),
29
- contentPathLocalized: utils_1.getPluginI18nPath({
30
+ contentPathLocalized: (0, utils_1.getPluginI18nPath)({
30
31
  siteDir,
31
32
  locale: currentLocale,
32
33
  pluginName: 'docusaurus-plugin-content-blog',
@@ -36,21 +37,30 @@ function pluginContentBlog(context, options) {
36
37
  const pluginId = (_a = options.id) !== null && _a !== void 0 ? _a : constants_1.DEFAULT_PLUGIN_ID;
37
38
  const pluginDataDirRoot = path_1.default.join(generatedFilesDir, 'docusaurus-plugin-content-blog');
38
39
  const dataDir = path_1.default.join(pluginDataDirRoot, pluginId);
39
- const aliasedSource = (source) => `~blog/${utils_1.posixPath(path_1.default.relative(pluginDataDirRoot, source))}`;
40
+ const aliasedSource = (source) => `~blog/${(0, utils_1.posixPath)(path_1.default.relative(pluginDataDirRoot, source))}`;
40
41
  return {
41
42
  name: 'docusaurus-plugin-content-blog',
42
43
  getPathsToWatch() {
43
- const { include = [] } = options;
44
- return lodash_1.flatten(blogUtils_1.getContentPathList(contentPaths).map((contentPath) => {
44
+ const { include, authorsMapPath } = options;
45
+ const contentMarkdownGlobs = (0, lodash_1.flatten)((0, blogUtils_1.getContentPathList)(contentPaths).map((contentPath) => {
45
46
  return include.map((pattern) => `${contentPath}/${pattern}`);
46
47
  }));
48
+ // TODO: we should read this path in plugin! but plugins do not support async init for now :'(
49
+ // const authorsMapFilePath = await getAuthorsMapFilePath({authorsMapPath,contentPaths,});
50
+ // simplified impl, better than nothing for now:
51
+ const authorsMapFilePath = path_1.default.join(contentPaths.contentPath, authorsMapPath);
52
+ return [authorsMapFilePath, ...contentMarkdownGlobs];
53
+ },
54
+ async getTranslationFiles() {
55
+ return (0, translations_1.getTranslationFiles)(options);
47
56
  },
48
57
  // Fetches blog contents and returns metadata for the necessary routes.
49
58
  async loadContent() {
50
- const { postsPerPage, routeBasePath } = options;
51
- const blogPosts = await blogUtils_1.generateBlogPosts(contentPaths, context, options);
59
+ const { postsPerPage: postsPerPageOption, routeBasePath, tagsBasePath, blogDescription, blogTitle, blogSidebarTitle, } = options;
60
+ const blogPosts = await (0, blogUtils_1.generateBlogPosts)(contentPaths, context, options);
52
61
  if (!blogPosts.length) {
53
62
  return {
63
+ blogSidebarTitle,
54
64
  blogPosts: [],
55
65
  blogListPaginated: [],
56
66
  blogTags: {},
@@ -77,14 +87,14 @@ function pluginContentBlog(context, options) {
77
87
  // Blog pagination routes.
78
88
  // Example: `/blog`, `/blog/page/1`, `/blog/page/2`
79
89
  const totalCount = blogPosts.length;
90
+ const postsPerPage = postsPerPageOption === 'ALL' ? totalCount : postsPerPageOption;
80
91
  const numberOfPages = Math.ceil(totalCount / postsPerPage);
81
- const { siteConfig: { baseUrl = '' }, } = context;
82
- const basePageUrl = utils_1.normalizeUrl([baseUrl, routeBasePath]);
92
+ const baseBlogUrl = (0, utils_1.normalizeUrl)([baseUrl, routeBasePath]);
83
93
  const blogListPaginated = [];
84
94
  function blogPaginationPermalink(page) {
85
95
  return page > 0
86
- ? utils_1.normalizeUrl([basePageUrl, `page/${page + 1}`])
87
- : basePageUrl;
96
+ ? (0, utils_1.normalizeUrl)([baseBlogUrl, `page/${page + 1}`])
97
+ : baseBlogUrl;
88
98
  }
89
99
  for (let page = 0; page < numberOfPages; page += 1) {
90
100
  blogListPaginated.push({
@@ -98,48 +108,19 @@ function pluginContentBlog(context, options) {
98
108
  nextPage: page < numberOfPages - 1
99
109
  ? blogPaginationPermalink(page + 1)
100
110
  : null,
101
- blogDescription: options.blogDescription,
102
- blogTitle: options.blogTitle,
111
+ blogDescription,
112
+ blogTitle,
103
113
  },
104
114
  items: blogPosts
105
115
  .slice(page * postsPerPage, (page + 1) * postsPerPage)
106
116
  .map((item) => item.id),
107
117
  });
108
118
  }
109
- const blogTags = {};
110
- const tagsPath = utils_1.normalizeUrl([basePageUrl, 'tags']);
111
- blogPosts.forEach((blogPost) => {
112
- const { tags } = blogPost.metadata;
113
- if (!tags || tags.length === 0) {
114
- // TODO: Extract tags out into a separate plugin.
115
- // eslint-disable-next-line no-param-reassign
116
- blogPost.metadata.tags = [];
117
- return;
118
- }
119
- // eslint-disable-next-line no-param-reassign
120
- blogPost.metadata.tags = tags.map((tag) => {
121
- if (typeof tag === 'string') {
122
- const normalizedTag = lodash_1.kebabCase(tag);
123
- const permalink = utils_1.normalizeUrl([tagsPath, normalizedTag]);
124
- if (!blogTags[normalizedTag]) {
125
- blogTags[normalizedTag] = {
126
- // Will only use the name of the first occurrence of the tag.
127
- name: tag.toLowerCase(),
128
- items: [],
129
- permalink,
130
- };
131
- }
132
- blogTags[normalizedTag].items.push(blogPost.id);
133
- return {
134
- label: tag,
135
- permalink,
136
- };
137
- }
138
- return tag;
139
- });
140
- });
119
+ const blogTags = (0, blogUtils_1.getBlogTags)(blogPosts);
120
+ const tagsPath = (0, utils_1.normalizeUrl)([baseBlogUrl, tagsBasePath]);
141
121
  const blogTagsListPath = Object.keys(blogTags).length > 0 ? tagsPath : null;
142
122
  return {
123
+ blogSidebarTitle,
143
124
  blogPosts,
144
125
  blogListPaginated,
145
126
  blogTags,
@@ -150,19 +131,34 @@ function pluginContentBlog(context, options) {
150
131
  if (!blogContents) {
151
132
  return;
152
133
  }
153
- const { blogListComponent, blogPostComponent, blogTagsListComponent, blogTagsPostsComponent, } = options;
134
+ const { blogListComponent, blogPostComponent, blogTagsListComponent, blogTagsPostsComponent, routeBasePath, archiveBasePath, } = options;
154
135
  const { addRoute, createData } = actions;
155
- const { blogPosts, blogListPaginated, blogTags, blogTagsListPath, } = blogContents;
136
+ const { blogSidebarTitle, blogPosts, blogListPaginated, blogTags, blogTagsListPath, } = blogContents;
156
137
  const blogItemsToMetadata = {};
157
138
  const sidebarBlogPosts = options.blogSidebarCount === 'ALL'
158
139
  ? blogPosts
159
- : lodash_1.take(blogPosts, options.blogSidebarCount);
140
+ : (0, lodash_1.take)(blogPosts, options.blogSidebarCount);
141
+ const archiveUrl = (0, utils_1.normalizeUrl)([
142
+ baseUrl,
143
+ routeBasePath,
144
+ archiveBasePath,
145
+ ]);
146
+ // creates a blog archive route
147
+ const archiveProp = await createData(`${(0, utils_1.docuHash)(archiveUrl)}.json`, JSON.stringify({ blogPosts }, null, 2));
148
+ addRoute({
149
+ path: archiveUrl,
150
+ component: '@theme/BlogArchivePage',
151
+ exact: true,
152
+ modules: {
153
+ archive: aliasedSource(archiveProp),
154
+ },
155
+ });
160
156
  // This prop is useful to provide the blog list sidebar
161
157
  const sidebarProp = await createData(
162
158
  // Note that this created data path must be in sync with
163
159
  // metadataPath provided to mdx-loader.
164
160
  `blog-post-list-prop-${pluginId}.json`, JSON.stringify({
165
- title: options.blogSidebarTitle,
161
+ title: blogSidebarTitle,
166
162
  items: sidebarBlogPosts.map((blogPost) => ({
167
163
  title: blogPost.metadata.title,
168
164
  permalink: blogPost.metadata.permalink,
@@ -174,7 +170,7 @@ function pluginContentBlog(context, options) {
174
170
  await createData(
175
171
  // Note that this created data path must be in sync with
176
172
  // metadataPath provided to mdx-loader.
177
- `${utils_1.docuHash(metadata.source)}.json`, JSON.stringify(metadata, null, 2));
173
+ `${(0, utils_1.docuHash)(metadata.source)}.json`, JSON.stringify(metadata, null, 2));
178
174
  addRoute({
179
175
  path: metadata.permalink,
180
176
  component: blogPostComponent,
@@ -190,7 +186,7 @@ function pluginContentBlog(context, options) {
190
186
  await Promise.all(blogListPaginated.map(async (listPage) => {
191
187
  const { metadata, items } = listPage;
192
188
  const { permalink } = metadata;
193
- const pageMetadataPath = await createData(`${utils_1.docuHash(permalink)}.json`, JSON.stringify(metadata, null, 2));
189
+ const pageMetadataPath = await createData(`${(0, utils_1.docuHash)(permalink)}.json`, JSON.stringify(metadata, null, 2));
194
190
  addRoute({
195
191
  path: permalink,
196
192
  component: blogListComponent,
@@ -220,6 +216,7 @@ function pluginContentBlog(context, options) {
220
216
  const tagsModule = {};
221
217
  await Promise.all(Object.keys(blogTags).map(async (tag) => {
222
218
  const { name, items, permalink } = blogTags[tag];
219
+ // Refactor all this, see docs implementation
223
220
  tagsModule[tag] = {
224
221
  allTagsPath: blogTagsListPath,
225
222
  slug: tag,
@@ -227,7 +224,7 @@ function pluginContentBlog(context, options) {
227
224
  count: items.length,
228
225
  permalink,
229
226
  };
230
- const tagsMetadataPath = await createData(`${utils_1.docuHash(permalink)}.json`, JSON.stringify(tagsModule[tag], null, 2));
227
+ const tagsMetadataPath = await createData(`${(0, utils_1.docuHash)(permalink)}.json`, JSON.stringify(tagsModule[tag], null, 2));
231
228
  addRoute({
232
229
  path: permalink,
233
230
  component: blogTagsPostsComponent,
@@ -252,7 +249,7 @@ function pluginContentBlog(context, options) {
252
249
  }));
253
250
  // Only create /tags page if there are tags.
254
251
  if (Object.keys(blogTags).length > 0) {
255
- const tagsListPath = await createData(`${utils_1.docuHash(`${blogTagsListPath}-tags`)}.json`, JSON.stringify(tagsModule, null, 2));
252
+ const tagsListPath = await createData(`${(0, utils_1.docuHash)(`${blogTagsListPath}-tags`)}.json`, JSON.stringify(tagsModule, null, 2));
256
253
  addRoute({
257
254
  path: blogTagsListPath,
258
255
  component: blogTagsListComponent,
@@ -264,21 +261,24 @@ function pluginContentBlog(context, options) {
264
261
  });
265
262
  }
266
263
  },
264
+ translateContent({ content, translationFiles }) {
265
+ return (0, translations_1.translateContent)(content, translationFiles);
266
+ },
267
267
  configureWebpack(_config, isServer, { getJSLoader }, content) {
268
268
  const { rehypePlugins, remarkPlugins, truncateMarker, beforeDefaultRemarkPlugins, beforeDefaultRehypePlugins, } = options;
269
269
  const markdownLoaderOptions = {
270
270
  siteDir,
271
271
  contentPaths,
272
272
  truncateMarker,
273
- sourceToPermalink: blogUtils_1.getSourceToPermalink(content.blogPosts),
273
+ sourceToPermalink: (0, blogUtils_1.getSourceToPermalink)(content.blogPosts),
274
274
  onBrokenMarkdownLink: (brokenMarkdownLink) => {
275
275
  if (onBrokenMarkdownLinks === 'ignore') {
276
276
  return;
277
277
  }
278
- utils_1.reportMessage(`Blog markdown link couldn't be resolved: (${brokenMarkdownLink.link}) in ${brokenMarkdownLink.filePath}`, onBrokenMarkdownLinks);
278
+ (0, utils_1.reportMessage)(`Blog markdown link couldn't be resolved: (${brokenMarkdownLink.link}) in ${brokenMarkdownLink.filePath}`, onBrokenMarkdownLinks);
279
279
  },
280
280
  };
281
- const contentDirs = blogUtils_1.getContentPathList(contentPaths);
281
+ const contentDirs = (0, blogUtils_1.getContentPathList)(contentPaths);
282
282
  return {
283
283
  resolve: {
284
284
  alias: {
@@ -302,16 +302,23 @@ function pluginContentBlog(context, options) {
302
302
  beforeDefaultRemarkPlugins,
303
303
  beforeDefaultRehypePlugins,
304
304
  staticDir: path_1.default.join(siteDir, constants_1.STATIC_DIR_NAME),
305
- isMDXPartial: utils_1.createAbsoluteFilePathMatcher(options.exclude, contentDirs),
305
+ isMDXPartial: (0, utils_1.createAbsoluteFilePathMatcher)(options.exclude, contentDirs),
306
306
  metadataPath: (mdxPath) => {
307
307
  // Note that metadataPath must be the same/in-sync as
308
308
  // the path from createData for each MDX.
309
- const aliasedPath = utils_1.aliasedSitePath(mdxPath, siteDir);
310
- return path_1.default.join(dataDir, `${utils_1.docuHash(aliasedPath)}.json`);
309
+ const aliasedPath = (0, utils_1.aliasedSitePath)(mdxPath, siteDir);
310
+ return path_1.default.join(dataDir, `${(0, utils_1.docuHash)(aliasedPath)}.json`);
311
311
  },
312
312
  // For blog posts a title in markdown is always removed
313
313
  // Blog posts title are rendered separately
314
314
  removeContentTitle: true,
315
+ // Assets allow to convert some relative images paths to require() calls
316
+ createAssets: ({ frontMatter, metadata, }) => {
317
+ return {
318
+ image: frontMatter.image,
319
+ authorsImageUrls: metadata.authors.map((author) => author.imageURL),
320
+ };
321
+ },
315
322
  },
316
323
  },
317
324
  {
@@ -325,11 +332,10 @@ function pluginContentBlog(context, options) {
325
332
  };
326
333
  },
327
334
  async postBuild({ outDir }) {
328
- var _a;
329
- if (!((_a = options.feedOptions) === null || _a === void 0 ? void 0 : _a.type)) {
335
+ if (!options.feedOptions.type) {
330
336
  return;
331
337
  }
332
- const feed = await blogUtils_1.generateBlogFeed(contentPaths, context, options);
338
+ const feed = await (0, blogUtils_1.generateBlogFeed)(contentPaths, context, options);
333
339
  if (!feed) {
334
340
  return;
335
341
  }
@@ -346,7 +352,7 @@ function pluginContentBlog(context, options) {
346
352
  }));
347
353
  },
348
354
  injectHtmlTags({ content }) {
349
- var _a;
355
+ var _a, _b;
350
356
  if (!content.blogPosts.length) {
351
357
  return {};
352
358
  }
@@ -354,17 +360,17 @@ function pluginContentBlog(context, options) {
354
360
  return {};
355
361
  }
356
362
  const feedTypes = options.feedOptions.type;
357
- const { siteConfig: { title }, baseUrl, } = context;
363
+ const feedTitle = (_b = options.feedOptions.title) !== null && _b !== void 0 ? _b : context.siteConfig.title;
358
364
  const feedsConfig = {
359
365
  rss: {
360
366
  type: 'application/rss+xml',
361
367
  path: 'rss.xml',
362
- title: `${title} Blog RSS Feed`,
368
+ title: `${feedTitle} RSS Feed`,
363
369
  },
364
370
  atom: {
365
371
  type: 'application/atom+xml',
366
372
  path: 'atom.xml',
367
- title: `${title} Blog Atom Feed`,
373
+ title: `${feedTitle} Atom Feed`,
368
374
  },
369
375
  };
370
376
  const headTags = [];
@@ -379,7 +385,7 @@ function pluginContentBlog(context, options) {
379
385
  attributes: {
380
386
  rel: 'alternate',
381
387
  type,
382
- href: utils_1.normalizeUrl([
388
+ href: (0, utils_1.normalizeUrl)([
383
389
  baseUrl,
384
390
  options.routeBasePath,
385
391
  feedConfigPath,
@@ -14,17 +14,17 @@ const markdownLoader = function (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
  };
@@ -5,30 +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
- export declare const DEFAULT_OPTIONS: {
9
- feedOptions: {
10
- type: string[];
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
- exclude: string[];
30
- routeBasePath: string;
31
- path: string;
32
- editLocalizedFiles: boolean;
33
- };
34
- 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>;
@@ -10,7 +10,7 @@ exports.PluginOptionSchema = exports.DEFAULT_OPTIONS = void 0;
10
10
  const utils_validation_1 = require("@docusaurus/utils-validation");
11
11
  const utils_1 = require("@docusaurus/utils");
12
12
  exports.DEFAULT_OPTIONS = {
13
- feedOptions: { type: ['rss', 'atom'] },
13
+ feedOptions: { type: ['rss', 'atom'], copyright: '' },
14
14
  beforeDefaultRehypePlugins: [],
15
15
  beforeDefaultRemarkPlugins: [],
16
16
  admonitions: {},
@@ -27,23 +27,27 @@ exports.DEFAULT_OPTIONS = {
27
27
  blogSidebarCount: 5,
28
28
  blogSidebarTitle: 'Recent posts',
29
29
  postsPerPage: 10,
30
- include: ['*.md', '*.mdx'],
30
+ include: ['**/*.{md,mdx}'],
31
31
  exclude: utils_1.GlobExcludeDefault,
32
32
  routeBasePath: 'blog',
33
+ tagsBasePath: 'tags',
34
+ archiveBasePath: 'archive',
33
35
  path: 'blog',
34
36
  editLocalizedFiles: false,
37
+ authorsMapPath: 'authors.yml',
35
38
  };
36
39
  exports.PluginOptionSchema = utils_validation_1.Joi.object({
37
40
  path: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.path),
41
+ archiveBasePath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.archiveBasePath),
38
42
  routeBasePath: utils_validation_1.Joi.string()
39
43
  // '' not allowed, see https://github.com/facebook/docusaurus/issues/3374
40
44
  // .allow('')
41
45
  .default(exports.DEFAULT_OPTIONS.routeBasePath),
46
+ tagsBasePath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.tagsBasePath),
42
47
  include: utils_validation_1.Joi.array().items(utils_validation_1.Joi.string()).default(exports.DEFAULT_OPTIONS.include),
43
48
  exclude: utils_validation_1.Joi.array().items(utils_validation_1.Joi.string()).default(exports.DEFAULT_OPTIONS.exclude),
44
- postsPerPage: utils_validation_1.Joi.number()
45
- .integer()
46
- .min(1)
49
+ postsPerPage: utils_validation_1.Joi.alternatives()
50
+ .try(utils_validation_1.Joi.equal('ALL').required(), utils_validation_1.Joi.number().integer().min(1).required())
47
51
  .default(exports.DEFAULT_OPTIONS.postsPerPage),
48
52
  blogListComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogListComponent),
49
53
  blogPostComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogPostComponent),
@@ -54,7 +58,7 @@ exports.PluginOptionSchema = utils_validation_1.Joi.object({
54
58
  .allow('')
55
59
  .default(exports.DEFAULT_OPTIONS.blogDescription),
56
60
  blogSidebarCount: utils_validation_1.Joi.alternatives()
57
- .try(utils_validation_1.Joi.equal('ALL').required(), utils_validation_1.Joi.number().required())
61
+ .try(utils_validation_1.Joi.equal('ALL').required(), utils_validation_1.Joi.number().integer().min(0).required())
58
62
  .default(exports.DEFAULT_OPTIONS.blogSidebarCount),
59
63
  blogSidebarTitle: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogSidebarTitle),
60
64
  showReadingTime: utils_validation_1.Joi.bool().default(exports.DEFAULT_OPTIONS.showReadingTime),
@@ -75,7 +79,15 @@ exports.PluginOptionSchema = utils_validation_1.Joi.object({
75
79
  .default(exports.DEFAULT_OPTIONS.feedOptions.type),
76
80
  title: utils_validation_1.Joi.string().allow(''),
77
81
  description: utils_validation_1.Joi.string().allow(''),
78
- copyright: utils_validation_1.Joi.string(),
82
+ // only add default value when user actually wants a feed (type is not null)
83
+ copyright: utils_validation_1.Joi.when('type', {
84
+ is: utils_validation_1.Joi.any().valid(null),
85
+ then: utils_validation_1.Joi.string().optional(),
86
+ otherwise: utils_validation_1.Joi.string()
87
+ .allow('')
88
+ .default(exports.DEFAULT_OPTIONS.feedOptions.copyright),
89
+ }),
79
90
  language: utils_validation_1.Joi.string(),
80
91
  }).default(exports.DEFAULT_OPTIONS.feedOptions),
92
+ authorsMapPath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.authorsMapPath),
81
93
  });
@@ -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;
package/lib/types.d.ts CHANGED
@@ -5,32 +5,43 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import type { RemarkAndRehypePluginOptions } from '@docusaurus/mdx-loader';
8
- import { BrokenMarkdownLink, ContentPaths } from '@docusaurus/utils/lib/markdownLinks';
8
+ import type { Tag } from '@docusaurus/utils';
9
+ import type { BrokenMarkdownLink, ContentPaths } from '@docusaurus/utils/lib/markdownLinks';
10
+ import { Overwrite } from 'utility-types';
9
11
  export declare type BlogContentPaths = ContentPaths;
10
12
  export interface BlogContent {
13
+ blogSidebarTitle: string;
11
14
  blogPosts: BlogPost[];
12
15
  blogListPaginated: BlogPaginated[];
13
16
  blogTags: BlogTags;
14
17
  blogTagsListPath: string | null;
15
18
  }
16
- export interface DateLink {
17
- date: Date;
18
- link: string;
19
- }
20
19
  export declare type FeedType = 'rss' | 'atom';
20
+ export declare type FeedOptions = {
21
+ type?: FeedType[] | null;
22
+ title?: string;
23
+ description?: string;
24
+ copyright: string;
25
+ language?: string;
26
+ };
27
+ export declare type UserFeedOptions = Overwrite<Partial<FeedOptions>, {
28
+ type?: FeedOptions['type'] | 'all';
29
+ }>;
21
30
  export declare type EditUrlFunction = (editUrlParams: {
22
31
  blogDirPath: string;
23
32
  blogPath: string;
24
33
  permalink: string;
25
34
  locale: string;
26
35
  }) => string | undefined;
27
- export interface PluginOptions extends RemarkAndRehypePluginOptions {
36
+ export declare type PluginOptions = RemarkAndRehypePluginOptions & {
28
37
  id?: string;
29
38
  path: string;
30
39
  routeBasePath: string;
40
+ tagsBasePath: string;
41
+ archiveBasePath: string;
31
42
  include: string[];
32
43
  exclude: string[];
33
- postsPerPage: number;
44
+ postsPerPage: number | 'ALL';
34
45
  blogListComponent: string;
35
46
  blogPostComponent: string;
36
47
  blogTagsListComponent: string;
@@ -42,7 +53,7 @@ export interface PluginOptions extends RemarkAndRehypePluginOptions {
42
53
  truncateMarker: RegExp;
43
54
  showReadingTime: boolean;
44
55
  feedOptions: {
45
- type?: [FeedType] | null;
56
+ type?: FeedType[] | null;
46
57
  title?: string;
47
58
  description?: string;
48
59
  copyright: string;
@@ -51,7 +62,11 @@ export interface PluginOptions extends RemarkAndRehypePluginOptions {
51
62
  editUrl?: string | EditUrlFunction;
52
63
  editLocalizedFiles?: boolean;
53
64
  admonitions: Record<string, unknown>;
54
- }
65
+ authorsMapPath: string;
66
+ };
67
+ export declare type UserPluginOptions = Overwrite<Partial<PluginOptions>, {
68
+ feedOptions?: UserFeedOptions;
69
+ }>;
55
70
  export interface BlogTags {
56
71
  [key: string]: BlogTag;
57
72
  }
@@ -63,6 +78,7 @@ export interface BlogTag {
63
78
  export interface BlogPost {
64
79
  id: string;
65
80
  metadata: MetaData;
81
+ content: string;
66
82
  }
67
83
  export interface BlogPaginatedMetadata {
68
84
  permalink: string;
@@ -79,28 +95,35 @@ export interface BlogPaginated {
79
95
  metadata: BlogPaginatedMetadata;
80
96
  items: string[];
81
97
  }
98
+ export interface Author extends Record<string, unknown> {
99
+ name?: string;
100
+ imageURL?: string;
101
+ url?: string;
102
+ title?: string;
103
+ }
82
104
  export interface MetaData {
83
105
  permalink: string;
84
106
  source: string;
85
107
  description: string;
86
108
  date: Date;
87
109
  formattedDate: string;
88
- tags: (Tag | string)[];
110
+ tags: Tag[];
89
111
  title: string;
90
112
  readingTime?: number;
91
113
  prevItem?: Paginator;
92
114
  nextItem?: Paginator;
93
115
  truncated: boolean;
94
116
  editUrl?: string;
117
+ authors: Author[];
118
+ }
119
+ export interface Assets {
120
+ image?: string;
121
+ authorsImageUrls: (string | undefined)[];
95
122
  }
96
123
  export interface Paginator {
97
124
  title: string;
98
125
  permalink: string;
99
126
  }
100
- export interface Tag {
101
- label: string;
102
- permalink: string;
103
- }
104
127
  export interface BlogItemsToMetadata {
105
128
  [key: string]: MetaData;
106
129
  }