docusaurus-plugin-openapi-docs 3.0.0-beta.4 → 3.0.0-beta.6

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 (40) hide show
  1. package/README.md +2 -0
  2. package/lib/index.js +62 -9
  3. package/lib/markdown/createAuthentication.js +4 -3
  4. package/lib/markdown/createCallbacks.d.ts +6 -0
  5. package/lib/markdown/createCallbacks.js +78 -0
  6. package/lib/markdown/createHeading.js +4 -3
  7. package/lib/markdown/createRequestBodyDetails.d.ts +1 -1
  8. package/lib/markdown/createRequestHeader.d.ts +1 -1
  9. package/lib/markdown/createRequestHeader.js +10 -1
  10. package/lib/markdown/createStatusCodes.d.ts +3 -1
  11. package/lib/markdown/createStatusCodes.js +7 -5
  12. package/lib/markdown/index.d.ts +3 -2
  13. package/lib/markdown/index.js +29 -4
  14. package/lib/markdown/utils.d.ts +4 -1
  15. package/lib/markdown/utils.js +6 -2
  16. package/lib/openapi/openapi.d.ts +3 -3
  17. package/lib/openapi/openapi.js +59 -6
  18. package/lib/openapi/openapi.test.js +2 -0
  19. package/lib/openapi/types.d.ts +5 -0
  20. package/lib/options.js +2 -1
  21. package/lib/sidebars/index.d.ts +2 -2
  22. package/lib/sidebars/index.js +50 -10
  23. package/lib/types.d.ts +15 -2
  24. package/package.json +2 -2
  25. package/src/index.ts +114 -11
  26. package/src/markdown/createAuthentication.ts +10 -5
  27. package/src/markdown/createCallbacks.ts +101 -0
  28. package/src/markdown/createHeading.ts +9 -4
  29. package/src/markdown/createRequestBodyDetails.ts +1 -1
  30. package/src/markdown/createRequestHeader.ts +15 -1
  31. package/src/markdown/createStatusCodes.ts +9 -5
  32. package/src/markdown/index.ts +37 -6
  33. package/src/markdown/utils.ts +14 -3
  34. package/src/openapi/__fixtures__/examples/openapi.yaml +29 -0
  35. package/src/openapi/openapi.test.ts +3 -0
  36. package/src/openapi/openapi.ts +75 -7
  37. package/src/openapi/types.ts +6 -0
  38. package/src/options.ts +2 -1
  39. package/src/sidebars/index.ts +70 -16
  40. package/src/types.ts +21 -1
package/README.md CHANGED
@@ -31,6 +31,7 @@ Key Features:
31
31
 
32
32
  | Docusaurus OpenAPI Docs | Docusaurus |
33
33
  | ----------------------- | --------------- |
34
+ | 3.0.0-beta.x (beta) | `3.0.1 - 3.1.1` |
34
35
  | 2.0.x (current) | `2.4.1 - 2.4.3` |
35
36
  | 1.7.3 (legacy) | `2.0.1 - 2.2.0` |
36
37
 
@@ -159,6 +160,7 @@ The `docusaurus-plugin-openapi-docs` plugin can be configured with the following
159
160
  | `baseUrl` | `string` | `null` | _Optional:_ Version base URL used when generating version selector dropdown menu. |
160
161
  | `versions` | `object` | `null` | _Optional:_ Set of options for versioning configuration. See below for a list of supported options. |
161
162
  | `markdownGenerators` | `object` | `null` | _Optional:_ Customize MDX content with a set of options for specifying markdown generator functions. See below for a list of supported options. |
163
+ | `showSchemas` | `boolean` | `null` | _Optional:_ If set to `true`, generates schema pages and adds them to the sidebar. |
162
164
 
163
165
  `sidebarOptions` can be configured with the following options:
164
166
 
