docusaurus-plugin-openapi-docs 1.0.1 → 1.0.2

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 (42) hide show
  1. package/README.md +7 -6
  2. package/lib/index.js +32 -7
  3. package/lib/markdown/createContactInfo.d.ts +2 -0
  4. package/lib/markdown/createContactInfo.js +49 -0
  5. package/lib/markdown/createLicense.d.ts +2 -0
  6. package/lib/markdown/createLicense.js +33 -0
  7. package/lib/markdown/createSchemaDetails.js +4 -1
  8. package/lib/markdown/createStatusCodes.js +1 -1
  9. package/lib/markdown/createTermsOfService.d.ts +1 -0
  10. package/lib/markdown/createTermsOfService.js +32 -0
  11. package/lib/markdown/index.d.ts +1 -1
  12. package/lib/markdown/index.js +8 -2
  13. package/lib/openapi/openapi.d.ts +4 -3
  14. package/lib/openapi/openapi.js +35 -21
  15. package/lib/openapi/types.d.ts +5 -1
  16. package/lib/sidebars/index.d.ts +2 -1
  17. package/lib/sidebars/index.js +72 -19
  18. package/lib/types.d.ts +2 -1
  19. package/package.json +2 -3
  20. package/src/index.ts +44 -8
  21. package/src/markdown/createContactInfo.ts +52 -0
  22. package/src/markdown/createLicense.ts +34 -0
  23. package/src/markdown/createSchemaDetails.ts +6 -2
  24. package/src/markdown/createStatusCodes.ts +1 -1
  25. package/src/markdown/createTermsOfService.ts +30 -0
  26. package/src/markdown/index.ts +9 -2
  27. package/src/openapi/openapi.ts +32 -16
  28. package/src/openapi/types.ts +5 -1
  29. package/src/{markdown/createRequestBodyTable.ts → postman-collection.d.ts} +2 -9
  30. package/src/sidebars/index.ts +90 -20
  31. package/src/types.ts +2 -2
  32. package/lib/markdown/createFullWidthTable.d.ts +0 -2
  33. package/lib/markdown/createFullWidthTable.js +0 -18
  34. package/lib/markdown/createParamsTable.d.ts +0 -7
  35. package/lib/markdown/createParamsTable.js +0 -80
  36. package/lib/markdown/createRequestBodyTable.d.ts +0 -6
  37. package/lib/markdown/createRequestBodyTable.js +0 -14
  38. package/lib/markdown/createSchemaTable.d.ts +0 -14
  39. package/lib/markdown/createSchemaTable.js +0 -217
  40. package/src/markdown/createFullWidthTable.ts +0 -16
  41. package/src/markdown/createParamsTable.ts +0 -102
  42. package/src/markdown/createSchemaTable.ts +0 -275
package/README.md CHANGED
@@ -110,12 +110,13 @@ Here is an example of properly configuring your `docusaurus.config.js` file for
110
110
 
111
111
  `sidebarOptions` can be configured with the following options:
112
112
 
113
- | Name | Type | Default | Description |
114
- | -------------------- | --------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------- |
115
- | `groupPathsBy` | `string` | `null` | Organize and group sidebar slice by specified option. Note: Currently, `groupPathsBy` only contains support for grouping by "tags". |
116
- | `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default. |
117
- | `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default. |
118
- | `customProps` | `object` | `null` | Additional props for customizing a sidebar item. |
113
+ | Name | Type | Default | Description |
114
+ | -------------------- | --------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
115
+ | `groupPathsBy` | `string` | `null` | Organize and group sidebar slice by specified option. Note: Currently, `groupPathsBy` only contains support for grouping by "tags". |
116
+ | `categoryLinkSource` | `string` | `null` | Defines what source to use for rendering category link pages when grouping paths by tag. <br/></br>The supported options are as follows: <br/></br> `tag`: Sets the category link config type to `generated-index` and uses the tag description as the link config description. <br/><br/>`info`: Sets the category link config type to `doc` and renders the `info` section as the category link (recommended only for multi/micro-spec scenarios). |
117
+ | `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default. |
118
+ | `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default. |
119
+ | `customProps` | `object` | `null` | Additional props for customizing a sidebar item. |
119
120
 
120
121
  > Note: You may optionally configure a `sidebarOptions`. In doing so, an individual `sidebar.js` slice with the configured options will be generated within the respective `outputDir`.
121
122
 
