docusaurus-plugin-openapi-docs 2.0.0-beta.5 → 2.0.1
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 +97 -82
- package/lib/index.js +11 -7
- package/lib/markdown/createRequestSchema.js +2 -2
- package/lib/markdown/createResponseSchema.js +1 -1
- package/lib/markdown/createSchema.d.ts +1 -1
- package/lib/markdown/createSchema.js +29 -10
- package/lib/markdown/createSchema.test.js +1 -1
- package/lib/openapi/openapi.js +1 -1
- package/lib/options.js +6 -0
- package/lib/types.d.ts +6 -0
- package/package.json +7 -7
- package/src/index.ts +22 -9
- package/src/markdown/createRequestSchema.ts +2 -2
- package/src/markdown/createResponseSchema.ts +1 -1
- package/src/markdown/createSchema.test.ts +1 -1
- package/src/markdown/createSchema.ts +35 -10
- package/src/openapi/openapi.ts +1 -2
- package/src/options.ts +7 -0
- package/src/types.ts +7 -0
package/README.md
CHANGED
|
@@ -25,9 +25,39 @@ Key Features:
|
|
|
25
25
|
- **Compatible:** Works with Swagger 2.0 and OpenAPI 3.0.
|
|
26
26
|
- **Fast:** Convert large OpenAPI specs into MDX docs in seconds. 🔥
|
|
27
27
|
- **Stylish:** Based on the same [Infima styling framework](https://infima.dev/) that powers the Docusaurus UI.
|
|
28
|
-
- **
|
|
28
|
+
- **Flexible:** Supports single, multi and _even micro_ OpenAPI specs.
|
|
29
29
|
|
|
30
|
-
##
|
|
30
|
+
## Compatibility Matrix
|
|
31
|
+
|
|
32
|
+
| Docusaurus OpenAPI Docs | Docusaurus |
|
|
33
|
+
| ----------------------- | --------------- |
|
|
34
|
+
| 2.0.x (current) | `2.4.1 - 2.4.3` |
|
|
35
|
+
| 1.7.3 (legacy) | `2.0.1 - 2.2.0` |
|
|
36
|
+
|
|
37
|
+
## Bootstrapping from Template (new Docusaurus site)
|
|
38
|
+
|
|
39
|
+
Run the following to bootstrap a Docsaurus v2 site (classic theme) with `docusaurus-openapi-docs`:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
npx create-docusaurus@2.4.3 my-website --package-manager yarn
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
> When prompted to select a template choose `Git repository`.
|
|
46
|
+
|
|
47
|
+
Template Repository URL:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
https://github.com/PaloAltoNetworks/docusaurus-template-openapi-docs.git
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
> When asked how the template repo should be cloned choose "copy" (unless you know better).
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
cd my-website
|
|
57
|
+
yarn start
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Installation (existing Docusaurus site)
|
|
31
61
|
|
|
32
62
|
Plugin:
|
|
33
63
|
|
|
@@ -43,51 +73,48 @@ yarn add docusaurus-theme-openapi-docs
|
|
|
43
73
|
|
|
44
74
|
## Configuring `docusaurus.config.js` (Plugin and theme usage)
|
|
45
75
|
|
|
46
|
-
Here is an example of properly configuring
|
|
76
|
+
Here is an example of properly configuring `docusaurus.config.js` file for `docusaurus-plugin-openapi-docs` and `docusaurus-theme-openapi-docs` usage.
|
|
47
77
|
|
|
48
78
|
```js
|
|
49
79
|
// docusaurus.config.js
|
|
50
80
|
|
|
51
81
|
{
|
|
52
82
|
presets: [
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
"
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
76
|
-
})
|
|
77
|
-
]
|
|
78
|
-
],
|
|
83
|
+
[
|
|
84
|
+
"classic",
|
|
85
|
+
/** @type {import('@docusaurus/preset-classic').Options} */
|
|
86
|
+
({
|
|
87
|
+
docs: {
|
|
88
|
+
sidebarPath: require.resolve("./sidebars.js"),
|
|
89
|
+
editUrl:
|
|
90
|
+
"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/",
|
|
91
|
+
docLayoutComponent: "@theme/DocPage",
|
|
92
|
+
docItemComponent: "@theme/ApiItem" // derived from docusaurus-theme-openapi-docs
|
|
93
|
+
},
|
|
94
|
+
blog: {
|
|
95
|
+
showReadingTime: true,
|
|
96
|
+
editUrl:
|
|
97
|
+
"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/"
|
|
98
|
+
},
|
|
99
|
+
theme: {
|
|
100
|
+
customCss: require.resolve("./src/css/custom.css")
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
]
|
|
104
|
+
],
|
|
79
105
|
|
|
80
106
|
plugins: [
|
|
107
|
+
[
|
|
81
108
|
'docusaurus-plugin-openapi-docs',
|
|
82
109
|
{
|
|
83
|
-
id: "
|
|
84
|
-
docsPluginId: "classic",
|
|
110
|
+
id: "api", // plugin id
|
|
111
|
+
docsPluginId: "classic", // id of plugin-content-docs or preset for rendering docs
|
|
85
112
|
config: {
|
|
86
|
-
petstore: { //
|
|
87
|
-
specPath: "examples/petstore.yaml", //
|
|
88
|
-
outputDir: "api/petstore", //
|
|
89
|
-
sidebarOptions: {
|
|
90
|
-
groupPathsBy: "tag",
|
|
113
|
+
petstore: { // the <id> referenced when running CLI commands
|
|
114
|
+
specPath: "examples/petstore.yaml", // path to OpenAPI spec, URLs supported
|
|
115
|
+
outputDir: "api/petstore", // output directory for generated files
|
|
116
|
+
sidebarOptions: { // optional, instructs plugin to generate sidebar.js
|
|
117
|
+
groupPathsBy: "tag", // group sidebar items by operation "tag"
|
|
91
118
|
},
|
|
92
119
|
},
|
|
93
120
|
burgers: {
|
|
@@ -98,7 +125,7 @@ Here is an example of properly configuring your `docusaurus.config.js` file for
|
|
|
98
125
|
},
|
|
99
126
|
]
|
|
100
127
|
],
|
|
101
|
-
themes: ["docusaurus-theme-openapi-docs"] //
|
|
128
|
+
themes: ["docusaurus-theme-openapi-docs"], // export theme components
|
|
102
129
|
}
|
|
103
130
|
```
|
|
104
131
|
|
|
@@ -110,37 +137,38 @@ The `docusaurus-plugin-openapi-docs` plugin can be configured with the following
|
|
|
110
137
|
|
|
111
138
|
| Name | Type | Default | Description |
|
|
112
139
|
| -------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
113
|
-
| `id` | `string` | `null` | A unique
|
|
140
|
+
| `id` | `string` | `null` | A unique plugin id. |
|
|
114
141
|
| `docsPluginId` | `string` | `null` | The ID associated with the `plugin-content-docs` or `preset` instance used to render the OpenAPI docs (e.g. "your-plugin-id", "classic", "default"). |
|
|
115
142
|
|
|
116
143
|
### config
|
|
117
144
|
|
|
118
145
|
`config` can be configured with the following options:
|
|
119
146
|
|
|
120
|
-
| Name
|
|
121
|
-
|
|
|
122
|
-
| `specPath`
|
|
123
|
-
| `ouputDir`
|
|
124
|
-
| `proxy`
|
|
125
|
-
| `template`
|
|
126
|
-
| `downloadUrl`
|
|
127
|
-
| `hideSendButton`
|
|
128
|
-
| `showExtensions`
|
|
129
|
-
| `sidebarOptions`
|
|
130
|
-
| `version`
|
|
131
|
-
| `label`
|
|
132
|
-
| `baseUrl`
|
|
133
|
-
| `versions`
|
|
147
|
+
| Name | Type | Default | Description |
|
|
148
|
+
| -------------------- | --------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
149
|
+
| `specPath` | `string` | `null` | Designated URL or path to the source of an OpenAPI specification file or directory of multiple OpenAPI specification files. |
|
|
150
|
+
| `ouputDir` | `string` | `null` | Desired output path for generated MDX files. |
|
|
151
|
+
| `proxy` | `string` | `null` | _Optional:_ Proxy URL to prepend to base URL when performing API requests from browser. |
|
|
152
|
+
| `template` | `string` | `null` | _Optional:_ Customize MDX content with a desired template. |
|
|
153
|
+
| `downloadUrl` | `string` | `null` | _Optional:_ Designated URL for downloading OpenAPI specification. (requires `info` section/doc) |
|
|
154
|
+
| `hideSendButton` | `boolean` | `null` | _Optional:_ If set to `true`, hides the "Send API Request" button in API demo panel |
|
|
155
|
+
| `showExtensions` | `boolean` | `null` | _Optional:_ If set to `true`, renders operation-level vendor-extensions in description. |
|
|
156
|
+
| `sidebarOptions` | `object` | `null` | _Optional:_ Set of options for sidebar configuration. See below for a list of supported options. |
|
|
157
|
+
| `version` | `string` | `null` | _Optional:_ Version assigned to single or micro-spec API specified in `specPath`. |
|
|
158
|
+
| `label` | `string` | `null` | _Optional:_ Version label used when generating version selector dropdown menu. |
|
|
159
|
+
| `baseUrl` | `string` | `null` | _Optional:_ Version base URL used when generating version selector dropdown menu. |
|
|
160
|
+
| `versions` | `object` | `null` | _Optional:_ Set of options for versioning configuration. See below for a list of supported options. |
|
|
161
|
+
| `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. |
|
|
134
162
|
|
|
135
163
|
`sidebarOptions` can be configured with the following options:
|
|
136
164
|
|
|
137
|
-
| Name | Type | Default | Description
|
|
138
|
-
| -------------------- | --------- | ------- |
|
|
139
|
-
| `groupPathsBy` | `string` | `null` | Organize and group sidebar slice by specified option. Note: Currently, `groupPathsBy` only contains support for grouping by `tag`.
|
|
140
|
-
| `categoryLinkSource` | `string` | `null` | Defines what source to use for rendering category pages when grouping paths by tag.
|
|
141
|
-
| `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default.
|
|
142
|
-
| `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default.
|
|
143
|
-
| `customProps` | `object` | `null` | Additional props for customizing a sidebar item.
|
|
165
|
+
| Name | Type | Default | Description |
|
|
166
|
+
| -------------------- | --------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
167
|
+
| `groupPathsBy` | `string` | `null` | Organize and group sidebar slice by specified option. Note: Currently, `groupPathsBy` only contains support for grouping by `tag`. |
|
|
168
|
+
| `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). <br/><br/>`none`: Does not create pages for categories, only groups that can be expanded/collapsed. |
|
|
169
|
+
| `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default. |
|
|
170
|
+
| `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default. |
|
|
171
|
+
| `customProps` | `object` | `null` | Additional props for customizing a sidebar item. |
|
|
144
172
|
|
|
145
173
|
> 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`.
|
|
146
174
|
|
|
@@ -155,6 +183,16 @@ The `docusaurus-plugin-openapi-docs` plugin can be configured with the following
|
|
|
155
183
|
|
|
156
184
|
> All versions will automatically inherit `sidebarOptions` from the parent/base config.
|
|
157
185
|
|
|
186
|
+
### markdownGenerators
|
|
187
|
+
|
|
188
|
+
`markdownGenerators` can be configured with the following options:
|
|
189
|
+
|
|
190
|
+
| Name | Type | Default | Description |
|
|
191
|
+
| ------------------ | ---------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
192
|
+
| `createApiPageMD` | `function` | `null` | _Optional:_ Returns a string of the raw markdown body for API pages.<br/><br/>**Function type:** `(pageData: ApiPageMetadata) => string` |
|
|
193
|
+
| `createInfoPageMD` | `function` | `null` | _Optional:_ Returns a string of the raw markdown body for info pages.<br/><br/>**Function type:** `(pageData: InfoPageMetadata) => string` |
|
|
194
|
+
| `createTagPageMD` | `function` | `null` | _Optional:_ Returns a string of the raw markdown body for tag pages.<br/><br/>**Function type:** `(pageData: TagPageMetadata) => string` |
|
|
195
|
+
|
|
158
196
|
## CLI Usage
|
|
159
197
|
|
|
160
198
|
```bash
|
|
@@ -245,29 +283,6 @@ yarn docusaurus gen-api-docs:version petstore:all
|
|
|
245
283
|
|
|
246
284
|
> Substitue `all` with a specific version ID to generate/clean a specific version. Generating for `all` or a specific version ID will automatically update the `versions.json` file.
|
|
247
285
|
|
|
248
|
-
## Installing from Template
|
|
249
|
-
|
|
250
|
-
Run the following to bootstrap a Docsaurus v2 site (classic theme) with `docusaurus-openapi-docs`:
|
|
251
|
-
|
|
252
|
-
```bash
|
|
253
|
-
npx create-docusaurus@2.0.1 my-website --package-manager yarn
|
|
254
|
-
```
|
|
255
|
-
|
|
256
|
-
> When prompted to select a template choose `Git repository`.
|
|
257
|
-
|
|
258
|
-
Template Repository URL:
|
|
259
|
-
|
|
260
|
-
```bash
|
|
261
|
-
https://github.com/PaloAltoNetworks/docusaurus-template-openapi-docs.git
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
> When asked how the template repo should be cloned choose "copy" (unless you know better).
|
|
265
|
-
|
|
266
|
-
```bash
|
|
267
|
-
cd my-website
|
|
268
|
-
yarn
|
|
269
|
-
```
|
|
270
|
-
|
|
271
286
|
## Developer Quick Start
|
|
272
287
|
|
|
273
288
|
> Looking to make a contribution? Make sure to checkout out our contributing guide.
|
package/lib/index.js
CHANGED
|
@@ -77,7 +77,8 @@ function pluginOpenAPIDocs(context, options) {
|
|
|
77
77
|
let docRouteBasePath = docData ? docData.routeBasePath : undefined;
|
|
78
78
|
let docPath = docData ? (docData.path ? docData.path : "docs") : undefined;
|
|
79
79
|
async function generateApiDocs(options, pluginId) {
|
|
80
|
-
|
|
80
|
+
var _a, _b, _c;
|
|
81
|
+
let { specPath, outputDir, template, markdownGenerators, downloadUrl, sidebarOptions, } = options;
|
|
81
82
|
// Remove trailing slash before proceeding
|
|
82
83
|
outputDir = outputDir.replace(/\/$/, "");
|
|
83
84
|
// Override docPath if pluginId provided
|
|
@@ -194,12 +195,21 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
|
|
|
194
195
|
<DocCardList items={useCurrentSidebarCategory().items}/>
|
|
195
196
|
\`\`\`
|
|
196
197
|
`;
|
|
198
|
+
const apiPageGenerator = (_a = markdownGenerators === null || markdownGenerators === void 0 ? void 0 : markdownGenerators.createApiPageMD) !== null && _a !== void 0 ? _a : markdown_1.createApiPageMD;
|
|
199
|
+
const infoPageGenerator = (_b = markdownGenerators === null || markdownGenerators === void 0 ? void 0 : markdownGenerators.createInfoPageMD) !== null && _b !== void 0 ? _b : markdown_1.createInfoPageMD;
|
|
200
|
+
const tagPageGenerator = (_c = markdownGenerators === null || markdownGenerators === void 0 ? void 0 : markdownGenerators.createTagPageMD) !== null && _c !== void 0 ? _c : markdown_1.createTagPageMD;
|
|
197
201
|
loadedApi.map(async (item) => {
|
|
198
202
|
if (item.type === "info") {
|
|
199
203
|
if (downloadUrl && isURL(downloadUrl)) {
|
|
200
204
|
item.downloadUrl = downloadUrl;
|
|
201
205
|
}
|
|
202
206
|
}
|
|
207
|
+
const markdown = item.type === "api"
|
|
208
|
+
? apiPageGenerator(item)
|
|
209
|
+
: item.type === "info"
|
|
210
|
+
? infoPageGenerator(item)
|
|
211
|
+
: tagPageGenerator(item);
|
|
212
|
+
item.markdown = markdown;
|
|
203
213
|
if (item.type === "api") {
|
|
204
214
|
// opportunity to compress JSON
|
|
205
215
|
// const serialize = (o: any) => {
|
|
@@ -220,12 +230,6 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
|
|
|
220
230
|
if (item.infoId)
|
|
221
231
|
item.infoPath = infoBasePath;
|
|
222
232
|
}
|
|
223
|
-
const markdown = item.type === "api"
|
|
224
|
-
? (0, markdown_1.createApiPageMD)(item)
|
|
225
|
-
: item.type === "info"
|
|
226
|
-
? (0, markdown_1.createInfoPageMD)(item)
|
|
227
|
-
: (0, markdown_1.createTagPageMD)(item);
|
|
228
|
-
item.markdown = markdown;
|
|
229
233
|
const view = (0, mustache_1.render)(mdTemplate, item);
|
|
230
234
|
const utils = (0, mustache_1.render)(infoMdTemplate, item);
|
|
231
235
|
// eslint-disable-next-line testing-library/render-result-naming-convention
|
|
@@ -74,7 +74,7 @@ function createRequestSchema({ title, body, ...rest }) {
|
|
|
74
74
|
}),
|
|
75
75
|
(0, utils_1.create)("ul", {
|
|
76
76
|
style: { marginLeft: "1rem" },
|
|
77
|
-
children: (0, createSchema_1.createNodes)(firstBody),
|
|
77
|
+
children: (0, createSchema_1.createNodes)(firstBody, "request"),
|
|
78
78
|
}),
|
|
79
79
|
],
|
|
80
80
|
}),
|
|
@@ -139,7 +139,7 @@ function createRequestSchema({ title, body, ...rest }) {
|
|
|
139
139
|
}),
|
|
140
140
|
(0, utils_1.create)("ul", {
|
|
141
141
|
style: { marginLeft: "1rem" },
|
|
142
|
-
children: (0, createSchema_1.createNodes)(firstBody),
|
|
142
|
+
children: (0, createSchema_1.createNodes)(firstBody, "request"),
|
|
143
143
|
}),
|
|
144
144
|
],
|
|
145
145
|
}),
|
|
@@ -89,7 +89,7 @@ function createResponseSchema({ title, body, ...rest }) {
|
|
|
89
89
|
}),
|
|
90
90
|
(0, utils_1.create)("ul", {
|
|
91
91
|
style: { marginLeft: "1rem" },
|
|
92
|
-
children: (0, createSchema_1.createNodes)(firstBody),
|
|
92
|
+
children: (0, createSchema_1.createNodes)(firstBody, "response"),
|
|
93
93
|
}),
|
|
94
94
|
],
|
|
95
95
|
}),
|
|
@@ -9,4 +9,4 @@ export declare function mergeAllOf(allOf: SchemaObject[]): {
|
|
|
9
9
|
/**
|
|
10
10
|
* Creates a hierarchical level of a schema tree. Nodes produce edges that can branch into sub-nodes with edges, recursively.
|
|
11
11
|
*/
|
|
12
|
-
export declare function createNodes(schema: SchemaObject): any;
|
|
12
|
+
export declare function createNodes(schema: SchemaObject, schemaType: "request" | "response"): any;
|
|
@@ -18,6 +18,7 @@ const createDetailsSummary_1 = require("./createDetailsSummary");
|
|
|
18
18
|
const schema_1 = require("./schema");
|
|
19
19
|
const utils_1 = require("./utils");
|
|
20
20
|
const jsonSchemaMergeAllOf = require("json-schema-merge-allof");
|
|
21
|
+
let SCHEMA_TYPE;
|
|
21
22
|
/**
|
|
22
23
|
* Returns a merged representation of allOf array of schemas.
|
|
23
24
|
*/
|
|
@@ -27,6 +28,9 @@ function mergeAllOf(allOf) {
|
|
|
27
28
|
readOnly: function () {
|
|
28
29
|
return true;
|
|
29
30
|
},
|
|
31
|
+
writeOnly: function () {
|
|
32
|
+
return true;
|
|
33
|
+
},
|
|
30
34
|
example: function () {
|
|
31
35
|
return true;
|
|
32
36
|
},
|
|
@@ -68,7 +72,7 @@ function createAnyOneOf(schema) {
|
|
|
68
72
|
delete anyOneSchema.properties;
|
|
69
73
|
}
|
|
70
74
|
if (anyOneSchema.allOf !== undefined) {
|
|
71
|
-
anyOneChildren.push(createNodes(anyOneSchema));
|
|
75
|
+
anyOneChildren.push(createNodes(anyOneSchema, SCHEMA_TYPE));
|
|
72
76
|
delete anyOneSchema.allOf;
|
|
73
77
|
}
|
|
74
78
|
if (anyOneSchema.items !== undefined) {
|
|
@@ -79,7 +83,7 @@ function createAnyOneOf(schema) {
|
|
|
79
83
|
anyOneSchema.type === "number" ||
|
|
80
84
|
anyOneSchema.type === "integer" ||
|
|
81
85
|
anyOneSchema.type === "boolean") {
|
|
82
|
-
anyOneChildren.push(createNodes(anyOneSchema));
|
|
86
|
+
anyOneChildren.push(createNodes(anyOneSchema, SCHEMA_TYPE));
|
|
83
87
|
}
|
|
84
88
|
if (anyOneChildren.length) {
|
|
85
89
|
if (schema.type === "array") {
|
|
@@ -257,7 +261,7 @@ function createItems(schema) {
|
|
|
257
261
|
((_l = schema.items) === null || _l === void 0 ? void 0 : _l.type) === "object") {
|
|
258
262
|
return [
|
|
259
263
|
(0, createArrayBracket_1.createOpeningArrayBracket)(),
|
|
260
|
-
createNodes(schema.items),
|
|
264
|
+
createNodes(schema.items, SCHEMA_TYPE),
|
|
261
265
|
(0, createArrayBracket_1.createClosingArrayBracket)(),
|
|
262
266
|
].flat();
|
|
263
267
|
}
|
|
@@ -344,7 +348,7 @@ function createDetailsNode(name, schemaName, schema, required, nullable) {
|
|
|
344
348
|
style: { marginTop: ".5rem", marginBottom: ".5rem" },
|
|
345
349
|
children: (0, createDescription_1.createDescription)(description),
|
|
346
350
|
})),
|
|
347
|
-
createNodes(schema),
|
|
351
|
+
createNodes(schema, SCHEMA_TYPE),
|
|
348
352
|
],
|
|
349
353
|
}),
|
|
350
354
|
],
|
|
@@ -466,7 +470,7 @@ function createPropertyDiscriminator(name, schemaName, schema, discriminator, re
|
|
|
466
470
|
// className: "openapi-tabs__discriminator-item",
|
|
467
471
|
label: label,
|
|
468
472
|
value: `${index}-item-discriminator`,
|
|
469
|
-
children: [createNodes(discriminator === null || discriminator === void 0 ? void 0 : discriminator.mapping[key])],
|
|
473
|
+
children: [createNodes(discriminator === null || discriminator === void 0 ? void 0 : discriminator.mapping[key], SCHEMA_TYPE)],
|
|
470
474
|
});
|
|
471
475
|
}),
|
|
472
476
|
}),
|
|
@@ -503,8 +507,15 @@ function createEdges({ name, schema, required, discriminator, }) {
|
|
|
503
507
|
if (((_a = mergedSchemas.items) === null || _a === void 0 ? void 0 : _a.properties) !== undefined) {
|
|
504
508
|
return createDetailsNode(name, mergedSchemaName, mergedSchemas, required, schema.nullable);
|
|
505
509
|
}
|
|
506
|
-
if (
|
|
507
|
-
|
|
510
|
+
if (SCHEMA_TYPE === "request") {
|
|
511
|
+
if (mergedSchemas.readOnly && mergedSchemas.readOnly === true) {
|
|
512
|
+
return undefined;
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
if (SCHEMA_TYPE === "response") {
|
|
516
|
+
if (mergedSchemas.writeOnly && mergedSchemas.writeOnly === true) {
|
|
517
|
+
return undefined;
|
|
518
|
+
}
|
|
508
519
|
}
|
|
509
520
|
return (0, utils_1.create)("SchemaItem", {
|
|
510
521
|
collapsible: false,
|
|
@@ -528,8 +539,15 @@ function createEdges({ name, schema, required, discriminator, }) {
|
|
|
528
539
|
if (((_c = schema.items) === null || _c === void 0 ? void 0 : _c.anyOf) !== undefined || ((_d = schema.items) === null || _d === void 0 ? void 0 : _d.oneOf) !== undefined) {
|
|
529
540
|
return createDetailsNode(name, schemaName, schema, required, schema.nullable);
|
|
530
541
|
}
|
|
531
|
-
if (
|
|
532
|
-
|
|
542
|
+
if (SCHEMA_TYPE === "request") {
|
|
543
|
+
if (schema.readOnly && schema.readOnly === true) {
|
|
544
|
+
return undefined;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
if (SCHEMA_TYPE === "response") {
|
|
548
|
+
if (schema.writeOnly && schema.writeOnly === true) {
|
|
549
|
+
return undefined;
|
|
550
|
+
}
|
|
533
551
|
}
|
|
534
552
|
// primitives and array of non-objects
|
|
535
553
|
return (0, utils_1.create)("SchemaItem", {
|
|
@@ -544,7 +562,8 @@ function createEdges({ name, schema, required, discriminator, }) {
|
|
|
544
562
|
/**
|
|
545
563
|
* Creates a hierarchical level of a schema tree. Nodes produce edges that can branch into sub-nodes with edges, recursively.
|
|
546
564
|
*/
|
|
547
|
-
function createNodes(schema) {
|
|
565
|
+
function createNodes(schema, schemaType) {
|
|
566
|
+
SCHEMA_TYPE = schemaType;
|
|
548
567
|
const nodes = [];
|
|
549
568
|
// if (schema.discriminator !== undefined) {
|
|
550
569
|
// return createDiscriminator(schema);
|
|
@@ -68,6 +68,6 @@ describe("createNodes", () => {
|
|
|
68
68
|
},
|
|
69
69
|
},
|
|
70
70
|
};
|
|
71
|
-
expect((0, createSchema_1.createNodes)(schema).map((md) => prettier.format(md, { parser: "babel" }))).toMatchSnapshot();
|
|
71
|
+
expect((0, createSchema_1.createNodes)(schema, "request").map((md) => prettier.format(md, { parser: "babel" }))).toMatchSnapshot();
|
|
72
72
|
});
|
|
73
73
|
});
|
package/lib/openapi/openapi.js
CHANGED
|
@@ -373,7 +373,7 @@ function bindCollectionToApiItems(items, postmanCollection) {
|
|
|
373
373
|
const method = item.request.method.toLowerCase();
|
|
374
374
|
const path = item.request.url
|
|
375
375
|
.getPath({ unresolved: true }) // unresolved returns "/:variableName" instead of "/<type>"
|
|
376
|
-
.replace(
|
|
376
|
+
.replace(/(?<![a-z0-9-_]+):([a-z0-9-_]+)/gi, "{$1}"); // replace "/:variableName" with "/{variableName}"
|
|
377
377
|
const apiItem = items.find((item) => {
|
|
378
378
|
if (item.type === "info" || item.type === "tag") {
|
|
379
379
|
return false;
|
package/lib/options.js
CHANGED
|
@@ -15,6 +15,11 @@ const sidebarOptions = utils_validation_1.Joi.object({
|
|
|
15
15
|
sidebarCollapsible: utils_validation_1.Joi.boolean(),
|
|
16
16
|
sidebarCollapsed: utils_validation_1.Joi.boolean(),
|
|
17
17
|
});
|
|
18
|
+
const markdownGenerators = utils_validation_1.Joi.object({
|
|
19
|
+
createApiPageMD: utils_validation_1.Joi.function(),
|
|
20
|
+
createInfoPageMD: utils_validation_1.Joi.function(),
|
|
21
|
+
createTagPageMD: utils_validation_1.Joi.function(),
|
|
22
|
+
});
|
|
18
23
|
exports.OptionsSchema = utils_validation_1.Joi.object({
|
|
19
24
|
id: utils_validation_1.Joi.string().required(),
|
|
20
25
|
docsPluginId: utils_validation_1.Joi.string().required(),
|
|
@@ -28,6 +33,7 @@ exports.OptionsSchema = utils_validation_1.Joi.object({
|
|
|
28
33
|
hideSendButton: utils_validation_1.Joi.boolean(),
|
|
29
34
|
showExtensions: utils_validation_1.Joi.boolean(),
|
|
30
35
|
sidebarOptions: sidebarOptions,
|
|
36
|
+
markdownGenerators: markdownGenerators,
|
|
31
37
|
version: utils_validation_1.Joi.string().when("versions", {
|
|
32
38
|
is: utils_validation_1.Joi.exist(),
|
|
33
39
|
then: utils_validation_1.Joi.required(),
|
package/lib/types.d.ts
CHANGED
|
@@ -23,6 +23,12 @@ export interface APIOptions {
|
|
|
23
23
|
[key: string]: APIVersionOptions;
|
|
24
24
|
};
|
|
25
25
|
proxy?: string;
|
|
26
|
+
markdownGenerators?: MarkdownGenerator;
|
|
27
|
+
}
|
|
28
|
+
export interface MarkdownGenerator {
|
|
29
|
+
createApiPageMD?: (pageData: ApiPageMetadata) => string;
|
|
30
|
+
createInfoPageMD?: (pageData: InfoPageMetadata) => string;
|
|
31
|
+
createTagPageMD?: (pageData: TagPageMetadata) => string;
|
|
26
32
|
}
|
|
27
33
|
export interface SidebarOptions {
|
|
28
34
|
groupPathsBy?: string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "docusaurus-plugin-openapi-docs",
|
|
3
3
|
"description": "OpenAPI plugin for Docusaurus.",
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"openapi",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"watch": "tsc --watch"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@docusaurus/types": ">=2.
|
|
31
|
+
"@docusaurus/types": ">=2.4.1 <=2.4.3",
|
|
32
32
|
"@types/fs-extra": "^9.0.13",
|
|
33
33
|
"@types/json-pointer": "^1.0.31",
|
|
34
34
|
"@types/json-schema": "^7.0.9",
|
|
@@ -37,9 +37,9 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@apidevtools/json-schema-ref-parser": "^10.1.0",
|
|
40
|
-
"@docusaurus/plugin-content-docs": ">=2.
|
|
41
|
-
"@docusaurus/utils": ">=2.
|
|
42
|
-
"@docusaurus/utils-validation": ">=2.
|
|
40
|
+
"@docusaurus/plugin-content-docs": ">=2.4.1 <=2.4.3",
|
|
41
|
+
"@docusaurus/utils": ">=2.4.1 <=2.4.3",
|
|
42
|
+
"@docusaurus/utils-validation": ">=2.4.1 <=2.4.3",
|
|
43
43
|
"@paloaltonetworks/openapi-to-postmanv2": "3.1.0-hotfix.1",
|
|
44
44
|
"@paloaltonetworks/postman-collection": "^4.1.0",
|
|
45
45
|
"@redocly/openapi-core": "^1.0.0-beta.125",
|
|
@@ -55,10 +55,10 @@
|
|
|
55
55
|
"xml-formatter": "^2.6.1"
|
|
56
56
|
},
|
|
57
57
|
"peerDependencies": {
|
|
58
|
-
"react": "^16.8.4 || ^17.0.0"
|
|
58
|
+
"react": "^16.8.4 || ^17.0.0 || ^18.0.0"
|
|
59
59
|
},
|
|
60
60
|
"engines": {
|
|
61
61
|
"node": ">=14"
|
|
62
62
|
},
|
|
63
|
-
"gitHead": "
|
|
63
|
+
"gitHead": "6f9eff64e6b32c63100daaa7f70431edc8cf455d"
|
|
64
64
|
}
|
package/src/index.ts
CHANGED
|
@@ -92,8 +92,14 @@ export default function pluginOpenAPIDocs(
|
|
|
92
92
|
let docPath = docData ? (docData.path ? docData.path : "docs") : undefined;
|
|
93
93
|
|
|
94
94
|
async function generateApiDocs(options: APIOptions, pluginId: any) {
|
|
95
|
-
let {
|
|
96
|
-
|
|
95
|
+
let {
|
|
96
|
+
specPath,
|
|
97
|
+
outputDir,
|
|
98
|
+
template,
|
|
99
|
+
markdownGenerators,
|
|
100
|
+
downloadUrl,
|
|
101
|
+
sidebarOptions,
|
|
102
|
+
} = options;
|
|
97
103
|
|
|
98
104
|
// Remove trailing slash before proceeding
|
|
99
105
|
outputDir = outputDir.replace(/\/$/, "");
|
|
@@ -238,12 +244,26 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
|
|
|
238
244
|
\`\`\`
|
|
239
245
|
`;
|
|
240
246
|
|
|
247
|
+
const apiPageGenerator =
|
|
248
|
+
markdownGenerators?.createApiPageMD ?? createApiPageMD;
|
|
249
|
+
const infoPageGenerator =
|
|
250
|
+
markdownGenerators?.createInfoPageMD ?? createInfoPageMD;
|
|
251
|
+
const tagPageGenerator =
|
|
252
|
+
markdownGenerators?.createTagPageMD ?? createTagPageMD;
|
|
253
|
+
|
|
241
254
|
loadedApi.map(async (item) => {
|
|
242
255
|
if (item.type === "info") {
|
|
243
256
|
if (downloadUrl && isURL(downloadUrl)) {
|
|
244
257
|
item.downloadUrl = downloadUrl;
|
|
245
258
|
}
|
|
246
259
|
}
|
|
260
|
+
const markdown =
|
|
261
|
+
item.type === "api"
|
|
262
|
+
? apiPageGenerator(item)
|
|
263
|
+
: item.type === "info"
|
|
264
|
+
? infoPageGenerator(item)
|
|
265
|
+
: tagPageGenerator(item);
|
|
266
|
+
item.markdown = markdown;
|
|
247
267
|
if (item.type === "api") {
|
|
248
268
|
// opportunity to compress JSON
|
|
249
269
|
// const serialize = (o: any) => {
|
|
@@ -263,13 +283,6 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
|
|
|
263
283
|
}
|
|
264
284
|
if (item.infoId) item.infoPath = infoBasePath;
|
|
265
285
|
}
|
|
266
|
-
const markdown =
|
|
267
|
-
item.type === "api"
|
|
268
|
-
? createApiPageMD(item)
|
|
269
|
-
: item.type === "info"
|
|
270
|
-
? createInfoPageMD(item)
|
|
271
|
-
: createTagPageMD(item);
|
|
272
|
-
item.markdown = markdown;
|
|
273
286
|
|
|
274
287
|
const view = render(mdTemplate, item);
|
|
275
288
|
const utils = render(infoMdTemplate, item);
|
|
@@ -90,7 +90,7 @@ export function createRequestSchema({ title, body, ...rest }: Props) {
|
|
|
90
90
|
}),
|
|
91
91
|
create("ul", {
|
|
92
92
|
style: { marginLeft: "1rem" },
|
|
93
|
-
children: createNodes(firstBody),
|
|
93
|
+
children: createNodes(firstBody, "request"),
|
|
94
94
|
}),
|
|
95
95
|
],
|
|
96
96
|
}),
|
|
@@ -161,7 +161,7 @@ export function createRequestSchema({ title, body, ...rest }: Props) {
|
|
|
161
161
|
}),
|
|
162
162
|
create("ul", {
|
|
163
163
|
style: { marginLeft: "1rem" },
|
|
164
|
-
children: createNodes(firstBody),
|
|
164
|
+
children: createNodes(firstBody, "request"),
|
|
165
165
|
}),
|
|
166
166
|
],
|
|
167
167
|
}),
|
|
@@ -20,6 +20,8 @@ import { create, guard } from "./utils";
|
|
|
20
20
|
|
|
21
21
|
const jsonSchemaMergeAllOf = require("json-schema-merge-allof");
|
|
22
22
|
|
|
23
|
+
let SCHEMA_TYPE: "request" | "response";
|
|
24
|
+
|
|
23
25
|
/**
|
|
24
26
|
* Returns a merged representation of allOf array of schemas.
|
|
25
27
|
*/
|
|
@@ -29,6 +31,9 @@ export function mergeAllOf(allOf: SchemaObject[]) {
|
|
|
29
31
|
readOnly: function () {
|
|
30
32
|
return true;
|
|
31
33
|
},
|
|
34
|
+
writeOnly: function () {
|
|
35
|
+
return true;
|
|
36
|
+
},
|
|
32
37
|
example: function () {
|
|
33
38
|
return true;
|
|
34
39
|
},
|
|
@@ -74,7 +79,7 @@ function createAnyOneOf(schema: SchemaObject): any {
|
|
|
74
79
|
}
|
|
75
80
|
|
|
76
81
|
if (anyOneSchema.allOf !== undefined) {
|
|
77
|
-
anyOneChildren.push(createNodes(anyOneSchema));
|
|
82
|
+
anyOneChildren.push(createNodes(anyOneSchema, SCHEMA_TYPE));
|
|
78
83
|
delete anyOneSchema.allOf;
|
|
79
84
|
}
|
|
80
85
|
|
|
@@ -89,7 +94,7 @@ function createAnyOneOf(schema: SchemaObject): any {
|
|
|
89
94
|
anyOneSchema.type === "integer" ||
|
|
90
95
|
anyOneSchema.type === "boolean"
|
|
91
96
|
) {
|
|
92
|
-
anyOneChildren.push(createNodes(anyOneSchema));
|
|
97
|
+
anyOneChildren.push(createNodes(anyOneSchema, SCHEMA_TYPE));
|
|
93
98
|
}
|
|
94
99
|
if (anyOneChildren.length) {
|
|
95
100
|
if (schema.type === "array") {
|
|
@@ -304,7 +309,7 @@ function createItems(schema: SchemaObject) {
|
|
|
304
309
|
) {
|
|
305
310
|
return [
|
|
306
311
|
createOpeningArrayBracket(),
|
|
307
|
-
createNodes(schema.items),
|
|
312
|
+
createNodes(schema.items, SCHEMA_TYPE),
|
|
308
313
|
createClosingArrayBracket(),
|
|
309
314
|
].flat();
|
|
310
315
|
}
|
|
@@ -411,7 +416,7 @@ function createDetailsNode(
|
|
|
411
416
|
children: createDescription(description),
|
|
412
417
|
})
|
|
413
418
|
),
|
|
414
|
-
createNodes(schema),
|
|
419
|
+
createNodes(schema, SCHEMA_TYPE),
|
|
415
420
|
],
|
|
416
421
|
}),
|
|
417
422
|
],
|
|
@@ -565,7 +570,7 @@ function createPropertyDiscriminator(
|
|
|
565
570
|
// className: "openapi-tabs__discriminator-item",
|
|
566
571
|
label: label,
|
|
567
572
|
value: `${index}-item-discriminator`,
|
|
568
|
-
children: [createNodes(discriminator?.mapping[key])],
|
|
573
|
+
children: [createNodes(discriminator?.mapping[key], SCHEMA_TYPE)],
|
|
569
574
|
});
|
|
570
575
|
}),
|
|
571
576
|
}),
|
|
@@ -664,8 +669,16 @@ function createEdges({
|
|
|
664
669
|
);
|
|
665
670
|
}
|
|
666
671
|
|
|
667
|
-
if (
|
|
668
|
-
|
|
672
|
+
if (SCHEMA_TYPE === "request") {
|
|
673
|
+
if (mergedSchemas.readOnly && mergedSchemas.readOnly === true) {
|
|
674
|
+
return undefined;
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
if (SCHEMA_TYPE === "response") {
|
|
679
|
+
if (mergedSchemas.writeOnly && mergedSchemas.writeOnly === true) {
|
|
680
|
+
return undefined;
|
|
681
|
+
}
|
|
669
682
|
}
|
|
670
683
|
|
|
671
684
|
return create("SchemaItem", {
|
|
@@ -719,8 +732,16 @@ function createEdges({
|
|
|
719
732
|
);
|
|
720
733
|
}
|
|
721
734
|
|
|
722
|
-
if (
|
|
723
|
-
|
|
735
|
+
if (SCHEMA_TYPE === "request") {
|
|
736
|
+
if (schema.readOnly && schema.readOnly === true) {
|
|
737
|
+
return undefined;
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
if (SCHEMA_TYPE === "response") {
|
|
742
|
+
if (schema.writeOnly && schema.writeOnly === true) {
|
|
743
|
+
return undefined;
|
|
744
|
+
}
|
|
724
745
|
}
|
|
725
746
|
|
|
726
747
|
// primitives and array of non-objects
|
|
@@ -737,7 +758,11 @@ function createEdges({
|
|
|
737
758
|
/**
|
|
738
759
|
* Creates a hierarchical level of a schema tree. Nodes produce edges that can branch into sub-nodes with edges, recursively.
|
|
739
760
|
*/
|
|
740
|
-
export function createNodes(
|
|
761
|
+
export function createNodes(
|
|
762
|
+
schema: SchemaObject,
|
|
763
|
+
schemaType: "request" | "response"
|
|
764
|
+
): any {
|
|
765
|
+
SCHEMA_TYPE = schemaType;
|
|
741
766
|
const nodes = [];
|
|
742
767
|
// if (schema.discriminator !== undefined) {
|
|
743
768
|
// return createDiscriminator(schema);
|
package/src/openapi/openapi.ts
CHANGED
|
@@ -469,8 +469,7 @@ function bindCollectionToApiItems(
|
|
|
469
469
|
const method = item.request.method.toLowerCase();
|
|
470
470
|
const path = item.request.url
|
|
471
471
|
.getPath({ unresolved: true }) // unresolved returns "/:variableName" instead of "/<type>"
|
|
472
|
-
.replace(
|
|
473
|
-
|
|
472
|
+
.replace(/(?<![a-z0-9-_]+):([a-z0-9-_]+)/gi, "{$1}"); // replace "/:variableName" with "/{variableName}"
|
|
474
473
|
const apiItem = items.find((item) => {
|
|
475
474
|
if (item.type === "info" || item.type === "tag") {
|
|
476
475
|
return false;
|
package/src/options.ts
CHANGED
|
@@ -15,6 +15,12 @@ const sidebarOptions = Joi.object({
|
|
|
15
15
|
sidebarCollapsed: Joi.boolean(),
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
+
const markdownGenerators = Joi.object({
|
|
19
|
+
createApiPageMD: Joi.function(),
|
|
20
|
+
createInfoPageMD: Joi.function(),
|
|
21
|
+
createTagPageMD: Joi.function(),
|
|
22
|
+
});
|
|
23
|
+
|
|
18
24
|
export const OptionsSchema = Joi.object({
|
|
19
25
|
id: Joi.string().required(),
|
|
20
26
|
docsPluginId: Joi.string().required(),
|
|
@@ -30,6 +36,7 @@ export const OptionsSchema = Joi.object({
|
|
|
30
36
|
hideSendButton: Joi.boolean(),
|
|
31
37
|
showExtensions: Joi.boolean(),
|
|
32
38
|
sidebarOptions: sidebarOptions,
|
|
39
|
+
markdownGenerators: markdownGenerators,
|
|
33
40
|
version: Joi.string().when("versions", {
|
|
34
41
|
is: Joi.exist(),
|
|
35
42
|
then: Joi.required(),
|
package/src/types.ts
CHANGED
|
@@ -43,6 +43,13 @@ export interface APIOptions {
|
|
|
43
43
|
[key: string]: APIVersionOptions;
|
|
44
44
|
};
|
|
45
45
|
proxy?: string;
|
|
46
|
+
markdownGenerators?: MarkdownGenerator;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface MarkdownGenerator {
|
|
50
|
+
createApiPageMD?: (pageData: ApiPageMetadata) => string;
|
|
51
|
+
createInfoPageMD?: (pageData: InfoPageMetadata) => string;
|
|
52
|
+
createTagPageMD?: (pageData: TagPageMetadata) => string;
|
|
46
53
|
}
|
|
47
54
|
|
|
48
55
|
export interface SidebarOptions {
|