package/lib/index.js CHANGED
@@ -78,7 +78,7 @@ function pluginOpenAPIDocs(context, options) {
78
78
  let docRouteBasePath = docData ? docData.routeBasePath : undefined;
79
79
  let docPath = docData ? (docData.path ? docData.path : "docs") : undefined;
80
80
  async function generateApiDocs(options, pluginId) {
81
- var _a, _b, _c;
81
+ var _a, _b, _c, _d;
82
82
  let { specPath, outputDir, template, markdownGenerators, downloadUrl, sidebarOptions, } = options;
83
83
  // Remove trailing slash before proceeding
84
84
  outputDir = outputDir.replace(/\/$/, "");
@@ -93,7 +93,7 @@ function pluginOpenAPIDocs(context, options) {
93
93
  : path_1.default.resolve(siteDir, specPath);
94
94
  try {
95
95
  const openapiFiles = await (0, openapi_1.readOpenapiFiles)(contentPath);
96
- const [loadedApi, tags] = await (0, openapi_1.processOpenapiFiles)(openapiFiles, options, sidebarOptions);
96
+ const [loadedApi, tags, tagGroups] = await (0, openapi_1.processOpenapiFiles)(openapiFiles, options, sidebarOptions);
97
97
  if (!fs_1.default.existsSync(outputDir)) {
98
98
  try {
99
99
  fs_1.default.mkdirSync(outputDir, { recursive: true });
@@ -105,7 +105,7 @@ function pluginOpenAPIDocs(context, options) {
105
105
  }
106
106
  // TODO: figure out better way to set default
107
107
  if (Object.keys(sidebarOptions !== null && sidebarOptions !== void 0 ? sidebarOptions : {}).length > 0) {
108
- const sidebarSlice = (0, sidebars_1.default)(sidebarOptions, options, loadedApi, tags, docPath);
108
+ const sidebarSlice = (0, sidebars_1.default)(sidebarOptions, options, loadedApi, tags, docPath, tagGroups);
109
109
  let sidebarSliceTemplate = `import type { SidebarsConfig } from "@docusaurus/plugin-content-docs";\n\n`;
110
110
  sidebarSliceTemplate += `const sidebar: SidebarsConfig = {{{slice}}};\n\n`;
111
111
  sidebarSliceTemplate += `export default sidebar.apisidebar;\n`;
@@ -198,20 +198,35 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
198
198
  <DocCardList items={useCurrentSidebarCategory().items}/>
199
199
  \`\`\`
200
200
  `;
201
+ const schemaMdTemplate = `---
202
+ id: {{{id}}}
203
+ title: "{{{title}}}"
204
+ description: "{{{frontMatter.description}}}"
205
+ sidebar_label: "{{{title}}}"
206
+ hide_title: true
207
+ schema: true
208
+ custom_edit_url: null
209
+ ---
210
+
211
+ {{{markdown}}}
212
+ `;
201
213
  const apiPageGenerator = (_a = markdownGenerators === null || markdownGenerators === void 0 ? void 0 : markdownGenerators.createApiPageMD) !== null && _a !== void 0 ? _a : markdown_1.createApiPageMD;
202
214
  const infoPageGenerator = (_b = markdownGenerators === null || markdownGenerators === void 0 ? void 0 : markdownGenerators.createInfoPageMD) !== null && _b !== void 0 ? _b : markdown_1.createInfoPageMD;
203
215
  const tagPageGenerator = (_c = markdownGenerators === null || markdownGenerators === void 0 ? void 0 : markdownGenerators.createTagPageMD) !== null && _c !== void 0 ? _c : markdown_1.createTagPageMD;
216
+ const schemaPageGenerator = (_d = markdownGenerators === null || markdownGenerators === void 0 ? void 0 : markdownGenerators.createSchemaPageMD) !== null && _d !== void 0 ? _d : markdown_1.createSchemaPageMD;
217
+ const pageGeneratorByType = {
218
+ api: apiPageGenerator,
219
+ info: infoPageGenerator,
220
+ tag: tagPageGenerator,
221
+ schema: schemaPageGenerator,
222
+ };
204
223
  loadedApi.map(async (item) => {
205
224
  if (item.type === "info") {
206
225
  if (downloadUrl && isURL(downloadUrl)) {
207
226
  item.downloadUrl = downloadUrl;
208
227
  }
209
228
  }
210
- const markdown = item.type === "api"
211
- ? apiPageGenerator(item)
212
- : item.type === "info"
213
- ? infoPageGenerator(item)
214
- : tagPageGenerator(item);
229
+ const markdown = pageGeneratorByType[item.type](item);
215
230
  item.markdown = markdown;
216
231
  if (item.type === "api") {
217
232
  // opportunity to compress JSON
@@ -277,6 +292,32 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
277
292
  }
278
293
  }
279
294
  }
295
+ if (item.type === "schema") {
296
+ if (!fs_1.default.existsSync(`${outputDir}/schemas/${item.id}.schema.mdx`)) {
297
+ if (!fs_1.default.existsSync(`${outputDir}/schemas`)) {
298
+ try {
299
+ fs_1.default.mkdirSync(`${outputDir}/schemas`, { recursive: true });
300
+ console.log(chalk_1.default.green(`Successfully created "${outputDir}/schemas"`));
301
+ }
302
+ catch (err) {
303
+ console.error(chalk_1.default.red(`Failed to create "${outputDir}/schemas"`), chalk_1.default.yellow(err));
304
+ }
305
+ }
306
+ try {
307
+ // kebabCase(arg) returns 0-length string when arg is undefined
308
+ if (item.id.length === 0) {
309
+ throw Error("Schema must have title defined");
310
+ }
311
+ // eslint-disable-next-line testing-library/render-result-naming-convention
312
+ const schemaView = (0, mustache_1.render)(schemaMdTemplate, item);
313
+ fs_1.default.writeFileSync(`${outputDir}/schemas/${item.id}.schema.mdx`, schemaView, "utf8");
314
+ console.log(chalk_1.default.green(`Successfully created "${outputDir}/${item.id}.schema.mdx"`));
315
+ }
316
+ catch (err) {
317
+ console.error(chalk_1.default.red(`Failed to write "${outputDir}/${item.id}.schema.mdx"`), chalk_1.default.yellow(err));
318
+ }
319
+ }
320
+ }
280
321
  return;
281
322
  });
282
323
  return;
@@ -293,7 +334,11 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
293
334
  cwd: path_1.default.resolve(apiDir),
294
335
  deep: 1,
295
336
  });
296
- const sidebarFile = await (0, utils_1.Globby)(["sidebar.ts"], {
337
+ const schemaMdxFiles = await (0, utils_1.Globby)(["*.schema.mdx"], {
338
+ cwd: path_1.default.resolve(apiDir, "schemas"),
339
+ deep: 1,
340
+ });
341
+ const sidebarFile = await (0, utils_1.Globby)(["sidebar.js"], {
297
342
  cwd: path_1.default.resolve(apiDir),
298
343
  deep: 1,
299
344
  });
@@ -305,6 +350,14 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
305
350
  console.log(chalk_1.default.green(`Cleanup succeeded for "${apiDir}/${mdx}"`));
306
351
  }
307
352
  }));
353
+ schemaMdxFiles.map((mdx) => fs_1.default.unlink(`${apiDir}/schemas/${mdx}`, (err) => {
354
+ if (err) {
355
+ console.error(chalk_1.default.red(`Cleanup failed for "${apiDir}/schemas/${mdx}"`), chalk_1.default.yellow(err));
356
+ }
357
+ else {
358
+ console.log(chalk_1.default.green(`Cleanup succeeded for "${apiDir}/schemas/${mdx}"`));
359
+ }
360
+ }));
308
361
  sidebarFile.map((sidebar) => fs_1.default.unlink(`${apiDir}/${sidebar}`, (err) => {
309
362
  if (err) {
310
363
  console.error(chalk_1.default.red(`Cleanup failed for "${apiDir}/${sidebar}"`), chalk_1.default.yellow(err));
@@ -148,11 +148,12 @@ function createAuthentication(securitySchemes) {
148
148
  };
149
149
  return (0, utils_1.create)("div", {
150
150
  children: [
151
- (0, utils_1.create)("h2", {
151
+ (0, utils_1.create)("Heading", {
152
152
  children: "Authentication",
153
153
  id: "authentication",
154
- style: { marginBottom: "1rem" },
155
- }),
154
+ as: "h2",
155
+ className: "openapi-tabs__heading",
156
+ }, { inline: true }),
156
157
  (0, utils_1.create)("SchemaTabs", {
157
158
  className: "openapi-tabs__security-schemes",
158
159
  children: Object.entries(securitySchemes).map(([schemeKey, schemeObj]) => (0, utils_1.create)("TabItem", {
@@ -0,0 +1,6 @@
1
+ import { ApiItem } from "../types";
2
+ interface Props {
3
+ callbacks: ApiItem["callbacks"];
4
+ }
5
+ export declare function createCallbacks({ callbacks }: Props): string | undefined;
6
+ export {};
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ /* ============================================================================
3
+ * Copyright (c) Palo Alto Networks
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ * ========================================================================== */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.createCallbacks = void 0;
10
+ const createDescription_1 = require("./createDescription");
11
+ const createMethodEndpoint_1 = require("./createMethodEndpoint");
12
+ const createRequestBodyDetails_1 = require("./createRequestBodyDetails");
13
+ const createStatusCodes_1 = require("./createStatusCodes");
14
+ const utils_1 = require("./utils");
15
+ function createCallbacks({ callbacks }) {
16
+ if (callbacks === undefined) {
17
+ return undefined;
18
+ }
19
+ const callbacksNames = Object.keys(callbacks);
20
+ if (callbacksNames.length === 0) {
21
+ return undefined;
22
+ }
23
+ return (0, utils_1.create)("div", {
24
+ children: [
25
+ (0, utils_1.create)("div", {
26
+ className: "openapi__divider",
27
+ }),
28
+ (0, utils_1.create)("Heading", {
29
+ children: "Callbacks",
30
+ id: "callbacks",
31
+ as: "h2",
32
+ className: "openapi-tabs__heading",
33
+ }, { inline: true }),
34
+ (0, utils_1.create)("OperationTabs", {
35
+ className: "openapi-tabs__operation",
36
+ children: callbacksNames.flatMap((name) => {
37
+ const path = Object.keys(callbacks[name])[0];
38
+ const methods = new Map([
39
+ ["delete", callbacks[name][path].delete],
40
+ ["get", callbacks[name][path].get],
41
+ ["head", callbacks[name][path].head],
42
+ ["options", callbacks[name][path].options],
43
+ ["patch", callbacks[name][path].patch],
44
+ ["post", callbacks[name][path].post],
45
+ ["put", callbacks[name][path].put],
46
+ ["trace", callbacks[name][path].trace],
47
+ ]);
48
+ return Array.from(methods).flatMap(([method, operationObject]) => {
49
+ if (!operationObject)
50
+ return [];
51
+ const { description, requestBody, responses } = operationObject;
52
+ return [
53
+ (0, utils_1.create)("TabItem", {
54
+ label: `${method.toUpperCase()} ${name}`,
55
+ value: `${method}-${name}`,
56
+ children: [
57
+ (0, createMethodEndpoint_1.createMethodEndpoint)(method, path),
58
+ // TODO: add `deprecation notice` when markdown support is added
59
+ (0, createDescription_1.createDescription)(description),
60
+ (0, createRequestBodyDetails_1.createRequestBodyDetails)({
61
+ title: "Body",
62
+ body: requestBody,
63
+ }),
64
+ (0, createStatusCodes_1.createStatusCodes)({
65
+ id: "callbacks-responses",
66
+ label: "Callbacks Responses",
67
+ responses,
68
+ }),
69
+ ],
70
+ }),
71
+ ];
72
+ });
73
+ }),
74
+ }),
75
+ ],
76
+ });
77
+ }
78
+ exports.createCallbacks = createCallbacks;
@@ -10,10 +10,11 @@ exports.createHeading = void 0;
10
10
  const utils_1 = require("./utils");
11
11
  function createHeading(heading) {
12
12
  return [
13
- (0, utils_1.create)("h1", {
14
- className: "openapi__heading",
13
+ (0, utils_1.create)("Heading", {
15
14
  children: (0, utils_1.clean)(heading),
16
- }),
15
+ as: "h1",
16
+ className: "openapi__heading",
17
+ }, { inline: true }),
17
18
  `\n\n`,
18
19
  ];
19
20
  }
@@ -9,5 +9,5 @@ interface Props {
9
9
  required?: boolean;
10
10
  };
11
11
  }
12
- export declare function createRequestBodyDetails({ title, body }: Props): any;
12
+ export declare function createRequestBodyDetails({ title, body }: Props): string | undefined;
13
13
  export {};
@@ -1 +1 @@
1
- export declare function createRequestHeader(header: string): string;
1
+ export declare function createRequestHeader(header: string): string[];
@@ -7,7 +7,16 @@
7
7
  * ========================================================================== */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.createRequestHeader = void 0;
10
+ const utils_1 = require("./utils");
10
11
  function createRequestHeader(header) {
11
- return `## ${header}\n\n`;
12
+ return [
13
+ (0, utils_1.create)("Heading", {
14
+ children: header,
15
+ id: header.replace(" ", "-").toLowerCase(),
16
+ as: "h2",
17
+ className: "openapi-tabs__heading",
18
+ }, { inline: true }),
19
+ `\n\n`,
20
+ ];
12
21
  }
13
22
  exports.createRequestHeader = createRequestHeader;
@@ -1,10 +1,12 @@
1
1
  import { ApiItem } from "../types";
2
2
  export default function json2xml(o: any, tab: any): string;
3
3
  interface Props {
4
+ id?: string;
5
+ label?: string;
4
6
  responses: ApiItem["responses"];
5
7
  }
6
8
  export declare function createResponseExamples(responseExamples: any, mimeType: string): string[];
7
9
  export declare function createResponseExample(responseExample: any, mimeType: string): string;
8
10
  export declare function createExampleFromSchema(schema: any, mimeType: string): string | undefined;
9
- export declare function createStatusCodes({ responses }: Props): string | undefined;
11
+ export declare function createStatusCodes({ label, id, responses }: Props): string | undefined;
10
12
  export {};
@@ -118,7 +118,7 @@ function createResponseExamples(responseExamples, mimeType) {
118
118
  value: `${exampleName}`,
119
119
  children: [
120
120
  (0, utils_2.guard)(exampleValue.summary, (summary) => [
121
- (0, utils_1.create)("p", {
121
+ (0, utils_1.create)("Markdown", {
122
122
  children: ` ${summary}`,
123
123
  }),
124
124
  ]),
@@ -134,7 +134,7 @@ function createResponseExamples(responseExamples, mimeType) {
134
134
  value: `${exampleName}`,
135
135
  children: [
136
136
  (0, utils_2.guard)(exampleValue.summary, (summary) => [
137
- (0, utils_1.create)("p", {
137
+ (0, utils_1.create)("Markdown", {
138
138
  children: ` ${summary}`,
139
139
  }),
140
140
  ]),
@@ -161,7 +161,7 @@ function createResponseExample(responseExample, mimeType) {
161
161
  value: `Example`,
162
162
  children: [
163
163
  (0, utils_2.guard)(responseExample.summary, (summary) => [
164
- (0, utils_1.create)("p", {
164
+ (0, utils_1.create)("Markdown", {
165
165
  children: ` ${summary}`,
166
166
  }),
167
167
  ]),
@@ -177,7 +177,7 @@ function createResponseExample(responseExample, mimeType) {
177
177
  value: `Example`,
178
178
  children: [
179
179
  (0, utils_2.guard)(responseExample.summary, (summary) => [
180
- (0, utils_1.create)("p", {
180
+ (0, utils_1.create)("Markdown", {
181
181
  children: ` ${summary}`,
182
182
  }),
183
183
  ]),
@@ -248,7 +248,7 @@ function createExampleFromSchema(schema, mimeType) {
248
248
  return undefined;
249
249
  }
250
250
  exports.createExampleFromSchema = createExampleFromSchema;
251
- function createStatusCodes({ responses }) {
251
+ function createStatusCodes({ label, id, responses }) {
252
252
  if (responses === undefined) {
253
253
  return undefined;
254
254
  }
@@ -261,6 +261,8 @@ function createStatusCodes({ responses }) {
261
261
  (0, utils_1.create)("div", {
262
262
  children: [
263
263
  (0, utils_1.create)("ApiTabs", {
264
+ label,
265
+ id,
264
266
  children: codes.map((code) => {
265
267
  const responseHeaders = responses[code].headers;
266
268
  return (0, utils_1.create)("TabItem", {
@@ -1,4 +1,5 @@
1
- import { ApiPageMetadata, InfoPageMetadata, TagPageMetadata } from "../types";
2
- export declare function createApiPageMD({ title, api: { deprecated, "x-deprecated-description": deprecatedDescription, description, method, path, extensions, parameters, requestBody, responses, }, infoPath, frontMatter, }: ApiPageMetadata): string;
1
+ import { ApiPageMetadata, InfoPageMetadata, SchemaPageMetadata, TagPageMetadata } from "../types";
2
+ export declare function createApiPageMD({ title, api: { deprecated, "x-deprecated-description": deprecatedDescription, description, method, path, extensions, parameters, requestBody, responses, callbacks, }, infoPath, frontMatter, }: ApiPageMetadata): string;
3
3
  export declare function createInfoPageMD({ info: { title, version, description, contact, license, termsOfService, logo, darkLogo, }, securitySchemes, downloadUrl, }: InfoPageMetadata): string;
4
4
  export declare function createTagPageMD({ tag: { description } }: TagPageMetadata): string;
5
+ export declare function createSchemaPageMD({ schema }: SchemaPageMetadata): string;
@@ -6,9 +6,10 @@
6
6
  * LICENSE file in the root directory of this source tree.
7
7
  * ========================================================================== */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.createTagPageMD = exports.createInfoPageMD = exports.createApiPageMD = void 0;
9
+ exports.createSchemaPageMD = exports.createTagPageMD = exports.createInfoPageMD = exports.createApiPageMD = void 0;
10
10
  const createAuthentication_1 = require("./createAuthentication");
11
11
  const createAuthorization_1 = require("./createAuthorization");
12
+ const createCallbacks_1 = require("./createCallbacks");
12
13
  const createContactInfo_1 = require("./createContactInfo");
13
14
  const createDeprecationNotice_1 = require("./createDeprecationNotice");
14
15
  const createDescription_1 = require("./createDescription");
@@ -20,12 +21,13 @@ const createMethodEndpoint_1 = require("./createMethodEndpoint");
20
21
  const createParamsDetails_1 = require("./createParamsDetails");
21
22
  const createRequestBodyDetails_1 = require("./createRequestBodyDetails");
22
23
  const createRequestHeader_1 = require("./createRequestHeader");
24
+ const createSchema_1 = require("./createSchema");
23
25
  const createStatusCodes_1 = require("./createStatusCodes");
24
26
  const createTermsOfService_1 = require("./createTermsOfService");
25
27
  const createVendorExtensions_1 = require("./createVendorExtensions");
26
28
  const createVersionBadge_1 = require("./createVersionBadge");
27
29
  const utils_1 = require("./utils");
28
- function createApiPageMD({ title, api: { deprecated, "x-deprecated-description": deprecatedDescription, description, method, path, extensions, parameters, requestBody, responses, }, infoPath, frontMatter, }) {
30
+ function createApiPageMD({ title, api: { deprecated, "x-deprecated-description": deprecatedDescription, description, method, path, extensions, parameters, requestBody, responses, callbacks, }, infoPath, frontMatter, }) {
29
31
  return (0, utils_1.render)([
30
32
  `import ApiTabs from "@theme/ApiTabs";\n`,
31
33
  `import DiscriminatorTabs from "@theme/DiscriminatorTabs";\n`,
@@ -36,14 +38,19 @@ function createApiPageMD({ title, api: { deprecated, "x-deprecated-description":
36
38
  `import ResponseSamples from "@theme/ResponseSamples";\n`,
37
39
  `import SchemaItem from "@theme/SchemaItem";\n`,
38
40
  `import SchemaTabs from "@theme/SchemaTabs";\n`,
41
+ `import Markdown from "@theme/Markdown";\n`,
42
+ `import Heading from "@theme/Heading";\n`,
43
+ `import OperationTabs from "@theme/OperationTabs";\n`,
39
44
  `import TabItem from "@theme/TabItem";\n\n`,
40
45
  (0, createHeading_1.createHeading)(title),
41
46
  (0, createMethodEndpoint_1.createMethodEndpoint)(method, path),
42
47
  infoPath && (0, createAuthorization_1.createAuthorization)(infoPath),
43
- frontMatter.show_extensions && (0, createVendorExtensions_1.createVendorExtensions)(extensions),
48
+ frontMatter.show_extensions
49
+ ? (0, createVendorExtensions_1.createVendorExtensions)(extensions)
50
+ : undefined,
44
51
  (0, createDeprecationNotice_1.createDeprecationNotice)({ deprecated, description: deprecatedDescription }),
45
52
  (0, createDescription_1.createDescription)(description),
46
- (0, createRequestHeader_1.createRequestHeader)("Request"),
53
+ requestBody || parameters ? (0, createRequestHeader_1.createRequestHeader)("Request") : undefined,
47
54
  (0, createParamsDetails_1.createParamsDetails)({ parameters, type: "path" }),
48
55
  (0, createParamsDetails_1.createParamsDetails)({ parameters, type: "query" }),
49
56
  (0, createParamsDetails_1.createParamsDetails)({ parameters, type: "header" }),
@@ -53,12 +60,14 @@ function createApiPageMD({ title, api: { deprecated, "x-deprecated-description":
53
60
  body: requestBody,
54
61
  }),
55
62
  (0, createStatusCodes_1.createStatusCodes)({ responses }),
63
+ (0, createCallbacks_1.createCallbacks)({ callbacks }),
56
64
  ]);
57
65
  }
58
66
  exports.createApiPageMD = createApiPageMD;
59
67
  function createInfoPageMD({ info: { title, version, description, contact, license, termsOfService, logo, darkLogo, }, securitySchemes, downloadUrl, }) {
60
68
  return (0, utils_1.render)([
61
69
  `import ApiLogo from "@theme/ApiLogo";\n`,
70
+ `import Heading from "@theme/Heading";\n`,
62
71
  `import SchemaTabs from "@theme/SchemaTabs";\n`,
63
72
  `import TabItem from "@theme/TabItem";\n`,
64
73
  `import Export from "@theme/ApiExplorer/Export";\n\n`,
@@ -78,3 +87,19 @@ function createTagPageMD({ tag: { description } }) {
78
87
  return (0, utils_1.render)([(0, createDescription_1.createDescription)(description)]);
79
88
  }
80
89
  exports.createTagPageMD = createTagPageMD;
90
+ function createSchemaPageMD({ schema }) {
91
+ const { title = "", description } = schema;
92
+ return (0, utils_1.render)([
93
+ `import DiscriminatorTabs from "@theme/DiscriminatorTabs";\n`,
94
+ `import SchemaItem from "@theme/SchemaItem";\n`,
95
+ `import SchemaTabs from "@theme/SchemaTabs";\n`,
96
+ `import Heading from "@theme/Heading";\n`,
97
+ `import TabItem from "@theme/TabItem";\n\n`,
98
+ (0, createHeading_1.createHeading)(title.replace(utils_1.lessThan, "&lt;").replace(utils_1.greaterThan, "&gt;")),
99
+ (0, createDescription_1.createDescription)(description),
100
+ (0, utils_1.create)("ul", {
101
+ children: (0, createSchema_1.createNodes)(schema, "response"),
102
+ }),
103
+ ]);
104
+ }
105
+ exports.createSchemaPageMD = createSchemaPageMD;
@@ -2,7 +2,10 @@ export type Children = string | undefined | (string | string[] | undefined)[];
2
2
  export type Props = Record<string, any> & {
3
3
  children?: Children;
4
4
  };
5
- export declare function create(tag: string, props: Props): string;
5
+ export type Options = {
6
+ inline?: boolean;
7
+ };
8
+ export declare function create(tag: string, props: Props, options?: Options): string;
6
9
  export declare function guard<T>(value: T | undefined, cb: (value: T) => Children): string;
7
10
  export declare function render(children: Children): string;
8
11
  export declare const lessThan: RegExp;
@@ -7,14 +7,18 @@
7
7
  * ========================================================================== */
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.clean = exports.codeBlock = exports.curlyBrackets = exports.codeFence = exports.greaterThan = exports.lessThan = exports.render = exports.guard = exports.create = void 0;
10
- function create(tag, props) {
10
+ function create(tag, props, options = {}) {
11
11
  const { children, ...rest } = props;
12
12
  let propString = "";
13
13
  for (const [key, value] of Object.entries(rest)) {
14
14
  propString += `\n ${key}={${JSON.stringify(value)}}`;
15
15
  }
16
- propString += propString ? "\n" : "";
17
16
  let indentedChildren = render(children).replace(/^/gm, " ");
17
+ if (options.inline) {
18
+ propString += `\n children={${JSON.stringify(children)}}`;
19
+ indentedChildren = "";
20
+ }
21
+ propString += propString ? "\n" : "";
18
22
  indentedChildren += indentedChildren ? "\n" : "";
19
23
  return `<${tag}${propString}>\n${indentedChildren}</${tag}>`;
20
24
  }
@@ -1,4 +1,4 @@
1
- import { OpenApiObject, TagObject } from "./types";
1
+ import { OpenApiObject, TagGroupObject, TagObject } from "./types";
2
2
  import { ApiMetadata, APIOptions, SidebarOptions } from "../types";
3
3
  interface OpenApiFiles {
4
4
  source: string;
@@ -6,7 +6,7 @@ interface OpenApiFiles {
6
6
  data: OpenApiObject;
7
7
  }
8
8
  export declare function readOpenapiFiles(openapiPath: string): Promise<OpenApiFiles[]>;
9
- export declare function processOpenapiFiles(files: OpenApiFiles[], options: APIOptions, sidebarOptions: SidebarOptions): Promise<[ApiMetadata[], TagObject[][]]>;
10
- export declare function processOpenapiFile(openapiData: OpenApiObject, options: APIOptions, sidebarOptions: SidebarOptions): Promise<[ApiMetadata[], TagObject[]]>;
9
+ export declare function processOpenapiFiles(files: OpenApiFiles[], options: APIOptions, sidebarOptions: SidebarOptions): Promise<[ApiMetadata[], TagObject[][], TagGroupObject[]]>;
10
+ export declare function processOpenapiFile(openapiData: OpenApiObject, options: APIOptions, sidebarOptions: SidebarOptions): Promise<[ApiMetadata[], TagObject[], TagGroupObject[]]>;
11
11
  export declare function getTagDisplayName(tagName: string, tags: TagObject[]): string;
12
12
  export {};
@@ -61,7 +61,7 @@ async function createPostmanCollection(openapiData) {
61
61
  return await jsonToCollection(data);
62
62
  }
63
63
  function createItems(openapiData, options, sidebarOptions) {
64
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0;
64
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4;
65
65
  // TODO: Find a better way to handle this
66
66
  let items = [];
67
67
  const infoIdSpaces = openapiData.info.title.replace(" ", "-").toLowerCase();
@@ -324,9 +324,42 @@ function createItems(openapiData, options, sidebarOptions) {
324
324
  items.push(apiPage);
325
325
  }
326
326
  }
327
+ if ((options === null || options === void 0 ? void 0 : options.showSchemas) === true) {
328
+ // Gather schemas
329
+ for (let [schema, schemaObject] of Object.entries((_1 = (_0 = openapiData === null || openapiData === void 0 ? void 0 : openapiData.components) === null || _0 === void 0 ? void 0 : _0.schemas) !== null && _1 !== void 0 ? _1 : {})) {
330
+ const baseIdSpaces = (_3 = (_2 = schemaObject === null || schemaObject === void 0 ? void 0 : schemaObject.title) === null || _2 === void 0 ? void 0 : _2.replace(" ", "-").toLowerCase()) !== null && _3 !== void 0 ? _3 : "";
331
+ const baseId = (0, kebabCase_1.default)(baseIdSpaces);
332
+ const schemaDescription = schemaObject.description;
333
+ let splitDescription;
334
+ if (schemaDescription) {
335
+ splitDescription = schemaDescription.match(/[^\r\n]+/g);
336
+ }
337
+ const schemaPage = {
338
+ type: "schema",
339
+ id: baseId,
340
+ infoId: infoId !== null && infoId !== void 0 ? infoId : "",
341
+ unversionedId: baseId,
342
+ title: schemaObject.title
343
+ ? schemaObject.title.replace(/((?:^|[^\\])(?:\\{2})*)"/g, "$1'")
344
+ : schema,
345
+ description: schemaObject.description
346
+ ? schemaObject.description.replace(/((?:^|[^\\])(?:\\{2})*)"/g, "$1'")
347
+ : "",
348
+ frontMatter: {
349
+ description: splitDescription
350
+ ? splitDescription[0]
351
+ .replace(/((?:^|[^\\])(?:\\{2})*)"/g, "$1'")
352
+ .replace(/\s+$/, "")
353
+ : "",
354
+ },
355
+ schema: schemaObject,
356
+ };
357
+ items.push(schemaPage);
358
+ }
359
+ }
327
360
  if ((sidebarOptions === null || sidebarOptions === void 0 ? void 0 : sidebarOptions.categoryLinkSource) === "tag") {
328
361
  // Get global tags
329
- const tags = (_0 = openapiData.tags) !== null && _0 !== void 0 ? _0 : [];
362
+ const tags = (_4 = openapiData.tags) !== null && _4 !== void 0 ? _4 : [];
330
363
  // Get operation tags
331
364
  const apiItems = items.filter((item) => {
332
365
  return item.type === "api";
@@ -375,7 +408,9 @@ function bindCollectionToApiItems(items, postmanCollection) {
375
408
  .getPath({ unresolved: true }) // unresolved returns "/:variableName" instead of "/<type>"
376
409
  .replace(/(?<![a-z0-9-_]+):([a-z0-9-_]+)/gi, "{$1}"); // replace "/:variableName" with "/{variableName}"
377
410
  const apiItem = items.find((item) => {
378
- if (item.type === "info" || item.type === "tag") {
411
+ if (item.type === "info" ||
412
+ item.type === "tag" ||
413
+ item.type === "schema") {
379
414
  return false;
380
415
  }
381
416
  return item.api.path === path && item.api.method === method;
@@ -426,7 +461,8 @@ async function processOpenapiFiles(files, options, sidebarOptions) {
426
461
  ...item,
427
462
  }));
428
463
  const tags = processedFile[1];
429
- return [itemsObjectsArray, tags];
464
+ const tagGroups = processedFile[2];
465
+ return [itemsObjectsArray, tags, tagGroups];
430
466
  }
431
467
  console.warn(chalk_1.default.yellow(`WARNING: the following OpenAPI spec returned undefined: ${file.source}`));
432
468
  return [];
@@ -449,7 +485,20 @@ async function processOpenapiFiles(files, options, sidebarOptions) {
449
485
  // Remove undefined tags due to transient parsing errors
450
486
  return x !== undefined;
451
487
  });
452
- return [items, tags];
488
+ const tagGroups = metadata
489
+ .map(function (x) {
490
+ return x[2];
491
+ })
492
+ .flat()
493
+ .filter(function (x) {
494
+ // Remove undefined tags due to transient parsing errors
495
+ return x !== undefined;
496
+ });
497
+ return [
498
+ items,
499
+ tags,
500
+ tagGroups,
501
+ ];
453
502
  }
454
503
  exports.processOpenapiFiles = processOpenapiFiles;
455
504
  async function processOpenapiFile(openapiData, options, sidebarOptions) {
@@ -460,7 +509,11 @@ async function processOpenapiFile(openapiData, options, sidebarOptions) {
460
509
  if (openapiData.tags !== undefined) {
461
510
  tags = openapiData.tags;
462
511
  }
463
- return [items, tags];
512
+ let tagGroups = [];
513
+ if (openapiData["x-tagGroups"] !== undefined) {
514
+ tagGroups = openapiData["x-tagGroups"];
515
+ }
516
+ return [items, tags, tagGroups];
464
517
  }
465
518
  exports.processOpenapiFile = processOpenapiFile;
466
519
  // order for picking items as a display name of tags
@@ -24,6 +24,8 @@ describe("openapi", () => {
24
24
  const yaml = results.find((x) => x.source.endsWith("openapi.yaml"));
25
25
  expect(yaml).toBeTruthy();
26
26
  expect(yaml === null || yaml === void 0 ? void 0 : yaml.sourceDirName).toBe(".");
27
+ expect(yaml === null || yaml === void 0 ? void 0 : yaml.data.tags).toBeDefined();
28
+ expect(yaml === null || yaml === void 0 ? void 0 : yaml.data["x-tagGroups"]).toBeDefined();
27
29
  });
28
30
  });
29
31
  });
@@ -13,6 +13,7 @@ export interface OpenApiObject {
13
13
  externalDocs?: ExternalDocumentationObject;
14
14
  swagger?: string;
15
15
  "x-webhooks"?: PathsObject;
16
+ "x-tagGroups"?: TagGroupObject[];
16
17
  }
17
18
  export interface OpenApiObjectWithRef {
18
19
  openapi: string;
@@ -252,6 +253,10 @@ export interface TagObject {
252
253
  externalDocs?: ExternalDocumentationObject;
253
254
  "x-displayName"?: string;
254
255
  }
256
+ export interface TagGroupObject {
257
+ name: string;
258
+ tags: string[];
259
+ }
255
260
  export interface ReferenceObject {
256
261
  $ref: string;
257
262
  }