package/lib/index.js CHANGED
@@ -25,7 +25,7 @@ function pluginOpenAPI(context, options) {
25
25
  const contentPath = path_1.default.resolve(siteDir, specPath);
26
26
  try {
27
27
  const openapiFiles = await (0, openapi_1.readOpenapiFiles)(contentPath, {});
28
- const loadedApi = await (0, openapi_1.processOpenapiFiles)(openapiFiles);
28
+ const [loadedApi, tags] = await (0, openapi_1.processOpenapiFiles)(openapiFiles);
29
29
  if (!fs_1.default.existsSync(outputDir)) {
30
30
  try {
31
31
  fs_1.default.mkdirSync(outputDir, { recursive: true });
@@ -38,7 +38,7 @@ function pluginOpenAPI(context, options) {
38
38
  // TODO: figure out better way to set default
39
39
  if (Object.keys(sidebarOptions !== null && sidebarOptions !== void 0 ? sidebarOptions : {}).length > 0) {
40
40
  const sidebarSlice = (0, sidebars_1.default)(sidebarOptions, // TODO: find a better way to handle null
41
- options, loadedApi);
41
+ options, loadedApi, tags);
42
42
  const sidebarSliceTemplate = template
43
43
  ? fs_1.default.readFileSync(template).toString()
44
44
  : `module.exports = {{{slice}}};`;
@@ -59,7 +59,12 @@ function pluginOpenAPI(context, options) {
59
59
  ? fs_1.default.readFileSync(template).toString()
60
60
  : `---
61
61
  id: {{{id}}}
62
+ {{^api}}
63
+ sidebar_label: Introduction
64
+ {{/api}}
65
+ {{#api}}
62
66
  sidebar_label: {{{title}}}
67
+ {{/api}}
63
68
  {{^api}}
64
69
  sidebar_position: 0
65
70
  {{/api}}
@@ -76,6 +81,23 @@ sidebar_class_name: "{{{api.method}}} api-method"
76
81
  ---
77
82
 
78
83
  {{{markdown}}}
84
+ `;
85
+ const infoMdTemplate = template
86
+ ? fs_1.default.readFileSync(template).toString()
87
+ : `---
88
+ id: {{{id}}}
89
+ sidebar_label: {{{title}}}
90
+ hide_title: true
91
+ ---
92
+
93
+ {{{markdown}}}
94
+
95
+ \`\`\`mdx-code-block
96
+ import DocCardList from '@theme/DocCardList';
97
+ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
98
+
99
+ <DocCardList items={useCurrentSidebarCategory().items}/>
100
+ \`\`\`
79
101
  `;
80
102
  loadedApi.map(async (item) => {
81
103
  const markdown = item.type === "api" ? (0, markdown_1.createApiPageMD)(item) : (0, markdown_1.createInfoPageMD)(item);
@@ -84,6 +106,7 @@ sidebar_class_name: "{{{api.method}}} api-method"
84
106
  item.json = JSON.stringify(item.api);
85
107
  }
86
108
  const view = (0, mustache_1.render)(mdTemplate, item);
109
+ const utils = (0, mustache_1.render)(infoMdTemplate, item);
87
110
  if (item.type === "api") {
88
111
  if (!fs_1.default.existsSync(`${outputDir}/${item.id}.api.mdx`)) {
89
112
  try {
@@ -97,13 +120,15 @@ sidebar_class_name: "{{{api.method}}} api-method"
97
120
  }
98
121
  // TODO: determine if we actually want/need this
99
122
  if (item.type === "info") {
100
- if (!fs_1.default.existsSync(`${outputDir}/index.api.mdx`)) {
123
+ if (!fs_1.default.existsSync(`${outputDir}/${item.id}.info.mdx`)) {
101
124
  try {
102
- fs_1.default.writeFileSync(`${outputDir}/index.api.mdx`, view, "utf8");
103
- console.log(chalk_1.default.green(`Successfully created "${outputDir}/index.api.mdx"`));
125
+ (sidebarOptions === null || sidebarOptions === void 0 ? void 0 : sidebarOptions.categoryLinkSource) === "info" // Only use utils template if set to "info"
126
+ ? fs_1.default.writeFileSync(`${outputDir}/${item.id}.info.mdx`, utils, "utf8")
127
+ : fs_1.default.writeFileSync(`${outputDir}/${item.id}.info.mdx`, view, "utf8");
128
+ console.log(chalk_1.default.green(`Successfully created "${outputDir}/${item.id}.info.mdx"`));
104
129
  }
105
130
  catch (err) {
106
- console.error(chalk_1.default.red(`Failed to write "${outputDir}/index.api.mdx"`), chalk_1.default.yellow(err));
131
+ console.error(chalk_1.default.red(`Failed to write "${outputDir}/${item.id}.info.mdx"`), chalk_1.default.yellow(err));
107
132
  }
108
133
  }
109
134
  }
@@ -119,7 +144,7 @@ sidebar_class_name: "{{{api.method}}} api-method"
119
144
  async function cleanApiDocs(options) {
120
145
  const { outputDir } = options;
121
146
  const apiDir = path_1.default.join(siteDir, outputDir);
122
- const apiMdxFiles = await (0, utils_1.Globby)(["*.api.mdx"], {
147
+ const apiMdxFiles = await (0, utils_1.Globby)(["*.api.mdx", "*.info.mdx"], {
123
148
  cwd: path_1.default.resolve(apiDir),
124
149
  });
125
150
  const sidebarFile = await (0, utils_1.Globby)(["sidebar.js"], {
@@ -0,0 +1,2 @@
1
+ import { ContactObject } from "../openapi/types";
2
+ export declare function createContactInfo(contact: ContactObject): string;
@@ -0,0 +1,49 @@
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.createContactInfo = void 0;
10
+ const utils_1 = require("./utils");
11
+ function createContactInfo(contact) {
12
+ if (!contact || !Object.keys(contact).length)
13
+ return "";
14
+ const { name, url, email } = contact;
15
+ return (0, utils_1.create)("div", {
16
+ style: {
17
+ display: "flex",
18
+ flexDirection: "column",
19
+ marginBottom: "var(--ifm-paragraph-margin-bottom)",
20
+ },
21
+ children: [
22
+ (0, utils_1.create)("h3", {
23
+ style: {
24
+ marginBottom: "0.25rem",
25
+ },
26
+ children: "Contact",
27
+ }),
28
+ (0, utils_1.create)("span", {
29
+ children: [
30
+ (0, utils_1.guard)(name, () => `${name}: `),
31
+ (0, utils_1.guard)(email, () => (0, utils_1.create)("a", {
32
+ href: `mailto:${email}`,
33
+ children: `${email}`,
34
+ })),
35
+ ],
36
+ }),
37
+ (0, utils_1.guard)(url, () => (0, utils_1.create)("span", {
38
+ children: [
39
+ "URL: ",
40
+ (0, utils_1.create)("a", {
41
+ href: `${url}`,
42
+ children: `${url}`,
43
+ }),
44
+ ],
45
+ })),
46
+ ],
47
+ });
48
+ }
49
+ exports.createContactInfo = createContactInfo;
@@ -0,0 +1,2 @@
1
+ import { LicenseObject } from "../openapi/types";
2
+ export declare function createLicense(license: LicenseObject): string;
@@ -0,0 +1,33 @@
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.createLicense = void 0;
10
+ const utils_1 = require("./utils");
11
+ function createLicense(license) {
12
+ if (!license || !Object.keys(license).length)
13
+ return "";
14
+ const { name, url } = license;
15
+ return (0, utils_1.create)("div", {
16
+ style: {
17
+ marginBottom: "var(--ifm-paragraph-margin-bottom)",
18
+ },
19
+ children: [
20
+ (0, utils_1.create)("h3", {
21
+ style: {
22
+ marginBottom: "0.25rem",
23
+ },
24
+ children: "License",
25
+ }),
26
+ (0, utils_1.guard)(url, () => (0, utils_1.create)("a", {
27
+ href: url,
28
+ children: name !== null && name !== void 0 ? name : url,
29
+ })),
30
+ ],
31
+ });
32
+ }
33
+ exports.createLicense = createLicense;
@@ -185,7 +185,10 @@ function createRowsRoot({ schema }) {
185
185
  });
186
186
  }
187
187
  function createSchemaDetails({ title, body, ...rest }) {
188
- if (body === undefined || body.content === undefined) {
188
+ if (body === undefined ||
189
+ body.content === undefined ||
190
+ Object.keys(body).length === 0 ||
191
+ Object.keys(body.content).length === 0) {
189
192
  return undefined;
190
193
  }
191
194
  // TODO:
@@ -20,7 +20,7 @@ function createStatusCodes({ responses }) {
20
20
  }
21
21
  return (0, utils_1.create)("div", {
22
22
  children: [
23
- (0, utils_1.create)("Tabs", {
23
+ (0, utils_1.create)("ApiTabs", {
24
24
  children: codes.map((code) => {
25
25
  return (0, utils_1.create)("TabItem", {
26
26
  label: code,
@@ -0,0 +1 @@
1
+ export declare function createTermsOfService(termsOfService: string | undefined): string;
@@ -0,0 +1,32 @@
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.createTermsOfService = void 0;
10
+ const utils_1 = require("./utils");
11
+ function createTermsOfService(termsOfService) {
12
+ if (!termsOfService)
13
+ return "";
14
+ return (0, utils_1.create)("div", {
15
+ style: {
16
+ marginBottom: "var(--ifm-paragraph-margin-bottom)",
17
+ },
18
+ children: [
19
+ (0, utils_1.create)("h3", {
20
+ style: {
21
+ marginBottom: "0.25rem",
22
+ },
23
+ children: "Terms of Service",
24
+ }),
25
+ (0, utils_1.create)("a", {
26
+ href: `${termsOfService}`,
27
+ children: termsOfService,
28
+ }),
29
+ ],
30
+ });
31
+ }
32
+ exports.createTermsOfService = createTermsOfService;
@@ -1,3 +1,3 @@
1
1
  import { ApiPageMetadata, InfoPageMetadata } from "../types";
2
2
  export declare function createApiPageMD({ title, api: { deprecated, "x-deprecated-description": deprecatedDescription, description, parameters, requestBody, responses, }, }: ApiPageMetadata): string;
3
- export declare function createInfoPageMD({ info: { title, version, description }, }: InfoPageMetadata): string;
3
+ export declare function createInfoPageMD({ info: { title, version, description, contact, license, termsOfService }, }: InfoPageMetadata): string;
@@ -8,18 +8,21 @@
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.createInfoPageMD = exports.createApiPageMD = void 0;
10
10
  const lodash_1 = require("lodash");
11
+ const createContactInfo_1 = require("./createContactInfo");
11
12
  const createDeprecationNotice_1 = require("./createDeprecationNotice");
12
13
  const createDescription_1 = require("./createDescription");
14
+ const createLicense_1 = require("./createLicense");
13
15
  const createParamsDetails_1 = require("./createParamsDetails");
14
16
  const createRequestBodyDetails_1 = require("./createRequestBodyDetails");
15
17
  const createStatusCodes_1 = require("./createStatusCodes");
18
+ const createTermsOfService_1 = require("./createTermsOfService");
16
19
  const createVersionBadge_1 = require("./createVersionBadge");
17
20
  const utils_1 = require("./utils");
18
21
  function createApiPageMD({ title, api: { deprecated, "x-deprecated-description": deprecatedDescription, description, parameters, requestBody, responses, }, }) {
19
22
  return (0, utils_1.render)([
20
23
  `import ParamsItem from "@theme/ParamsItem";\n`,
21
24
  `import SchemaItem from "@theme/SchemaItem"\n`,
22
- `import Tabs from "@theme/Tabs";\n`,
25
+ `import ApiTabs from "@theme/ApiTabs";\n`,
23
26
  `import TabItem from "@theme/TabItem";\n\n`,
24
27
  `## ${(0, lodash_1.escape)(title)}\n\n`,
25
28
  (0, createDeprecationNotice_1.createDeprecationNotice)({ deprecated, description: deprecatedDescription }),
@@ -33,11 +36,14 @@ function createApiPageMD({ title, api: { deprecated, "x-deprecated-description":
33
36
  ]);
34
37
  }
35
38
  exports.createApiPageMD = createApiPageMD;
36
- function createInfoPageMD({ info: { title, version, description }, }) {
39
+ function createInfoPageMD({ info: { title, version, description, contact, license, termsOfService }, }) {
37
40
  return (0, utils_1.render)([
38
41
  (0, createVersionBadge_1.createVersionBadge)(version),
39
42
  `# ${(0, lodash_1.escape)(title)}\n\n`,
40
43
  (0, createDescription_1.createDescription)(description),
44
+ (0, createContactInfo_1.createContactInfo)(contact),
45
+ (0, createTermsOfService_1.createTermsOfService)(termsOfService),
46
+ (0, createLicense_1.createLicense)(license),
41
47
  ]);
42
48
  }
43
49
  exports.createInfoPageMD = createInfoPageMD;
@@ -1,11 +1,12 @@
1
1
  import { ApiMetadata } from "../types";
2
- import { OpenApiObjectWithRef } from "./types";
2
+ import { OpenApiObjectWithRef, TagObject } from "./types";
3
3
  interface OpenApiFiles {
4
4
  source: string;
5
5
  sourceDirName: string;
6
6
  data: OpenApiObjectWithRef;
7
7
  }
8
8
  export declare function readOpenapiFiles(openapiPath: string, _options: {}): Promise<OpenApiFiles[]>;
9
- export declare function processOpenapiFiles(files: OpenApiFiles[]): Promise<ApiMetadata[]>;
10
- export declare function processOpenapiFile(openapiDataWithRefs: OpenApiObjectWithRef): Promise<ApiMetadata[]>;
9
+ export declare function processOpenapiFiles(files: OpenApiFiles[]): Promise<[ApiMetadata[], TagObject[]]>;
10
+ export declare function processOpenapiFile(openapiDataWithRefs: OpenApiObjectWithRef): Promise<[ApiMetadata[], TagObject[]]>;
11
+ export declare function getTagDisplayName(tagName: string, tags: TagObject[]): string;
11
12
  export {};
@@ -9,11 +9,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
9
9
  return (mod && mod.__esModule) ? mod : { "default": mod };
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.processOpenapiFile = exports.processOpenapiFiles = exports.readOpenapiFiles = void 0;
12
+ exports.getTagDisplayName = exports.processOpenapiFile = exports.processOpenapiFiles = exports.readOpenapiFiles = void 0;
13
13
  const path_1 = __importDefault(require("path"));
14
14
  const utils_1 = require("@docusaurus/utils");
15
15
  const openapi_to_postmanv2_1 = __importDefault(require("@paloaltonetworks/openapi-to-postmanv2"));
16
- // @ts-ignore
17
16
  const postman_collection_1 = __importDefault(require("@paloaltonetworks/postman-collection"));
18
17
  const chalk_1 = __importDefault(require("chalk"));
19
18
  const fs_extra_1 = __importDefault(require("fs-extra"));
@@ -65,22 +64,24 @@ async function createPostmanCollection(openapiData) {
65
64
  return await jsonToCollection(data);
66
65
  }
67
66
  function createItems(openapiData) {
68
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
67
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
69
68
  // TODO: Find a better way to handle this
70
69
  let items = [];
71
70
  // Only create an info page if we have a description.
72
71
  if (openapiData.info.description) {
72
+ const infoId = (0, lodash_1.kebabCase)(openapiData.info.title);
73
73
  const infoPage = {
74
74
  type: "info",
75
- id: "introduction",
76
- unversionedId: "introduction",
77
- title: "Introduction",
75
+ id: infoId,
76
+ unversionedId: infoId,
77
+ title: openapiData.info.title,
78
78
  description: openapiData.info.description,
79
- slug: "/introduction",
79
+ slug: "/" + infoId,
80
80
  frontMatter: {},
81
81
  info: {
82
82
  ...openapiData.info,
83
- title: (_a = openapiData.info.title) !== null && _a !== void 0 ? _a : "Introduction",
83
+ tags: (_a = openapiData.tags) === null || _a === void 0 ? void 0 : _a.map((tagName) => { var _a; return getTagDisplayName(tagName.name, (_a = openapiData.tags) !== null && _a !== void 0 ? _a : []); }),
84
+ title: (_b = openapiData.info.title) !== null && _b !== void 0 ? _b : "Introduction",
84
85
  },
85
86
  };
86
87
  items.push(infoPage);
@@ -88,16 +89,16 @@ function createItems(openapiData) {
88
89
  for (let [path, pathObject] of Object.entries(openapiData.paths)) {
89
90
  const { $ref, description, parameters, servers, summary, ...rest } = pathObject;
90
91
  for (let [method, operationObject] of Object.entries({ ...rest })) {
91
- const title = (_c = (_b = operationObject.summary) !== null && _b !== void 0 ? _b : operationObject.operationId) !== null && _c !== void 0 ? _c : "Missing summary";
92
+ const title = (_d = (_c = operationObject.summary) !== null && _c !== void 0 ? _c : operationObject.operationId) !== null && _d !== void 0 ? _d : "Missing summary";
92
93
  if (operationObject.description === undefined) {
93
94
  operationObject.description =
94
- (_e = (_d = operationObject.summary) !== null && _d !== void 0 ? _d : operationObject.operationId) !== null && _e !== void 0 ? _e : "";
95
+ (_f = (_e = operationObject.summary) !== null && _e !== void 0 ? _e : operationObject.operationId) !== null && _f !== void 0 ? _f : "";
95
96
  }
96
97
  const baseId = (0, lodash_1.kebabCase)(title);
97
- const servers = (_g = (_f = operationObject.servers) !== null && _f !== void 0 ? _f : pathObject.servers) !== null && _g !== void 0 ? _g : openapiData.servers;
98
- const security = (_h = operationObject.security) !== null && _h !== void 0 ? _h : openapiData.security;
98
+ const servers = (_h = (_g = operationObject.servers) !== null && _g !== void 0 ? _g : pathObject.servers) !== null && _h !== void 0 ? _h : openapiData.servers;
99
+ const security = (_j = operationObject.security) !== null && _j !== void 0 ? _j : openapiData.security;
99
100
  // Add security schemes so we know how to handle security.
100
- const securitySchemes = (_j = openapiData.components) === null || _j === void 0 ? void 0 : _j.securitySchemes;
101
+ const securitySchemes = (_k = openapiData.components) === null || _k === void 0 ? void 0 : _k.securitySchemes;
101
102
  // Make sure schemes are lowercase. See: https://github.com/cloud-annotations/docusaurus-plugin-openapi/issues/79
102
103
  if (securitySchemes) {
103
104
  for (let securityScheme of Object.values(securitySchemes)) {
@@ -107,7 +108,7 @@ function createItems(openapiData) {
107
108
  }
108
109
  }
109
110
  let jsonRequestBodyExample;
110
- const body = (_l = (_k = operationObject.requestBody) === null || _k === void 0 ? void 0 : _k.content) === null || _l === void 0 ? void 0 : _l["application/json"];
111
+ const body = (_m = (_l = operationObject.requestBody) === null || _l === void 0 ? void 0 : _l.content) === null || _m === void 0 ? void 0 : _m["application/json"];
111
112
  if (body === null || body === void 0 ? void 0 : body.schema) {
112
113
  jsonRequestBodyExample = (0, createExample_1.sampleFromSchema)(body.schema);
113
114
  }
@@ -123,7 +124,7 @@ function createItems(openapiData) {
123
124
  frontMatter: {},
124
125
  api: {
125
126
  ...defaults,
126
- tags: (_m = operationObject.tags) === null || _m === void 0 ? void 0 : _m.map((tagName) => { var _a; return getTagDisplayName(tagName, (_a = openapiData.tags) !== null && _a !== void 0 ? _a : []); }),
127
+ tags: (_o = operationObject.tags) === null || _o === void 0 ? void 0 : _o.map((tagName) => { var _a; return getTagDisplayName(tagName, (_a = openapiData.tags) !== null && _a !== void 0 ? _a : []); }),
127
128
  method,
128
129
  path,
129
130
  servers,
@@ -142,7 +143,6 @@ function createItems(openapiData) {
142
143
  * Attach Postman Request objects to the corresponding ApiItems.
143
144
  */
144
145
  function bindCollectionToApiItems(items, postmanCollection) {
145
- // @ts-ignore
146
146
  postmanCollection.forEachItem((item) => {
147
147
  const method = item.request.method.toLowerCase();
148
148
  const path = item.request.url
@@ -194,14 +194,23 @@ async function readOpenapiFiles(openapiPath, _options) {
194
194
  exports.readOpenapiFiles = readOpenapiFiles;
195
195
  async function processOpenapiFiles(files) {
196
196
  const promises = files.map(async (file) => {
197
- const items = await processOpenapiFile(file.data);
198
- return items.map((item) => ({
197
+ const processedFile = await processOpenapiFile(file.data);
198
+ const itemsObjectsArray = processedFile[0].map((item) => ({
199
199
  ...item,
200
200
  }));
201
+ const tags = processedFile[1];
202
+ return [itemsObjectsArray, tags];
201
203
  });
202
204
  const metadata = await Promise.all(promises);
203
- const items = metadata.flat();
204
- return items;
205
+ const items = metadata
206
+ .map(function (x) {
207
+ return x[0];
208
+ })
209
+ .flat();
210
+ const tags = metadata.map(function (x) {
211
+ return x[1];
212
+ });
213
+ return [items, tags];
205
214
  }
206
215
  exports.processOpenapiFiles = processOpenapiFiles;
207
216
  async function processOpenapiFile(openapiDataWithRefs) {
@@ -209,7 +218,11 @@ async function processOpenapiFile(openapiDataWithRefs) {
209
218
  const postmanCollection = await createPostmanCollection(openapiData);
210
219
  const items = createItems(openapiData);
211
220
  bindCollectionToApiItems(items, postmanCollection);
212
- return items;
221
+ let tags = [];
222
+ if (openapiData.tags !== undefined) {
223
+ tags = openapiData.tags;
224
+ }
225
+ return [items, tags];
213
226
  }
214
227
  exports.processOpenapiFile = processOpenapiFile;
215
228
  // order for picking items as a display name of tags
@@ -231,3 +244,4 @@ function getTagDisplayName(tagName, tags) {
231
244
  // always default to the tagName
232
245
  return tagName;
233
246
  }
247
+ exports.getTagDisplayName = getTagDisplayName;
@@ -29,6 +29,7 @@ export interface InfoObject {
29
29
  contact?: ContactObject;
30
30
  license?: LicenseObject;
31
31
  version: string;
32
+ tags?: String[];
32
33
  }
33
34
  export interface ContactObject {
34
35
  name?: string;
@@ -151,6 +152,7 @@ export interface ParameterObject {
151
152
  example?: any;
152
153
  examples?: Map<ExampleObject>;
153
154
  content?: Map<MediaTypeObject>;
155
+ param?: Object;
154
156
  }
155
157
  export interface ParameterObjectWithRef {
156
158
  name: string;
@@ -236,7 +238,7 @@ export interface LinkObject {
236
238
  export declare type HeaderObject = Omit<ParameterObject, "name" | "in">;
237
239
  export declare type HeaderObjectWithRef = Omit<ParameterObjectWithRef, "name" | "in">;
238
240
  export interface TagObject {
239
- name: string;
241
+ name?: string;
240
242
  description?: string;
241
243
  externalDocs?: ExternalDocumentationObject;
242
244
  "x-displayName"?: string;
@@ -304,6 +306,8 @@ export interface HttpSecuritySchemeObject {
304
306
  description?: string;
305
307
  scheme: string;
306
308
  bearerFormat?: string;
309
+ name?: string;
310
+ in?: string;
307
311
  }
308
312
  export interface Oauth2SecuritySchemeObject {
309
313
  type: "oauth2";
@@ -1,3 +1,4 @@
1
1
  import { ProcessedSidebar } from "@docusaurus/plugin-content-docs/src/sidebars/types";
2
+ import { TagObject } from "../openapi/types";
2
3
  import type { SidebarOptions, APIOptions, ApiMetadata } from "../types";
3
- export default function generateSidebarSlice(sidebarOptions: SidebarOptions, options: APIOptions, api: ApiMetadata[]): ProcessedSidebar;
4
+ export default function generateSidebarSlice(sidebarOptions: SidebarOptions, options: APIOptions, api: ApiMetadata[], tags: TagObject[]): ProcessedSidebar;
@@ -10,25 +10,29 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  const clsx_1 = __importDefault(require("clsx"));
13
+ const lodash_1 = require("lodash");
13
14
  const uniq_1 = __importDefault(require("lodash/uniq"));
14
15
  function isApiItem(item) {
15
16
  return item.type === "api";
16
17
  }
17
- function groupByTags(items, sidebarOptions, options) {
18
- // TODO: Figure out how to handle these
19
- // const intros = items.filter(isInfoItem).map((item) => {
20
- // return {
21
- // type: "link" as const,
22
- // label: item.title,
23
- // href: item.permalink,
24
- // docId: item.id,
25
- // };
26
- // });
18
+ function isInfoItem(item) {
19
+ return item.type === "info";
20
+ }
21
+ function groupByTags(items, sidebarOptions, options, tags) {
27
22
  const { outputDir } = options;
28
- const { sidebarCollapsed, sidebarCollapsible, customProps } = sidebarOptions;
23
+ const { sidebarCollapsed, sidebarCollapsible, customProps, categoryLinkSource, } = sidebarOptions;
29
24
  const apiItems = items.filter(isApiItem);
25
+ const infoItems = items.filter(isInfoItem);
26
+ const intros = infoItems.map((item) => {
27
+ return {
28
+ id: item.id,
29
+ title: item.title,
30
+ description: item.description,
31
+ tags: item.info.tags,
32
+ };
33
+ });
30
34
  // TODO: make sure we only take the first tag
31
- const tags = (0, uniq_1.default)(apiItems
35
+ const apiTags = (0, uniq_1.default)(apiItems
32
36
  .flatMap((item) => item.api.tags)
33
37
  .filter((item) => !!item));
34
38
  // TODO: optimize this or make it a function
@@ -51,11 +55,56 @@ function groupByTags(items, sidebarOptions, options) {
51
55
  }, item.api.method),
52
56
  };
53
57
  }
54
- const tagged = tags
58
+ let rootIntroDoc = undefined;
59
+ if (infoItems.length === 1) {
60
+ const infoItem = infoItems[0];
61
+ const id = infoItem.id;
62
+ rootIntroDoc = {
63
+ type: "doc",
64
+ id: `${basePath}/${id}`,
65
+ };
66
+ }
67
+ const tagged = apiTags
55
68
  .map((tag) => {
69
+ // Map info object to tag
70
+ const infoObject = intros.find((i) => i.tags.includes(tag));
71
+ const tagObject = tags.flat().find((t) => {
72
+ var _a;
73
+ return (_a = (tag === t.name || tag === t["x-displayName"])) !== null && _a !== void 0 ? _a : {
74
+ name: tag,
75
+ description: `${tag} Index`,
76
+ };
77
+ });
78
+ // TODO: perhaps move this into a getLinkConfig() function
79
+ let linkConfig = undefined;
80
+ if (infoObject !== undefined && categoryLinkSource === "info") {
81
+ linkConfig = {
82
+ type: "doc",
83
+ id: `${basePath}/${infoObject.id}`,
84
+ };
85
+ }
86
+ // TODO: perhaps move this into a getLinkConfig() function
87
+ if (tagObject !== undefined && categoryLinkSource === "tag") {
88
+ const linkDescription = tagObject === null || tagObject === void 0 ? void 0 : tagObject.description;
89
+ linkConfig = {
90
+ type: "generated-index",
91
+ title: tag,
92
+ description: linkDescription,
93
+ slug: "/category/" + (0, lodash_1.kebabCase)(tag),
94
+ };
95
+ }
96
+ // Default behavior
97
+ if (categoryLinkSource === undefined) {
98
+ linkConfig = {
99
+ type: "generated-index",
100
+ title: tag,
101
+ slug: "/category/" + (0, lodash_1.kebabCase)(tag),
102
+ };
103
+ }
56
104
  return {
57
105
  type: "category",
58
106
  label: tag,
107
+ link: linkConfig,
59
108
  collapsible: sidebarCollapsible,
60
109
  collapsed: sidebarCollapsed,
61
110
  items: apiItems
@@ -64,25 +113,29 @@ function groupByTags(items, sidebarOptions, options) {
64
113
  };
65
114
  })
66
115
  .filter((item) => item.items.length > 0); // Filter out any categories with no items.
116
+ // TODO: determine how we want to handle these
67
117
  // const untagged = [
68
- // // TODO: determine if needed and how
69
118
  // {
70
119
  // type: "category" as const,
71
120
  // label: "UNTAGGED",
72
- // // collapsible: options.sidebarCollapsible, TODO: add option
73
- // // collapsed: options.sidebarCollapsed, TODO: add option
121
+ // collapsible: sidebarCollapsible,
122
+ // collapsed: sidebarCollapsed,
74
123
  // items: apiItems
75
- // //@ts-ignore
76
124
  // .filter(({ api }) => api.tags === undefined || api.tags.length === 0)
77
125
  // .map(createDocItem),
78
126
  // },
79
127
  // ];
128
+ // Shift root intro doc to top of sidebar
129
+ // TODO: Add input validation for categoryLinkSource options
130
+ if (rootIntroDoc && categoryLinkSource !== "info") {
131
+ tagged.unshift(rootIntroDoc);
132
+ }
80
133
  return [...tagged];
81
134
  }
82
- function generateSidebarSlice(sidebarOptions, options, api) {
135
+ function generateSidebarSlice(sidebarOptions, options, api, tags) {
83
136
  let sidebarSlice = [];
84
137
  if (sidebarOptions.groupPathsBy === "tags") {
85
- sidebarSlice = groupByTags(api, sidebarOptions, options);
138
+ sidebarSlice = groupByTags(api, sidebarOptions, options, tags);
86
139
  }
87
140
  return sidebarSlice;
88
141
  }