@docusaurus/plugin-content-docs 2.0.0-beta.21 → 2.0.0-beta.22

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/package.json CHANGED
@@ -1,14 +1,23 @@
1
1
  {
2
2
  "name": "@docusaurus/plugin-content-docs",
3
- "version": "2.0.0-beta.21",
3
+ "version": "2.0.0-beta.22",
4
4
  "description": "Docs plugin for Docusaurus.",
5
5
  "main": "lib/index.js",
6
6
  "sideEffects": false,
7
7
  "exports": {
8
8
  "./src/*": "./src/*",
9
- "./client": "./lib/client/index.js",
10
- "./server": "./lib/server-export.js",
11
- ".": "./lib/index.js"
9
+ "./client": {
10
+ "type": "./lib/client/index.d.ts",
11
+ "default": "./lib/client/index.js"
12
+ },
13
+ "./server": {
14
+ "type": "./lib/server-export.d.ts",
15
+ "default": "./lib/server-export.js"
16
+ },
17
+ ".": {
18
+ "types": "./src/plugin-content-docs.d.ts",
19
+ "default": "./lib/index.js"
20
+ }
12
21
  },
13
22
  "types": "src/plugin-content-docs.d.ts",
14
23
  "scripts": {
@@ -25,31 +34,31 @@
25
34
  },
26
35
  "license": "MIT",
27
36
  "dependencies": {
28
- "@docusaurus/core": "2.0.0-beta.21",
29
- "@docusaurus/logger": "2.0.0-beta.21",
30
- "@docusaurus/mdx-loader": "2.0.0-beta.21",
31
- "@docusaurus/utils": "2.0.0-beta.21",
32
- "@docusaurus/utils-validation": "2.0.0-beta.21",
37
+ "@docusaurus/core": "2.0.0-beta.22",
38
+ "@docusaurus/logger": "2.0.0-beta.22",
39
+ "@docusaurus/mdx-loader": "2.0.0-beta.22",
40
+ "@docusaurus/module-type-aliases": "2.0.0-beta.22",
41
+ "@docusaurus/types": "2.0.0-beta.22",
42
+ "@docusaurus/utils": "2.0.0-beta.22",
43
+ "@docusaurus/utils-validation": "2.0.0-beta.22",
44
+ "@types/react-router-config": "^5.0.6",
33
45
  "combine-promises": "^1.1.0",
34
46
  "fs-extra": "^10.1.0",
35
47
  "import-fresh": "^3.3.0",
36
48
  "js-yaml": "^4.1.0",
37
49
  "lodash": "^4.17.21",
38
- "remark-admonitions": "^1.2.1",
39
50
  "tslib": "^2.4.0",
40
51
  "utility-types": "^3.10.0",
41
- "webpack": "^5.72.1"
52
+ "webpack": "^5.73.0"
42
53
  },
43
54
  "devDependencies": {
44
- "@docusaurus/module-type-aliases": "2.0.0-beta.21",
45
55
  "@docusaurus/types": "2.0.0-beta.21",
46
56
  "@types/js-yaml": "^4.0.5",
47
57
  "@types/picomatch": "^2.3.0",
48
58
  "commander": "^5.1.0",
49
59
  "escape-string-regexp": "^4.0.0",
50
60
  "picomatch": "^2.3.1",
51
- "shelljs": "^0.8.5",
52
- "utility-types": "^3.10.0"
61
+ "shelljs": "^0.8.5"
53
62
  },
54
63
  "peerDependencies": {
55
64
  "react": "^16.8.4 || ^17.0.0",
@@ -58,5 +67,5 @@
58
67
  "engines": {
59
68
  "node": ">=16.14"
60
69
  },
61
- "gitHead": "69ac49fc6909517f13615ee40290c4bd00c39df4"
70
+ "gitHead": "daf9e462c4eebb7ac26a940932311f987e768f87"
62
71
  }
package/src/cli.ts CHANGED
@@ -85,13 +85,17 @@ export async function cliDocsVersionCommand(
85
85
 
86
86
  await Promise.all(
87
87
  i18n.locales.map(async (locale) => {
88
+ const localizationDir = path.resolve(
89
+ siteDir,
90
+ i18n.path,
91
+ i18n.localeConfigs[locale]!.path,
92
+ );
88
93
  // Copy docs files.
89
94
  const docsDir =
90
95
  locale === i18n.defaultLocale
91
96
  ? path.resolve(siteDir, docsPath)
92
97
  : getDocsDirPathLocalized({
93
- siteDir,
94
- locale,
98
+ localizationDir,
95
99
  pluginId,
96
100
  versionName: CURRENT_VERSION_NAME,
97
101
  });
@@ -114,8 +118,7 @@ export async function cliDocsVersionCommand(
114
118
  locale === i18n.defaultLocale
115
119
  ? getVersionDocsDirPath(siteDir, pluginId, version)
116
120
  : getDocsDirPathLocalized({
117
- siteDir,
118
- locale,
121
+ localizationDir,
119
122
  pluginId,
120
123
  versionName: version,
121
124
  });
@@ -18,15 +18,60 @@ import {
18
18
  getActiveDocContext,
19
19
  getDocVersionSuggestions,
20
20
  } from './docsClientUtils';
21
- import type {
22
- GlobalPluginData,
23
- GlobalVersion,
24
- ActivePlugin,
25
- ActiveDocContext,
26
- DocVersionSuggestions,
27
- } from '@docusaurus/plugin-content-docs/client';
28
21
  import type {UseDataOptions} from '@docusaurus/types';
29
22
 
23
+ export type ActivePlugin = {
24
+ pluginId: string;
25
+ pluginData: GlobalPluginData;
26
+ };
27
+ export type ActiveDocContext = {
28
+ activeVersion?: GlobalVersion;
29
+ activeDoc?: GlobalDoc;
30
+ alternateDocVersions: {[versionName: string]: GlobalDoc};
31
+ };
32
+ export type GlobalDoc = {
33
+ /**
34
+ * For generated index pages, this is the `slug`, **not** `permalink`
35
+ * (without base URL). Because slugs have leading slashes but IDs don't,
36
+ * there won't be clashes.
37
+ */
38
+ id: string;
39
+ path: string;
40
+ sidebar: string | undefined;
41
+ };
42
+
43
+ export type GlobalVersion = {
44
+ name: string;
45
+ label: string;
46
+ isLast: boolean;
47
+ path: string;
48
+ /** The doc with `slug: /`, or first doc in first sidebar */
49
+ mainDocId: string;
50
+ docs: GlobalDoc[];
51
+ /** Unversioned IDs. In development, this list is empty. */
52
+ draftIds: string[];
53
+ sidebars?: {[sidebarId: string]: GlobalSidebar};
54
+ };
55
+
56
+ export type GlobalSidebar = {
57
+ link?: {
58
+ label: string;
59
+ path: string;
60
+ };
61
+ // ... we may add other things here later
62
+ };
63
+ export type GlobalPluginData = {
64
+ path: string;
65
+ versions: GlobalVersion[];
66
+ breadcrumbs: boolean;
67
+ };
68
+ export type DocVersionSuggestions = {
69
+ /** Suggest the latest version */
70
+ latestVersionSuggestion: GlobalVersion;
71
+ /** Suggest the same doc, in latest version (if one exists) */
72
+ latestDocSuggestion?: GlobalDoc;
73
+ };
74
+
30
75
  // Important to use a constant object to avoid React useEffect executions etc.
31
76
  // see https://github.com/facebook/docusaurus/issues/5089
32
77
  const StableEmptyObject = {};
@@ -71,6 +116,7 @@ export function useActivePluginAndVersion(
71
116
  };
72
117
  }
73
118
 
119
+ /** Versions are returned ordered (most recent first). */
74
120
  export function useVersions(pluginId: string | undefined): GlobalVersion[] {
75
121
  const data = useDocsData(pluginId);
76
122
  return data.versions;
@@ -81,6 +127,10 @@ export function useLatestVersion(pluginId: string | undefined): GlobalVersion {
81
127
  return getLatestVersion(data);
82
128
  }
83
129
 
130
+ /**
131
+ * Returns `undefined` on doc-unrelated pages, because there's no version
132
+ * currently considered as active.
133
+ */
84
134
  export function useActiveVersion(
85
135
  pluginId: string | undefined,
86
136
  ): GlobalVersion | undefined {
@@ -96,7 +146,9 @@ export function useActiveDocContext(
96
146
  const {pathname} = useLocation();
97
147
  return getActiveDocContext(data, pathname);
98
148
  }
99
-
149
+ /**
150
+ * Useful to say "hey, you are not on the latest docs version, please switch"
151
+ */
100
152
  export function useDocVersionSuggestions(
101
153
  pluginId: string | undefined,
102
154
  ): DocVersionSuggestions {
package/src/docs.ts CHANGED
@@ -37,6 +37,7 @@ import type {
37
37
  VersionMetadata,
38
38
  DocFrontMatter,
39
39
  LoadedVersion,
40
+ FileChange,
40
41
  } from '@docusaurus/plugin-content-docs';
41
42
  import type {LoadContext} from '@docusaurus/types';
42
43
  import type {SidebarsUtils} from './sidebars/utils';
@@ -50,9 +51,21 @@ type LastUpdateOptions = Pick<
50
51
  async function readLastUpdateData(
51
52
  filePath: string,
52
53
  options: LastUpdateOptions,
54
+ lastUpdateFrontMatter: FileChange | undefined,
53
55
  ): Promise<LastUpdateData> {
54
56
  const {showLastUpdateAuthor, showLastUpdateTime} = options;
55
57
  if (showLastUpdateAuthor || showLastUpdateTime) {
58
+ const frontMatterTimestamp = lastUpdateFrontMatter?.date
59
+ ? new Date(lastUpdateFrontMatter.date).getTime() / 1000
60
+ : undefined;
61
+
62
+ if (lastUpdateFrontMatter?.author && lastUpdateFrontMatter.date) {
63
+ return {
64
+ lastUpdatedAt: frontMatterTimestamp,
65
+ lastUpdatedBy: lastUpdateFrontMatter.author,
66
+ };
67
+ }
68
+
56
69
  // Use fake data in dev for faster development.
57
70
  const fileLastUpdateData =
58
71
  process.env.NODE_ENV === 'production'
@@ -61,14 +74,16 @@ async function readLastUpdateData(
61
74
  author: 'Author',
62
75
  timestamp: 1539502055,
63
76
  };
64
-
65
- if (fileLastUpdateData) {
66
- const {author, timestamp} = fileLastUpdateData;
67
- return {
68
- lastUpdatedAt: showLastUpdateTime ? timestamp : undefined,
69
- lastUpdatedBy: showLastUpdateAuthor ? author : undefined,
70
- };
71
- }
77
+ const {author, timestamp} = fileLastUpdateData ?? {};
78
+
79
+ return {
80
+ lastUpdatedBy: showLastUpdateAuthor
81
+ ? lastUpdateFrontMatter?.author ?? author
82
+ : undefined,
83
+ lastUpdatedAt: showLastUpdateTime
84
+ ? frontMatterTimestamp ?? timestamp
85
+ : undefined,
86
+ };
72
87
  }
73
88
 
74
89
  return {};
@@ -80,7 +95,6 @@ export async function readDocFile(
80
95
  'contentPath' | 'contentPathLocalized'
81
96
  >,
82
97
  source: string,
83
- options: LastUpdateOptions,
84
98
  ): Promise<DocFile> {
85
99
  const contentPath = await getFolderContainingFile(
86
100
  getContentPathList(versionMetadata),
@@ -89,11 +103,8 @@ export async function readDocFile(
89
103
 
90
104
  const filePath = path.join(contentPath, source);
91
105
 
92
- const [content, lastUpdate] = await Promise.all([
93
- fs.readFile(filePath, 'utf-8'),
94
- readLastUpdateData(filePath, options),
95
- ]);
96
- return {source, content, lastUpdate, contentPath, filePath};
106
+ const content = await fs.readFile(filePath, 'utf-8');
107
+ return {source, content, contentPath, filePath};
97
108
  }
98
109
 
99
110
  export async function readVersionDocs(
@@ -108,7 +119,7 @@ export async function readVersionDocs(
108
119
  ignore: options.exclude,
109
120
  });
110
121
  return Promise.all(
111
- sources.map((source) => readDocFile(versionMetadata, source, options)),
122
+ sources.map((source) => readDocFile(versionMetadata, source)),
112
123
  );
113
124
  }
114
125
 
@@ -125,7 +136,7 @@ function isDraftForEnvironment({
125
136
  return (env === 'production' && frontMatter.draft) ?? false;
126
137
  }
127
138
 
128
- function doProcessDocMetadata({
139
+ async function doProcessDocMetadata({
129
140
  docFile,
130
141
  versionMetadata,
131
142
  context,
@@ -137,8 +148,8 @@ function doProcessDocMetadata({
137
148
  context: LoadContext;
138
149
  options: MetadataOptions;
139
150
  env: DocEnv;
140
- }): DocMetadataBase {
141
- const {source, content, lastUpdate, contentPath, filePath} = docFile;
151
+ }): Promise<DocMetadataBase> {
152
+ const {source, content, contentPath, filePath} = docFile;
142
153
  const {siteDir, i18n} = context;
143
154
 
144
155
  const {
@@ -155,8 +166,15 @@ function doProcessDocMetadata({
155
166
  // (01-MyFolder/01-MyDoc.md => MyFolder/MyDoc)
156
167
  // but allow to disable this behavior with front matter
157
168
  parse_number_prefixes: parseNumberPrefixes = true,
169
+ last_update: lastUpdateFrontMatter,
158
170
  } = frontMatter;
159
171
 
172
+ const lastUpdate = await readLastUpdateData(
173
+ filePath,
174
+ options,
175
+ lastUpdateFrontMatter,
176
+ );
177
+
160
178
  // E.g. api/plugins/myDoc -> myDoc; myDoc -> myDoc
161
179
  const sourceFileNameWithoutExtension = path.basename(
162
180
  source,
@@ -252,6 +270,21 @@ function doProcessDocMetadata({
252
270
 
253
271
  const draft = isDraftForEnvironment({env, frontMatter});
254
272
 
273
+ const formatDate = (locale: string, date: Date, calendar: string): string => {
274
+ try {
275
+ return new Intl.DateTimeFormat(locale, {
276
+ day: 'numeric',
277
+ month: 'short',
278
+ year: 'numeric',
279
+ timeZone: 'UTC',
280
+ calendar,
281
+ }).format(date);
282
+ } catch (err) {
283
+ logger.error`Can't format docs lastUpdatedAt date "${String(date)}"`;
284
+ throw err;
285
+ }
286
+ };
287
+
255
288
  // Assign all of object properties during instantiation (if possible) for
256
289
  // NodeJS optimization.
257
290
  // Adding properties to object after instantiation will cause hidden
@@ -272,9 +305,11 @@ function doProcessDocMetadata({
272
305
  lastUpdatedBy: lastUpdate.lastUpdatedBy,
273
306
  lastUpdatedAt: lastUpdate.lastUpdatedAt,
274
307
  formattedLastUpdatedAt: lastUpdate.lastUpdatedAt
275
- ? new Intl.DateTimeFormat(i18n.currentLocale, {
276
- calendar: i18n.localeConfigs[i18n.currentLocale]!.calendar,
277
- }).format(lastUpdate.lastUpdatedAt * 1000)
308
+ ? formatDate(
309
+ i18n.currentLocale,
310
+ new Date(lastUpdate.lastUpdatedAt * 1000),
311
+ i18n.localeConfigs[i18n.currentLocale]!.calendar,
312
+ )
278
313
  : undefined,
279
314
  sidebarPosition,
280
315
  frontMatter,
@@ -287,7 +322,7 @@ export function processDocMetadata(args: {
287
322
  context: LoadContext;
288
323
  options: MetadataOptions;
289
324
  env: DocEnv;
290
- }): DocMetadataBase {
325
+ }): Promise<DocMetadataBase> {
291
326
  try {
292
327
  return doProcessDocMetadata(args);
293
328
  } catch (err) {
@@ -14,6 +14,9 @@ import {
14
14
  } from '@docusaurus/utils-validation';
15
15
  import type {DocFrontMatter} from '@docusaurus/plugin-content-docs';
16
16
 
17
+ const FrontMatterLastUpdateErrorMessage =
18
+ '{{#label}} does not look like a valid front matter FileChange object. Please use a FileChange object (with an author and/or date).';
19
+
17
20
  // NOTE: we don't add any default value on purpose here
18
21
  // We don't want default values to magically appear in doc metadata and props
19
22
  // While the user did not provide those values explicitly
@@ -42,6 +45,15 @@ const DocFrontMatterSchema = Joi.object<DocFrontMatter>({
42
45
  pagination_prev: Joi.string().allow(null),
43
46
  draft: Joi.boolean(),
44
47
  ...FrontMatterTOCHeadingLevels,
48
+ last_update: Joi.object({
49
+ author: Joi.string(),
50
+ date: Joi.date().raw(),
51
+ })
52
+ .or('author', 'date')
53
+ .messages({
54
+ 'object.missing': FrontMatterLastUpdateErrorMessage,
55
+ 'object.base': FrontMatterLastUpdateErrorMessage,
56
+ }),
45
57
  }).unknown();
46
58
 
47
59
  export function validateDocFrontMatter(frontMatter: {
package/src/index.ts CHANGED
@@ -13,7 +13,6 @@ import {
13
13
  docuHash,
14
14
  aliasedSitePath,
15
15
  getContentPathList,
16
- reportMessage,
17
16
  posixPath,
18
17
  addTrailingPathSeparator,
19
18
  createAbsoluteFilePathMatcher,
@@ -100,9 +99,9 @@ export default async function pluginContentDocs(
100
99
  .command(command)
101
100
  .arguments('<version>')
102
101
  .description(commandDescription)
103
- .action((version: unknown) => {
104
- cliDocsVersionCommand(version, options, context);
105
- });
102
+ .action((version: unknown) =>
103
+ cliDocsVersionCommand(version, options, context),
104
+ );
106
105
  },
107
106
 
108
107
  getTranslationFiles({content}) {
@@ -330,13 +329,9 @@ export default async function pluginContentDocs(
330
329
  sourceToPermalink: getSourceToPermalink(),
331
330
  versionsMetadata,
332
331
  onBrokenMarkdownLink: (brokenMarkdownLink) => {
333
- if (siteConfig.onBrokenMarkdownLinks === 'ignore') {
334
- return;
335
- }
336
- reportMessage(
337
- `Docs markdown link couldn't be resolved: (${brokenMarkdownLink.link}) in ${brokenMarkdownLink.filePath} for version ${brokenMarkdownLink.contentPaths.versionName}`,
332
+ logger.report(
338
333
  siteConfig.onBrokenMarkdownLinks,
339
- );
334
+ )`Docs markdown link couldn't be resolved: (url=${brokenMarkdownLink.link}) in path=${brokenMarkdownLink.filePath} for version number=${brokenMarkdownLink.contentPaths.versionName}`;
340
335
  },
341
336
  };
342
337
 
@@ -352,6 +347,7 @@ export default async function pluginContentDocs(
352
347
  {
353
348
  loader: require.resolve('@docusaurus/mdx-loader'),
354
349
  options: {
350
+ admonitions: options.admonitions,
355
351
  remarkPlugins,
356
352
  rehypePlugins,
357
353
  beforeDefaultRehypePlugins,
package/src/lastUpdate.ts CHANGED
@@ -16,7 +16,7 @@ let showedGitRequirementError = false;
16
16
  let showedFileNotTrackedError = false;
17
17
 
18
18
  export async function getFileLastUpdate(
19
- filePath?: string,
19
+ filePath: string,
20
20
  ): Promise<{timestamp: number; author: string} | null> {
21
21
  if (!filePath) {
22
22
  return null;
package/src/options.ts CHANGED
@@ -14,7 +14,6 @@ import {
14
14
  URISchema,
15
15
  } from '@docusaurus/utils-validation';
16
16
  import {GlobExcludeDefault} from '@docusaurus/utils';
17
- import admonitions from 'remark-admonitions';
18
17
  import {DefaultSidebarItemsGenerator} from './sidebars/generator';
19
18
  import {
20
19
  DefaultNumberPrefixParser,
@@ -42,7 +41,7 @@ export const DEFAULT_OPTIONS: Omit<PluginOptions, 'id' | 'sidebarPath'> = {
42
41
  beforeDefaultRehypePlugins: [],
43
42
  showLastUpdateTime: false,
44
43
  showLastUpdateAuthor: false,
45
- admonitions: {},
44
+ admonitions: true,
46
45
  includeCurrentVersion: true,
47
46
  disableVersioning: false,
48
47
  lastVersion: undefined,
@@ -123,9 +122,7 @@ const OptionsSchema = Joi.object<PluginOptions>({
123
122
  beforeDefaultRehypePlugins: RehypePluginsSchema.default(
124
123
  DEFAULT_OPTIONS.beforeDefaultRehypePlugins,
125
124
  ),
126
- admonitions: Joi.alternatives()
127
- .try(AdmonitionsSchema, Joi.boolean().invalid(true))
128
- .default(DEFAULT_OPTIONS.admonitions),
125
+ admonitions: AdmonitionsSchema.default(DEFAULT_OPTIONS.admonitions),
129
126
  showLastUpdateTime: Joi.bool().default(DEFAULT_OPTIONS.showLastUpdateTime),
130
127
  showLastUpdateAuthor: Joi.bool().default(
131
128
  DEFAULT_OPTIONS.showLastUpdateAuthor,
@@ -167,11 +164,5 @@ export function validateOptions({
167
164
 
168
165
  const normalizedOptions = validate(OptionsSchema, options);
169
166
 
170
- if (normalizedOptions.admonitions) {
171
- normalizedOptions.remarkPlugins = normalizedOptions.remarkPlugins.concat([
172
- [admonitions, normalizedOptions.admonitions],
173
- ]);
174
- }
175
-
176
167
  return normalizedOptions;
177
168
  }
@@ -8,7 +8,8 @@
8
8
  /// <reference types="@docusaurus/module-type-aliases" />
9
9
 
10
10
  declare module '@docusaurus/plugin-content-docs' {
11
- import type {MDXOptions} from '@docusaurus/mdx-loader';
11
+ import type {MDXOptions, LoadedMDXContent} from '@docusaurus/mdx-loader';
12
+
12
13
  import type {
13
14
  ContentPaths,
14
15
  FrontMatterTag,
@@ -23,6 +24,14 @@ declare module '@docusaurus/plugin-content-docs' {
23
24
  image?: string;
24
25
  };
25
26
 
27
+ export type FileChange = {
28
+ author?: string;
29
+ /** Date can be any
30
+ * [parsable date string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse).
31
+ */
32
+ date?: Date | string;
33
+ };
34
+
26
35
  /**
27
36
  * Custom callback for parsing number prefixes from file/folder names.
28
37
  */
@@ -198,7 +207,6 @@ declare module '@docusaurus/plugin-content-docs' {
198
207
  docTagsListComponent: string;
199
208
  /** Root component of the generated category index page. */
200
209
  docCategoryGeneratedIndexComponent: string;
201
- admonitions: {[key: string]: unknown};
202
210
  sidebarItemsGenerator: import('./sidebars/types').SidebarItemsGeneratorOption;
203
211
  /**
204
212
  * URL route for the tags section of your doc version. Will be appended to
@@ -371,6 +379,8 @@ declare module '@docusaurus/plugin-content-docs' {
371
379
  pagination_prev?: string | null;
372
380
  /** Should this doc be excluded from production builds? */
373
381
  draft?: boolean;
382
+ /** Allows overriding the last updated author and/or date. */
383
+ last_update?: FileChange;
374
384
  };
375
385
 
376
386
  export type LastUpdateData = {
@@ -482,6 +492,12 @@ declare module '@docusaurus/plugin-content-docs' {
482
492
  [docId: string]: PropVersionDoc;
483
493
  };
484
494
 
495
+ export type PropDocContent = LoadedMDXContent<
496
+ DocFrontMatter,
497
+ DocMetadata,
498
+ Assets
499
+ >;
500
+
485
501
  export type PropVersionMetadata = Pick<
486
502
  VersionMetadata,
487
503
  'label' | 'banner' | 'badge' | 'className' | 'isLast'
@@ -540,13 +556,7 @@ declare module '@docusaurus/plugin-content-docs' {
540
556
  }
541
557
 
542
558
  declare module '@theme/DocItem' {
543
- import type {LoadedMDXContent} from '@docusaurus/mdx-loader';
544
- import type {
545
- PropVersionMetadata,
546
- Assets,
547
- DocMetadata,
548
- DocFrontMatter,
549
- } from '@docusaurus/plugin-content-docs';
559
+ import type {PropDocContent} from '@docusaurus/plugin-content-docs';
550
560
 
551
561
  export type DocumentRoute = {
552
562
  readonly component: () => JSX.Element;
@@ -557,8 +567,7 @@ declare module '@theme/DocItem' {
557
567
 
558
568
  export interface Props {
559
569
  readonly route: DocumentRoute;
560
- readonly versionMetadata: PropVersionMetadata;
561
- readonly content: LoadedMDXContent<DocFrontMatter, DocMetadata, Assets>;
570
+ readonly content: PropDocContent;
562
571
  }
563
572
 
564
573
  export default function DocItem(props: Props): JSX.Element;
@@ -607,89 +616,3 @@ declare module '@theme/DocPage' {
607
616
 
608
617
  export default function DocPage(props: Props): JSX.Element;
609
618
  }
610
-
611
- // TODO TS only supports reading `exports` in 4.7. We will need to merge the
612
- // type defs (and JSDoc) here with the implementation after that
613
- declare module '@docusaurus/plugin-content-docs/client' {
614
- import type {UseDataOptions} from '@docusaurus/types';
615
-
616
- export type ActivePlugin = {
617
- pluginId: string;
618
- pluginData: GlobalPluginData;
619
- };
620
- export type ActiveDocContext = {
621
- activeVersion?: GlobalVersion;
622
- activeDoc?: GlobalDoc;
623
- alternateDocVersions: {[versionName: string]: GlobalDoc};
624
- };
625
- export type GlobalDoc = {
626
- /**
627
- * For generated index pages, this is the `slug`, **not** `permalink`
628
- * (without base URL). Because slugs have leading slashes but IDs don't,
629
- * there won't be clashes.
630
- */
631
- id: string;
632
- path: string;
633
- sidebar: string | undefined;
634
- };
635
-
636
- export type GlobalVersion = {
637
- name: string;
638
- label: string;
639
- isLast: boolean;
640
- path: string;
641
- /** The doc with `slug: /`, or first doc in first sidebar */
642
- mainDocId: string;
643
- docs: GlobalDoc[];
644
- /** Unversioned IDs. In development, this list is empty. */
645
- draftIds: string[];
646
- sidebars?: {[sidebarId: string]: GlobalSidebar};
647
- };
648
-
649
- export type GlobalSidebar = {
650
- link?: {
651
- label: string;
652
- path: string;
653
- };
654
- // ... we may add other things here later
655
- };
656
- export type GlobalPluginData = {
657
- path: string;
658
- versions: GlobalVersion[];
659
- breadcrumbs: boolean;
660
- };
661
- export type DocVersionSuggestions = {
662
- /** Suggest the latest version */
663
- latestVersionSuggestion: GlobalVersion;
664
- /** Suggest the same doc, in latest version (if one exists) */
665
- latestDocSuggestion?: GlobalDoc;
666
- };
667
-
668
- export const useAllDocsData: () => {[pluginId: string]: GlobalPluginData};
669
- export const useDocsData: (pluginId?: string) => GlobalPluginData;
670
- export const useActivePlugin: (
671
- options?: UseDataOptions,
672
- ) => ActivePlugin | undefined;
673
- export const useActivePluginAndVersion: (
674
- options?: UseDataOptions,
675
- ) =>
676
- | {activePlugin: ActivePlugin; activeVersion: GlobalVersion | undefined}
677
- | undefined;
678
- /** Versions are returned ordered (most recent first). */
679
- export const useVersions: (pluginId?: string) => GlobalVersion[];
680
- export const useLatestVersion: (pluginId?: string) => GlobalVersion;
681
- /**
682
- * Returns `undefined` on doc-unrelated pages, because there's no version
683
- * currently considered as active.
684
- */
685
- export const useActiveVersion: (
686
- pluginId?: string,
687
- ) => GlobalVersion | undefined;
688
- export const useActiveDocContext: (pluginId?: string) => ActiveDocContext;
689
- /**
690
- * Useful to say "hey, you are not on the latest docs version, please switch"
691
- */
692
- export const useDocVersionSuggestions: (
693
- pluginId?: string,
694
- ) => DocVersionSuggestions;
695
- }
package/src/props.ts CHANGED
@@ -73,10 +73,28 @@ Available document ids are:
73
73
  }
74
74
  }
75
75
 
76
+ function getCategoryLinkCustomProps(
77
+ link: SidebarItemCategoryLink | undefined,
78
+ ) {
79
+ switch (link?.type) {
80
+ case 'doc':
81
+ return getDocById(link.id).frontMatter.sidebar_custom_props;
82
+ default:
83
+ return undefined;
84
+ }
85
+ }
86
+
76
87
  function convertCategory(item: SidebarItemCategory): PropSidebarItemCategory {
77
88
  const {link, ...rest} = item;
78
89
  const href = getCategoryLinkHref(link);
79
- return {...rest, items: item.items.map(normalizeItem), ...(href && {href})};
90
+ const customProps = item.customProps ?? getCategoryLinkCustomProps(link);
91
+
92
+ return {
93
+ ...rest,
94
+ items: item.items.map(normalizeItem),
95
+ ...(href && {href}),
96
+ ...(customProps && {customProps}),
97
+ };
80
98
  }
81
99
 
82
100
  function normalizeItem(item: SidebarItem): PropSidebarItem {