@docusaurus/plugin-content-blog 2.0.0-beta.677e53d4d → 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 (56) 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 +78 -77
  9. package/lib/markdownLoader.js +3 -3
  10. package/lib/pluginOptionSchema.d.ts +3 -26
  11. package/lib/pluginOptionSchema.js +22 -7
  12. package/lib/translations.d.ts +10 -0
  13. package/lib/translations.js +53 -0
  14. package/lib/types.d.ts +38 -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/_partials/somePartial.md +3 -0
  33. package/src/__tests__/__fixtures__/website/blog/_partials/subfolder/somePartial.md +3 -0
  34. package/src/__tests__/__fixtures__/website/blog/_somePartial.md +3 -0
  35. package/src/__tests__/__fixtures__/website/blog/authors.yml +4 -0
  36. package/src/__tests__/__fixtures__/website/blog/mdx-blog-post.mdx +36 -0
  37. package/src/__tests__/__fixtures__/website/blog/simple-slug.md +4 -0
  38. package/src/__tests__/__fixtures__/website/i18n/en/docusaurus-plugin-content-blog/2018-12-14-Happy-First-Birthday-Slash.md +3 -0
  39. package/src/__tests__/__fixtures__/website/i18n/en/docusaurus-plugin-content-blog/authors.yml +5 -0
  40. package/src/__tests__/__snapshots__/generateBlogFeed.test.ts.snap +81 -3
  41. package/src/__tests__/__snapshots__/translations.test.ts.snap +64 -0
  42. package/src/__tests__/authors.test.ts +608 -0
  43. package/src/__tests__/blogFrontMatter.test.ts +93 -16
  44. package/src/__tests__/blogUtils.test.ts +94 -0
  45. package/src/__tests__/generateBlogFeed.test.ts +7 -1
  46. package/src/__tests__/index.test.ts +63 -12
  47. package/src/__tests__/pluginOptionSchema.test.ts +3 -3
  48. package/src/__tests__/translations.test.ts +92 -0
  49. package/src/authors.ts +202 -0
  50. package/src/blogFrontMatter.ts +73 -33
  51. package/src/blogUtils.ts +206 -131
  52. package/src/index.ts +98 -71
  53. package/{index.d.ts → src/plugin-content-blog.d.ts} +35 -31
  54. package/src/pluginOptionSchema.ts +25 -9
  55. package/src/translations.ts +63 -0
  56. package/src/types.ts +48 -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,28 +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];
47
53
  },
