docusaurus-theme-openapi-docs 0.0.0-1268 → 0.0.0-1294
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 +34 -10
- package/lib/markdown/schema.test.js +35 -0
- package/lib/theme/ApiItem/index.js +14 -2
- package/package.json +3 -3
- package/src/markdown/schema.test.ts +41 -0
- package/src/markdown/schema.ts +38 -10
- package/src/theme/ApiItem/index.tsx +15 -3
package/lib/markdown/schema.js
CHANGED
|
@@ -42,13 +42,36 @@ function getTypeFromSchema(schema) {
|
|
|
42
42
|
}
|
|
43
43
|
return undefined;
|
|
44
44
|
}
|
|
45
|
+
// OpenAPI 3.1 / JSON Schema 2020-12 allows `type` to be an array of type names
|
|
46
|
+
// (e.g. `["string", "null"]`). Normalize to a single name and a pretty-printed
|
|
47
|
+
// union form joined with ` | `.
|
|
48
|
+
function normalizeType(type) {
|
|
49
|
+
if (Array.isArray(type)) {
|
|
50
|
+
const filtered = type.filter((t) => typeof t === "string");
|
|
51
|
+
if (filtered.length === 0)
|
|
52
|
+
return { isUnion: false };
|
|
53
|
+
if (filtered.length === 1)
|
|
54
|
+
return { single: filtered[0], isUnion: false };
|
|
55
|
+
return { pretty: filtered.join(" | "), isUnion: true };
|
|
56
|
+
}
|
|
57
|
+
if (typeof type === "string")
|
|
58
|
+
return { single: type, isUnion: false };
|
|
59
|
+
return { isUnion: false };
|
|
60
|
+
}
|
|
45
61
|
function prettyName(schema, circular) {
|
|
46
62
|
// Handle enum-only schemas (valid in JSON Schema)
|
|
47
63
|
// When enum is present without explicit type, treat as string
|
|
48
64
|
if (schema.enum && !schema.type) {
|
|
49
65
|
return "string";
|
|
50
66
|
}
|
|
67
|
+
const t = normalizeType(schema.type);
|
|
51
68
|
if (schema.format) {
|
|
69
|
+
if (t.single) {
|
|
70
|
+
return `${t.single}<${schema.format}>`;
|
|
71
|
+
}
|
|
72
|
+
if (t.isUnion) {
|
|
73
|
+
return `(${t.pretty})<${schema.format}>`;
|
|
74
|
+
}
|
|
52
75
|
return schema.format;
|
|
53
76
|
}
|
|
54
77
|
if (schema.allOf) {
|
|
@@ -72,22 +95,23 @@ function prettyName(schema, circular) {
|
|
|
72
95
|
if (schema.anyOf) {
|
|
73
96
|
return "object";
|
|
74
97
|
}
|
|
75
|
-
if (
|
|
76
|
-
return schema.xml?.name ??
|
|
77
|
-
// return schema.type;
|
|
98
|
+
if (t.single === "object") {
|
|
99
|
+
return schema.xml?.name ?? t.single;
|
|
78
100
|
}
|
|
79
|
-
if (
|
|
80
|
-
return schema.xml?.name ??
|
|
81
|
-
// return schema.type;
|
|
101
|
+
if (t.single === "array") {
|
|
102
|
+
return schema.xml?.name ?? t.single;
|
|
82
103
|
}
|
|
83
|
-
if (
|
|
84
|
-
return
|
|
104
|
+
if (t.isUnion) {
|
|
105
|
+
return t.pretty;
|
|
85
106
|
}
|
|
86
|
-
return schema.title ??
|
|
107
|
+
return schema.title ?? t.single;
|
|
87
108
|
}
|
|
88
109
|
function getSchemaName(schema, circular) {
|
|
89
110
|
if (schema.items) {
|
|
90
|
-
|
|
111
|
+
const items = schema.items;
|
|
112
|
+
const inner = getSchemaName(items, circular);
|
|
113
|
+
const needsParens = Array.isArray(items.type) && items.type.length > 1;
|
|
114
|
+
return needsParens ? `(${inner})[]` : `${inner}[]`;
|
|
91
115
|
}
|
|
92
116
|
return prettyName(schema, circular) ?? "";
|
|
93
117
|
}
|
|
@@ -48,4 +48,39 @@ describe("getSchemaName", () => {
|
|
|
48
48
|
};
|
|
49
49
|
expect((0, schema_1.getSchemaName)(schema)).toBe("integer[][][]");
|
|
50
50
|
});
|
|
51
|
+
it("joins OpenAPI 3.1 type arrays with ` | ` (issue #950)", () => {
|
|
52
|
+
const schema = { type: ["string", "null"] };
|
|
53
|
+
expect((0, schema_1.getSchemaName)(schema)).toBe("string | null");
|
|
54
|
+
});
|
|
55
|
+
it("unwraps a single-element type array", () => {
|
|
56
|
+
const schema = { type: ["integer"] };
|
|
57
|
+
expect((0, schema_1.getSchemaName)(schema)).toBe("integer");
|
|
58
|
+
});
|
|
59
|
+
it("renders single type with format as `type<format>`", () => {
|
|
60
|
+
const schema = {
|
|
61
|
+
type: "string",
|
|
62
|
+
format: "uuid",
|
|
63
|
+
};
|
|
64
|
+
expect((0, schema_1.getSchemaName)(schema)).toBe("string<uuid>");
|
|
65
|
+
});
|
|
66
|
+
it("renders type union with format", () => {
|
|
67
|
+
const schema = {
|
|
68
|
+
type: ["string", "null"],
|
|
69
|
+
format: "uuid",
|
|
70
|
+
};
|
|
71
|
+
expect((0, schema_1.getSchemaName)(schema)).toBe("(string | null)<uuid>");
|
|
72
|
+
});
|
|
73
|
+
it("resolves type from an allOf wrapper that contains an enum", () => {
|
|
74
|
+
const schema = {
|
|
75
|
+
allOf: [{ type: "string", enum: ["a", "b"] }],
|
|
76
|
+
};
|
|
77
|
+
expect((0, schema_1.getSchemaName)(schema)).toBe("string");
|
|
78
|
+
});
|
|
79
|
+
it("renders array of items whose type is a union", () => {
|
|
80
|
+
const schema = {
|
|
81
|
+
type: "array",
|
|
82
|
+
items: { type: ["string", "null"] },
|
|
83
|
+
};
|
|
84
|
+
expect((0, schema_1.getSchemaName)(schema)).toBe("(string | null)[]");
|
|
85
|
+
});
|
|
51
86
|
});
|
|
@@ -101,9 +101,21 @@ function ApiItem(props) {
|
|
|
101
101
|
api?.parameters?.forEach((param) => {
|
|
102
102
|
const paramType = param.in;
|
|
103
103
|
const paramsArray = params[paramType];
|
|
104
|
-
const
|
|
104
|
+
const p = param;
|
|
105
|
+
// Prefill order: schema.default, then example sources. `default` is
|
|
106
|
+
// semantically a server-side fallback, so for required params authors
|
|
107
|
+
// typically rely on `example` / `examples`. See #544 and #1079.
|
|
108
|
+
const firstNamedExample =
|
|
109
|
+
p.examples && typeof p.examples === "object"
|
|
110
|
+
? Object.values(p.examples)[0]?.value
|
|
111
|
+
: undefined;
|
|
112
|
+
const prefill =
|
|
113
|
+
p.schema?.default ??
|
|
114
|
+
p.example ??
|
|
115
|
+
p.schema?.example ??
|
|
116
|
+
firstNamedExample;
|
|
105
117
|
const initialized =
|
|
106
|
-
|
|
118
|
+
prefill !== undefined ? { ...param, value: prefill } : param;
|
|
107
119
|
paramsArray?.push(initialized);
|
|
108
120
|
});
|
|
109
121
|
const auth = (0, slice_1.createAuth)({
|
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": "0.0.0-
|
|
4
|
+
"version": "0.0.0-1294",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"openapi",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@types/postman-collection": "^3.5.11",
|
|
39
39
|
"@types/react-modal": "^3.16.3",
|
|
40
40
|
"concurrently": "^9.2.0",
|
|
41
|
-
"docusaurus-plugin-openapi-docs": "0.0.0-
|
|
41
|
+
"docusaurus-plugin-openapi-docs": "0.0.0-1294",
|
|
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": "dcce97d6a3cae4f76af8f02e81571e8ce5a394ac"
|
|
86
86
|
}
|
|
@@ -58,4 +58,45 @@ describe("getSchemaName", () => {
|
|
|
58
58
|
} as SchemaObject;
|
|
59
59
|
expect(getSchemaName(schema)).toBe("integer[][][]");
|
|
60
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
|
+
});
|
|
61
102
|
});
|
package/src/markdown/schema.ts
CHANGED
|
@@ -48,6 +48,24 @@ function getTypeFromSchema(schema: SchemaObject): string | undefined {
|
|
|
48
48
|
return undefined;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
+
// OpenAPI 3.1 / JSON Schema 2020-12 allows `type` to be an array of type names
|
|
52
|
+
// (e.g. `["string", "null"]`). Normalize to a single name and a pretty-printed
|
|
53
|
+
// union form joined with ` | `.
|
|
54
|
+
function normalizeType(type: unknown): {
|
|
55
|
+
single?: string;
|
|
56
|
+
pretty?: string;
|
|
57
|
+
isUnion: boolean;
|
|
58
|
+
} {
|
|
59
|
+
if (Array.isArray(type)) {
|
|
60
|
+
const filtered = type.filter((t): t is string => typeof t === "string");
|
|
61
|
+
if (filtered.length === 0) return { isUnion: false };
|
|
62
|
+
if (filtered.length === 1) return { single: filtered[0], isUnion: false };
|
|
63
|
+
return { pretty: filtered.join(" | "), isUnion: true };
|
|
64
|
+
}
|
|
65
|
+
if (typeof type === "string") return { single: type, isUnion: false };
|
|
66
|
+
return { isUnion: false };
|
|
67
|
+
}
|
|
68
|
+
|
|
51
69
|
function prettyName(schema: SchemaObject, circular?: boolean) {
|
|
52
70
|
// Handle enum-only schemas (valid in JSON Schema)
|
|
53
71
|
// When enum is present without explicit type, treat as string
|
|
@@ -55,7 +73,15 @@ function prettyName(schema: SchemaObject, circular?: boolean) {
|
|
|
55
73
|
return "string";
|
|
56
74
|
}
|
|
57
75
|
|
|
76
|
+
const t = normalizeType(schema.type);
|
|
77
|
+
|
|
58
78
|
if (schema.format) {
|
|
79
|
+
if (t.single) {
|
|
80
|
+
return `${t.single}<${schema.format}>`;
|
|
81
|
+
}
|
|
82
|
+
if (t.isUnion) {
|
|
83
|
+
return `(${t.pretty})<${schema.format}>`;
|
|
84
|
+
}
|
|
59
85
|
return schema.format;
|
|
60
86
|
}
|
|
61
87
|
|
|
@@ -83,21 +109,19 @@ function prettyName(schema: SchemaObject, circular?: boolean) {
|
|
|
83
109
|
return "object";
|
|
84
110
|
}
|
|
85
111
|
|
|
86
|
-
if (
|
|
87
|
-
return schema.xml?.name ??
|
|
88
|
-
// return schema.type;
|
|
112
|
+
if (t.single === "object") {
|
|
113
|
+
return schema.xml?.name ?? t.single;
|
|
89
114
|
}
|
|
90
115
|
|
|
91
|
-
if (
|
|
92
|
-
return schema.xml?.name ??
|
|
93
|
-
// return schema.type;
|
|
116
|
+
if (t.single === "array") {
|
|
117
|
+
return schema.xml?.name ?? t.single;
|
|
94
118
|
}
|
|
95
119
|
|
|
96
|
-
if (
|
|
97
|
-
return
|
|
120
|
+
if (t.isUnion) {
|
|
121
|
+
return t.pretty;
|
|
98
122
|
}
|
|
99
123
|
|
|
100
|
-
return schema.title ??
|
|
124
|
+
return schema.title ?? t.single;
|
|
101
125
|
}
|
|
102
126
|
|
|
103
127
|
export function getSchemaName(
|
|
@@ -105,7 +129,11 @@ export function getSchemaName(
|
|
|
105
129
|
circular?: boolean
|
|
106
130
|
): string {
|
|
107
131
|
if (schema.items) {
|
|
108
|
-
|
|
132
|
+
const items = schema.items as SchemaObject;
|
|
133
|
+
const inner = getSchemaName(items, circular);
|
|
134
|
+
const needsParens =
|
|
135
|
+
Array.isArray((items as any).type) && (items as any).type.length > 1;
|
|
136
|
+
return needsParens ? `(${inner})[]` : `${inner}[]`;
|
|
109
137
|
}
|
|
110
138
|
|
|
111
139
|
return prettyName(schema, circular) ?? "";
|
|
@@ -123,10 +123,22 @@ export default function ApiItem(props: Props): JSX.Element {
|
|
|
123
123
|
(param: { in: "path" | "query" | "header" | "cookie" }) => {
|
|
124
124
|
const paramType = param.in;
|
|
125
125
|
const paramsArray: ParameterObject[] = params[paramType];
|
|
126
|
-
const
|
|
126
|
+
const p = param as any;
|
|
127
|
+
// Prefill order: schema.default, then example sources. `default` is
|
|
128
|
+
// semantically a server-side fallback, so for required params authors
|
|
129
|
+
// typically rely on `example` / `examples`. See #544 and #1079.
|
|
130
|
+
const firstNamedExample =
|
|
131
|
+
p.examples && typeof p.examples === "object"
|
|
132
|
+
? (Object.values(p.examples)[0] as any)?.value
|
|
133
|
+
: undefined;
|
|
134
|
+
const prefill =
|
|
135
|
+
p.schema?.default ??
|
|
136
|
+
p.example ??
|
|
137
|
+
p.schema?.example ??
|
|
138
|
+
firstNamedExample;
|
|
127
139
|
const initialized =
|
|
128
|
-
|
|
129
|
-
? ({ ...param, value:
|
|
140
|
+
prefill !== undefined
|
|
141
|
+
? ({ ...param, value: prefill } as unknown as ParameterObject)
|
|
130
142
|
: (param as ParameterObject);
|
|
131
143
|
paramsArray?.push(initialized);
|
|
132
144
|
}
|