@docusaurus/plugin-content-blog 2.0.0-beta.8e9b829d9 → 2.0.0-beta.9

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