48
- getClientModules() {
49
- const modules = [];
50
- if (options.admonitions) {
51
- modules.push(require.resolve('remark-admonitions/styles/infima.css'));
52
- }
53
- return modules;
54
+ async getTranslationFiles() {
55
+ return (0, translations_1.getTranslationFiles)(options);
54
56
  },
55
57
  // Fetches blog contents and returns metadata for the necessary routes.
56
58
  async loadContent() {
57
- const { postsPerPage, routeBasePath } = options;
58
- 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);
59
61
  if (!blogPosts.length) {
60
62
  return {
63
+ blogSidebarTitle,
61
64
  blogPosts: [],
62
65
  blogListPaginated: [],
63
66
  blogTags: {},
@@ -84,14 +87,14 @@ function pluginContentBlog(context, options) {
84
87
  // Blog pagination routes.
85
88
  // Example: `/blog`, `/blog/page/1`, `/blog/page/2`
86
89
  const totalCount = blogPosts.length;
90
+ const postsPerPage = postsPerPageOption === 'ALL' ? totalCount : postsPerPageOption;
87
91
  const numberOfPages = Math.ceil(totalCount / postsPerPage);
88
- const { siteConfig: { baseUrl = '' }, } = context;
89
- const basePageUrl = utils_1.normalizeUrl([baseUrl, routeBasePath]);
92
+ const baseBlogUrl = (0, utils_1.normalizeUrl)([baseUrl, routeBasePath]);
90
93
  const blogListPaginated = [];
91
94
  function blogPaginationPermalink(page) {
92
95
  return page > 0
93
- ? utils_1.normalizeUrl([basePageUrl, `page/${page + 1}`])
94
- : basePageUrl;
96
+ ? (0, utils_1.normalizeUrl)([baseBlogUrl, `page/${page + 1}`])
97
+ : baseBlogUrl;
95
98
  }
96
99
  for (let page = 0; page < numberOfPages; page += 1) {
97
100
  blogListPaginated.push({
@@ -105,48 +108,19 @@ function pluginContentBlog(context, options) {
105
108
  nextPage: page < numberOfPages - 1
106
109
  ? blogPaginationPermalink(page + 1)
107
110
  : null,
108
- blogDescription: options.blogDescription,
109
- blogTitle: options.blogTitle,
111
+ blogDescription,
112
+ blogTitle,
110
113
  },
111
114
  items: blogPosts
112
115
  .slice(page * postsPerPage, (page + 1) * postsPerPage)
113
116
  .map((item) => item.id),
114
117
  });
115
118
  }
116
- const blogTags = {};
117
- const tagsPath = utils_1.normalizeUrl([basePageUrl, 'tags']);
118
- blogPosts.forEach((blogPost) => {
119
- const { tags } = blogPost.metadata;
120
- if (!tags || tags.length === 0) {
121
- // TODO: Extract tags out into a separate plugin.
122
- // eslint-disable-next-line no-param-reassign
123
- blogPost.metadata.tags = [];
124
- return;
125
- }
126
- // eslint-disable-next-line no-param-reassign
127
- blogPost.metadata.tags = tags.map((tag) => {
128
- if (typeof tag === 'string') {
129
- const normalizedTag = lodash_1.kebabCase(tag);
130
- const permalink = utils_1.normalizeUrl([tagsPath, normalizedTag]);
131
- if (!blogTags[normalizedTag]) {
132
- blogTags[normalizedTag] = {
133
- // Will only use the name of the first occurrence of the tag.
134
- name: tag.toLowerCase(),
135
- items: [],
136
- permalink,
137
- };
138
- }
139
- blogTags[normalizedTag].items.push(blogPost.id);
140
- return {
141
- label: tag,
142
- permalink,
143
- };
144
- }
145
- return tag;
146
- });
147
- });
119
+ const blogTags = (0, blogUtils_1.getBlogTags)(blogPosts);
120
+ const tagsPath = (0, utils_1.normalizeUrl)([baseBlogUrl, tagsBasePath]);
148
121
  const blogTagsListPath = Object.keys(blogTags).length > 0 ? tagsPath : null;
149
122
  return {
123
+ blogSidebarTitle,
150
124
  blogPosts,
151
125
  blogListPaginated,
152
126
  blogTags,
@@ -157,19 +131,34 @@ function pluginContentBlog(context, options) {
157
131
  if (!blogContents) {
158
132
  return;
159
133
  }
160
- const { blogListComponent, blogPostComponent, blogTagsListComponent, blogTagsPostsComponent, } = options;
134
+ const { blogListComponent, blogPostComponent, blogTagsListComponent, blogTagsPostsComponent, routeBasePath, archiveBasePath, } = options;
161
135
  const { addRoute, createData } = actions;
162
- const { blogPosts, blogListPaginated, blogTags, blogTagsListPath, } = blogContents;
136
+ const { blogSidebarTitle, blogPosts, blogListPaginated, blogTags, blogTagsListPath, } = blogContents;
163
137
  const blogItemsToMetadata = {};
164
138
  const sidebarBlogPosts = options.blogSidebarCount === 'ALL'
165
139
  ? blogPosts
166
- : 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
+ });
167
156
  // This prop is useful to provide the blog list sidebar
168
157
  const sidebarProp = await createData(
169
158
  // Note that this created data path must be in sync with
170
159
  // metadataPath provided to mdx-loader.
171
160
  `blog-post-list-prop-${pluginId}.json`, JSON.stringify({
172
- title: options.blogSidebarTitle,
161
+ title: blogSidebarTitle,
173
162
  items: sidebarBlogPosts.map((blogPost) => ({
174
163
  title: blogPost.metadata.title,
175
164
  permalink: blogPost.metadata.permalink,
@@ -181,7 +170,7 @@ function pluginContentBlog(context, options) {
181
170
  await createData(
182
171
  // Note that this created data path must be in sync with
183
172
  // metadataPath provided to mdx-loader.
184
- `${utils_1.docuHash(metadata.source)}.json`, JSON.stringify(metadata, null, 2));
173
+ `${(0, utils_1.docuHash)(metadata.source)}.json`, JSON.stringify(metadata, null, 2));
185
174
  addRoute({
186
175
  path: metadata.permalink,
187
176
  component: blogPostComponent,
@@ -197,7 +186,7 @@ function pluginContentBlog(context, options) {
197
186
  await Promise.all(blogListPaginated.map(async (listPage) => {
198
187
  const { metadata, items } = listPage;
199
188
  const { permalink } = metadata;
200
- 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));
201
190
  addRoute({
202
191
  path: permalink,
203
192
  component: blogListComponent,
@@ -227,6 +216,7 @@ function pluginContentBlog(context, options) {
227
216
  const tagsModule = {};
228
217
  await Promise.all(Object.keys(blogTags).map(async (tag) => {
229
218
  const { name, items, permalink } = blogTags[tag];
219
+ // Refactor all this, see docs implementation
230
220
  tagsModule[tag] = {
231
221
  allTagsPath: blogTagsListPath,
232
222
  slug: tag,
@@ -234,7 +224,7 @@ function pluginContentBlog(context, options) {
234
224
  count: items.length,
235
225
  permalink,
236
226
  };
237
- 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));
238
228
  addRoute({
239
229
  path: permalink,
240
230
  component: blogTagsPostsComponent,
@@ -259,7 +249,7 @@ function pluginContentBlog(context, options) {
259
249
  }));
260
250
  // Only create /tags page if there are tags.
261
251
  if (Object.keys(blogTags).length > 0) {
262
- 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));
263
253
  addRoute({
264
254
  path: blogTagsListPath,
265
255
  component: blogTagsListComponent,
@@ -271,20 +261,24 @@ function pluginContentBlog(context, options) {
271
261
  });
272
262
  }
273
263
  },
264
+ translateContent({ content, translationFiles }) {
265
+ return (0, translations_1.translateContent)(content, translationFiles);
266
+ },
274
267
  configureWebpack(_config, isServer, { getJSLoader }, content) {
275
268
  const { rehypePlugins, remarkPlugins, truncateMarker, beforeDefaultRemarkPlugins, beforeDefaultRehypePlugins, } = options;
276
269
  const markdownLoaderOptions = {
277
270
  siteDir,
278
271
  contentPaths,
279
272
  truncateMarker,
280
- sourceToPermalink: blogUtils_1.getSourceToPermalink(content.blogPosts),
273
+ sourceToPermalink: (0, blogUtils_1.getSourceToPermalink)(content.blogPosts),
281
274
  onBrokenMarkdownLink: (brokenMarkdownLink) => {
282
275
  if (onBrokenMarkdownLinks === 'ignore') {
283
276
  return;
284
277
  }
285
- 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);
286
279
  },
287
280
  };
281
+ const contentDirs = (0, blogUtils_1.getContentPathList)(contentPaths);
288
282
  return {
289
283
  resolve: {
290
284
  alias: {
@@ -295,7 +289,7 @@ function pluginContentBlog(context, options) {
295
289
  rules: [
296
290
  {
297
291
  test: /(\.mdx?)$/,
298
- include: blogUtils_1.getContentPathList(contentPaths)
292
+ include: contentDirs
299
293
  // Trailing slash is important, see https://github.com/facebook/docusaurus/pull/3970
300
294
  .map(utils_1.addTrailingPathSeparator),
301
295
  use: [
@@ -308,15 +302,23 @@ function pluginContentBlog(context, options) {
308
302
  beforeDefaultRemarkPlugins,
309
303
  beforeDefaultRehypePlugins,
310
304
  staticDir: path_1.default.join(siteDir, constants_1.STATIC_DIR_NAME),
311
- // Note that metadataPath must be the same/in-sync as
312
- // the path from createData for each MDX.
305
+ isMDXPartial: (0, utils_1.createAbsoluteFilePathMatcher)(options.exclude, contentDirs),
313
306
  metadataPath: (mdxPath) => {
314
- const aliasedPath = utils_1.aliasedSitePath(mdxPath, siteDir);
315
- return path_1.default.join(dataDir, `${utils_1.docuHash(aliasedPath)}.json`);
307
+ // Note that metadataPath must be the same/in-sync as
308
+ // the path from createData for each MDX.
309
+ const aliasedPath = (0, utils_1.aliasedSitePath)(mdxPath, siteDir);
310
+ return path_1.default.join(dataDir, `${(0, utils_1.docuHash)(aliasedPath)}.json`);
316
311
  },
317
312
  // For blog posts a title in markdown is always removed
318
313
  // Blog posts title are rendered separately
319
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
+ },
320
322
  },
321
323
  },
322
324
  {
@@ -330,11 +332,10 @@ function pluginContentBlog(context, options) {
330
332
  };
331
333
  },
332
334
  async postBuild({ outDir }) {
333
- var _a;
334
- if (!((_a = options.feedOptions) === null || _a === void 0 ? void 0 : _a.type)) {
335
+ if (!options.feedOptions.type) {
335
336
  return;
336
337
  }
337
- const feed = await blogUtils_1.generateBlogFeed(contentPaths, context, options);
338
+ const feed = await (0, blogUtils_1.generateBlogFeed)(contentPaths, context, options);
338
339
  if (!feed) {
339
340
  return;
340
341
  }
@@ -351,7 +352,7 @@ function pluginContentBlog(context, options) {
351
352
  }));
352
353
  },
353
354
  injectHtmlTags({ content }) {
354
- var _a;
355
+ var _a, _b;
355
356
  if (!content.blogPosts.length) {
356
357
  return {};
357
358
  }
@@ -359,17 +360,17 @@ function pluginContentBlog(context, options) {
359
360
  return {};
360
361
  }
361
362
  const feedTypes = options.feedOptions.type;
362
- const { siteConfig: { title }, baseUrl, } = context;
363
+ const feedTitle = (_b = options.feedOptions.title) !== null && _b !== void 0 ? _b : context.siteConfig.title;
363
364
  const feedsConfig = {
364
365
  rss: {
365
366
  type: 'application/rss+xml',
366
367
  path: 'rss.xml',
367
- title: `${title} Blog RSS Feed`,
368
+ title: `${feedTitle} RSS Feed`,
368
369
  },
369
370
  atom: {
370
371
  type: 'application/atom+xml',
371
372
  path: 'atom.xml',
372
- title: `${title} Blog Atom Feed`,
373
+ title: `${feedTitle} Atom Feed`,
373
374
  },
374
375
  };
375
376
  const headTags = [];
@@ -384,7 +385,7 @@ function pluginContentBlog(context, options) {
384
385
  attributes: {
385
386
  rel: 'alternate',
386
387
  type,
387
- href: utils_1.normalizeUrl([
388
+ href: (0, utils_1.normalizeUrl)([
388
389
  baseUrl,
389
390
  options.routeBasePath,
390
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,29 +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
- routeBasePath: string;
30
- path: string;
31
- editLocalizedFiles: boolean;
32
- };
33
- 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>;
@@ -8,8 +8,9 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.PluginOptionSchema = exports.DEFAULT_OPTIONS = void 0;
10
10
  const utils_validation_1 = require("@docusaurus/utils-validation");
11
+ const utils_1 = require("@docusaurus/utils");
11
12
  exports.DEFAULT_OPTIONS = {
12
- feedOptions: { type: ['rss', 'atom'] },
13
+ feedOptions: { type: ['rss', 'atom'], copyright: '' },
13
14
  beforeDefaultRehypePlugins: [],
14
15
  beforeDefaultRemarkPlugins: [],
15
16
  admonitions: {},
@@ -26,21 +27,27 @@ exports.DEFAULT_OPTIONS = {
26
27
  blogSidebarCount: 5,
27
28
  blogSidebarTitle: 'Recent posts',
28
29
  postsPerPage: 10,
29
- include: ['*.md', '*.mdx'],
30
+ include: ['**/*.{md,mdx}'],
31
+ exclude: utils_1.GlobExcludeDefault,
30
32
  routeBasePath: 'blog',
33
+ tagsBasePath: 'tags',
34
+ archiveBasePath: 'archive',
31
35
  path: 'blog',
32
36
  editLocalizedFiles: false,
37
+ authorsMapPath: 'authors.yml',
33
38
  };
34
39
  exports.PluginOptionSchema = utils_validation_1.Joi.object({
35
40
  path: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.path),
41
+ archiveBasePath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.archiveBasePath),
36
42
  routeBasePath: utils_validation_1.Joi.string()
37
43
  // '' not allowed, see https://github.com/facebook/docusaurus/issues/3374
38
44
  // .allow('')
39
45
  .default(exports.DEFAULT_OPTIONS.routeBasePath),
46
+ tagsBasePath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.tagsBasePath),
40
47
  include: utils_validation_1.Joi.array().items(utils_validation_1.Joi.string()).default(exports.DEFAULT_OPTIONS.include),
41
- postsPerPage: utils_validation_1.Joi.number()
42
- .integer()
43
- .min(1)
48
+ exclude: utils_validation_1.Joi.array().items(utils_validation_1.Joi.string()).default(exports.DEFAULT_OPTIONS.exclude),
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())
44
51
  .default(exports.DEFAULT_OPTIONS.postsPerPage),
45
52
  blogListComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogListComponent),
46
53
  blogPostComponent: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogPostComponent),
@@ -51,7 +58,7 @@ exports.PluginOptionSchema = utils_validation_1.Joi.object({
51
58
  .allow('')
52
59
  .default(exports.DEFAULT_OPTIONS.blogDescription),
53
60
  blogSidebarCount: utils_validation_1.Joi.alternatives()
54
- .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())
55
62
  .default(exports.DEFAULT_OPTIONS.blogSidebarCount),
56
63
  blogSidebarTitle: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.blogSidebarTitle),
57
64
  showReadingTime: utils_validation_1.Joi.bool().default(exports.DEFAULT_OPTIONS.showReadingTime),
@@ -72,7 +79,15 @@ exports.PluginOptionSchema = utils_validation_1.Joi.object({
72
79
  .default(exports.DEFAULT_OPTIONS.feedOptions.type),
73
80
  title: utils_validation_1.Joi.string().allow(''),
74
81
  description: utils_validation_1.Joi.string().allow(''),
75
- 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
+ }),
76
90
  language: utils_validation_1.Joi.string(),
77
91
  }).default(exports.DEFAULT_OPTIONS.feedOptions),
92
+ authorsMapPath: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.authorsMapPath),
78
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,31 +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
- postsPerPage: number;
43
+ exclude: string[];
44
+ postsPerPage: number | 'ALL';
33
45
  blogListComponent: string;
34
46
  blogPostComponent: string;
35
47
  blogTagsListComponent: string;
@@ -41,7 +53,7 @@ export interface PluginOptions extends RemarkAndRehypePluginOptions {
41
53
  truncateMarker: RegExp;
42
54
  showReadingTime: boolean;
43
55
  feedOptions: {
44
- type?: [FeedType] | null;
56
+ type?: FeedType[] | null;
45
57
  title?: string;
46
58
  description?: string;
47
59
  copyright: string;
@@ -50,7 +62,11 @@ export interface PluginOptions extends RemarkAndRehypePluginOptions {
50
62
  editUrl?: string | EditUrlFunction;
51
63
  editLocalizedFiles?: boolean;
52
64
  admonitions: Record<string, unknown>;
53
- }
65
+ authorsMapPath: string;
66
+ };
67
+ export declare type UserPluginOptions = Overwrite<Partial<PluginOptions>, {
68
+ feedOptions?: UserFeedOptions;
69
+ }>;
54
70
  export interface BlogTags {
55
71
  [key: string]: BlogTag;
56
72
  }
@@ -62,6 +78,7 @@ export interface BlogTag {
62
78
  export interface BlogPost {
63
79
  id: string;
64
80
  metadata: MetaData;
81
+ content: string;
65
82
  }
66
83
  export interface BlogPaginatedMetadata {
67
84
  permalink: string;
@@ -78,28 +95,35 @@ export interface BlogPaginated {
78
95
  metadata: BlogPaginatedMetadata;
79
96
  items: string[];
80
97
  }
98
+ export interface Author extends Record<string, unknown> {
99
+ name?: string;
100
+ imageURL?: string;
101
+ url?: string;
102
+ title?: string;
103
+ }
81
104
  export interface MetaData {
82
105
  permalink: string;
83
106
  source: string;
84
107
  description: string;
85
108
  date: Date;
86
109
  formattedDate: string;
87
- tags: (Tag | string)[];
110
+ tags: Tag[];
88
111
  title: string;
89
112
  readingTime?: number;
90
113
  prevItem?: Paginator;
91
114
  nextItem?: Paginator;
92
115
  truncated: boolean;
93
116
  editUrl?: string;
117
+ authors: Author[];
118
+ }
119
+ export interface Assets {
120
+ image?: string;
121
+ authorsImageUrls: (string | undefined)[];
94
122
  }
95
123
  export interface Paginator {
96
124
  title: string;
97
125
  permalink: string;
98
126
  }
99
- export interface Tag {
100
- label: string;
101
- permalink: string;
102
- }
103
127
  export interface BlogItemsToMetadata {
104
128
  [key: string]: MetaData;
105
129
  }