docusaurus-plugin-openapi-docs 4.0.1 → 4.1.0

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.
@@ -368,6 +368,93 @@ Array [
368
368
  ]
369
369
  `;
370
370
 
371
+ exports[`createNodes anyOf should render oneOf within anyOf 1`] = `
372
+ Array [
373
+ "<SchemaItem collapsible={true} className={\\"schemaItem\\"}>
374
+ <details style={{}} className={\\"openapi-markdown__details\\"}>
375
+ <summary style={{}}>
376
+ <span className={\\"openapi-schema__container\\"}>
377
+ <strong className={\\"openapi-schema__property\\"}>oneOfProperty</strong>
378
+ <span className={\\"openapi-schema__name\\"}>object</span>
379
+ </span>
380
+ </summary>
381
+ <div style={{ marginLeft: \\"1rem\\" }}>
382
+ <div>
383
+ <span className={\\"badge badge--info\\"} style={{ marginBottom: \\"1rem\\" }}>
384
+ anyOf
385
+ </span>
386
+ <SchemaTabs>
387
+ <TabItem label={\\"An int or a bool\\"} value={\\"0-item-properties\\"}>
388
+ <div>
389
+ <span
390
+ className={\\"badge badge--info\\"}
391
+ style={{ marginBottom: \\"1rem\\" }}
392
+ >
393
+ oneOf
394
+ </span>
395
+ <SchemaTabs>
396
+ <TabItem label={\\"MOD1\\"} value={\\"0-item-properties\\"}>
397
+ <div style={{ marginTop: \\".5rem\\", marginBottom: \\".5rem\\" }}>
398
+ integer
399
+ </div>
400
+ </TabItem>
401
+ <TabItem label={\\"MOD2\\"} value={\\"1-item-properties\\"}>
402
+ <div style={{ marginTop: \\".5rem\\", marginBottom: \\".5rem\\" }}>
403
+ boolean
404
+ </div>
405
+ </TabItem>
406
+ </SchemaTabs>
407
+ </div>
408
+ </TabItem>
409
+ <TabItem label={\\"MOD2\\"} value={\\"1-item-properties\\"}>
410
+ <div style={{ marginTop: \\".5rem\\", marginBottom: \\".5rem\\" }}>
411
+ string
412
+ </div>
413
+ </TabItem>
414
+ </SchemaTabs>
415
+ </div>
416
+ </div>
417
+ </details>
418
+ </SchemaItem>;
419
+ ",
420
+ ]
421
+ `;
422
+
423
+ exports[`createNodes anyOf should render primitives within anyOf 1`] = `
424
+ Array [
425
+ "<SchemaItem collapsible={true} className={\\"schemaItem\\"}>
426
+ <details style={{}} className={\\"openapi-markdown__details\\"}>
427
+ <summary style={{}}>
428
+ <span className={\\"openapi-schema__container\\"}>
429
+ <strong className={\\"openapi-schema__property\\"}>oneOfProperty</strong>
430
+ <span className={\\"openapi-schema__name\\"}>object</span>
431
+ </span>
432
+ </summary>
433
+ <div style={{ marginLeft: \\"1rem\\" }}>
434
+ <div>
435
+ <span className={\\"badge badge--info\\"} style={{ marginBottom: \\"1rem\\" }}>
436
+ anyOf
437
+ </span>
438
+ <SchemaTabs>
439
+ <TabItem label={\\"MOD1\\"} value={\\"0-item-properties\\"}>
440
+ <div style={{ marginTop: \\".5rem\\", marginBottom: \\".5rem\\" }}>
441
+ integer
442
+ </div>
443
+ </TabItem>
444
+ <TabItem label={\\"MOD2\\"} value={\\"1-item-properties\\"}>
445
+ <div style={{ marginTop: \\".5rem\\", marginBottom: \\".5rem\\" }}>
446
+ boolean
447
+ </div>
448
+ </TabItem>
449
+ </SchemaTabs>
450
+ </div>
451
+ </div>
452
+ </details>
453
+ </SchemaItem>;
454
+ ",
455
+ ]
456
+ `;
457
+
371
458
  exports[`createNodes discriminator should handle basic discriminator with mapping 1`] = `
