docusaurus-plugin-openapi-docs 4.0.1 → 4.2.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.
Files changed (55) hide show
  1. package/README.md +11 -0
  2. package/lib/index.js +4 -0
  3. package/lib/markdown/createCallbackMethodEndpoint.d.ts +1 -0
  4. package/lib/markdown/createCallbackMethodEndpoint.js +21 -0
  5. package/lib/markdown/createCallbacks.js +2 -2
  6. package/lib/markdown/createContactInfo.js +1 -1
  7. package/lib/markdown/createDeprecationNotice.js +5 -6
  8. package/lib/markdown/createMethodEndpoint.js +8 -1
  9. package/lib/markdown/createParamsDetails.d.ts +1 -2
  10. package/lib/markdown/createParamsDetails.js +7 -36
  11. package/lib/markdown/createRequestBodyDetails.d.ts +1 -1
  12. package/lib/markdown/createRequestSchema.d.ts +1 -1
  13. package/lib/markdown/createRequestSchema.js +8 -132
  14. package/lib/markdown/createResponseSchema.d.ts +1 -1
  15. package/lib/markdown/createResponseSchema.js +8 -94
  16. package/lib/markdown/createSchema.d.ts +1 -4
  17. package/lib/markdown/createSchema.js +35 -50
  18. package/lib/markdown/createSchema.test.js +48 -0
  19. package/lib/markdown/createStatusCodes.d.ts +1 -4
  20. package/lib/markdown/createStatusCodes.js +10 -259
  21. package/lib/markdown/index.js +11 -22
  22. package/lib/markdown/utils.d.ts +4 -0
  23. package/lib/openapi/createRequestExample.js +2 -2
  24. package/lib/openapi/createResponseExample.js +2 -2
  25. package/lib/openapi/openapi.js +16 -14
  26. package/lib/openapi/types.d.ts +4 -0
  27. package/lib/openapi/utils/services/OpenAPIParser.js +1 -1
  28. package/lib/options.js +5 -0
  29. package/lib/sidebars/index.js +32 -26
  30. package/lib/types.d.ts +9 -0
  31. package/package.json +7 -7
  32. package/src/index.ts +4 -0
  33. package/src/markdown/__snapshots__/createSchema.test.ts.snap +142 -0
  34. package/src/markdown/createCallbackMethodEndpoint.ts +19 -0
  35. package/src/markdown/createCallbacks.ts +2 -2
  36. package/src/markdown/createContactInfo.ts +1 -1
  37. package/src/markdown/createDeprecationNotice.ts +3 -2
  38. package/src/markdown/createMethodEndpoint.ts +8 -1
  39. package/src/markdown/createParamsDetails.ts +7 -42
  40. package/src/markdown/createRequestSchema.ts +9 -143
  41. package/src/markdown/createResponseSchema.ts +9 -112
  42. package/src/markdown/createSchema.test.ts +64 -0
  43. package/src/markdown/createSchema.ts +30 -50
  44. package/src/markdown/createStatusCodes.ts +9 -268
  45. package/src/markdown/index.ts +11 -22
  46. package/src/markdown/utils.ts +4 -0
  47. package/src/openapi/createRequestExample.ts +2 -5
  48. package/src/openapi/createResponseExample.ts +2 -5
  49. package/src/openapi/openapi.ts +4 -2
  50. package/src/openapi/types.ts +4 -0
  51. package/src/openapi/utils/loadAndResolveSpec.ts +1 -1
  52. package/src/openapi/utils/services/OpenAPIParser.ts +1 -0
  53. package/src/options.ts +6 -0
  54. package/src/sidebars/index.ts +47 -40
  55. package/src/types.ts +11 -0
@@ -5,15 +5,7 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import format from "xml-formatter";
9
-
10
- import { createDescription } from "./createDescription";
11
- import { createDetails } from "./createDetails";
12
- import { createDetailsSummary } from "./createDetailsSummary";
13
- import { createResponseSchema } from "./createResponseSchema";
14
8
  import { create } from "./utils";
15
- import { guard } from "./utils";
16
- import { sampleResponseFromSchema } from "../openapi/createResponseExample";
17
9
  import { ApiItem } from "../types";
18
10
 
