docusaurus-plugin-openapi-docs 4.5.1 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -22
- package/lib/index.js +122 -50
- package/lib/markdown/createHeading.js +1 -1
- package/lib/markdown/createRequestHeader.js +5 -3
- package/lib/markdown/createSchema.js +2 -2
- package/lib/markdown/index.js +3 -2
- package/lib/markdown/schema.js +5 -0
- package/lib/markdown/utils.d.ts +38 -1
- package/lib/markdown/utils.js +100 -2
- package/lib/openapi/createSchemaExample.js +16 -2
- package/lib/openapi/createSchemaExample.test.d.ts +1 -0
- package/lib/openapi/createSchemaExample.test.js +48 -0
- package/lib/openapi/openapi.js +38 -17
- package/lib/openapi/openapi.test.js +48 -0
- package/lib/openapi/webhooks.test.d.ts +1 -0
- package/lib/openapi/webhooks.test.js +23 -0
- package/lib/options.js +4 -0
- package/lib/sidebars/index.js +12 -3
- package/package.json +16 -16
- package/src/index.ts +165 -62
- package/src/markdown/createHeading.ts +2 -2
- package/src/markdown/createRequestHeader.ts +9 -11
- package/src/markdown/createSchema.ts +4 -2
- package/src/markdown/index.ts +3 -2
- package/src/markdown/schema.ts +6 -0
- package/src/markdown/utils.ts +153 -3
- package/src/openapi/__fixtures__/webhook/openapi.yaml +17 -0
- package/src/openapi/createSchemaExample.test.ts +57 -0
- package/src/openapi/createSchemaExample.ts +26 -2
- package/src/openapi/openapi.test.ts +58 -0
- package/src/openapi/openapi.ts +35 -6
- package/src/openapi/webhooks.test.ts +30 -0
- package/src/options.ts +4 -0
- package/src/plugin-openapi.d.ts +1 -1
- package/src/sidebars/index.ts +15 -3
- package/src/{types.ts → types.d.ts} +12 -2
- package/lib/types.d.ts +0 -135
- package/lib/types.js +0 -8
- package/src/plugin-content-docs-types.d.ts +0 -42
package/src/markdown/utils.ts
CHANGED
|
@@ -5,9 +5,93 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
* ========================================================================== */
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Represents an external JSON file to be written alongside the MDX.
|
|
10
|
+
*/
|
|
11
|
+
export interface ExternalFile {
|
|
12
|
+
/** The filename for the JSON file (relative to outputDir) */
|
|
13
|
+
filename: string;
|
|
14
|
+
/** The JSON content to write */
|
|
15
|
+
content: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Result of running MDX generation with externalization.
|
|
20
|
+
*/
|
|
21
|
+
export interface ExternalizationResult<T> {
|
|
22
|
+
/** The result of the generation function */
|
|
23
|
+
result: T;
|
|
24
|
+
/** External JSON files to write */
|
|
25
|
+
files: ExternalFile[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Context for externalization during MDX generation.
|
|
30
|
+
*/
|
|
31
|
+
interface ExternalizationContext {
|
|
32
|
+
/** Base filename for external files (e.g., "add-pet" for "add-pet.api.mdx") */
|
|
33
|
+
baseFilename: string;
|
|
34
|
+
/** Counter for generating unique filenames per component type */
|
|
35
|
+
componentCounters: Record<string, number>;
|
|
36
|
+
/** Collected external files during generation */
|
|
37
|
+
files: ExternalFile[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Module-level externalization context.
|
|
42
|
+
* Note: AsyncLocalStorage would be cleaner but isn't available in browser bundles.
|
|
43
|
+
*/
|
|
44
|
+
let externalizationContext: ExternalizationContext | null = null;
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Components whose props should be externalized to separate JSON files.
|
|
48
|
+
* These are the components that typically receive large JSON objects.
|
|
49
|
+
*/
|
|
50
|
+
const EXTERNALIZABLE_COMPONENTS = new Set([
|
|
51
|
+
"StatusCodes",
|
|
52
|
+
"ParamsDetails",
|
|
53
|
+
"RequestSchema",
|
|
54
|
+
"Schema",
|
|
55
|
+
"SchemaItem",
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Runs a function with externalization enabled.
|
|
60
|
+
* Any calls to create() within the function will externalize eligible component props.
|
|
61
|
+
*
|
|
62
|
+
* @param baseFilename - Base filename for the MDX file (without extension)
|
|
63
|
+
* @param fn - Function to run with externalization enabled
|
|
64
|
+
* @returns The function result and any external files that were collected
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* const { result: mdx, files } = runWithExternalization("add-pet", () => {
|
|
68
|
+
* return createApiPageMD(item);
|
|
69
|
+
* });
|
|
70
|
+
*/
|
|
71
|
+
export function runWithExternalization<T>(
|
|
72
|
+
baseFilename: string,
|
|
73
|
+
fn: () => T
|
|
74
|
+
): ExternalizationResult<T> {
|
|
75
|
+
// Set up context
|
|
76
|
+
externalizationContext = {
|
|
77
|
+
baseFilename,
|
|
78
|
+
componentCounters: {},
|
|
79
|
+
files: [],
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
try {
|
|
83
|
+
const result = fn();
|
|
84
|
+
const files = externalizationContext.files;
|
|
85
|
+
return { result, files };
|
|
86
|
+
} finally {
|
|
87
|
+
// Always clear context
|
|
88
|
+
externalizationContext = null;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
8
92
|
/**
|
|
9
93
|
* Children in the plugin does not accept DOM elements, when compared with Children in the theme.
|
|
10
|
-
* It is designed for rendering HTML
|
|
94
|
+
* It is designed for rendering HTML as strings.
|
|
11
95
|
*/
|
|
12
96
|
export type Children = string | undefined | (string | string[] | undefined)[];
|
|
13
97
|
|
|
@@ -15,6 +99,11 @@ export type Props = Record<string, any> & { children?: Children };
|
|
|
15
99
|
|
|
16
100
|
export type Options = { inline?: boolean };
|
|
17
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Creates a JSX component string with the given tag, props, and options.
|
|
104
|
+
* When called within runWithExternalization(), props for eligible
|
|
105
|
+
* components are externalized to a single JSON file and spread.
|
|
106
|
+
*/
|
|
18
107
|
export function create(
|
|
19
108
|
tag: string,
|
|
20
109
|
props: Props,
|
|
@@ -23,9 +112,27 @@ export function create(
|
|
|
23
112
|
const { children, ...rest } = props;
|
|
24
113
|
|
|
25
114
|
let propString = "";
|
|
26
|
-
|
|
27
|
-
|
|
115
|
+
|
|
116
|
+
// Check if this component's props should be externalized
|
|
117
|
+
if (shouldExternalizeComponent(tag, rest)) {
|
|
118
|
+
const filename = generateExternalFilename(tag);
|
|
119
|
+
const content = JSON.stringify(rest);
|
|
120
|
+
|
|
121
|
+
// Add to external files
|
|
122
|
+
externalizationContext!.files.push({
|
|
123
|
+
filename,
|
|
124
|
+
content,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Use spread syntax with require
|
|
128
|
+
propString = `\n {...require("./${filename}")}`;
|
|
129
|
+
} else {
|
|
130
|
+
// Inline props as usual
|
|
131
|
+
for (const [key, value] of Object.entries(rest)) {
|
|
132
|
+
propString += `\n ${key}={${JSON.stringify(value)}}`;
|
|
133
|
+
}
|
|
28
134
|
}
|
|
135
|
+
|
|
29
136
|
let indentedChildren = render(children).replace(/^/gm, " ");
|
|
30
137
|
|
|
31
138
|
if (options.inline) {
|
|
@@ -38,6 +145,49 @@ export function create(
|
|
|
38
145
|
return `<${tag}${propString}>\n${indentedChildren}</${tag}>`;
|
|
39
146
|
}
|
|
40
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Determines if a component's props should be externalized.
|
|
150
|
+
*/
|
|
151
|
+
function shouldExternalizeComponent(
|
|
152
|
+
tag: string,
|
|
153
|
+
props: Record<string, any>
|
|
154
|
+
): boolean {
|
|
155
|
+
// No context means externalization is not enabled
|
|
156
|
+
if (!externalizationContext) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (!EXTERNALIZABLE_COMPONENTS.has(tag)) {
|
|
161
|
+
return false;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Don't externalize if props are empty or only contain undefined/null
|
|
165
|
+
const hasContent = Object.values(props).some(
|
|
166
|
+
(v) => v !== undefined && v !== null
|
|
167
|
+
);
|
|
168
|
+
if (!hasContent) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Generates a unique filename for an externalized component's props.
|
|
177
|
+
*/
|
|
178
|
+
function generateExternalFilename(componentName: string): string {
|
|
179
|
+
if (!externalizationContext) {
|
|
180
|
+
throw new Error("Externalization context not set");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const count =
|
|
184
|
+
(externalizationContext.componentCounters[componentName] ?? 0) + 1;
|
|
185
|
+
externalizationContext.componentCounters[componentName] = count;
|
|
186
|
+
|
|
187
|
+
const suffix = count > 1 ? `.${count}` : "";
|
|
188
|
+
return `${externalizationContext.baseFilename}.${componentName}${suffix}.json`;
|
|
189
|
+
}
|
|
190
|
+
|
|
41
191
|
export function guard<T>(
|
|
42
192
|
value: T | undefined,
|
|
43
193
|
cb: (value: T) => Children
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
openapi: 3.0.3
|
|
2
|
+
info:
|
|
3
|
+
title: Webhook Example
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
paths: {}
|
|
6
|
+
webhooks:
|
|
7
|
+
order.created:
|
|
8
|
+
post:
|
|
9
|
+
requestBody:
|
|
10
|
+
description: example body
|
|
11
|
+
content:
|
|
12
|
+
application/json:
|
|
13
|
+
schema:
|
|
14
|
+
type: object
|
|
15
|
+
responses:
|
|
16
|
+
"200":
|
|
17
|
+
description: OK
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Copyright (c) Palo Alto Networks
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
* ========================================================================== */
|
|
7
|
+
|
|
8
|
+
import { sampleFromSchema } from "./createSchemaExample";
|
|
9
|
+
import { SchemaObject } from "./types";
|
|
10
|
+
|
|
11
|
+
describe("sampleFromSchema", () => {
|
|
12
|
+
describe("const support", () => {
|
|
13
|
+
it("should return default string value when const is not present", () => {
|
|
14
|
+
const schema: SchemaObject = {
|
|
15
|
+
type: "string",
|
|
16
|
+
};
|
|
17
|
+
const context = { type: "request" as const };
|
|
18
|
+
|
|
19
|
+
const result = sampleFromSchema(schema, context);
|
|
20
|
+
|
|
21
|
+
expect(result).toBe("string");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("should return const value when const is present", () => {
|
|
25
|
+
const schema: SchemaObject = {
|
|
26
|
+
type: "string",
|
|
27
|
+
const: "example",
|
|
28
|
+
};
|
|
29
|
+
const context = { type: "request" as const };
|
|
30
|
+
|
|
31
|
+
const result = sampleFromSchema(schema, context);
|
|
32
|
+
|
|
33
|
+
expect(result).toBe("example");
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should handle anyOf with const values", () => {
|
|
37
|
+
const schema: SchemaObject = {
|
|
38
|
+
type: "string",
|
|
39
|
+
anyOf: [
|
|
40
|
+
{
|
|
41
|
+
type: "string",
|
|
42
|
+
const: "dog",
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
type: "string",
|
|
46
|
+
const: "cat",
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
};
|
|
50
|
+
const context = { type: "request" as const };
|
|
51
|
+
|
|
52
|
+
const result = sampleFromSchema(schema, context);
|
|
53
|
+
|
|
54
|
+
expect(result).toBe("dog");
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
});
|
|
@@ -91,7 +91,12 @@ function sampleFromProp(
|
|
|
91
91
|
|
|
92
92
|
// TODO: handle discriminators
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
// Check for explicit example/examples first (OAS 3.1 support)
|
|
95
|
+
if (prop.example !== undefined) {
|
|
96
|
+
obj[name] = prop.example;
|
|
97
|
+
} else if (prop.examples !== undefined && prop.examples.length > 0) {
|
|
98
|
+
obj[name] = prop.examples[0];
|
|
99
|
+
} else if (prop.oneOf) {
|
|
95
100
|
obj[name] = sampleFromSchema(prop.oneOf[0], context);
|
|
96
101
|
} else if (prop.anyOf) {
|
|
97
102
|
obj[name] = sampleFromSchema(prop.anyOf[0], context);
|
|
@@ -111,12 +116,27 @@ export const sampleFromSchema = (
|
|
|
111
116
|
try {
|
|
112
117
|
// deep copy schema before processing
|
|
113
118
|
let schemaCopy = JSON.parse(JSON.stringify(schema));
|
|
114
|
-
let {
|
|
119
|
+
let {
|
|
120
|
+
type,
|
|
121
|
+
example,
|
|
122
|
+
examples,
|
|
123
|
+
allOf,
|
|
124
|
+
properties,
|
|
125
|
+
items,
|
|
126
|
+
oneOf,
|
|
127
|
+
anyOf,
|
|
128
|
+
const: constant,
|
|
129
|
+
} = schemaCopy;
|
|
115
130
|
|
|
116
131
|
if (example !== undefined) {
|
|
117
132
|
return example;
|
|
118
133
|
}
|
|
119
134
|
|
|
135
|
+
// OAS 3.1 / JSON Schema: examples is an array
|
|
136
|
+
if (examples !== undefined && examples.length > 0) {
|
|
137
|
+
return examples[0];
|
|
138
|
+
}
|
|
139
|
+
|
|
120
140
|
if (oneOf) {
|
|
121
141
|
if (properties) {
|
|
122
142
|
const combinedSchemas = merge(schemaCopy, oneOf[0]);
|
|
@@ -218,6 +238,10 @@ export const sampleFromSchema = (
|
|
|
218
238
|
return undefined;
|
|
219
239
|
}
|
|
220
240
|
|
|
241
|
+
if (constant) {
|
|
242
|
+
return constant;
|
|
243
|
+
}
|
|
244
|
+
|
|
221
245
|
return primitive(schemaCopy);
|
|
222
246
|
} catch (err) {
|
|
223
247
|
console.error(
|
|
@@ -11,6 +11,8 @@ import path from "path";
|
|
|
11
11
|
import { posixPath } from "@docusaurus/utils";
|
|
12
12
|
|
|
13
13
|
import { readOpenapiFiles } from ".";
|
|
14
|
+
import { processOpenapiFile } from "./openapi";
|
|
15
|
+
import type { APIOptions, SidebarOptions } from "../types";
|
|
14
16
|
|
|
15
17
|
// npx jest packages/docusaurus-plugin-openapi/src/openapi/openapi.test.ts --watch
|
|
16
18
|
|
|
@@ -37,4 +39,60 @@ describe("openapi", () => {
|
|
|
37
39
|
).toBeDefined();
|
|
38
40
|
});
|
|
39
41
|
});
|
|
42
|
+
|
|
43
|
+
describe("schemasOnly", () => {
|
|
44
|
+
it("includes schema metadata when showSchemas is disabled", async () => {
|
|
45
|
+
const openapiData = {
|
|
46
|
+
openapi: "3.0.0",
|
|
47
|
+
info: {
|
|
48
|
+
title: "Schema Only",
|
|
49
|
+
version: "1.0.0",
|
|
50
|
+
},
|
|
51
|
+
paths: {
|
|
52
|
+
"/ping": {
|
|
53
|
+
get: {
|
|
54
|
+
summary: "Ping",
|
|
55
|
+
responses: {
|
|
56
|
+
"200": {
|
|
57
|
+
description: "OK",
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
components: {
|
|
64
|
+
schemas: {
|
|
65
|
+
WithoutTags: {
|
|
66
|
+
title: "Without Tags",
|
|
67
|
+
type: "object",
|
|
68
|
+
properties: {
|
|
69
|
+
value: {
|
|
70
|
+
type: "string",
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const options: APIOptions = {
|
|
79
|
+
specPath: "dummy", // required by the type but unused in this context
|
|
80
|
+
outputDir: "build",
|
|
81
|
+
showSchemas: false,
|
|
82
|
+
schemasOnly: true,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const sidebarOptions = {} as SidebarOptions;
|
|
86
|
+
|
|
87
|
+
const [items] = await processOpenapiFile(
|
|
88
|
+
openapiData as any,
|
|
89
|
+
options,
|
|
90
|
+
sidebarOptions
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
const schemaItems = items.filter((item) => item.type === "schema");
|
|
94
|
+
expect(schemaItems).toHaveLength(1);
|
|
95
|
+
expect(schemaItems[0].id).toBe("without-tags");
|
|
96
|
+
});
|
|
97
|
+
});
|
|
40
98
|
});
|
package/src/openapi/openapi.ts
CHANGED
|
@@ -43,9 +43,15 @@ function jsonToCollection(data: OpenApiObject): Promise<Collection> {
|
|
|
43
43
|
{ schemaFaker: false }
|
|
44
44
|
);
|
|
45
45
|
schemaPack.computedOptions.schemaFaker = false;
|
|
46
|
+
|
|
47
|
+
// Make sure the schema was properly validated or reject with error
|
|
48
|
+
if (!schemaPack.validationResult?.result) {
|
|
49
|
+
return reject(schemaPack.validationResult?.reason);
|
|
50
|
+
}
|
|
51
|
+
|
|
46
52
|
schemaPack.convert((_err: any, conversionResult: any) => {
|
|
47
|
-
if (!conversionResult.result) {
|
|
48
|
-
return reject(conversionResult.reason);
|
|
53
|
+
if (_err || !conversionResult.result) {
|
|
54
|
+
return reject(_err || conversionResult.reason);
|
|
49
55
|
}
|
|
50
56
|
return resolve(new sdk.Collection(conversionResult.output[0].data));
|
|
51
57
|
});
|
|
@@ -89,9 +95,13 @@ function createItems(
|
|
|
89
95
|
let items: PartialPage<ApiMetadata>[] = [];
|
|
90
96
|
const infoIdSpaces = openapiData.info.title.replace(" ", "-").toLowerCase();
|
|
91
97
|
const infoId = kebabCase(infoIdSpaces);
|
|
98
|
+
const schemasOnly = options?.schemasOnly === true;
|
|
92
99
|
|
|
93
|
-
|
|
94
|
-
|
|
100
|
+
// Only create an info page if we have a description/title AND showInfoPage is not false
|
|
101
|
+
if (
|
|
102
|
+
(openapiData.info.description || openapiData.info.title) &&
|
|
103
|
+
options?.showInfoPage !== false
|
|
104
|
+
) {
|
|
95
105
|
const infoDescription = openapiData.info?.description;
|
|
96
106
|
let splitDescription: any;
|
|
97
107
|
if (infoDescription) {
|
|
@@ -250,6 +260,9 @@ function createItems(
|
|
|
250
260
|
...(options?.showExtensions && {
|
|
251
261
|
show_extensions: options.showExtensions,
|
|
252
262
|
}),
|
|
263
|
+
...(options?.maskCredentials === false && {
|
|
264
|
+
mask_credentials_disabled: true,
|
|
265
|
+
}),
|
|
253
266
|
},
|
|
254
267
|
api: {
|
|
255
268
|
...defaults,
|
|
@@ -274,11 +287,19 @@ function createItems(
|
|
|
274
287
|
for (let [path, pathObject] of Object.entries(
|
|
275
288
|
openapiData["x-webhooks"] ?? openapiData["webhooks"] ?? {}
|
|
276
289
|
)) {
|
|
290
|
+
const eventName = path;
|
|
277
291
|
path = "webhook";
|
|
278
292
|
const { $ref, description, parameters, servers, summary, ...rest } =
|
|
279
293
|
pathObject;
|
|
280
294
|
for (let [method, operationObject] of Object.entries({ ...rest })) {
|
|
281
295
|
method = "event";
|
|
296
|
+
if (
|
|
297
|
+
operationObject.summary === undefined &&
|
|
298
|
+
operationObject.operationId === undefined
|
|
299
|
+
) {
|
|
300
|
+
operationObject.summary = eventName;
|
|
301
|
+
}
|
|
302
|
+
|
|
282
303
|
const title =
|
|
283
304
|
operationObject.summary ??
|
|
284
305
|
operationObject.operationId ??
|
|
@@ -290,7 +311,7 @@ function createItems(
|
|
|
290
311
|
|
|
291
312
|
const baseId = operationObject.operationId
|
|
292
313
|
? kebabCase(operationObject.operationId)
|
|
293
|
-
: kebabCase(operationObject.summary);
|
|
314
|
+
: kebabCase(operationObject.summary ?? eventName);
|
|
294
315
|
|
|
295
316
|
const extensions = [];
|
|
296
317
|
const commonExtensions = ["x-codeSamples"];
|
|
@@ -395,6 +416,9 @@ function createItems(
|
|
|
395
416
|
...(options?.showExtensions && {
|
|
396
417
|
show_extensions: options.showExtensions,
|
|
397
418
|
}),
|
|
419
|
+
...(options?.maskCredentials === false && {
|
|
420
|
+
mask_credentials_disabled: true,
|
|
421
|
+
}),
|
|
398
422
|
},
|
|
399
423
|
api: {
|
|
400
424
|
...defaults,
|
|
@@ -414,6 +438,7 @@ function createItems(
|
|
|
414
438
|
}
|
|
415
439
|
|
|
416
440
|
if (
|
|
441
|
+
schemasOnly ||
|
|
417
442
|
options?.showSchemas === true ||
|
|
418
443
|
Object.entries(openapiData?.components?.schemas ?? {})
|
|
419
444
|
.flatMap(([_, s]) => s["x-tags"])
|
|
@@ -423,7 +448,11 @@ function createItems(
|
|
|
423
448
|
for (let [schema, schemaObject] of Object.entries(
|
|
424
449
|
openapiData?.components?.schemas ?? {}
|
|
425
450
|
)) {
|
|
426
|
-
if (
|
|
451
|
+
if (
|
|
452
|
+
schemasOnly ||
|
|
453
|
+
options?.showSchemas === true ||
|
|
454
|
+
schemaObject["x-tags"]
|
|
455
|
+
) {
|
|
427
456
|
const baseIdSpaces =
|
|
428
457
|
schemaObject?.title?.replace(" ", "-").toLowerCase() ?? "";
|
|
429
458
|
const baseId = kebabCase(baseIdSpaces);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/* ============================================================================
|
|
2
|
+
* Copyright (c) Palo Alto Networks
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
* ========================================================================== */
|
|
7
|
+
|
|
8
|
+
import path from "path";
|
|
9
|
+
|
|
10
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
11
|
+
import { posixPath } from "@docusaurus/utils";
|
|
12
|
+
|
|
13
|
+
import { readOpenapiFiles, processOpenapiFiles } from ".";
|
|
14
|
+
|
|
15
|
+
describe("webhooks", () => {
|
|
16
|
+
it("uses event name when summary and operationId are missing", async () => {
|
|
17
|
+
const files = await readOpenapiFiles(
|
|
18
|
+
posixPath(path.join(__dirname, "__fixtures__/webhook/openapi.yaml"))
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const [items] = await processOpenapiFiles(
|
|
22
|
+
files,
|
|
23
|
+
{ specPath: "", outputDir: "" } as any,
|
|
24
|
+
{}
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
const webhookItem = items.find((item) => item.type === "api");
|
|
28
|
+
expect(webhookItem?.id).toBe("order-created");
|
|
29
|
+
});
|
|
30
|
+
});
|
package/src/options.ts
CHANGED
|
@@ -48,7 +48,11 @@ export const OptionsSchema = Joi.object({
|
|
|
48
48
|
sidebarOptions: sidebarOptions,
|
|
49
49
|
markdownGenerators: markdownGenerators,
|
|
50
50
|
showSchemas: Joi.boolean(),
|
|
51
|
+
showInfoPage: Joi.boolean(),
|
|
52
|
+
schemasOnly: Joi.boolean(),
|
|
51
53
|
disableCompression: Joi.boolean(),
|
|
54
|
+
maskCredentials: Joi.boolean(),
|
|
55
|
+
externalJsonProps: Joi.boolean().default(true),
|
|
52
56
|
version: Joi.string().when("versions", {
|
|
53
57
|
is: Joi.exist(),
|
|
54
58
|
then: Joi.required(),
|
package/src/plugin-openapi.d.ts
CHANGED
|
@@ -11,7 +11,7 @@ import type { FrontMatter as DocsFrontMatter } from "@docusaurus/types";
|
|
|
11
11
|
import type { Props as DocsProps } from "@docusaurus/types";
|
|
12
12
|
|
|
13
13
|
declare module "docusaurus-plugin-openapi-docs" {
|
|
14
|
-
import type { PropSidebars } from "@docusaurus/plugin-content-docs
|
|
14
|
+
import type { PropSidebars } from "@docusaurus/plugin-content-docs/lib/sidebars/types";
|
|
15
15
|
|
|
16
16
|
export type Options = Partial<import("./types").APIOptions>;
|
|
17
17
|
|
package/src/sidebars/index.ts
CHANGED
|
@@ -125,9 +125,21 @@ function groupByTags(
|
|
|
125
125
|
apiTags = uniq(apiTags.concat(operationTags, schemaTags));
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
:
|
|
128
|
+
// Extract base path from outputDir, handling cases where docPath may not be in outputDir
|
|
129
|
+
const getBasePathFromOutput = (
|
|
130
|
+
output: string,
|
|
131
|
+
doc: string | undefined
|
|
132
|
+
): string => {
|
|
133
|
+
if (doc && output.includes(doc)) {
|
|
134
|
+
return output.split(doc)[1]?.replace(/^\/+/g, "") ?? "";
|
|
135
|
+
}
|
|
136
|
+
const slashIndex = output.indexOf("/", 1);
|
|
137
|
+
return slashIndex === -1
|
|
138
|
+
? ""
|
|
139
|
+
: output.slice(slashIndex).replace(/^\/+/g, "");
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const basePath = getBasePathFromOutput(outputDir, docPath);
|
|
131
143
|
|
|
132
144
|
const createDocItemFnContext = {
|
|
133
145
|
sidebarOptions,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
* ========================================================================== */
|
|
7
7
|
|
|
8
|
-
import { SidebarItemDoc } from "@docusaurus/plugin-content-docs/
|
|
8
|
+
import type { SidebarItemDoc } from "@docusaurus/plugin-content-docs/lib/sidebars/types";
|
|
9
9
|
import Request from "postman-collection";
|
|
10
10
|
|
|
11
11
|
import {
|
|
@@ -21,7 +21,7 @@ export type {
|
|
|
21
21
|
SidebarItemLink,
|
|
22
22
|
PropSidebar,
|
|
23
23
|
PropSidebarItem,
|
|
24
|
-
} from "@docusaurus/plugin-content-docs
|
|
24
|
+
} from "@docusaurus/plugin-content-docs/lib/sidebars/types";
|
|
25
25
|
export interface PluginOptions {
|
|
26
26
|
id?: string;
|
|
27
27
|
docsPlugin?: string;
|
|
@@ -51,7 +51,17 @@ export interface APIOptions {
|
|
|
51
51
|
proxy?: string;
|
|
52
52
|
markdownGenerators?: MarkdownGenerator;
|
|
53
53
|
showSchemas?: boolean;
|
|
54
|
+
showInfoPage?: boolean;
|
|
55
|
+
schemasOnly?: boolean;
|
|
54
56
|
disableCompression?: boolean;
|
|
57
|
+
maskCredentials?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* When enabled, large JSON props in generated MDX are written to external
|
|
60
|
+
* files and loaded via require(). This can significantly improve MDX
|
|
61
|
+
* compilation performance for large OpenAPI specs.
|
|
62
|
+
* @see https://github.com/facebook/docusaurus/discussions/11664
|
|
63
|
+
*/
|
|
64
|
+
externalJsonProps?: boolean;
|
|
55
65
|
}
|
|
56
66
|
|
|
57
67
|
export interface MarkdownGenerator {
|