372
459
  Array [
373
460
  "<div>
@@ -0,0 +1,19 @@
1
+ /* ============================================================================
2
+ * Copyright (c) Palo Alto Networks
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
+
8
+ import { create } from "./utils";
9
+
10
+ export function createCallbackMethodEndpoint(method: String, path: String) {
11
+ return [
12
+ create("MethodEndpoint", {
13
+ method: method,
14
+ path: path,
15
+ context: "callback",
16
+ }),
17
+ "\n\n",
18
+ ];
19
+ }
@@ -5,8 +5,8 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
+ import { createCallbackMethodEndpoint } from "./createCallbackMethodEndpoint";
8
9
  import { createDescription } from "./createDescription";
9
- import { createMethodEndpoint } from "./createMethodEndpoint";
10
10
  import { createRequestBodyDetails } from "./createRequestBodyDetails";
11
11
  import { createStatusCodes } from "./createStatusCodes";
12
12
  import { create } from "./utils";
@@ -78,7 +78,7 @@ export function createCallbacks({ callbacks }: Props) {
78
78
  label: `${method.toUpperCase()} ${name}`,
79
79
  value: `${method}-${name}`,
80
80
  children: [
81
- createMethodEndpoint(method, path),
81
+ createCallbackMethodEndpoint(method, path),
82
82
  // TODO: add `deprecation notice` when markdown support is added
83
83
  createDescription(description),
84
84
  createRequestBodyDetails({
@@ -23,8 +23,9 @@ export function createDeprecationNotice({
23
23
  return guard(deprecated, () =>
24
24
  createAdmonition({
25
25
  children:
26
- clean(description) ??
27
- "This endpoint has been deprecated and may be replaced or removed in future versions of the API.",
26
+ description && description.length > 0
27
+ ? clean(description)
28
+ : "This endpoint has been deprecated and may be replaced or removed in future versions of the API.",
28
29
  })
29
30
  );
30
31
  }
@@ -8,5 +8,12 @@
8
8
  import { create } from "./utils";
9
9
 
10
10
  export function createMethodEndpoint(method: String, path: String) {
11
- return [create("MethodEndpoint", { method: method, path: path }), "\n\n"];
11
+ return [
12
+ create("MethodEndpoint", {
13
+ method: method,
14
+ path: path,
15
+ context: "endpoint",
16
+ }),
17
+ "\n\n",
18
+ ];
12
19
  }
@@ -43,12 +43,19 @@ export function createParamsDetails({ parameters, type }: Props) {
43
43
  create("div", {
44
44
  children: [
45
45
  create("ul", {
46
- children: params.map((param) =>
47
- create("ParamsItem", {
46
+ children: params.map((param) => {
47
+ return create("ParamsItem", {
48
48
  className: "paramsItem",
49
- param: param,
50
- })
51
- ),
49
+ param: {
50
+ ...param,
51
+ enumDescriptions: Object.entries(
52
+ param?.schema?.["x-enumDescriptions"] ??
53
+ param?.schema?.items?.["x-enumDescriptions"] ??
54
+ {}
55
+ ),
56
+ },
57
+ });
58
+ }),
52
59
  }),
53
60
  ],
54
61
  }),
@@ -246,6 +246,70 @@ describe("createNodes", () => {
246
246
  });
247
247
  });
248
248
 
249
+ describe("anyOf", () => {
250
+ it("should render primitives within anyOf", async () => {
251
+ const schema: SchemaObject = {
252
+ type: "object",
253
+ properties: {
254
+ oneOfProperty: {
255
+ anyOf: [
256
+ {
257
+ type: "integer",
258
+ },
259
+ {
260
+ type: "boolean",
261
+ },
262
+ ],
263
+ title: "One of int or bool",
264
+ },
265
+ },
266
+ };
267
+
268
+ expect(
269
+ await Promise.all(
270
+ createNodes(schema, "response").map(
271
+ async (md: any) => await prettier.format(md, { parser: "babel" })
272
+ )
273
+ )
274
+ ).toMatchSnapshot();
275
+ });
276
+
277
+ it("should render oneOf within anyOf", async () => {
278
+ const schema: SchemaObject = {
279
+ type: "object",
280
+ properties: {
281
+ oneOfProperty: {
282
+ anyOf: [
283
+ {
284
+ oneOf: [
285
+ {
286
+ type: "integer",
287
+ },
288
+ {
289
+ type: "boolean",
290
+ },
291
+ ],
292
+ title: "An int or a bool",
293
+ },
294
+ {
295
+ type: "string",
296
+ },
297
+ ],
298
+ title: "One of int or bool, or a string",
299
+ },
300
+ },
301
+ };
302
+
303
+ expect(
304
+ await Promise.all(
305
+ createNodes(schema, "response").map(
306
+ async (md: any) => await prettier.format(md, { parser: "babel" })
307
+ )
308
+ )
309
+ ).toMatchSnapshot();
310
+ });
311
+ });
312
+
249
313
  describe("allOf", () => {
250
314
  it("should render same-level properties with allOf", async () => {
251
315
  const schema: SchemaObject = {
@@ -104,6 +104,11 @@ function createAnyOneOf(schema: SchemaObject): any {
104
104
  delete anyOneSchema.allOf;
105
105
  }
106
106
 
107
+ if (anyOneSchema.oneOf !== undefined) {
108
+ anyOneChildren.push(createNodes(anyOneSchema, SCHEMA_TYPE));
109
+ delete anyOneSchema.oneOf;
110
+ }
111
+
107
112
  if (anyOneSchema.items !== undefined) {
108
113
  anyOneChildren.push(createItems(anyOneSchema));
109
114
  delete anyOneSchema.items;
@@ -411,16 +416,16 @@ function createDetailsNode(
411
416
  create("div", {
412
417
  style: { marginLeft: "1rem" },
413
418
  children: [
414
- guard(getQualifierMessage(schema), (message) =>
419
+ guard(schema.description, (description) =>
415
420
  create("div", {
416
421
  style: { marginTop: ".5rem", marginBottom: ".5rem" },
417
- children: createDescription(message),
422
+ children: createDescription(description),
418
423
  })
419
424
  ),
420
- guard(schema.description, (description) =>
425
+ guard(getQualifierMessage(schema), (message) =>
421
426
  create("div", {
422
427
  style: { marginTop: ".5rem", marginBottom: ".5rem" },
423
- children: createDescription(description),
428
+ children: createDescription(message),
424
429
  })
425
430
  ),
426
431
  createNodes(schema, SCHEMA_TYPE),
@@ -554,20 +559,20 @@ function createPropertyDiscriminator(
554
559
  ]),
555
560
  ],
556
561
  }),
557
- guard(getQualifierMessage(discriminator), (message) =>
562
+ guard(schema.description, (description) =>
558
563
  create("div", {
559
564
  style: {
560
565
  paddingLeft: "1rem",
561
566
  },
562
- children: createDescription(message),
567
+ children: createDescription(description),
563
568
  })
564
569
  ),
565
- guard(schema.description, (description) =>
570
+ guard(getQualifierMessage(discriminator), (message) =>
566
571
  create("div", {
567
572
  style: {
568
573
  paddingLeft: "1rem",
569
574
  },
570
- children: createDescription(description),
575
+ children: createDescription(message),
571
576
  })
572
577
  ),
573
578
  create("DiscriminatorTabs", {
@@ -682,50 +687,57 @@ function createEdges({
682
687
  const { mergedSchemas }: { mergedSchemas: SchemaObject } = mergeAllOf(
683
688
  schema.allOf
684
689
  );
690
+ delete schema.allOf;
691
+ const combinedSchemas = { ...schema, ...mergedSchemas };
685
692
 
686
693
  if (SCHEMA_TYPE === "request") {
687
- if (mergedSchemas.readOnly && mergedSchemas.readOnly === true) {
694
+ if (combinedSchemas.readOnly && combinedSchemas.readOnly === true) {
688
695
  return undefined;
689
696
  }
690
697
  }
691
698
 
692
699
  if (SCHEMA_TYPE === "response") {
693
- if (mergedSchemas.writeOnly && mergedSchemas.writeOnly === true) {
700
+ if (combinedSchemas.writeOnly && combinedSchemas.writeOnly === true) {
694
701
  return undefined;
695
702
  }
696
703
  }
697
704
 
698
- const mergedSchemaName = getSchemaName(mergedSchemas);
705
+ const mergedSchemaName = getSchemaName(combinedSchemas);
706
+
707
+ if (name === "eventName") {
708
+ console.log(mergedSchemaName, combinedSchemas);
709
+ }
710
+
699
711
  if (
700
- mergedSchemas.oneOf !== undefined ||
701
- mergedSchemas.anyOf !== undefined
712
+ combinedSchemas.oneOf !== undefined ||
713
+ combinedSchemas.anyOf !== undefined
702
714
  ) {
703
715
  return createDetailsNode(
704
716
  name,
705
717
  mergedSchemaName,
706
- mergedSchemas,
718
+ combinedSchemas,
707
719
  required,
708
- schema.nullable
720
+ combinedSchemas.nullable
709
721
  );
710
722
  }
711
723
 
712
- if (mergedSchemas.properties !== undefined) {
724
+ if (combinedSchemas.properties !== undefined) {
713
725
  return createDetailsNode(
714
726
  name,
715
727
  mergedSchemaName,
716
- mergedSchemas,
728
+ combinedSchemas,
717
729
  required,
718
- schema.nullable
730
+ combinedSchemas.nullable
719
731
  );
720
732
  }
721
733
 
722
- if (mergedSchemas.additionalProperties !== undefined) {
734
+ if (combinedSchemas.additionalProperties !== undefined) {
723
735
  return createDetailsNode(
724
736
  name,
725
737
  mergedSchemaName,
726
- mergedSchemas,
738
+ combinedSchemas,
727
739
  required,
728
- schema.nullable
740
+ combinedSchemas.nullable
729
741
  );
730
742
  }
731
743
 
@@ -734,9 +746,9 @@ function createEdges({
734
746
  return createDetailsNode(
735
747
  name,
736
748
  mergedSchemaName,
737
- mergedSchemas,
749
+ combinedSchemas,
738
750
  required,
739
- schema.nullable
751
+ combinedSchemas.nullable
740
752
  );
741
753
  }
742
754
 
@@ -745,8 +757,8 @@ function createEdges({
745
757
  name,
746
758
  required: Array.isArray(required) ? required.includes(name) : required,
747
759
  schemaName: mergedSchemaName,
748
- qualifierMessage: getQualifierMessage(mergedSchemas),
749
- schema: mergedSchemas,
760
+ qualifierMessage: getQualifierMessage(combinedSchemas),
761
+ schema: combinedSchemas,
750
762
  });
751
763
  }
752
764
 
@@ -5,6 +5,10 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
+ /**
9
+ * Children in the plugin does not accept DOM elements, when compared with Children in the theme.
10
+ * It is designed for rendering HTML a strings.
11
+ */
8
12
  export type Children = string | undefined | (string | string[] | undefined)[];
9
13
 
10
14
  export type Props = Record<string, any> & { children?: Children };
@@ -269,7 +269,7 @@ function createItems(
269
269
 
270
270
  // Gather x-webhooks endpoints
271
271
  for (let [path, pathObject] of Object.entries(
272
- openapiData["x-webhooks"] ?? {}
272
+ openapiData["x-webhooks"] ?? openapiData["webhooks"] ?? {}
273
273
  )) {
274
274
  path = "webhook";
275
275
  const { $ref, description, parameters, servers, summary, ...rest } =
@@ -21,6 +21,7 @@ export interface OpenApiObject {
21
21
  tags?: TagObject[];
22
22
  externalDocs?: ExternalDocumentationObject;
23
23
  swagger?: string;
24
+ webhooks?: PathsObject;
24
25
  "x-webhooks"?: PathsObject;
25
26
  "x-tagGroups"?: TagGroupObject[];
26
27
  }
@@ -197,6 +198,7 @@ export interface ParameterObject {
197
198
  param?: Object;
198
199
  // ignoring stylings: matrix, label, form, simple, spaceDelimited,
199
200
  // pipeDelimited and deepObject
201
+ "x-enumDescriptions"?: Record<string, string>;
200
202
  }
201
203
 
202
204
  export interface ParameterObjectWithRef {
@@ -353,6 +355,7 @@ export type SchemaObject = Omit<
353
355
  example?: any;
354
356
  deprecated?: boolean;
355
357
  "x-tags"?: string[];
358
+ "x-enumDescriptions"?: Record<string, string>;
356
359
  };
357
360
 
358
361
  export type SchemaObjectWithRef = Omit<
@@ -270,6 +270,7 @@ export class OpenAPIParser {
270
270
  const {
271
271
  type,
272
272
  enum: enumProperty,
273
+ "x-enumDescription": enumDescription,
273
274
  properties,
274
275
  items,
275
276
  required,
package/src/options.ts CHANGED
@@ -7,12 +7,17 @@
7
7
 
8
8
  import { Joi } from "@docusaurus/utils-validation";
9
9
 
10
+ const sidebarGenerators = Joi.object({
11
+ createDocItem: Joi.function(),
12
+ });
13
+
10
14
  const sidebarOptions = Joi.object({
11
15
  groupPathsBy: Joi.string().valid("tag", "tagGroup"),
12
16
  categoryLinkSource: Joi.string().valid("tag", "info", "auto"),
13
17
  customProps: Joi.object(),
14
18
  sidebarCollapsible: Joi.boolean(),
15
19
  sidebarCollapsed: Joi.boolean(),
20
+ sidebarGenerators: sidebarGenerators,
16
21
  });
17
22
 
18
23
  const markdownGenerators = Joi.object({
@@ -12,7 +12,6 @@ import {
12
12
  ProcessedSidebar,
13
13
  SidebarItemCategory,
14
14
  SidebarItemCategoryLinkConfig,
15
- SidebarItemDoc,
16
15
  } from "@docusaurus/plugin-content-docs/src/sidebars/types";
17
16
  import { posixPath } from "@docusaurus/utils";
18
17
  import clsx from "clsx";
@@ -27,6 +26,7 @@ import type {
27
26
  ApiMetadata,
28
27
  InfoPageMetadata,
29
28
  SchemaPageMetadata,
29
+ ApiDocItemGenerator,
30
30
  } from "../types";
31
31
 
32
32
  function isApiItem(item: ApiMetadata): item is ApiMetadata {
@@ -41,6 +41,37 @@ function isSchemaItem(item: ApiMetadata): item is ApiMetadata {
41
41
  return item.type === "schema";
42
42
  }
43
43
 
44
+ const createDocItem: ApiDocItemGenerator = (
45
+ item,
46
+ { sidebarOptions: { customProps }, basePath }
47
+ ) => {
48
+ const sidebar_label = item.frontMatter.sidebar_label;
49
+ const title = item.title;
50
+ const id = item.type === "schema" ? `schemas/${item.id}` : item.id;
51
+ const className =
52
+ item.type === "api"
53
+ ? clsx(
54
+ {
55
+ "menu__list-item--deprecated": item.api.deprecated,
56
+ "api-method": !!item.api.method,
57
+ },
58
+ item.api.method
59
+ )
60
+ : clsx(
61
+ {
62
+ "menu__list-item--deprecated": item.schema.deprecated,
63
+ },
64
+ "schema"
65
+ );
66
+ return {
67
+ type: "doc" as const,
68
+ id: basePath === "" || undefined ? `${id}` : `${basePath}/${id}`,
69
+ label: (sidebar_label as string) ?? title ?? id,
70
+ customProps: customProps,
71
+ className: className ? className : undefined,
72
+ };
73
+ };
74
+
44
75
  function groupByTags(
45
76
  items: ApiMetadata[],
46
77
  sidebarOptions: SidebarOptions,
@@ -53,12 +84,8 @@ function groupByTags(
53
84
  // Remove trailing slash before proceeding
54
85
  outputDir = outputDir.replace(/\/$/, "");
55
86
 
56
- const {
57
- sidebarCollapsed,
58
- sidebarCollapsible,
59
- customProps,
60
- categoryLinkSource,
61
- } = sidebarOptions;
87
+ const { sidebarCollapsed, sidebarCollapsible, categoryLinkSource } =
88
+ sidebarOptions;
62
89
 
63
90
  const apiItems = items.filter(isApiItem) as ApiPageMetadata[];
64
91
  const infoItems = items.filter(isInfoItem) as InfoPageMetadata[];
@@ -101,35 +128,13 @@ function groupByTags(
101
128
  const basePath = docPath
102
129
  ? outputDir.split(docPath!)[1].replace(/^\/+/g, "")
103
130
  : outputDir.slice(outputDir.indexOf("/", 1)).replace(/^\/+/g, "");
104
- function createDocItem(
105
- item: ApiPageMetadata | SchemaPageMetadata
106
- ): SidebarItemDoc {
107
- const sidebar_label = item.frontMatter.sidebar_label;
108
- const title = item.title;
109
- const id = item.type === "schema" ? `schemas/${item.id}` : item.id;
110
- const className =
111
- item.type === "api"
112
- ? clsx(
113
- {
114
- "menu__list-item--deprecated": item.api.deprecated,
115
- "api-method": !!item.api.method,
116
- },
117
- item.api.method
118
- )
119
- : clsx(
120
- {
121
- "menu__list-item--deprecated": item.schema.deprecated,
122
- },
123
- "schema"
124
- );
125
- return {
126
- type: "doc" as const,
127
- id: basePath === "" || undefined ? `${id}` : `${basePath}/${id}`,
128
- label: (sidebar_label as string) ?? title ?? id,
129
- customProps: customProps,
130
- className: className ? className : undefined,
131
- };
132
- }
131
+
132
+ const createDocItemFnContext = {
133
+ sidebarOptions,
134
+ basePath,
135
+ };
136
+ const createDocItemFn =
137
+ sidebarOptions.sidebarGenerators?.createDocItem ?? createDocItem;
133
138
 
134
139
  let rootIntroDoc = undefined;
135
140
  if (infoItems.length === 1) {
@@ -208,7 +213,9 @@ function groupByTags(
208
213
  link: linkConfig,
209
214
  collapsible: sidebarCollapsible,
210
215
  collapsed: sidebarCollapsed,
211
- items: [...taggedSchemaItems, ...taggedApiItems].map(createDocItem),
216
+ items: [...taggedSchemaItems, ...taggedApiItems].map((item) =>
217
+ createDocItemFn(item, createDocItemFnContext)
218
+ ),
212
219
  };
213
220
  })
214
221
  .filter((item) => item.items.length > 0); // Filter out any categories with no items.
@@ -216,7 +223,7 @@ function groupByTags(
216
223
  // Handle items with no tag
217
224
  const untaggedItems = apiItems
218
225
  .filter(({ api }) => api.tags === undefined || api.tags.length === 0)
219
- .map(createDocItem);
226
+ .map((item) => createDocItemFn(item, createDocItemFnContext));
220
227
  let untagged: SidebarItemCategory[] = [];
221
228
  if (untaggedItems.length > 0) {
222
229
  untagged = [
@@ -227,7 +234,7 @@ function groupByTags(
227
234
  collapsed: sidebarCollapsed!,
228
235
  items: apiItems
229
236
  .filter(({ api }) => api.tags === undefined || api.tags.length === 0)
230
- .map(createDocItem),
237
+ .map((item) => createDocItemFn(item, createDocItemFnContext)),
231
238
  },
232
239
  ];
233
240
  }
@@ -242,7 +249,7 @@ function groupByTags(
242
249
  collapsed: sidebarCollapsed!,
243
250
  items: schemaItems
244
251
  .filter(({ schema }) => !schema["x-tags"])
245
- .map(createDocItem),
252
+ .map((item) => createDocItemFn(item, createDocItemFnContext)),
246
253
  },
247
254
  ];
248
255
  }
package/src/types.ts CHANGED
@@ -5,6 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
+ import { SidebarItemDoc } from "@docusaurus/plugin-content-docs/src/sidebars/types";
8
9
  import type Request from "postman-collection";
9
10
 
10
11
  import {
@@ -57,12 +58,22 @@ export interface MarkdownGenerator {
57
58
  createSchemaPageMD?: (pageData: SchemaPageMetadata) => string;
58
59
  }
59
60
 
61
+ export type ApiDocItemGenerator = (
62
+ item: ApiPageMetadata | SchemaPageMetadata,
63
+ context: { sidebarOptions: SidebarOptions; basePath: string }
64
+ ) => SidebarItemDoc;
65
+
66
+ export interface SidebarGenerators {
67
+ createDocItem?: ApiDocItemGenerator;
68
+ }
69
+
60
70
  export interface SidebarOptions {
61
71
  groupPathsBy?: string;
62
72
  categoryLinkSource?: "info" | "tag" | "auto";
63
73
  customProps?: { [key: string]: unknown };
64
74
  sidebarCollapsible?: boolean;
65
75
  sidebarCollapsed?: boolean;
76
+ sidebarGenerators?: SidebarGenerators;
66
77
  }
67
78
 
68
79
  export interface APIVersionOptions {