docusaurus-theme-openapi-docs 5.0.2 → 5.1.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/lib/markdown/schema.js +38 -15
- package/lib/markdown/schema.test.d.ts +1 -0
- package/lib/markdown/schema.test.js +86 -0
- package/lib/theme/ApiExplorer/ApiCodeBlock/Container/index.js +4 -2
- package/lib/theme/ApiExplorer/ApiCodeBlock/Content/String.js +9 -6
- package/lib/theme/ApiExplorer/ApiCodeBlock/Line/index.d.ts +1 -1
- package/lib/theme/ApiExplorer/ApiCodeBlock/index.d.ts +1 -1
- package/lib/theme/ApiExplorer/Authorization/index.js +9 -10
- package/lib/theme/ApiExplorer/Body/index.js +4 -5
- package/lib/theme/ApiExplorer/CodeSnippets/index.js +96 -61
- package/lib/theme/ApiExplorer/CodeSnippets/languages.js +12 -1
- package/lib/theme/ApiExplorer/CodeSnippets/languages.test.d.ts +1 -0
- package/lib/theme/ApiExplorer/CodeSnippets/languages.test.js +102 -0
- package/lib/theme/ApiExplorer/CodeTabs/index.d.ts +1 -1
- package/lib/theme/ApiExplorer/CodeTabs/index.js +6 -5
- package/lib/theme/ApiExplorer/Export/index.js +9 -2
- package/lib/theme/ApiExplorer/FormFileUpload/index.js +1 -2
- package/lib/theme/ApiExplorer/FormLabel/index.js +1 -2
- package/lib/theme/ApiExplorer/FormTextInput/index.js +1 -2
- package/lib/theme/ApiExplorer/LiveEditor/index.js +1 -2
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.js +5 -3
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.js +75 -4
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.js +1 -2
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.js +67 -4
- package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.js +65 -1
- package/lib/theme/ApiExplorer/ParamOptions/index.js +2 -3
- package/lib/theme/ApiExplorer/Request/index.js +17 -18
- package/lib/theme/ApiExplorer/Response/index.js +54 -12
- package/lib/theme/ApiExplorer/SecuritySchemes/index.js +57 -50
- package/lib/theme/ApiExplorer/Server/index.js +2 -3
- package/lib/theme/ApiItem/index.js +59 -33
- package/lib/theme/ApiTabs/index.d.ts +1 -1
- package/lib/theme/ApiTabs/index.js +7 -7
- package/lib/theme/DiscriminatorTabs/index.d.ts +1 -1
- package/lib/theme/DiscriminatorTabs/index.js +6 -5
- package/lib/theme/Example/index.js +3 -4
- package/lib/theme/MimeTabs/index.d.ts +1 -1
- package/lib/theme/MimeTabs/index.js +6 -5
- package/lib/theme/OperationTabs/index.d.ts +1 -1
- package/lib/theme/OperationTabs/index.js +6 -5
- package/lib/theme/ParamsDetails/index.js +1 -2
- package/lib/theme/ParamsItem/index.js +7 -8
- package/lib/theme/RequestSchema/index.js +57 -57
- package/lib/theme/ResponseExamples/index.js +3 -4
- package/lib/theme/ResponseSchema/index.js +26 -24
- package/lib/theme/Schema/index.js +148 -27
- package/lib/theme/SchemaExpansion/_SchemaExpansion.scss +113 -0
- package/lib/theme/SchemaExpansion/context.d.ts +24 -0
- package/lib/theme/SchemaExpansion/context.js +187 -0
- package/lib/theme/SchemaExpansion/index.d.ts +4 -0
- package/lib/theme/SchemaExpansion/index.js +314 -0
- package/lib/theme/SchemaItem/index.js +9 -10
- package/lib/theme/SchemaTabs/index.d.ts +1 -1
- package/lib/theme/SchemaTabs/index.js +6 -5
- package/lib/theme/StatusCodes/index.js +2 -4
- package/lib/theme/TabItem/index.d.ts +5 -0
- package/lib/theme/TabItem/index.js +51 -0
- package/lib/theme/TabItem/styles.module.css +3 -0
- package/lib/theme/Tabs/index.d.ts +5 -0
- package/lib/theme/Tabs/index.js +148 -0
- package/lib/theme/Tabs/styles.module.css +7 -0
- package/lib/theme/styles.scss +1 -0
- package/lib/theme/translationIds.d.ts +1 -93
- package/lib/theme/translationIds.js +0 -109
- package/lib/theme/utils/codeBlockUtils.d.ts +28 -0
- package/lib/theme/utils/codeBlockUtils.js +223 -0
- package/lib/theme/utils/reactUtils.d.ts +1 -0
- package/lib/theme/utils/reactUtils.js +23 -0
- package/lib/theme/utils/scrollUtils.d.ts +7 -0
- package/lib/theme/utils/scrollUtils.js +175 -0
- package/lib/theme/utils/tabsUtils.d.ts +47 -0
- package/lib/theme/utils/tabsUtils.js +299 -0
- package/lib/theme/utils/useCodeWordWrap.d.ts +8 -0
- package/lib/theme/utils/useCodeWordWrap.js +84 -0
- package/lib/theme/utils/useMutationObserver.d.ts +3 -0
- package/lib/theme/utils/useMutationObserver.js +34 -0
- package/package.json +4 -4
- package/src/markdown/schema.test.ts +102 -0
- package/src/markdown/schema.ts +42 -15
- package/src/theme/ApiExplorer/ApiCodeBlock/Container/index.tsx +2 -1
- package/src/theme/ApiExplorer/ApiCodeBlock/Content/String.tsx +8 -7
- package/src/theme/ApiExplorer/ApiCodeBlock/Line/index.tsx +1 -1
- package/src/theme/ApiExplorer/ApiCodeBlock/index.tsx +1 -1
- package/src/theme/ApiExplorer/Authorization/index.tsx +9 -10
- package/src/theme/ApiExplorer/Body/index.tsx +7 -5
- package/src/theme/ApiExplorer/CodeSnippets/index.tsx +103 -59
- package/src/theme/ApiExplorer/CodeSnippets/languages.test.ts +109 -0
- package/src/theme/ApiExplorer/CodeSnippets/languages.ts +13 -1
- package/src/theme/ApiExplorer/CodeTabs/index.tsx +5 -5
- package/src/theme/ApiExplorer/Export/index.tsx +6 -2
- package/src/theme/ApiExplorer/FormFileUpload/index.tsx +1 -2
- package/src/theme/ApiExplorer/FormLabel/index.tsx +1 -2
- package/src/theme/ApiExplorer/FormTextInput/index.tsx +1 -2
- package/src/theme/ApiExplorer/LiveEditor/index.tsx +1 -2
- package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.tsx +5 -3
- package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.tsx +20 -4
- package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.tsx +1 -2
- package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.tsx +15 -4
- package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.tsx +11 -1
- package/src/theme/ApiExplorer/ParamOptions/index.tsx +2 -3
- package/src/theme/ApiExplorer/Request/index.tsx +23 -18
- package/src/theme/ApiExplorer/Response/index.tsx +63 -9
- package/src/theme/ApiExplorer/SecuritySchemes/index.tsx +60 -52
- package/src/theme/ApiExplorer/Server/index.tsx +8 -3
- package/src/theme/ApiItem/index.tsx +43 -21
- package/src/theme/ApiTabs/index.tsx +8 -8
- package/src/theme/DiscriminatorTabs/index.tsx +6 -5
- package/src/theme/Example/index.tsx +3 -4
- package/src/theme/MimeTabs/index.tsx +9 -8
- package/src/theme/OperationTabs/index.tsx +5 -4
- package/src/theme/ParamsDetails/index.tsx +1 -2
- package/src/theme/ParamsItem/index.tsx +13 -8
- package/src/theme/RequestSchema/index.tsx +38 -40
- package/src/theme/ResponseExamples/index.tsx +3 -4
- package/src/theme/ResponseSchema/index.tsx +16 -17
- package/src/theme/Schema/index.tsx +156 -27
- package/src/theme/SchemaExpansion/_SchemaExpansion.scss +113 -0
- package/src/theme/SchemaExpansion/context.tsx +154 -0
- package/src/theme/SchemaExpansion/index.tsx +236 -0
- package/src/theme/SchemaItem/index.tsx +18 -10
- package/src/theme/SchemaTabs/index.tsx +6 -5
- package/src/theme/StatusCodes/index.tsx +2 -3
- package/src/theme/TabItem/index.tsx +61 -0
- package/src/theme/TabItem/styles.module.css +3 -0
- package/src/theme/Tabs/index.tsx +164 -0
- package/src/theme/Tabs/styles.module.css +7 -0
- package/src/theme/styles.scss +1 -0
- package/src/theme/translationIds.ts +37 -106
- package/src/theme/utils/codeBlockUtils.ts +296 -0
- package/src/theme/utils/reactUtils.ts +22 -0
- package/src/theme/utils/scrollUtils.tsx +153 -0
- package/src/theme/utils/tabsUtils.tsx +329 -0
- package/src/theme/utils/useCodeWordWrap.ts +110 -0
- package/src/theme/utils/useMutationObserver.ts +43 -0
- package/src/theme-classic.d.ts +0 -96
- package/src/types.d.ts +27 -0
- package/tsconfig.tsbuildinfo +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "docusaurus-theme-openapi-docs",
|
|
3
3
|
"description": "OpenAPI theme for Docusaurus.",
|
|
4
|
-
"version": "5.0
|
|
4
|
+
"version": "5.1.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"openapi",
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
"@types/pako": "^2.0.3",
|
|
38
38
|
"@types/postman-collection": "^3.5.11",
|
|
39
39
|
"@types/react-modal": "^3.16.3",
|
|
40
|
-
"concurrently": "^
|
|
41
|
-
"docusaurus-plugin-openapi-docs": "^5.0
|
|
40
|
+
"concurrently": "^10.0.3",
|
|
41
|
+
"docusaurus-plugin-openapi-docs": "^5.1.0",
|
|
42
42
|
"docusaurus-plugin-sass": "^0.2.6",
|
|
43
43
|
"eslint-plugin-prettier": "^5.5.1"
|
|
44
44
|
},
|
|
@@ -82,5 +82,5 @@
|
|
|
82
82
|
"engines": {
|
|
83
83
|
"node": ">=14"
|
|
84
84
|
},
|
|
85
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "977ec415b37207142f71f6e3d3780df834301d31"
|
|
86
86
|
}
|
|
@@ -0,0 +1,102 @@
|
|
|
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
|
+
jest.mock(
|
|
9
|
+
"@docusaurus/Translate",
|
|
10
|
+
() => ({
|
|
11
|
+
translate: ({ message }: { message: string }) => message,
|
|
12
|
+
}),
|
|
13
|
+
{ virtual: true }
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
import { getSchemaName } from "./schema";
|
|
17
|
+
import { SchemaObject } from "../types";
|
|
18
|
+
|
|
19
|
+
describe("getSchemaName", () => {
|
|
20
|
+
it("returns the type for a primitive schema", () => {
|
|
21
|
+
expect(getSchemaName({ type: "string" } as SchemaObject)).toBe("string");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("appends [] for an array of primitives", () => {
|
|
25
|
+
const schema: SchemaObject = {
|
|
26
|
+
type: "array",
|
|
27
|
+
items: { type: "string" },
|
|
28
|
+
} as SchemaObject;
|
|
29
|
+
expect(getSchemaName(schema)).toBe("string[]");
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("appends [][] for an array of arrays of primitives", () => {
|
|
33
|
+
const schema: SchemaObject = {
|
|
34
|
+
type: "array",
|
|
35
|
+
items: { type: "array", items: { type: "string" } },
|
|
36
|
+
} as SchemaObject;
|
|
37
|
+
expect(getSchemaName(schema)).toBe("string[][]");
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("appends [][] for an array of arrays of objects (issue #1114)", () => {
|
|
41
|
+
const schema: SchemaObject = {
|
|
42
|
+
type: "array",
|
|
43
|
+
items: {
|
|
44
|
+
type: "array",
|
|
45
|
+
items: { type: "object", properties: { foo: { type: "string" } } },
|
|
46
|
+
},
|
|
47
|
+
} as SchemaObject;
|
|
48
|
+
expect(getSchemaName(schema)).toBe("object[][]");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("handles three levels of array nesting", () => {
|
|
52
|
+
const schema: SchemaObject = {
|
|
53
|
+
type: "array",
|
|
54
|
+
items: {
|
|
55
|
+
type: "array",
|
|
56
|
+
items: { type: "array", items: { type: "integer" } },
|
|
57
|
+
},
|
|
58
|
+
} as SchemaObject;
|
|
59
|
+
expect(getSchemaName(schema)).toBe("integer[][][]");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it("joins OpenAPI 3.1 type arrays with ` | ` (issue #950)", () => {
|
|
63
|
+
const schema = { type: ["string", "null"] } as unknown as SchemaObject;
|
|
64
|
+
expect(getSchemaName(schema)).toBe("string | null");
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("unwraps a single-element type array", () => {
|
|
68
|
+
const schema = { type: ["integer"] } as unknown as SchemaObject;
|
|
69
|
+
expect(getSchemaName(schema)).toBe("integer");
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("renders single type with format as `type<format>`", () => {
|
|
73
|
+
const schema = {
|
|
74
|
+
type: "string",
|
|
75
|
+
format: "uuid",
|
|
76
|
+
} as SchemaObject;
|
|
77
|
+
expect(getSchemaName(schema)).toBe("string<uuid>");
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it("renders type union with format", () => {
|
|
81
|
+
const schema = {
|
|
82
|
+
type: ["string", "null"],
|
|
83
|
+
format: "uuid",
|
|
84
|
+
} as unknown as SchemaObject;
|
|
85
|
+
expect(getSchemaName(schema)).toBe("(string | null)<uuid>");
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("resolves type from an allOf wrapper that contains an enum", () => {
|
|
89
|
+
const schema = {
|
|
90
|
+
allOf: [{ type: "string", enum: ["a", "b"] }],
|
|
91
|
+
} as unknown as SchemaObject;
|
|
92
|
+
expect(getSchemaName(schema)).toBe("string");
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("renders array of items whose type is a union", () => {
|
|
96
|
+
const schema: SchemaObject = {
|
|
97
|
+
type: "array",
|
|
98
|
+
items: { type: ["string", "null"] } as any,
|
|
99
|
+
} as SchemaObject;
|
|
100
|
+
expect(getSchemaName(schema)).toBe("(string | null)[]");
|
|
101
|
+
});
|
|
102
|
+
});
|
package/src/markdown/schema.ts
CHANGED
|
@@ -7,7 +7,6 @@
|
|
|
7
7
|
|
|
8
8
|
import { translate } from "@docusaurus/Translate";
|
|
9
9
|
|
|
10
|
-
import { OPENAPI_SCHEMA_ITEM } from "../theme/translationIds";
|
|
11
10
|
import { SchemaObject } from "../types";
|
|
12
11
|
|
|
13
12
|
/**
|
|
@@ -48,6 +47,24 @@ function getTypeFromSchema(schema: SchemaObject): string | undefined {
|
|
|
48
47
|
return undefined;
|
|
49
48
|
}
|
|
50
49
|
|
|
50
|
+
// OpenAPI 3.1 / JSON Schema 2020-12 allows `type` to be an array of type names
|
|
51
|
+
// (e.g. `["string", "null"]`). Normalize to a single name and a pretty-printed
|
|
52
|
+
// union form joined with ` | `.
|
|
53
|
+
function normalizeType(type: unknown): {
|
|
54
|
+
single?: string;
|
|
55
|
+
pretty?: string;
|
|
56
|
+
isUnion: boolean;
|
|
57
|
+
} {
|
|
58
|
+
if (Array.isArray(type)) {
|
|
59
|
+
const filtered = type.filter((t): t is string => typeof t === "string");
|
|
60
|
+
if (filtered.length === 0) return { isUnion: false };
|
|
61
|
+
if (filtered.length === 1) return { single: filtered[0], isUnion: false };
|
|
62
|
+
return { pretty: filtered.join(" | "), isUnion: true };
|
|
63
|
+
}
|
|
64
|
+
if (typeof type === "string") return { single: type, isUnion: false };
|
|
65
|
+
return { isUnion: false };
|
|
66
|
+
}
|
|
67
|
+
|
|
51
68
|
function prettyName(schema: SchemaObject, circular?: boolean) {
|
|
52
69
|
// Handle enum-only schemas (valid in JSON Schema)
|
|
53
70
|
// When enum is present without explicit type, treat as string
|
|
@@ -55,7 +72,15 @@ function prettyName(schema: SchemaObject, circular?: boolean) {
|
|
|
55
72
|
return "string";
|
|
56
73
|
}
|
|
57
74
|
|
|
75
|
+
const t = normalizeType(schema.type);
|
|
76
|
+
|
|
58
77
|
if (schema.format) {
|
|
78
|
+
if (t.single) {
|
|
79
|
+
return `${t.single}<${schema.format}>`;
|
|
80
|
+
}
|
|
81
|
+
if (t.isUnion) {
|
|
82
|
+
return `(${t.pretty})<${schema.format}>`;
|
|
83
|
+
}
|
|
59
84
|
return schema.format;
|
|
60
85
|
}
|
|
61
86
|
|
|
@@ -83,21 +108,19 @@ function prettyName(schema: SchemaObject, circular?: boolean) {
|
|
|
83
108
|
return "object";
|
|
84
109
|
}
|
|
85
110
|
|
|
86
|
-
if (
|
|
87
|
-
return schema.xml?.name ??
|
|
88
|
-
// return schema.type;
|
|
111
|
+
if (t.single === "object") {
|
|
112
|
+
return schema.xml?.name ?? t.single;
|
|
89
113
|
}
|
|
90
114
|
|
|
91
|
-
if (
|
|
92
|
-
return schema.xml?.name ??
|
|
93
|
-
// return schema.type;
|
|
115
|
+
if (t.single === "array") {
|
|
116
|
+
return schema.xml?.name ?? t.single;
|
|
94
117
|
}
|
|
95
118
|
|
|
96
|
-
if (
|
|
97
|
-
return
|
|
119
|
+
if (t.isUnion) {
|
|
120
|
+
return t.pretty;
|
|
98
121
|
}
|
|
99
122
|
|
|
100
|
-
return schema.title ??
|
|
123
|
+
return schema.title ?? t.single;
|
|
101
124
|
}
|
|
102
125
|
|
|
103
126
|
export function getSchemaName(
|
|
@@ -105,7 +128,11 @@ export function getSchemaName(
|
|
|
105
128
|
circular?: boolean
|
|
106
129
|
): string {
|
|
107
130
|
if (schema.items) {
|
|
108
|
-
|
|
131
|
+
const items = schema.items as SchemaObject;
|
|
132
|
+
const inner = getSchemaName(items, circular);
|
|
133
|
+
const needsParens =
|
|
134
|
+
Array.isArray((items as any).type) && (items as any).type.length > 1;
|
|
135
|
+
return needsParens ? `(${inner})[]` : `${inner}[]`;
|
|
109
136
|
}
|
|
110
137
|
|
|
111
138
|
return prettyName(schema, circular) ?? "";
|
|
@@ -130,7 +157,7 @@ export function getQualifierMessage(schema?: SchemaObject): string | undefined {
|
|
|
130
157
|
}
|
|
131
158
|
|
|
132
159
|
let message = `**${translate({
|
|
133
|
-
id:
|
|
160
|
+
id: "theme.openapi.schemaItem.possibleValues",
|
|
134
161
|
message: "Possible values:",
|
|
135
162
|
})}** `;
|
|
136
163
|
|
|
@@ -149,11 +176,11 @@ export function getQualifierMessage(schema?: SchemaObject): string | undefined {
|
|
|
149
176
|
let minLength;
|
|
150
177
|
let maxLength;
|
|
151
178
|
const charactersMessage = translate({
|
|
152
|
-
id:
|
|
179
|
+
id: "theme.openapi.schemaItem.characters",
|
|
153
180
|
message: "characters",
|
|
154
181
|
});
|
|
155
182
|
const nonEmptyMessage = translate({
|
|
156
|
-
id:
|
|
183
|
+
id: "theme.openapi.schemaItem.nonEmpty",
|
|
157
184
|
message: "non-empty",
|
|
158
185
|
});
|
|
159
186
|
if (schema.minLength && schema.minLength > 1) {
|
|
@@ -218,7 +245,7 @@ export function getQualifierMessage(schema?: SchemaObject): string | undefined {
|
|
|
218
245
|
|
|
219
246
|
if (schema.pattern) {
|
|
220
247
|
const expressionMessage = translate({
|
|
221
|
-
id:
|
|
248
|
+
id: "theme.openapi.schemaItem.expression",
|
|
222
249
|
message: "Value must match regular expression",
|
|
223
250
|
});
|
|
224
251
|
qualifierGroups.push(`${expressionMessage} \`${schema.pattern}\``);
|
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
import React, { ComponentProps } from "react";
|
|
9
9
|
|
|
10
10
|
import { ThemeClassNames, usePrismTheme } from "@docusaurus/theme-common";
|
|
11
|
-
import { getPrismCssVariables } from "@docusaurus/theme-common/internal";
|
|
12
11
|
import clsx from "clsx";
|
|
13
12
|
|
|
13
|
+
import { getPrismCssVariables } from "@theme/utils/codeBlockUtils";
|
|
14
|
+
|
|
14
15
|
export default function CodeBlockContainer<T extends "div" | "pre">({
|
|
15
16
|
as: As,
|
|
16
17
|
...props
|
|
@@ -8,13 +8,6 @@
|
|
|
8
8
|
import React from "react";
|
|
9
9
|
|
|
10
10
|
import { useThemeConfig, usePrismTheme } from "@docusaurus/theme-common";
|
|
11
|
-
import {
|
|
12
|
-
parseCodeBlockTitle,
|
|
13
|
-
parseLanguage,
|
|
14
|
-
parseLines,
|
|
15
|
-
containsLineNumbers,
|
|
16
|
-
useCodeWordWrap,
|
|
17
|
-
} from "@docusaurus/theme-common/internal";
|
|
18
11
|
import Container from "@theme/ApiExplorer/ApiCodeBlock/Container";
|
|
19
12
|
import CopyButton from "@theme/ApiExplorer/ApiCodeBlock/CopyButton";
|
|
20
13
|
import ExpandButton from "@theme/ApiExplorer/ApiCodeBlock/ExpandButton";
|
|
@@ -24,6 +17,14 @@ import type { Props } from "@theme/CodeBlock/Content/String";
|
|
|
24
17
|
import clsx from "clsx";
|
|
25
18
|
import { Highlight, Language } from "prism-react-renderer";
|
|
26
19
|
|
|
20
|
+
import {
|
|
21
|
+
containsLineNumbers,
|
|
22
|
+
parseCodeBlockTitle,
|
|
23
|
+
parseLanguage,
|
|
24
|
+
parseLines,
|
|
25
|
+
} from "@theme/utils/codeBlockUtils";
|
|
26
|
+
import { useCodeWordWrap } from "@theme/utils/useCodeWordWrap";
|
|
27
|
+
|
|
27
28
|
export default function CodeBlockString({
|
|
28
29
|
children,
|
|
29
30
|
className: blockClassName = "",
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
import React, { isValidElement, ReactNode } from "react";
|
|
9
9
|
|
|
10
|
-
import { CodeBlockProps } from "@docusaurus/theme-common/internal";
|
|
11
10
|
import useIsBrowser from "@docusaurus/useIsBrowser";
|
|
11
|
+
import type { Props as CodeBlockProps } from "@theme/CodeBlock";
|
|
12
12
|
import ElementContent from "@theme/ApiExplorer/ApiCodeBlock/Content/Element";
|
|
13
13
|
import StringContent from "@theme/ApiExplorer/ApiCodeBlock/Content/String";
|
|
14
14
|
|
|
@@ -12,7 +12,6 @@ import FormItem from "@theme/ApiExplorer/FormItem";
|
|
|
12
12
|
import FormSelect from "@theme/ApiExplorer/FormSelect";
|
|
13
13
|
import FormTextInput from "@theme/ApiExplorer/FormTextInput";
|
|
14
14
|
import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
|
|
15
|
-
import { OPENAPI_AUTH } from "@theme/translationIds";
|
|
16
15
|
|
|
17
16
|
import { setAuthData, setSelectedAuth } from "./slice";
|
|
18
17
|
|
|
@@ -37,7 +36,7 @@ function Authorization() {
|
|
|
37
36
|
<FormItem>
|
|
38
37
|
<FormSelect
|
|
39
38
|
label={translate({
|
|
40
|
-
id:
|
|
39
|
+
id: "theme.openapi.auth.securityScheme",
|
|
41
40
|
message: "Security Scheme",
|
|
42
41
|
})}
|
|
43
42
|
options={optionKeys}
|
|
@@ -54,11 +53,11 @@ function Authorization() {
|
|
|
54
53
|
<FormItem key={a.key + "-bearer"}>
|
|
55
54
|
<FormTextInput
|
|
56
55
|
label={translate({
|
|
57
|
-
id:
|
|
56
|
+
id: "theme.openapi.auth.bearerToken",
|
|
58
57
|
message: "Bearer Token",
|
|
59
58
|
})}
|
|
60
59
|
placeholder={translate({
|
|
61
|
-
id:
|
|
60
|
+
id: "theme.openapi.auth.bearerToken",
|
|
62
61
|
message: "Bearer Token",
|
|
63
62
|
})}
|
|
64
63
|
password
|
|
@@ -83,11 +82,11 @@ function Authorization() {
|
|
|
83
82
|
<FormItem key={a.key + "-oauth2"}>
|
|
84
83
|
<FormTextInput
|
|
85
84
|
label={translate({
|
|
86
|
-
id:
|
|
85
|
+
id: "theme.openapi.auth.bearerToken",
|
|
87
86
|
message: "Bearer Token",
|
|
88
87
|
})}
|
|
89
88
|
placeholder={translate({
|
|
90
|
-
id:
|
|
89
|
+
id: "theme.openapi.auth.bearerToken",
|
|
91
90
|
message: "Bearer Token",
|
|
92
91
|
})}
|
|
93
92
|
password
|
|
@@ -113,11 +112,11 @@ function Authorization() {
|
|
|
113
112
|
<FormItem>
|
|
114
113
|
<FormTextInput
|
|
115
114
|
label={translate({
|
|
116
|
-
id:
|
|
115
|
+
id: "theme.openapi.auth.username",
|
|
117
116
|
message: "Username",
|
|
118
117
|
})}
|
|
119
118
|
placeholder={translate({
|
|
120
|
-
id:
|
|
119
|
+
id: "theme.openapi.auth.username",
|
|
121
120
|
message: "Username",
|
|
122
121
|
})}
|
|
123
122
|
value={data[a.key].username ?? ""}
|
|
@@ -136,11 +135,11 @@ function Authorization() {
|
|
|
136
135
|
<FormItem>
|
|
137
136
|
<FormTextInput
|
|
138
137
|
label={translate({
|
|
139
|
-
id:
|
|
138
|
+
id: "theme.openapi.auth.password",
|
|
140
139
|
message: "Password",
|
|
141
140
|
})}
|
|
142
141
|
placeholder={translate({
|
|
143
|
-
id:
|
|
142
|
+
id: "theme.openapi.auth.password",
|
|
144
143
|
message: "Password",
|
|
145
144
|
})}
|
|
146
145
|
password
|
|
@@ -16,7 +16,6 @@ import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
|
|
|
16
16
|
import Markdown from "@theme/Markdown";
|
|
17
17
|
import SchemaTabs from "@theme/SchemaTabs";
|
|
18
18
|
import TabItem from "@theme/TabItem";
|
|
19
|
-
import { OPENAPI_BODY, OPENAPI_REQUEST } from "@theme/translationIds";
|
|
20
19
|
import { sampleFromSchema } from "docusaurus-plugin-openapi-docs/lib/openapi/createSchemaExample";
|
|
21
20
|
import type { RequestBodyObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
|
|
22
21
|
import format from "xml-formatter";
|
|
@@ -292,7 +291,10 @@ function Body({
|
|
|
292
291
|
<FormFileUpload
|
|
293
292
|
placeholder={
|
|
294
293
|
schema.description ||
|
|
295
|
-
translate({
|
|
294
|
+
translate({
|
|
295
|
+
id: "theme.openapi.request.body.title",
|
|
296
|
+
message: "Body",
|
|
297
|
+
})
|
|
296
298
|
}
|
|
297
299
|
onChange={(file: any) => {
|
|
298
300
|
if (file === undefined) {
|
|
@@ -322,7 +324,7 @@ function Body({
|
|
|
322
324
|
{/* @ts-ignore */}
|
|
323
325
|
<TabItem
|
|
324
326
|
label={translate({
|
|
325
|
-
id:
|
|
327
|
+
id: "theme.openapi.body.exampleFromSchema",
|
|
326
328
|
message: "Example (from schema)",
|
|
327
329
|
})}
|
|
328
330
|
value="Example (from schema)"
|
|
@@ -412,7 +414,7 @@ function Body({
|
|
|
412
414
|
{/* @ts-ignore */}
|
|
413
415
|
<TabItem
|
|
414
416
|
label={translate({
|
|
415
|
-
id:
|
|
417
|
+
id: "theme.openapi.body.exampleFromSchema",
|
|
416
418
|
message: "Example (from schema)",
|
|
417
419
|
})}
|
|
418
420
|
value="Example (from schema)"
|
|
@@ -453,7 +455,7 @@ function Body({
|
|
|
453
455
|
{/* @ts-ignore */}
|
|
454
456
|
<TabItem
|
|
455
457
|
label={translate({
|
|
456
|
-
id:
|
|
458
|
+
id: "theme.openapi.body.exampleFromSchema",
|
|
457
459
|
message: "Example (from schema)",
|
|
458
460
|
})}
|
|
459
461
|
value="Example (from schema)"
|
|
@@ -5,14 +5,16 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
* ========================================================================== */
|
|
7
7
|
|
|
8
|
-
import React, {
|
|
8
|
+
import React, { useEffect, useMemo, useState } from "react";
|
|
9
9
|
|
|
10
|
+
import { useStorageSlot } from "@docusaurus/theme-common";
|
|
10
11
|
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
|
|
11
12
|
import ApiCodeBlock from "@theme/ApiExplorer/ApiCodeBlock";
|
|
12
13
|
import buildPostmanRequest from "@theme/ApiExplorer/buildPostmanRequest";
|
|
13
14
|
import CodeTabs from "@theme/ApiExplorer/CodeTabs";
|
|
14
15
|
import { useResolvedEncoding } from "@theme/ApiExplorer/EncodingSelection/useResolvedEncoding";
|
|
15
16
|
import { useTypedSelector } from "@theme/ApiItem/hooks";
|
|
17
|
+
import type { ThemeConfig } from "docusaurus-theme-openapi-docs/src/types";
|
|
16
18
|
import cloneDeep from "lodash/cloneDeep";
|
|
17
19
|
import codegen from "postman-code-generators";
|
|
18
20
|
import * as sdk from "postman-collection";
|
|
@@ -42,6 +44,21 @@ function CodeTab({ children, hidden, className }: any): React.JSX.Element {
|
|
|
42
44
|
);
|
|
43
45
|
}
|
|
44
46
|
|
|
47
|
+
/** Align with Docusaurus `<Tabs groupId="code-samples">` persisted tab value. */
|
|
48
|
+
function resolveOuterLanguageFromPersistedTab(
|
|
49
|
+
persistedTab: string | null,
|
|
50
|
+
langs: Language[]
|
|
51
|
+
): Language {
|
|
52
|
+
if (langs.length === 1) {
|
|
53
|
+
return langs[0];
|
|
54
|
+
}
|
|
55
|
+
const matched = langs.find((lang) => lang.language === persistedTab);
|
|
56
|
+
if (matched) {
|
|
57
|
+
return matched;
|
|
58
|
+
}
|
|
59
|
+
return langs[0];
|
|
60
|
+
}
|
|
61
|
+
|
|
45
62
|
function CodeSnippets({
|
|
46
63
|
postman,
|
|
47
64
|
codeSamples,
|
|
@@ -114,45 +131,66 @@ function CodeSnippets({
|
|
|
114
131
|
encoding,
|
|
115
132
|
});
|
|
116
133
|
|
|
134
|
+
const themeConfig = siteConfig.themeConfig as ThemeConfig;
|
|
135
|
+
const hideGeneratedSnippets =
|
|
136
|
+
themeConfig?.api?.hideGeneratedSnippets ?? false;
|
|
137
|
+
|
|
117
138
|
// User-defined languages array
|
|
118
139
|
// Can override languageSet, change order of langs, override options and variants
|
|
119
140
|
const userDefinedLanguageSet =
|
|
120
141
|
(siteConfig?.themeConfig?.languageTabs as Language[] | undefined) ??
|
|
121
142
|
languageSet;
|
|
122
143
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
144
|
+
const mergedLangs = useMemo(() => {
|
|
145
|
+
const filteredLanguageSet = languageSet.filter((ls) => {
|
|
146
|
+
return userDefinedLanguageSet?.some((lang) => {
|
|
147
|
+
return lang.language === ls.language;
|
|
148
|
+
});
|
|
127
149
|
});
|
|
128
|
-
|
|
150
|
+
return mergeCodeSampleLanguage(
|
|
151
|
+
mergeArraysbyLanguage(userDefinedLanguageSet, filteredLanguageSet),
|
|
152
|
+
codeSamples
|
|
153
|
+
);
|
|
154
|
+
}, [userDefinedLanguageSet, codeSamples]);
|
|
129
155
|
|
|
130
|
-
|
|
131
|
-
const mergedLangs = mergeCodeSampleLanguage(
|
|
132
|
-
mergeArraysbyLanguage(userDefinedLanguageSet, filteredLanguageSet),
|
|
133
|
-
codeSamples
|
|
134
|
-
);
|
|
156
|
+
const [persistedOuterTab] = useStorageSlot("docusaurus.tab.code-samples");
|
|
135
157
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
lang.language === localStorage.getItem("docusaurus.tab.code-samples")
|
|
158
|
+
const initialOuterLanguage = useMemo(
|
|
159
|
+
() => resolveOuterLanguageFromPersistedTab(persistedOuterTab, mergedLangs),
|
|
160
|
+
[persistedOuterTab, mergedLangs]
|
|
140
161
|
);
|
|
162
|
+
|
|
141
163
|
const [selectedVariant, setSelectedVariant] = useState<string | undefined>();
|
|
142
164
|
const [selectedSample, setSelectedSample] = useState<string | undefined>();
|
|
143
|
-
const [language, setLanguage] = useState(() =>
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
165
|
+
const [language, setLanguage] = useState(() =>
|
|
166
|
+
resolveOuterLanguageFromPersistedTab(persistedOuterTab, mergedLangs)
|
|
167
|
+
);
|
|
168
|
+
|
|
169
|
+
useEffect(() => {
|
|
170
|
+
const next = resolveOuterLanguageFromPersistedTab(
|
|
171
|
+
persistedOuterTab,
|
|
172
|
+
mergedLangs
|
|
173
|
+
);
|
|
174
|
+
setLanguage((prev) => {
|
|
175
|
+
if (prev?.language !== next.language) {
|
|
176
|
+
return next;
|
|
177
|
+
}
|
|
178
|
+
return mergedLangs.find((l) => l.language === next.language) ?? next;
|
|
179
|
+
});
|
|
180
|
+
}, [persistedOuterTab, mergedLangs]);
|
|
151
181
|
const [codeText, setCodeText] = useState<string>("");
|
|
152
182
|
const [codeSampleCodeText, setCodeSampleCodeText] = useState<string>(() =>
|
|
153
183
|
getCodeSampleSourceFromLanguage(language)
|
|
154
184
|
);
|
|
155
185
|
|
|
186
|
+
// Reset selectedSample whenever the active language changes so the inner
|
|
187
|
+
// tab strip falls back to its first sample instead of trying to match an
|
|
188
|
+
// id that belongs to a different language's samples.
|
|
189
|
+
useEffect(() => {
|
|
190
|
+
setSelectedSample(language?.samples?.[0]);
|
|
191
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
192
|
+
}, [language?.language]);
|
|
193
|
+
|
|
156
194
|
useEffect(() => {
|
|
157
195
|
if (language && !!language.sample) {
|
|
158
196
|
setCodeSampleCodeText(getCodeSampleSourceFromLanguage(language));
|
|
@@ -259,7 +297,7 @@ function CodeSnippets({
|
|
|
259
297
|
setSelectedSample: setSelectedSample,
|
|
260
298
|
}}
|
|
261
299
|
languageSet={mergedLangs}
|
|
262
|
-
defaultValue={
|
|
300
|
+
defaultValue={initialOuterLanguage.language}
|
|
263
301
|
lazy
|
|
264
302
|
>
|
|
265
303
|
{mergedLangs.map((lang) => {
|
|
@@ -282,7 +320,11 @@ function CodeSnippets({
|
|
|
282
320
|
}}
|
|
283
321
|
includeSample={true}
|
|
284
322
|
currentLanguage={lang}
|
|
285
|
-
defaultValue={
|
|
323
|
+
defaultValue={
|
|
324
|
+
selectedSample && lang.samples.includes(selectedSample)
|
|
325
|
+
? selectedSample
|
|
326
|
+
: lang.samples[0]
|
|
327
|
+
}
|
|
286
328
|
languageSet={mergedLangs}
|
|
287
329
|
lazy
|
|
288
330
|
>
|
|
@@ -295,7 +337,7 @@ function CodeSnippets({
|
|
|
295
337
|
? lang.samplesLabels[index]
|
|
296
338
|
: sample
|
|
297
339
|
}
|
|
298
|
-
key={`${lang.language}-${
|
|
340
|
+
key={`${lang.language}-${sample}`}
|
|
299
341
|
attributes={{
|
|
300
342
|
className: `openapi-tabs__code-item--sample`,
|
|
301
343
|
}}
|
|
@@ -315,40 +357,42 @@ function CodeSnippets({
|
|
|
315
357
|
)}
|
|
316
358
|
|
|
317
359
|
{/* Inner generated code snippets */}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
{/* @ts-ignore */}
|
|
341
|
-
<ApiCodeBlock
|
|
342
|
-
language={lang.highlight}
|
|
343
|
-
className="openapi-explorer__code-block"
|
|
344
|
-
showLineNumbers={true}
|
|
360
|
+
{!(hideGeneratedSnippets && lang.samples?.length) && (
|
|
361
|
+
<CodeTabs
|
|
362
|
+
className="openapi-tabs__code-container-inner"
|
|
363
|
+
action={{
|
|
364
|
+
setLanguage: setLanguage,
|
|
365
|
+
setSelectedVariant: setSelectedVariant,
|
|
366
|
+
}}
|
|
367
|
+
includeVariant={true}
|
|
368
|
+
currentLanguage={lang}
|
|
369
|
+
defaultValue={selectedVariant}
|
|
370
|
+
languageSet={mergedLangs}
|
|
371
|
+
lazy
|
|
372
|
+
>
|
|
373
|
+
{lang.variants.map((variant, index) => {
|
|
374
|
+
return (
|
|
375
|
+
<CodeTab
|
|
376
|
+
value={variant.toLowerCase()}
|
|
377
|
+
label={variant.toUpperCase()}
|
|
378
|
+
key={`${lang.language}-${variant}`}
|
|
379
|
+
attributes={{
|
|
380
|
+
className: `openapi-tabs__code-item--variant`,
|
|
381
|
+
}}
|
|
345
382
|
>
|
|
346
|
-
{
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
383
|
+
{/* @ts-ignore */}
|
|
384
|
+
<ApiCodeBlock
|
|
385
|
+
language={lang.highlight}
|
|
386
|
+
className="openapi-explorer__code-block"
|
|
387
|
+
showLineNumbers={true}
|
|
388
|
+
>
|
|
389
|
+
{codeText}
|
|
390
|
+
</ApiCodeBlock>
|
|
391
|
+
</CodeTab>
|
|
392
|
+
);
|
|
393
|
+
})}
|
|
394
|
+
</CodeTabs>
|
|
395
|
+
)}
|
|
352
396
|
</CodeTab>
|
|
353
397
|
);
|
|
354
398
|
})}
|