@docusaurus/plugin-content-blog 2.0.0-beta.17 → 2.0.0-beta.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/authors.d.ts CHANGED
@@ -6,7 +6,9 @@
6
6
  */
7
7
  import type { BlogContentPaths } from './types';
8
8
  import type { Author, BlogPostFrontMatter } from '@docusaurus/plugin-content-blog';
9
- export declare type AuthorsMap = Record<string, Author>;
9
+ export declare type AuthorsMap = {
10
+ [authorKey: string]: Author;
11
+ };
10
12
  export declare function validateAuthorsMap(content: unknown): AuthorsMap;
11
13
  export declare function getAuthorsMap(params: {
12
14
  authorsMapPath: string;
package/lib/authors.js CHANGED
@@ -9,7 +9,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.getBlogPostAuthors = exports.getAuthorsMap = exports.validateAuthorsMap = void 0;
10
10
  const utils_1 = require("@docusaurus/utils");
11
11
  const utils_validation_1 = require("@docusaurus/utils-validation");
12
- const AuthorsMapSchema = utils_validation_1.Joi.object().pattern(utils_validation_1.Joi.string(), utils_validation_1.Joi.object({
12
+ const AuthorsMapSchema = utils_validation_1.Joi.object()
13
+ .pattern(utils_validation_1.Joi.string(), utils_validation_1.Joi.object({
13
14
  name: utils_validation_1.Joi.string(),
14
15
  url: utils_validation_1.URISchema,
15
16
  imageURL: utils_validation_1.URISchema,
@@ -19,7 +20,14 @@ const AuthorsMapSchema = utils_validation_1.Joi.object().pattern(utils_validatio
19
20
  .rename('image_url', 'imageURL')
20
21
  .or('name', 'imageURL')
21
22
  .unknown()
22
- .required());
23
+ .required()
24
+ .messages({
25
+ 'object.base': '{#label} should be an author object containing properties like name, title, and imageURL.',
26
+ 'any.required': '{#label} cannot be undefined. It should be an author object containing properties like name, title, and imageURL.',
27
+ }))
28
+ .messages({
29
+ 'object.base': "The authors map file should contain an object where each entry contains an author key and the corresponding author's data.",
30
+ });
23
31
  function validateAuthorsMap(content) {
24
32
  return utils_validation_1.Joi.attempt(content, AuthorsMapSchema);
25
33
  }
@@ -8,7 +8,9 @@ import type { BlogPost, BlogContentPaths, BlogMarkdownLoaderOptions, BlogTags, B
8
8
  import type { LoadContext } from '@docusaurus/types';
9
9
  import type { PluginOptions } from '@docusaurus/plugin-content-blog';
10
10
  export declare function truncate(fileString: string, truncateMarker: RegExp): string;
11
- export declare function getSourceToPermalink(blogPosts: BlogPost[]): Record<string, string>;
11
+ export declare function getSourceToPermalink(blogPosts: BlogPost[]): {
12
+ [aliasedPath: string]: string;
13
+ };
12
14
  export declare function paginateBlogPosts({ blogPosts, basePageUrl, blogTitle, blogDescription, postsPerPageOption, }: {
13
15
  blogPosts: BlogPost[];
14
16
  basePageUrl: string;
package/lib/blogUtils.js CHANGED
@@ -13,7 +13,7 @@ const path_1 = tslib_1.__importDefault(require("path"));
13
13
  const reading_time_1 = tslib_1.__importDefault(require("reading-time"));
14
14
  const lodash_1 = tslib_1.__importDefault(require("lodash"));
15
15
  const utils_1 = require("@docusaurus/utils");
16
- const blogFrontMatter_1 = require("./blogFrontMatter");
16
+ const frontMatter_1 = require("./frontMatter");
17
17
  const authors_1 = require("./authors");
18
18
  const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
19
19
  function truncate(fileString, truncateMarker) {
@@ -30,7 +30,9 @@ function paginateBlogPosts({ blogPosts, basePageUrl, blogTitle, blogDescription,
30
30
  const numberOfPages = Math.ceil(totalCount / postsPerPage);
31
31
  const pages = [];
32
32
  function permalink(page) {
33
- return page > 0 ? `${basePageUrl}/page/${page + 1}` : basePageUrl;
33
+ return page > 0
34
+ ? (0, utils_1.normalizeUrl)([basePageUrl, `page/${page + 1}`])
35
+ : basePageUrl;
34
36
  }
35
37
  for (let page = 0; page < numberOfPages; page += 1) {
36
38
  pages.push({
@@ -43,8 +45,8 @@ function paginateBlogPosts({ blogPosts, basePageUrl, blogTitle, blogDescription,
43
45
  postsPerPage,
44
46
  totalPages: numberOfPages,
45
47
  totalCount,
46
- previousPage: page !== 0 ? permalink(page - 1) : null,
47
- nextPage: page < numberOfPages - 1 ? permalink(page + 1) : null,
48
+ previousPage: page !== 0 ? permalink(page - 1) : undefined,
49
+ nextPage: page < numberOfPages - 1 ? permalink(page + 1) : undefined,
48
50
  blogDescription,
49
51
  blogTitle,
50
52
  },
@@ -76,7 +78,7 @@ function parseBlogFileName(blogSourceRelative) {
76
78
  const date = new Date(`${dateString}Z`);
77
79
  const slugDate = dateString.replace(/-/g, '/');
78
80
  const slug = `/${slugDate}/${folder}${text}`;
79
- return { date, text, slug };
81
+ return { date, text: text, slug };
80
82
  }
81
83
  const text = blogSourceRelative.replace(/(?:\/index)?\.mdx?$/, '');
82
84
  const slug = `/${text}`;
@@ -105,7 +107,7 @@ async function parseBlogPostMarkdownFile(blogSourceAbsolute) {
105
107
  });
106
108
  return {
107
109
  ...result,
108
- frontMatter: (0, blogFrontMatter_1.validateBlogPostFrontMatter)(result.frontMatter),
110
+ frontMatter: (0, frontMatter_1.validateBlogPostFrontMatter)(result.frontMatter),
109
111
  };
110
112
  }
111
113
  catch (err) {
@@ -150,7 +152,7 @@ async function processBlogSourceFile(blogSourceRelative, contentPaths, context,
150
152
  return result.date;
151
153
  }
152
154
  catch (err) {
153
- logger_1.default.error(err);
155
+ logger_1.default.warn(err);
154
156
  return (await fs_extra_1.default.stat(blogSourceAbsolute)).birthtime;
155
157
  }
156
158
  }
package/lib/feed.d.ts CHANGED
@@ -7,9 +7,10 @@
7
7
  import type { BlogPost } from './types';
8
8
  import type { DocusaurusConfig } from '@docusaurus/types';
9
9
  import type { PluginOptions } from '@docusaurus/plugin-content-blog';
10
- export declare function createBlogFeedFiles({ blogPosts, options, siteConfig, outDir, }: {
10
+ export declare function createBlogFeedFiles({ blogPosts, options, siteConfig, outDir, locale, }: {
11
11
  blogPosts: BlogPost[];
12
12
  options: PluginOptions;
13
13
  siteConfig: DocusaurusConfig;
14
14
  outDir: string;
15
+ locale: string;
15
16
  }): Promise<void>;
package/lib/feed.js CHANGED
@@ -10,25 +10,25 @@ exports.createBlogFeedFiles = void 0;
10
10
  const tslib_1 = require("tslib");
11
11
  const feed_1 = require("feed");
12
12
  const utils_1 = require("@docusaurus/utils");
13
- const cheerio_1 = tslib_1.__importDefault(require("cheerio"));
13
+ const cheerio_1 = require("cheerio");
14
14
  const path_1 = tslib_1.__importDefault(require("path"));
15
15
  const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
16
16
  const utils_common_1 = require("@docusaurus/utils-common");
17
- async function generateBlogFeed({ blogPosts, options, siteConfig, outDir, }) {
17
+ async function generateBlogFeed({ blogPosts, options, siteConfig, outDir, locale, }) {
18
18
  if (!blogPosts.length) {
19
19
  return null;
20
20
  }
21
21
  const { feedOptions, routeBasePath } = options;
22
22
  const { url: siteUrl, baseUrl, title, favicon } = siteConfig;
23
23
  const blogBaseUrl = (0, utils_1.normalizeUrl)([siteUrl, baseUrl, routeBasePath]);
24
- const updated = blogPosts[0] && blogPosts[0].metadata.date;
24
+ const updated = blogPosts[0]?.metadata.date;
25
25
  const feed = new feed_1.Feed({
26
26
  id: blogBaseUrl,
27
- title: feedOptions.title || `${title} Blog`,
27
+ title: feedOptions.title ?? `${title} Blog`,
28
28
  updated,
29
- language: feedOptions.language,
29
+ language: feedOptions.language ?? locale,
30
30
  link: blogBaseUrl,
31
- description: feedOptions.description || `${siteConfig.title} Blog`,
31
+ description: feedOptions.description ?? `${siteConfig.title} Blog`,
32
32
  favicon: favicon ? (0, utils_1.normalizeUrl)([siteUrl, baseUrl, favicon]) : undefined,
33
33
  copyright: feedOptions.copyright,
34
34
  });
@@ -38,7 +38,7 @@ async function generateBlogFeed({ blogPosts, options, siteConfig, outDir, }) {
38
38
  await (0, utils_1.mapAsyncSequential)(blogPosts, async (post) => {
39
39
  const { id, metadata: { title: metadataTitle, permalink, date, description, authors, tags, }, } = post;
40
40
  const content = await (0, utils_1.readOutputHTMLFile)(permalink.replace(siteConfig.baseUrl, ''), outDir, siteConfig.trailingSlash);
41
- const $ = cheerio_1.default.load(content);
41
+ const $ = (0, cheerio_1.load)(content);
42
42
  const feedItem = {
43
43
  title: metadataTitle,
44
44
  id,
@@ -79,12 +79,13 @@ async function createBlogFeedFile({ feed, feedType, generatePath, }) {
79
79
  throw new Error(`Generating ${feedType} feed failed: ${err}.`);
80
80
  }
81
81
  }
82
- async function createBlogFeedFiles({ blogPosts, options, siteConfig, outDir, }) {
82
+ async function createBlogFeedFiles({ blogPosts, options, siteConfig, outDir, locale, }) {
83
83
  const feed = await generateBlogFeed({
84
84
  blogPosts,
85
85
  options,
86
86
  siteConfig,
87
87
  outDir,
88
+ locale,
88
89
  });
89
90
  const feedTypes = options.feedOptions.type;
90
91
  if (!feed || !feedTypes) {
@@ -5,4 +5,6 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import type { BlogPostFrontMatter } from '@docusaurus/plugin-content-blog';
8
- export declare function validateBlogPostFrontMatter(frontMatter: Record<string, unknown>): BlogPostFrontMatter;
8
+ export declare function validateBlogPostFrontMatter(frontMatter: {
9
+ [key: string]: unknown;
10
+ }): BlogPostFrontMatter;
File without changes
package/lib/index.d.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  */
7
7
  import type { BlogContent } from './types';
8
- import type { LoadContext, Plugin, OptionValidationContext, ValidationResult } from '@docusaurus/types';
8
+ import type { LoadContext, Plugin } from '@docusaurus/types';
9
9
  import type { PluginOptions } from '@docusaurus/plugin-content-blog';
10
10
  export default function pluginContentBlog(context: LoadContext, options: PluginOptions): Promise<Plugin<BlogContent>>;
11
- export declare function validateOptions({ validate, options, }: OptionValidationContext<PluginOptions>): ValidationResult<PluginOptions>;
11
+ export { validateOptions } from './options';
package/lib/index.js CHANGED
@@ -12,7 +12,6 @@ const path_1 = tslib_1.__importDefault(require("path"));
12
12
  const remark_admonitions_1 = tslib_1.__importDefault(require("remark-admonitions"));
13
13
  const utils_1 = require("@docusaurus/utils");
14
14
  const translations_1 = require("./translations");
15
- const pluginOptionSchema_1 = require("./pluginOptionSchema");
16
15
  const blogUtils_1 = require("./blogUtils");
17
16
  const feed_1 = require("./feed");
18
17
  async function pluginContentBlog(context, options) {
@@ -116,7 +115,7 @@ async function pluginContentBlog(context, options) {
116
115
  const sidebarBlogPosts = options.blogSidebarCount === 'ALL'
117
116
  ? blogPosts
118
117
  : blogPosts.slice(0, options.blogSidebarCount);
119
- if (archiveBasePath) {
118
+ if (archiveBasePath && blogPosts.length) {
120
119
  const archiveUrl = (0, utils_1.normalizeUrl)([
121
120
  baseUrl,
122
121
  routeBasePath,
@@ -193,10 +192,9 @@ async function pluginContentBlog(context, options) {
193
192
  if (blogTagsListPath === null) {
194
193
  return;
195
194
  }
196
- const tagsModule = Object.fromEntries(Object.entries(blogTags).map(([tagKey, tag]) => {
195
+ const tagsModule = Object.fromEntries(Object.entries(blogTags).map(([, tag]) => {
197
196
  const tagModule = {
198
197
  allTagsPath: blogTagsListPath,
199
- slug: tagKey,
200
198
  name: tag.name,
201
199
  count: tag.items.length,
202
200
  permalink: tag.permalink,
@@ -330,6 +328,7 @@ async function pluginContentBlog(context, options) {
330
328
  options,
331
329
  outDir,
332
330
  siteConfig,
331
+ locale: currentLocale,
333
332
  });
334
333
  },
335
334
  injectHtmlTags({ content }) {
@@ -360,11 +359,7 @@ async function pluginContentBlog(context, options) {
360
359
  };
361
360
  const headTags = [];
362
361
  feedTypes.forEach((feedType) => {
363
- const feedConfig = feedsConfig[feedType] || {};
364
- if (!feedsConfig) {
365
- return;
366
- }
367
- const { type, path: feedConfigPath, title: feedConfigTitle } = feedConfig;
362
+ const { type, path: feedConfigPath, title: feedConfigTitle, } = feedsConfig[feedType];
368
363
  headTags.push({
369
364
  tagName: 'link',
370
365
  attributes: {
@@ -386,8 +381,5 @@ async function pluginContentBlog(context, options) {
386
381
  };
387
382
  }
388
383
  exports.default = pluginContentBlog;
389
- function validateOptions({ validate, options, }) {
390
- const validatedOptions = validate(pluginOptionSchema_1.PluginOptionSchema, options);
391
- return validatedOptions;
392
- }
393
- exports.validateOptions = validateOptions;
384
+ var options_1 = require("./options");
385
+ Object.defineProperty(exports, "validateOptions", { enumerable: true, get: function () { return options_1.validateOptions; } });
@@ -25,6 +25,6 @@ function markdownLoader(source) {
25
25
  if (truncated) {
26
26
  finalContent = (0, blogUtils_1.truncate)(finalContent, markdownLoaderOptions.truncateMarker);
27
27
  }
28
- return callback && callback(null, finalContent);
28
+ return callback?.(null, finalContent);
29
29
  }
30
30
  exports.default = markdownLoader;
@@ -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 { PluginOptions, Options } from '@docusaurus/plugin-content-blog';
8
+ import type { OptionValidationContext } from '@docusaurus/types';
9
+ export declare const DEFAULT_OPTIONS: PluginOptions;
10
+ export declare function validateOptions({ validate, options, }: OptionValidationContext<Options, PluginOptions>): PluginOptions;
@@ -6,7 +6,7 @@
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.PluginOptionSchema = exports.DEFAULT_OPTIONS = void 0;
9
+ exports.validateOptions = 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 = {
@@ -39,7 +39,7 @@ exports.DEFAULT_OPTIONS = {
39
39
  readingTime: ({ content, defaultReadingTime }) => defaultReadingTime({ content }),
40
40
  sortPosts: 'descending',
41
41
  };
42
- exports.PluginOptionSchema = utils_validation_1.Joi.object({
42
+ const PluginOptionSchema = utils_validation_1.Joi.object({
43
43
  path: utils_validation_1.Joi.string().default(exports.DEFAULT_OPTIONS.path),
44
44
  archiveBasePath: utils_validation_1.Joi.string()
45
45
  .default(exports.DEFAULT_OPTIONS.archiveBasePath)
@@ -100,4 +100,9 @@ exports.PluginOptionSchema = utils_validation_1.Joi.object({
100
100
  sortPosts: utils_validation_1.Joi.string()
101
101
  .valid('descending', 'ascending')
102
102
  .default(exports.DEFAULT_OPTIONS.sortPosts),
103
- });
103
+ }).default(exports.DEFAULT_OPTIONS);
104
+ function validateOptions({ validate, options, }) {
105
+ const validatedOptions = validate(PluginOptionSchema, options);
106
+ return validatedOptions;
107
+ }
108
+ exports.validateOptions = validateOptions;
@@ -14,8 +14,8 @@ function translateListPage(blogListPaginated, translations) {
14
14
  items,
15
15
  metadata: {
16
16
  ...metadata,
17
- blogTitle: translations.title.message,
18
- blogDescription: translations.description.message,
17
+ blogTitle: translations.title?.message ?? page.metadata.blogTitle,
18
+ blogDescription: translations.description?.message ?? page.metadata.blogDescription,
19
19
  },
20
20
  };
21
21
  });
@@ -43,10 +43,10 @@ function getTranslationFiles(options) {
43
43
  }
44
44
  exports.getTranslationFiles = getTranslationFiles;
45
45
  function translateContent(content, translationFiles) {
46
- const [{ content: optionsTranslations }] = translationFiles;
46
+ const { content: optionsTranslations } = translationFiles[0];
47
47
  return {
48
48
  ...content,
49
- blogSidebarTitle: optionsTranslations['sidebar.title'].message,
49
+ blogSidebarTitle: optionsTranslations['sidebar.title']?.message ?? content.blogSidebarTitle,
50
50
  blogListPaginated: translateListPage(content.blogListPaginated, optionsTranslations),
51
51
  };
52
52
  }
package/lib/types.d.ts CHANGED
@@ -4,9 +4,9 @@
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
- import type { Tag } from '@docusaurus/utils';
8
- import type { BrokenMarkdownLink, ContentPaths } from '@docusaurus/utils/lib/markdownLinks';
9
- import type { BlogPostFrontMatter, Author } from '@docusaurus/plugin-content-blog';
7
+ import type { BrokenMarkdownLink, ContentPaths } from '@docusaurus/utils';
8
+ import type { BlogPostMetadata } from '@docusaurus/plugin-content-blog';
9
+ import type { Metadata as BlogPaginatedMetadata } from '@theme/BlogListPage';
10
10
  export declare type BlogContentPaths = ContentPaths;
11
11
  export interface BlogContent {
12
12
  blogSidebarTitle: string;
@@ -26,62 +26,20 @@ export interface BlogTag {
26
26
  }
27
27
  export interface BlogPost {
28
28
  id: string;
29
- metadata: MetaData;
29
+ metadata: BlogPostMetadata;
30
30
  content: string;
31
31
  }
32
- export interface BlogPaginatedMetadata {
33
- permalink: string;
34
- page: number;
35
- postsPerPage: number;
36
- totalPages: number;
37
- totalCount: number;
38
- previousPage: string | null;
39
- nextPage: string | null;
40
- blogTitle: string;
41
- blogDescription: string;
42
- }
43
32
  export interface BlogPaginated {
44
33
  metadata: BlogPaginatedMetadata;
45
34
  items: string[];
46
35
  }
47
- export interface MetaData {
48
- permalink: string;
49
- source: string;
50
- description: string;
51
- date: Date;
52
- formattedDate: string;
53
- tags: Tag[];
54
- title: string;
55
- readingTime?: number;
56
- prevItem?: Paginator;
57
- nextItem?: Paginator;
58
- truncated: boolean;
59
- editUrl?: string;
60
- authors: Author[];
61
- frontMatter: BlogPostFrontMatter & Record<string, unknown>;
62
- }
63
- export interface Paginator {
64
- title: string;
65
- permalink: string;
66
- }
67
- export interface BlogItemsToMetadata {
68
- [key: string]: MetaData;
69
- }
70
- export interface TagsModule {
71
- [key: string]: TagModule;
72
- }
73
- export interface TagModule {
74
- allTagsPath: string;
75
- slug: string;
76
- name: string;
77
- count: number;
78
- permalink: string;
79
- }
80
36
  export declare type BlogBrokenMarkdownLink = BrokenMarkdownLink<BlogContentPaths>;
81
37
  export declare type BlogMarkdownLoaderOptions = {
82
38
  siteDir: string;
83
39
  contentPaths: BlogContentPaths;
84
40
  truncateMarker: RegExp;
85
- sourceToPermalink: Record<string, string>;
41
+ sourceToPermalink: {
42
+ [aliasedPath: string]: string;
43
+ };
86
44
  onBrokenMarkdownLink: (brokenMarkdownLink: BlogBrokenMarkdownLink) => void;
87
45
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@docusaurus/plugin-content-blog",
3
- "version": "2.0.0-beta.17",
3
+ "version": "2.0.0-beta.18",
4
4
  "description": "Blog plugin for Docusaurus.",
5
5
  "main": "lib/index.js",
6
6
  "types": "src/plugin-content-blog.d.ts",
@@ -18,12 +18,12 @@
18
18
  },
19
19
  "license": "MIT",
20
20
  "dependencies": {
21
- "@docusaurus/core": "2.0.0-beta.17",
22
- "@docusaurus/logger": "2.0.0-beta.17",
23
- "@docusaurus/mdx-loader": "2.0.0-beta.17",
24
- "@docusaurus/utils": "2.0.0-beta.17",
25
- "@docusaurus/utils-common": "2.0.0-beta.17",
26
- "@docusaurus/utils-validation": "2.0.0-beta.17",
21
+ "@docusaurus/core": "2.0.0-beta.18",
22
+ "@docusaurus/logger": "2.0.0-beta.18",
23
+ "@docusaurus/mdx-loader": "2.0.0-beta.18",
24
+ "@docusaurus/utils": "2.0.0-beta.18",
25
+ "@docusaurus/utils-common": "2.0.0-beta.18",
26
+ "@docusaurus/utils-validation": "2.0.0-beta.18",
27
27
  "cheerio": "^1.0.0-rc.10",
28
28
  "feed": "^4.2.2",
29
29
  "fs-extra": "^10.0.1",
@@ -32,10 +32,10 @@
32
32
  "remark-admonitions": "^1.2.1",
33
33
  "tslib": "^2.3.1",
34
34
  "utility-types": "^3.10.0",
35
- "webpack": "^5.69.1"
35
+ "webpack": "^5.70.0"
36
36
  },
37
37
  "devDependencies": {
38
- "@docusaurus/types": "2.0.0-beta.17",
38
+ "@docusaurus/types": "2.0.0-beta.18",
39
39
  "escape-string-regexp": "^4.0.0"
40
40
  },
41
41
  "peerDependencies": {
@@ -45,5 +45,5 @@
45
45
  "engines": {
46
46
  "node": ">=14"
47
47
  },
48
- "gitHead": "0032c0b0480083227af2e1b4da2d3ee6ce992403"
48
+ "gitHead": "1a945d06993d53376e61bed2c942799fe07dc336"
49
49
  }
package/src/authors.ts CHANGED
@@ -15,22 +15,33 @@ import type {
15
15
  BlogPostFrontMatterAuthors,
16
16
  } from '@docusaurus/plugin-content-blog';
17
17
 
18
- export type AuthorsMap = Record<string, Author>;
19
-
20
- const AuthorsMapSchema = Joi.object<AuthorsMap>().pattern(
21
- Joi.string(),
22
- Joi.object({
23
- name: Joi.string(),
24
- url: URISchema,
25
- imageURL: URISchema,
26
- title: Joi.string(),
27
- email: Joi.string(),
28
- })
29
- .rename('image_url', 'imageURL')
30
- .or('name', 'imageURL')
31
- .unknown()
32
- .required(),
33
- );
18
+ export type AuthorsMap = {[authorKey: string]: Author};
19
+
20
+ const AuthorsMapSchema = Joi.object<AuthorsMap>()
21
+ .pattern(
22
+ Joi.string(),
23
+ Joi.object({
24
+ name: Joi.string(),
25
+ url: URISchema,
26
+ imageURL: URISchema,
27
+ title: Joi.string(),
28
+ email: Joi.string(),
29
+ })
30
+ .rename('image_url', 'imageURL')
31
+ .or('name', 'imageURL')
32
+ .unknown()
33
+ .required()
34
+ .messages({
35
+ 'object.base':
36
+ '{#label} should be an author object containing properties like name, title, and imageURL.',
37
+ 'any.required':
38
+ '{#label} cannot be undefined. It should be an author object containing properties like name, title, and imageURL.',
39
+ }),
40
+ )
41
+ .messages({
42
+ 'object.base':
43
+ "The authors map file should contain an object where each entry contains an author key and the corresponding author's data.",
44
+ });
34
45
 
35
46
  export function validateAuthorsMap(content: unknown): AuthorsMap {
36
47
  return Joi.attempt(content, AuthorsMapSchema);
@@ -59,7 +70,7 @@ type AuthorsParam = {
59
70
  // We may want to deprecate those in favor of using only frontMatter.authors
60
71
  function getFrontMatterAuthorLegacy(
61
72
  frontMatter: BlogPostFrontMatter,
62
- ): BlogPostFrontMatterAuthor | undefined {
73
+ ): Author | undefined {
63
74
  const name = frontMatter.author;
64
75
  const title = frontMatter.author_title ?? frontMatter.authorTitle;
65
76
  const url = frontMatter.author_url ?? frontMatter.authorURL;
@@ -81,7 +92,7 @@ function normalizeFrontMatterAuthors(
81
92
  frontMatterAuthors: BlogPostFrontMatterAuthors = [],
82
93
  ): BlogPostFrontMatterAuthor[] {
83
94
  function normalizeAuthor(
84
- authorInput: string | BlogPostFrontMatterAuthor,
95
+ authorInput: string | Author,
85
96
  ): BlogPostFrontMatterAuthor {
86
97
  if (typeof authorInput === 'string') {
87
98
  // Technically, we could allow users to provide an author's name here, but
package/src/blogUtils.ts CHANGED
@@ -31,7 +31,7 @@ import {
31
31
  getContentPathList,
32
32
  } from '@docusaurus/utils';
33
33
  import type {LoadContext} from '@docusaurus/types';
34
- import {validateBlogPostFrontMatter} from './blogFrontMatter';
34
+ import {validateBlogPostFrontMatter} from './frontMatter';
35
35
  import {type AuthorsMap, getAuthorsMap, getBlogPostAuthors} from './authors';
36
36
  import logger from '@docusaurus/logger';
37
37
  import type {
@@ -43,9 +43,9 @@ export function truncate(fileString: string, truncateMarker: RegExp): string {
43
43
  return fileString.split(truncateMarker, 1).shift()!;
44
44
  }
45
45
 
46
- export function getSourceToPermalink(
47
- blogPosts: BlogPost[],
48
- ): Record<string, string> {
46
+ export function getSourceToPermalink(blogPosts: BlogPost[]): {
47
+ [aliasedPath: string]: string;
48
+ } {
49
49
  return Object.fromEntries(
50
50
  blogPosts.map(({metadata: {source, permalink}}) => [source, permalink]),
51
51
  );
@@ -72,7 +72,9 @@ export function paginateBlogPosts({
72
72
  const pages: BlogPaginated[] = [];
73
73
 
74
74
  function permalink(page: number) {
75
- return page > 0 ? `${basePageUrl}/page/${page + 1}` : basePageUrl;
75
+ return page > 0
76
+ ? normalizeUrl([basePageUrl, `page/${page + 1}`])
77
+ : basePageUrl;
76
78
  }
77
79
 
78
80
  for (let page = 0; page < numberOfPages; page += 1) {
@@ -86,8 +88,8 @@ export function paginateBlogPosts({
86
88
  postsPerPage,
87
89
  totalPages: numberOfPages,
88
90
  totalCount,
89
- previousPage: page !== 0 ? permalink(page - 1) : null,
90
- nextPage: page < numberOfPages - 1 ? permalink(page + 1) : null,
91
+ previousPage: page !== 0 ? permalink(page - 1) : undefined,
92
+ nextPage: page < numberOfPages - 1 ? permalink(page + 1) : undefined,
91
93
  blogDescription,
92
94
  blogTitle,
93
95
  },
@@ -139,10 +141,10 @@ export function parseBlogFileName(
139
141
  if (dateFilenameMatch) {
140
142
  const {folder, text, date: dateString} = dateFilenameMatch.groups!;
141
143
  // Always treat dates as UTC by adding the `Z`
142
- const date = new Date(`${dateString}Z`);
143
- const slugDate = dateString.replace(/-/g, '/');
144
- const slug = `/${slugDate}/${folder}${text}`;
145
- return {date, text, slug};
144
+ const date = new Date(`${dateString!}Z`);
145
+ const slugDate = dateString!.replace(/-/g, '/');
146
+ const slug = `/${slugDate}/${folder!}${text!}`;
147
+ return {date, text: text!, slug};
146
148
  }
147
149
  const text = blogSourceRelative.replace(/(?:\/index)?\.mdx?$/, '');
148
150
  const slug = `/${text}`;
@@ -245,7 +247,7 @@ async function processBlogSourceFile(
245
247
  });
246
248
  return result.date;
247
249
  } catch (err) {
248
- logger.error(err);
250
+ logger.warn(err);
249
251
  return (await fs.stat(blogSourceAbsolute)).birthtime;
250
252
  }
251
253
  }
package/src/deps.d.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  */
7
7
 
8
8
  declare module 'remark-admonitions' {
9
- type Options = Record<string, unknown>;
9
+ type Options = {[key: string]: unknown};
10
10
 
11
11
  const plugin: (options?: Options) => void;
12
12
  export = plugin;