docusaurus-plugin-openapi-docs 3.0.0-beta.5 → 3.0.0-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/lib/index.js +62 -9
- package/lib/markdown/createAuthentication.js +4 -3
- package/lib/markdown/createCallbacks.js +4 -2
- package/lib/markdown/createHeading.js +4 -3
- package/lib/markdown/createRequestHeader.d.ts +1 -1
- package/lib/markdown/createRequestHeader.js +10 -1
- package/lib/markdown/index.d.ts +2 -1
- package/lib/markdown/index.js +21 -2
- package/lib/markdown/utils.d.ts +4 -1
- package/lib/markdown/utils.js +7 -3
- package/lib/openapi/openapi.d.ts +3 -3
- package/lib/openapi/openapi.js +59 -6
- package/lib/openapi/openapi.test.js +2 -0
- package/lib/openapi/types.d.ts +5 -0
- package/lib/options.js +2 -1
- package/lib/sidebars/index.d.ts +2 -2
- package/lib/sidebars/index.js +50 -10
- package/lib/types.d.ts +15 -2
- package/package.json +4 -4
- package/src/index.ts +114 -11
- package/src/markdown/createAuthentication.ts +10 -5
- package/src/markdown/createCallbacks.ts +10 -4
- package/src/markdown/createHeading.ts +9 -4
- package/src/markdown/createRequestHeader.ts +15 -1
- package/src/markdown/index.ts +27 -3
- package/src/markdown/utils.ts +15 -4
- package/src/openapi/__fixtures__/examples/openapi.yaml +29 -0
- package/src/openapi/openapi.test.ts +3 -0
- package/src/openapi/openapi.ts +75 -7
- package/src/openapi/types.ts +6 -0
- package/src/options.ts +2 -1
- package/src/sidebars/index.ts +70 -16
- 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
|
|
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
|
|
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)("
|
|
151
|
+
(0, utils_1.create)("Heading", {
|
|
152
152
|
children: "Authentication",
|
|
153
153
|
id: "authentication",
|
|
154
|
-
|
|
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", {
|
|
@@ -25,10 +25,12 @@ function createCallbacks({ callbacks }) {
|
|
|
25
25
|
(0, utils_1.create)("div", {
|
|
26
26
|
className: "openapi__divider",
|
|
27
27
|
}),
|
|
28
|
-
(0, utils_1.create)("
|
|
28
|
+
(0, utils_1.create)("Heading", {
|
|
29
29
|
children: "Callbacks",
|
|
30
30
|
id: "callbacks",
|
|
31
|
-
|
|
31
|
+
as: "h2",
|
|
32
|
+
className: "openapi-tabs__heading",
|
|
33
|
+
}, { inline: true }),
|
|
32
34
|
(0, utils_1.create)("OperationTabs", {
|
|
33
35
|
className: "openapi-tabs__operation",
|
|
34
36
|
children: callbacksNames.flatMap((name) => {
|
|
@@ -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)("
|
|
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
|
}
|
|
@@ -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
|
|
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;
|
package/lib/markdown/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { ApiPageMetadata, InfoPageMetadata, TagPageMetadata } from "../types";
|
|
1
|
+
import { ApiPageMetadata, InfoPageMetadata, SchemaPageMetadata, TagPageMetadata } from "../types";
|
|
2
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;
|
package/lib/markdown/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
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
12
|
const createCallbacks_1 = require("./createCallbacks");
|
|
@@ -21,6 +21,7 @@ const createMethodEndpoint_1 = require("./createMethodEndpoint");
|
|
|
21
21
|
const createParamsDetails_1 = require("./createParamsDetails");
|
|
22
22
|
const createRequestBodyDetails_1 = require("./createRequestBodyDetails");
|
|
23
23
|
const createRequestHeader_1 = require("./createRequestHeader");
|
|
24
|
+
const createSchema_1 = require("./createSchema");
|
|
24
25
|
const createStatusCodes_1 = require("./createStatusCodes");
|
|
25
26
|
const createTermsOfService_1 = require("./createTermsOfService");
|
|
26
27
|
const createVendorExtensions_1 = require("./createVendorExtensions");
|
|
@@ -38,6 +39,7 @@ function createApiPageMD({ title, api: { deprecated, "x-deprecated-description":
|
|
|
38
39
|
`import SchemaItem from "@theme/SchemaItem";\n`,
|
|
39
40
|
`import SchemaTabs from "@theme/SchemaTabs";\n`,
|
|
40
41
|
`import Markdown from "@theme/Markdown";\n`,
|
|
42
|
+
`import Heading from "@theme/Heading";\n`,
|
|
41
43
|
`import OperationTabs from "@theme/OperationTabs";\n`,
|
|
42
44
|
`import TabItem from "@theme/TabItem";\n\n`,
|
|
43
45
|
(0, createHeading_1.createHeading)(title),
|
|
@@ -48,7 +50,7 @@ function createApiPageMD({ title, api: { deprecated, "x-deprecated-description":
|
|
|
48
50
|
: undefined,
|
|
49
51
|
(0, createDeprecationNotice_1.createDeprecationNotice)({ deprecated, description: deprecatedDescription }),
|
|
50
52
|
(0, createDescription_1.createDescription)(description),
|
|
51
|
-
(0, createRequestHeader_1.createRequestHeader)("Request"),
|
|
53
|
+
requestBody || parameters ? (0, createRequestHeader_1.createRequestHeader)("Request") : undefined,
|
|
52
54
|
(0, createParamsDetails_1.createParamsDetails)({ parameters, type: "path" }),
|
|
53
55
|
(0, createParamsDetails_1.createParamsDetails)({ parameters, type: "query" }),
|
|
54
56
|
(0, createParamsDetails_1.createParamsDetails)({ parameters, type: "header" }),
|
|
@@ -65,6 +67,7 @@ exports.createApiPageMD = createApiPageMD;
|
|
|
65
67
|
function createInfoPageMD({ info: { title, version, description, contact, license, termsOfService, logo, darkLogo, }, securitySchemes, downloadUrl, }) {
|
|
66
68
|
return (0, utils_1.render)([
|
|
67
69
|
`import ApiLogo from "@theme/ApiLogo";\n`,
|
|
70
|
+
`import Heading from "@theme/Heading";\n`,
|
|
68
71
|
`import SchemaTabs from "@theme/SchemaTabs";\n`,
|
|
69
72
|
`import TabItem from "@theme/TabItem";\n`,
|
|
70
73
|
`import Export from "@theme/ApiExplorer/Export";\n\n`,
|
|
@@ -84,3 +87,19 @@ function createTagPageMD({ tag: { description } }) {
|
|
|
84
87
|
return (0, utils_1.render)([(0, createDescription_1.createDescription)(description)]);
|
|
85
88
|
}
|
|
86
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, "<").replace(utils_1.greaterThan, ">")),
|
|
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;
|
package/lib/markdown/utils.d.ts
CHANGED
|
@@ -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
|
|
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;
|
package/lib/markdown/utils.js
CHANGED
|
@@ -7,20 +7,24 @@
|
|
|
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
|
}
|
|
21
25
|
exports.create = create;
|
|
22
26
|
function guard(value, cb) {
|
|
23
|
-
if (!!value) {
|
|
27
|
+
if (!!value || value === 0) {
|
|
24
28
|
const children = cb(value);
|
|
25
29
|
return render(children);
|
|
26
30
|
}
|
package/lib/openapi/openapi.d.ts
CHANGED
|
@@ -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 {};
|
package/lib/openapi/openapi.js
CHANGED
|
@@ -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 = (
|
|
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" ||
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
});
|
package/lib/openapi/types.d.ts
CHANGED
|
@@ -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
|
}
|
package/lib/options.js
CHANGED
|
@@ -9,7 +9,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
9
9
|
exports.OptionsSchema = void 0;
|
|
10
10
|
const utils_validation_1 = require("@docusaurus/utils-validation");
|
|
11
11
|
const sidebarOptions = utils_validation_1.Joi.object({
|
|
12
|
-
groupPathsBy: utils_validation_1.Joi.string().valid("tag"),
|
|
12
|
+
groupPathsBy: utils_validation_1.Joi.string().valid("tag", "tagGroup"),
|
|
13
13
|
categoryLinkSource: utils_validation_1.Joi.string().valid("tag", "info", "auto"),
|
|
14
14
|
customProps: utils_validation_1.Joi.object(),
|
|
15
15
|
sidebarCollapsible: utils_validation_1.Joi.boolean(),
|
|
@@ -34,6 +34,7 @@ exports.OptionsSchema = utils_validation_1.Joi.object({
|
|
|
34
34
|
showExtensions: utils_validation_1.Joi.boolean(),
|
|
35
35
|
sidebarOptions: sidebarOptions,
|
|
36
36
|
markdownGenerators: markdownGenerators,
|
|
37
|
+
showSchemas: utils_validation_1.Joi.boolean(),
|
|
37
38
|
version: utils_validation_1.Joi.string().when("versions", {
|
|
38
39
|
is: utils_validation_1.Joi.exist(),
|
|
39
40
|
then: utils_validation_1.Joi.required(),
|
package/lib/sidebars/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { ProcessedSidebar } from "@docusaurus/plugin-content-docs/src/sidebars/types";
|
|
2
|
-
import { TagObject } from "../openapi/types";
|
|
2
|
+
import { TagGroupObject, TagObject } from "../openapi/types";
|
|
3
3
|
import type { SidebarOptions, APIOptions, ApiMetadata } from "../types";
|
|
4
|
-
export default function generateSidebarSlice(sidebarOptions: SidebarOptions, options: APIOptions, api: ApiMetadata[], tags: TagObject[][], docPath: string): ProcessedSidebar;
|
|
4
|
+
export default function generateSidebarSlice(sidebarOptions: SidebarOptions, options: APIOptions, api: ApiMetadata[], tags: TagObject[][], docPath: string, tagGroups?: TagGroupObject[]): ProcessedSidebar;
|
package/lib/sidebars/index.js
CHANGED
|
@@ -20,6 +20,9 @@ function isApiItem(item) {
|
|
|
20
20
|
function isInfoItem(item) {
|
|
21
21
|
return item.type === "info";
|
|
22
22
|
}
|
|
23
|
+
function isSchemaItem(item) {
|
|
24
|
+
return item.type === "schema";
|
|
25
|
+
}
|
|
23
26
|
function groupByTags(items, sidebarOptions, options, tags, docPath) {
|
|
24
27
|
let { outputDir, label } = options;
|
|
25
28
|
// Remove trailing slash before proceeding
|
|
@@ -27,6 +30,7 @@ function groupByTags(items, sidebarOptions, options, tags, docPath) {
|
|
|
27
30
|
const { sidebarCollapsed, sidebarCollapsible, customProps, categoryLinkSource, } = sidebarOptions;
|
|
28
31
|
const apiItems = items.filter(isApiItem);
|
|
29
32
|
const infoItems = items.filter(isInfoItem);
|
|
33
|
+
const schemaItems = items.filter(isSchemaItem);
|
|
30
34
|
const intros = infoItems.map((item) => {
|
|
31
35
|
return {
|
|
32
36
|
id: item.id,
|
|
@@ -48,7 +52,7 @@ function groupByTags(items, sidebarOptions, options, tags, docPath) {
|
|
|
48
52
|
apiTags.push(tag.name);
|
|
49
53
|
}
|
|
50
54
|
});
|
|
51
|
-
apiTags = (
|
|
55
|
+
// apiTags = uniq(apiTags.concat(operationTags));
|
|
52
56
|
const basePath = docPath
|
|
53
57
|
? outputDir.split(docPath)[1].replace(/^\/+/g, "")
|
|
54
58
|
: outputDir.slice(outputDir.indexOf("/", 1)).replace(/^\/+/g, "");
|
|
@@ -56,16 +60,21 @@ function groupByTags(items, sidebarOptions, options, tags, docPath) {
|
|
|
56
60
|
var _a, _b;
|
|
57
61
|
const sidebar_label = item.frontMatter.sidebar_label;
|
|
58
62
|
const title = item.title;
|
|
59
|
-
const id = item.id;
|
|
63
|
+
const id = item.type === "schema" ? `schemas/${item.id}` : item.id;
|
|
64
|
+
const className = item.type === "api"
|
|
65
|
+
? (0, clsx_1.default)({
|
|
66
|
+
"menu__list-item--deprecated": item.api.deprecated,
|
|
67
|
+
"api-method": !!item.api.method,
|
|
68
|
+
}, item.api.method)
|
|
69
|
+
: (0, clsx_1.default)({
|
|
70
|
+
"menu__list-item--deprecated": item.schema.deprecated,
|
|
71
|
+
});
|
|
60
72
|
return {
|
|
61
73
|
type: "doc",
|
|
62
|
-
id: basePath === "" || undefined ? `${
|
|
74
|
+
id: basePath === "" || undefined ? `${id}` : `${basePath}/${id}`,
|
|
63
75
|
label: (_b = (_a = sidebar_label) !== null && _a !== void 0 ? _a : title) !== null && _b !== void 0 ? _b : id,
|
|
64
76
|
customProps: customProps,
|
|
65
|
-
className:
|
|
66
|
-
"menu__list-item--deprecated": item.api.deprecated,
|
|
67
|
-
"api-method": !!item.api.method,
|
|
68
|
-
}, item.api.method),
|
|
77
|
+
className: className ? className : undefined,
|
|
69
78
|
};
|
|
70
79
|
}
|
|
71
80
|
let rootIntroDoc = undefined;
|
|
@@ -147,16 +156,47 @@ function groupByTags(items, sidebarOptions, options, tags, docPath) {
|
|
|
147
156
|
},
|
|
148
157
|
];
|
|
149
158
|
}
|
|
159
|
+
let schemas = [];
|
|
160
|
+
if (schemaItems.length > 0) {
|
|
161
|
+
schemas = [
|
|
162
|
+
{
|
|
163
|
+
type: "category",
|
|
164
|
+
label: "Schemas",
|
|
165
|
+
collapsible: sidebarCollapsible,
|
|
166
|
+
collapsed: sidebarCollapsed,
|
|
167
|
+
items: schemaItems.map(createDocItem),
|
|
168
|
+
},
|
|
169
|
+
];
|
|
170
|
+
}
|
|
150
171
|
// Shift root intro doc to top of sidebar
|
|
151
172
|
// TODO: Add input validation for categoryLinkSource options
|
|
152
173
|
if (rootIntroDoc && categoryLinkSource !== "info") {
|
|
153
174
|
tagged.unshift(rootIntroDoc);
|
|
154
175
|
}
|
|
155
|
-
return [...tagged, ...untagged];
|
|
176
|
+
return [...tagged, ...untagged, ...schemas];
|
|
156
177
|
}
|
|
157
|
-
function generateSidebarSlice(sidebarOptions, options, api, tags, docPath) {
|
|
178
|
+
function generateSidebarSlice(sidebarOptions, options, api, tags, docPath, tagGroups) {
|
|
158
179
|
let sidebarSlice = [];
|
|
159
|
-
if (sidebarOptions.groupPathsBy === "
|
|
180
|
+
if (sidebarOptions.groupPathsBy === "tagGroup") {
|
|
181
|
+
tagGroups === null || tagGroups === void 0 ? void 0 : tagGroups.forEach((tagGroup) => {
|
|
182
|
+
//filter tags only included in group
|
|
183
|
+
const filteredTags = [];
|
|
184
|
+
tags[0].forEach((tag) => {
|
|
185
|
+
if (tagGroup.tags.includes(tag.name)) {
|
|
186
|
+
filteredTags.push(tag);
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
const groupCategory = {
|
|
190
|
+
type: "category",
|
|
191
|
+
label: tagGroup.name,
|
|
192
|
+
collapsible: true,
|
|
193
|
+
collapsed: true,
|
|
194
|
+
items: groupByTags(api, sidebarOptions, options, [filteredTags], docPath),
|
|
195
|
+
};
|
|
196
|
+
sidebarSlice.push(groupCategory);
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
else if (sidebarOptions.groupPathsBy === "tag") {
|
|
160
200
|
sidebarSlice = groupByTags(api, sidebarOptions, options, tags, docPath);
|
|
161
201
|
}
|
|
162
202
|
return sidebarSlice;
|