19
11
  export default function json2xml(o: any, tab: any) {
@@ -59,264 +51,13 @@ interface Props {
59
51
  responses: ApiItem["responses"];
60
52
  }
61
53
 
62
- function createResponseHeaders(responseHeaders: any) {
63
- return guard(responseHeaders, () =>
64
- create("ul", {
65
- style: { marginLeft: "1rem" },
66
- children: [
67
- Object.entries(responseHeaders).map(
68
- ([headerName, headerObj]: [any, any]) => {
69
- const { description, example }: any = headerObj;
70
- const type = headerObj.schema?.type ?? "any";
71
-
72
- return create("li", {
73
- className: "schemaItem",
74
- children: [
75
- createDetailsSummary({
76
- children: [
77
- create("strong", { children: headerName }),
78
- guard(type, () => [
79
- create("span", {
80
- style: { opacity: "0.6" },
81
- children: ` ${type}`,
82
- }),
83
- ]),
84
- ],
85
- }),
86
- create("div", {
87
- children: [
88
- guard(description, (description) =>
89
- create("div", {
90
- style: {
91
- marginTop: ".5rem",
92
- marginBottom: ".5rem",
93
- },
94
- children: [
95
- guard(example, () => `Example: ${example}`),
96
- createDescription(description),
97
- ],
98
- })
99
- ),
100
- ],
101
- }),
102
- ],
103
- });
104
- }
105
- ),
106
- ],
107
- })
108
- );
109
- }
110
-
111
- export function createResponseExamples(
112
- responseExamples: any,
113
- mimeType: string
114
- ) {
115
- let language = "shell";
116
- if (mimeType.endsWith("json")) {
117
- language = "json";
118
- }
119
- if (mimeType.endsWith("xml")) {
120
- language = "xml";
121
- }
122
- return Object.entries(responseExamples).map(
123
- ([exampleName, exampleValue]: any) => {
124
- if (typeof exampleValue.value === "object") {
125
- return create("TabItem", {
126
- label: `${exampleName}`,
127
- value: `${exampleName}`,
128
- children: [
129
- guard(exampleValue.summary, (summary) => [
130
- create("div", {
131
- children: `${summary}`,
132
- className: "openapi-example__summary",
133
- }),
134
- ]),
135
- create("ResponseSamples", {
136
- responseExample: JSON.stringify(exampleValue.value, null, 2),
137
- language: language,
138
- }),
139
- ],
140
- });
141
- }
142
- return create("TabItem", {
143
- label: `${exampleName}`,
144
- value: `${exampleName}`,
145
- children: [
146
- guard(exampleValue.summary, (summary) => [
147
- create("div", {
148
- children: `${summary}`,
149
- className: "openapi-example__summary",
150
- }),
151
- ]),
152
- create("ResponseSamples", {
153
- responseExample: exampleValue.value,
154
- language: language,
155
- }),
156
- ],
157
- });
158
- }
159
- );
160
- }
161
-
162
- export function createResponseExample(responseExample: any, mimeType: string) {
163
- let language = "shell";
164
- if (mimeType.endsWith("json")) {
165
- language = "json";
166
- }
167
- if (mimeType.endsWith("xml")) {
168
- language = "xml";
169
- }
170
- if (typeof responseExample === "object") {
171
- return create("TabItem", {
172
- label: `Example`,
173
- value: `Example`,
174
- children: [
175
- guard(responseExample.summary, (summary) => [
176
- create("div", {
177
- children: `${summary}`,
178
- className: "openapi-example__summary",
179
- }),
180
- ]),
181
- create("ResponseSamples", {
182
- responseExample: JSON.stringify(responseExample, null, 2),
183
- language: language,
184
- }),
185
- ],
186
- });
187
- }
188
- return create("TabItem", {
189
- label: `Example`,
190
- value: `Example`,
191
- children: [
192
- guard(responseExample.summary, (summary) => [
193
- create("div", {
194
- children: `${summary}`,
195
- className: "openapi-example__summary",
196
- }),
197
- ]),
198
- create("ResponseSamples", {
199
- responseExample: responseExample,
200
- language: language,
201
- }),
202
- ],
203
- });
204
- }
205
-
206
- export function createExampleFromSchema(schema: any, mimeType: string) {
207
- const responseExample = sampleResponseFromSchema(schema);
208
- if (mimeType.endsWith("xml")) {
209
- let responseExampleObject;
210
- try {
211
- responseExampleObject = JSON.parse(JSON.stringify(responseExample));
212
- } catch {
213
- return undefined;
214
- }
215
-
216
- if (typeof responseExampleObject === "object") {
217
- let xmlExample;
218
- try {
219
- xmlExample = format(json2xml(responseExampleObject, ""), {
220
- indentation: " ",
221
- lineSeparator: "\n",
222
- collapseContent: true,
223
- });
224
- } catch {
225
- const xmlExampleWithRoot = { root: responseExampleObject };
226
- try {
227
- xmlExample = format(json2xml(xmlExampleWithRoot, ""), {
228
- indentation: " ",
229
- lineSeparator: "\n",
230
- collapseContent: true,
231
- });
232
- } catch {
233
- xmlExample = json2xml(responseExampleObject, "");
234
- }
235
- }
236
- return create("TabItem", {
237
- label: `Example (from schema)`,
238
- value: `Example (from schema)`,
239
- children: [
240
- create("ResponseSamples", {
241
- responseExample: xmlExample,
242
- language: "xml",
243
- }),
244
- ],
245
- });
246
- }
247
- }
248
- if (typeof responseExample === "object") {
249
- return create("TabItem", {
250
- label: `Example (from schema)`,
251
- value: `Example (from schema)`,
252
- children: [
253
- create("ResponseSamples", {
254
- responseExample: JSON.stringify(responseExample, null, 2),
255
- language: "json",
256
- }),
257
- ],
258
- });
259
- }
260
- return undefined;
261
- }
262
-
263
- export function createStatusCodes({ label, id, responses }: Props) {
264
- if (responses === undefined) {
265
- return undefined;
266
- }
267
-
268
- const codes = Object.keys(responses);
269
- if (codes.length === 0) {
270
- return undefined;
271
- }
272
-
273
- return create("div", {
274
- children: [
275
- create("div", {
276
- children: [
277
- create("ApiTabs", {
278
- label,
279
- id,
280
- children: codes.map((code) => {
281
- const responseHeaders: any = responses[code].headers;
282
- return create("TabItem", {
283
- label: code,
284
- value: code,
285
- children: [
286
- create("div", {
287
- children: createDescription(responses[code].description),
288
- }),
289
- responseHeaders &&
290
- createDetails({
291
- className: "openapi-markdown__details",
292
- "data-collapsed": true,
293
- open: false,
294
- style: { textAlign: "left", marginBottom: "1rem" },
295
- children: [
296
- createDetailsSummary({
297
- children: [
298
- create("strong", {
299
- children: "Response Headers",
300
- }),
301
- ],
302
- }),
303
- createResponseHeaders(responseHeaders),
304
- ],
305
- }),
306
- create("div", {
307
- children: createResponseSchema({
308
- title: "Schema",
309
- body: {
310
- content: responses[code].content,
311
- },
312
- }),
313
- }),
314
- ],
315
- });
316
- }),
317
- }),
318
- ],
319
- }),
320
- ],
321
- });
54
+ export function createStatusCodes({ id, label, responses }: Props) {
55
+ return [
56
+ create("StatusCodes", {
57
+ id: id,
58
+ label: label,
59
+ responses: responses,
60
+ }),
61
+ "\n\n",
62
+ ];
322
63
  }
@@ -19,7 +19,6 @@ import { createMethodEndpoint } from "./createMethodEndpoint";
19
19
  import { createParamsDetails } from "./createParamsDetails";
20
20
  import { createRequestBodyDetails } from "./createRequestBodyDetails";
21
21
  import { createRequestHeader } from "./createRequestHeader";
22
- import { createNodes } from "./createSchema";
23
22
  import { createStatusCodes } from "./createStatusCodes";
24
23
  import { createTermsOfService } from "./createTermsOfService";
25
24
  import { createVendorExtensions } from "./createVendorExtensions";
@@ -67,18 +66,13 @@ export function createApiPageMD({
67
66
  frontMatter,
68
67
  }: ApiPageMetadata) {
69
68
  return render([
70
- `import ApiTabs from "@theme/ApiTabs";\n`,
71
- `import DiscriminatorTabs from "@theme/DiscriminatorTabs";\n`,
72
69
  `import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint";\n`,
73
- `import SecuritySchemes from "@theme/ApiExplorer/SecuritySchemes";\n`,
74
- `import MimeTabs from "@theme/MimeTabs";\n`,
75
- `import ParamsItem from "@theme/ParamsItem";\n`,
76
- `import ResponseSamples from "@theme/ResponseSamples";\n`,
77
- `import SchemaItem from "@theme/SchemaItem";\n`,
78
- `import SchemaTabs from "@theme/SchemaTabs";\n`,
79
- `import Heading from "@theme/Heading";\n`,
70
+ `import ParamsDetails from "@theme/ParamsDetails";\n`,
71
+ `import RequestSchema from "@theme/RequestSchema";\n`,
72
+ `import StatusCodes from "@theme/StatusCodes";\n`,
80
73
  `import OperationTabs from "@theme/OperationTabs";\n`,
81
- `import TabItem from "@theme/TabItem";\n\n`,
74
+ `import TabItem from "@theme/TabItem";\n`,
75
+ `import Heading from "@theme/Heading";\n\n`,
82
76
  createHeading(title),
83
77
  createMethodEndpoint(method, path),
84
78
  infoPath && createAuthorization(infoPath),
@@ -88,10 +82,7 @@ export function createApiPageMD({
88
82
  createDeprecationNotice({ deprecated, description: deprecatedDescription }),
89
83
  createDescription(description),
90
84
  requestBody || parameters ? createRequestHeader("Request") : undefined,
91
- createParamsDetails({ parameters, type: "path" }),
92
- createParamsDetails({ parameters, type: "query" }),
93
- createParamsDetails({ parameters, type: "header" }),
94
- createParamsDetails({ parameters, type: "cookie" }),
85
+ createParamsDetails({ parameters }),
95
86
  createRequestBodyDetails({
96
87
  title: "Body",
97
88
  body: requestBody,
@@ -141,15 +132,13 @@ export function createTagPageMD({ tag: { description } }: TagPageMetadata) {
141
132
  export function createSchemaPageMD({ schema }: SchemaPageMetadata) {
142
133
  const { title = "", description } = schema;
143
134
  return render([
144
- `import DiscriminatorTabs from "@theme/DiscriminatorTabs";\n`,
145
- `import SchemaItem from "@theme/SchemaItem";\n`,
146
- `import SchemaTabs from "@theme/SchemaTabs";\n`,
147
- `import Heading from "@theme/Heading";\n`,
148
- `import TabItem from "@theme/TabItem";\n\n`,
135
+ `import Schema from "@theme/Schema";\n`,
136
+ `import Heading from "@theme/Heading";\n\n`,
149
137
  createHeading(title.replace(lessThan, "<").replace(greaterThan, ">")),
150
138
  createDescription(description),
151
- create("ul", {
152
- children: createNodes(schema, "response"),
139
+ create("Schema", {
140
+ schema: schema,
141
+ schemaType: "response",
153
142
  }),
154
143
  ]);
155
144
  }
@@ -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 };
@@ -66,9 +66,7 @@ function sampleRequestFromProp(name: string, prop: any, obj: any): any {
66
66
  } else if (prop.anyOf) {
67
67
  obj[name] = sampleRequestFromSchema(prop.anyOf[0]);
68
68
  } else if (prop.allOf) {
69
- const { mergedSchemas }: { mergedSchemas: SchemaObject } = mergeAllOf(
70
- prop.allOf
71
- );
69
+ const mergedSchemas = mergeAllOf(prop) as SchemaObject;
72
70
  sampleRequestFromProp(name, mergedSchemas, obj);
73
71
  } else {
74
72
  obj[name] = sampleRequestFromSchema(prop);
@@ -107,8 +105,7 @@ export const sampleRequestFromSchema = (schema: SchemaObject = {}): any => {
107
105
  }
108
106
 
109
107
  if (allOf) {
110
- const { mergedSchemas }: { mergedSchemas: SchemaObject } =
111
- mergeAllOf(allOf);
108
+ const mergedSchemas = mergeAllOf(schemaCopy) as SchemaObject;
112
109
  if (mergedSchemas.properties) {
113
110
  for (const [key, value] of Object.entries(mergedSchemas.properties)) {
114
111
  if ((value.readOnly && value.readOnly === true) || value.deprecated) {
@@ -66,9 +66,7 @@ function sampleResponseFromProp(name: string, prop: any, obj: any): any {
66
66
  } else if (prop.anyOf) {
67
67
  obj[name] = sampleResponseFromSchema(prop.anyOf[0]);
68
68
  } else if (prop.allOf) {
69
- const { mergedSchemas }: { mergedSchemas: SchemaObject } = mergeAllOf(
70
- prop.allOf
71
- );
69
+ const mergedSchemas = mergeAllOf(prop) as SchemaObject;
72
70
  sampleResponseFromProp(name, mergedSchemas, obj);
73
71
  } else {
74
72
  obj[name] = sampleResponseFromSchema(prop);
@@ -87,8 +85,7 @@ export const sampleResponseFromSchema = (schema: SchemaObject = {}): any => {
87
85
  }
88
86
 
89
87
  if (allOf) {
90
- const { mergedSchemas }: { mergedSchemas: SchemaObject } =
91
- mergeAllOf(allOf);
88
+ const mergedSchemas = mergeAllOf(schemaCopy) as SchemaObject;
92
89
  if (mergedSchemas.properties) {
93
90
  for (const [key, value] of Object.entries(mergedSchemas.properties)) {
94
91
  if (
@@ -20,7 +20,6 @@ import sdk from "postman-collection";
20
20
 
21
21
  import { sampleRequestFromSchema } from "./createRequestExample";
22
22
  import { OpenApiObject, TagGroupObject, TagObject } from "./types";
23
- import { loadAndResolveSpec } from "./utils/loadAndResolveSpec";
24
23
  import { isURL } from "../index";
25
24
  import {
26
25
  ApiMetadata,
@@ -31,6 +30,8 @@ import {
31
30
  SidebarOptions,
32
31
  TagPageMetadata,
33
32
  } from "../types";
33
+ import { sampleResponseFromSchema } from "./createResponseExample";
34
+ import { loadAndResolveSpec } from "./utils/loadAndResolveSpec";
34
35
 
35
36
  /**
36
37
  * Convenience function for converting raw JSON to a Postman Collection object.
@@ -269,7 +270,7 @@ function createItems(
269
270
 
270
271
  // Gather x-webhooks endpoints
271
272
  for (let [path, pathObject] of Object.entries(
272
- openapiData["x-webhooks"] ?? {}
273
+ openapiData["x-webhooks"] ?? openapiData["webhooks"] ?? {}
273
274
  )) {
274
275
  path = "webhook";
275
276
  const { $ref, description, parameters, servers, summary, ...rest } =
@@ -451,6 +452,7 @@ function createItems(
451
452
  .replace(/((?:^|[^\\])(?:\\{2})*)"/g, "$1'")
452
453
  .replace(/\s+$/, "")
453
454
  : "",
455
+ sample: JSON.stringify(sampleResponseFromSchema(schemaObject)),
454
456
  },
455
457
  schema: schemaObject,
456
458
  };
@@ -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 {
@@ -236,6 +238,7 @@ export interface MediaTypeObject {
236
238
  example?: any;
237
239
  examples?: Map<ExampleObject>;
238
240
  encoding?: Map<EncodingObject>;
241
+ type?: any;
239
242
  }
240
243
 
241
244
  export interface MediaTypeObjectWithRef {
@@ -353,6 +356,7 @@ export type SchemaObject = Omit<
353
356
  example?: any;
354
357
  deprecated?: boolean;
355
358
  "x-tags"?: string[];
359
+ "x-enumDescriptions"?: Record<string, string>;
356
360
  };
357
361
 
358
362
  export type SchemaObjectWithRef = Omit<
@@ -13,8 +13,8 @@ import chalk from "chalk";
13
13
  // @ts-ignore
14
14
  import { convertObj } from "swagger2openapi";
15
15
 
16
- import { OpenAPIParser } from "./services/OpenAPIParser";
17
16
  import { OpenApiObject } from "../types";
17
+ import { OpenAPIParser } from "./services/OpenAPIParser";
18
18
 
19
19
  function serializer(replacer: any, cycleReplacer: any) {
20
20
  var stack: any = [],
@@ -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,18 +7,24 @@
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({
19
24
  createApiPageMD: Joi.function(),
20
25
  createInfoPageMD: Joi.function(),
21
26
  createTagPageMD: Joi.function(),
27
+ createSchemaPageMD: Joi.function(),
22
28
  });
23
29
 
24
30
  export const OptionsSchema = 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
  }