fumadocs-openapi 5.0.3 → 5.2.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/dist/index.d.ts +4 -4
- package/dist/index.js +132 -99
- package/dist/server/index.d.ts +13 -9
- package/dist/server/index.js +23 -10
- package/dist/ui/{client-client-BIwAR59x.js → client-client-34yX5eij.js} +2 -1
- package/dist/ui/index.js +2 -2
- package/dist/ui/{playground-client-CjCikhf6.js → playground-client-itvkUjgt.js} +1 -1
- package/package.json +8 -8
package/dist/index.d.ts
CHANGED
|
@@ -221,6 +221,7 @@ interface GenerateOptions {
|
|
|
221
221
|
* A `full: true` property will be added by default.
|
|
222
222
|
*/
|
|
223
223
|
frontmatter?: (title: string, description: string | undefined, context: DocumentContext) => Record<string, unknown>;
|
|
224
|
+
cwd?: string;
|
|
224
225
|
}
|
|
225
226
|
interface GenerateTagOutput {
|
|
226
227
|
tag: string;
|
|
@@ -246,10 +247,10 @@ interface Config extends GenerateOptions {
|
|
|
246
247
|
output: string;
|
|
247
248
|
/**
|
|
248
249
|
* tag: Generate a page for each tag
|
|
249
|
-
*
|
|
250
250
|
* file: Generate a page for each schema
|
|
251
|
+
* operation: Generate a page for each API endpoint/operation
|
|
251
252
|
*
|
|
252
|
-
* @defaultValue
|
|
253
|
+
* @defaultValue 'operation'
|
|
253
254
|
*/
|
|
254
255
|
per?: 'tag' | 'file' | 'operation';
|
|
255
256
|
/**
|
|
@@ -269,8 +270,7 @@ interface Config extends GenerateOptions {
|
|
|
269
270
|
* @defaultValue 'none'
|
|
270
271
|
*/
|
|
271
272
|
groupBy?: 'tag' | 'route' | 'none';
|
|
272
|
-
cwd?: string;
|
|
273
273
|
}
|
|
274
|
-
declare function generateFiles(
|
|
274
|
+
declare function generateFiles(options: Config): Promise<void>;
|
|
275
275
|
|
|
276
276
|
export { type Config, type DocumentContext, type GenerateOperationOutput, type GenerateOptions, type GenerateTagOutput, type MethodInformation, type RenderContext, type RouteInformation, generateAll, generateFiles, generateOperations, generateTags };
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
+
import { resolve, join, parse, dirname } from 'node:path';
|
|
1
2
|
import Parser from '@apidevtools/json-schema-ref-parser';
|
|
2
|
-
import Slugger from 'github-slugger';
|
|
3
3
|
import { dump } from 'js-yaml';
|
|
4
|
+
import Slugger from 'github-slugger';
|
|
4
5
|
import { mkdir, writeFile } from 'node:fs/promises';
|
|
5
|
-
import { join, parse, dirname } from 'node:path';
|
|
6
6
|
import fg from 'fast-glob';
|
|
7
7
|
|
|
8
8
|
function createMethod(method, operation) {
|
|
@@ -55,41 +55,92 @@ const methodKeys = [
|
|
|
55
55
|
return map;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
function
|
|
58
|
+
function idToTitle(id) {
|
|
59
|
+
let result = [];
|
|
60
|
+
for (const c of id){
|
|
61
|
+
if (result.length === 0) result.push(c.toLocaleUpperCase());
|
|
62
|
+
else if (c === '.') result = [];
|
|
63
|
+
else if (/^[A-Z]$/.test(c) && result.at(-1) !== ' ') result.push(' ', c);
|
|
64
|
+
else if (c === '-') result.push(' ');
|
|
65
|
+
else result.push(c);
|
|
66
|
+
}
|
|
67
|
+
return result.join('');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function generateDocument(options) {
|
|
71
|
+
const { frontmatter } = options;
|
|
59
72
|
const out = [];
|
|
73
|
+
const extend = frontmatter?.(options.title, options.description, options.context);
|
|
74
|
+
let meta;
|
|
75
|
+
if (options.context.type === 'operation') {
|
|
76
|
+
meta = {
|
|
77
|
+
method: options.context.endpoint.method,
|
|
78
|
+
route: options.context.route.path
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
const data = generateStaticData(options.dereferenced, options.page);
|
|
60
82
|
const banner = dump({
|
|
61
|
-
title:
|
|
62
|
-
description:
|
|
83
|
+
title: options.title,
|
|
84
|
+
description: options.description,
|
|
63
85
|
full: true,
|
|
64
|
-
...
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
86
|
+
...extend,
|
|
87
|
+
_openapi: {
|
|
88
|
+
...meta,
|
|
89
|
+
...data,
|
|
90
|
+
...extend?._openapi
|
|
91
|
+
}
|
|
69
92
|
}).trim();
|
|
70
93
|
if (banner.length > 0) out.push(`---\n${banner}\n---`);
|
|
71
94
|
const imports = options.imports?.map((item)=>`import { ${item.names.join(', ')} } from ${JSON.stringify(item.from)};`).join('\n');
|
|
72
95
|
if (imports) {
|
|
73
96
|
out.push(imports);
|
|
74
97
|
}
|
|
75
|
-
out.push(
|
|
98
|
+
out.push(pageContent(options.page));
|
|
76
99
|
return out.join('\n\n');
|
|
77
100
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
101
|
+
function generateStaticData(dereferenced, props) {
|
|
102
|
+
const slugger = new Slugger();
|
|
103
|
+
const toc = [];
|
|
104
|
+
const structuredData = {
|
|
105
|
+
headings: [],
|
|
106
|
+
contents: []
|
|
107
|
+
};
|
|
108
|
+
for (const item of props.operations){
|
|
109
|
+
const operation = dereferenced.paths[item.path]?.[item.method];
|
|
110
|
+
if (!operation) continue;
|
|
111
|
+
if (props.hasHead && operation.operationId) {
|
|
112
|
+
const title = operation.summary ?? (operation.operationId ? idToTitle(operation.operationId) : item.path);
|
|
113
|
+
const id = slugger.slug(title);
|
|
114
|
+
toc.push({
|
|
115
|
+
depth: 2,
|
|
116
|
+
title,
|
|
117
|
+
url: `#${id}`
|
|
118
|
+
});
|
|
119
|
+
structuredData.headings.push({
|
|
120
|
+
content: title,
|
|
121
|
+
id
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
if (operation.description) structuredData.contents.push({
|
|
125
|
+
content: operation.description,
|
|
126
|
+
heading: structuredData.headings.at(-1)?.id
|
|
127
|
+
});
|
|
87
128
|
}
|
|
88
|
-
return
|
|
129
|
+
return {
|
|
130
|
+
toc,
|
|
131
|
+
structuredData
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function pageContent(props) {
|
|
135
|
+
return `<APIPage document={${JSON.stringify(props.document)}} operations={${JSON.stringify(props.operations)}} hasHead={${JSON.stringify(props.hasHead)}} />`;
|
|
89
136
|
}
|
|
90
137
|
|
|
138
|
+
async function dereference(pathOrDocument, options) {
|
|
139
|
+
return await Parser.dereference(// resolve paths
|
|
140
|
+
typeof pathOrDocument === 'string' && !pathOrDocument.startsWith('http://') && !pathOrDocument.startsWith('https://') ? resolve(options.cwd ?? process.cwd(), pathOrDocument) : pathOrDocument);
|
|
141
|
+
}
|
|
91
142
|
async function generateAll(pathOrDocument, options = {}) {
|
|
92
|
-
const document = await
|
|
143
|
+
const document = await dereference(pathOrDocument, options);
|
|
93
144
|
const routes = buildRoutes(document).get('all') ?? [];
|
|
94
145
|
const operations = [];
|
|
95
146
|
for (const route of routes){
|
|
@@ -100,12 +151,16 @@ async function generateAll(pathOrDocument, options = {}) {
|
|
|
100
151
|
});
|
|
101
152
|
}
|
|
102
153
|
}
|
|
103
|
-
return generateDocument(
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}), options, {
|
|
154
|
+
return generateDocument({
|
|
155
|
+
...options,
|
|
156
|
+
dereferenced: document,
|
|
107
157
|
title: document.info.title,
|
|
108
158
|
description: document.info.description,
|
|
159
|
+
page: {
|
|
160
|
+
operations,
|
|
161
|
+
hasHead: true,
|
|
162
|
+
document: pathOrDocument
|
|
163
|
+
},
|
|
109
164
|
context: {
|
|
110
165
|
type: 'file',
|
|
111
166
|
routes
|
|
@@ -113,20 +168,24 @@ async function generateAll(pathOrDocument, options = {}) {
|
|
|
113
168
|
});
|
|
114
169
|
}
|
|
115
170
|
async function generateOperations(pathOrDocument, options = {}) {
|
|
116
|
-
const document = await
|
|
171
|
+
const document = await dereference(pathOrDocument, options);
|
|
117
172
|
const routes = buildRoutes(document).get('all') ?? [];
|
|
118
173
|
return routes.flatMap((route)=>{
|
|
119
174
|
return route.methods.map((method)=>{
|
|
120
175
|
if (!method.operationId) throw new Error('Operation ID is required for generating docs.');
|
|
121
|
-
const content = generateDocument(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
176
|
+
const content = generateDocument({
|
|
177
|
+
...options,
|
|
178
|
+
page: {
|
|
179
|
+
operations: [
|
|
180
|
+
{
|
|
181
|
+
path: route.path,
|
|
182
|
+
method: method.method.toLowerCase()
|
|
183
|
+
}
|
|
184
|
+
],
|
|
185
|
+
hasHead: false,
|
|
186
|
+
document: pathOrDocument
|
|
187
|
+
},
|
|
188
|
+
dereferenced: document,
|
|
130
189
|
title: method.summary ?? idToTitle(method.operationId),
|
|
131
190
|
description: method.description,
|
|
132
191
|
context: {
|
|
@@ -144,7 +203,7 @@ async function generateOperations(pathOrDocument, options = {}) {
|
|
|
144
203
|
});
|
|
145
204
|
}
|
|
146
205
|
async function generateTags(pathOrDocument, options = {}) {
|
|
147
|
-
const document = await
|
|
206
|
+
const document = await dereference(pathOrDocument, options);
|
|
148
207
|
const tags = Array.from(buildRoutes(document).entries());
|
|
149
208
|
return tags.filter(([tag])=>tag !== 'all').map(([tag, routes])=>{
|
|
150
209
|
const info = document.tags?.find((t)=>t.name === tag);
|
|
@@ -159,10 +218,14 @@ async function generateTags(pathOrDocument, options = {}) {
|
|
|
159
218
|
}
|
|
160
219
|
return {
|
|
161
220
|
tag,
|
|
162
|
-
content: generateDocument(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
221
|
+
content: generateDocument({
|
|
222
|
+
...options,
|
|
223
|
+
page: {
|
|
224
|
+
document: pathOrDocument,
|
|
225
|
+
operations,
|
|
226
|
+
hasHead: true
|
|
227
|
+
},
|
|
228
|
+
dereferenced: document,
|
|
166
229
|
title: idToTitle(tag),
|
|
167
230
|
description: info?.description,
|
|
168
231
|
context: {
|
|
@@ -174,74 +237,41 @@ async function generateTags(pathOrDocument, options = {}) {
|
|
|
174
237
|
};
|
|
175
238
|
});
|
|
176
239
|
}
|
|
177
|
-
function pageContent(doc, props) {
|
|
178
|
-
const slugger = new Slugger();
|
|
179
|
-
const toc = [];
|
|
180
|
-
const structuredData = {
|
|
181
|
-
headings: [],
|
|
182
|
-
contents: []
|
|
183
|
-
};
|
|
184
|
-
for (const item of props.operations){
|
|
185
|
-
const operation = doc.paths[item.path]?.[item.method];
|
|
186
|
-
if (!operation) continue;
|
|
187
|
-
if (props.hasHead && operation.operationId) {
|
|
188
|
-
const title = operation.summary ?? (operation.operationId ? idToTitle(operation.operationId) : item.path);
|
|
189
|
-
const id = slugger.slug(title);
|
|
190
|
-
toc.push({
|
|
191
|
-
depth: 2,
|
|
192
|
-
title,
|
|
193
|
-
url: `#${id}`
|
|
194
|
-
});
|
|
195
|
-
structuredData.headings.push({
|
|
196
|
-
content: title,
|
|
197
|
-
id
|
|
198
|
-
});
|
|
199
|
-
}
|
|
200
|
-
if (operation.description) structuredData.contents.push({
|
|
201
|
-
content: operation.description,
|
|
202
|
-
heading: structuredData.headings.at(-1)?.id
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
// modify toc and structured data if possible
|
|
206
|
-
// it may not be compatible with other content sources except Fumadocs MDX
|
|
207
|
-
// TODO: Maybe add to frontmatter and let developers to handle them?
|
|
208
|
-
return `<APIPage operations={${JSON.stringify(props.operations)}} hasHead={${JSON.stringify(props.hasHead)}} />
|
|
209
|
-
|
|
210
|
-
export function startup() {
|
|
211
|
-
if (typeof toc !== 'undefined') {
|
|
212
|
-
// toc might be immutable
|
|
213
|
-
while (toc.length > 0) toc.pop()
|
|
214
|
-
toc.push(...${JSON.stringify(toc)})
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
if (typeof structuredData !== 'undefined') {
|
|
218
|
-
structuredData.headings = ${JSON.stringify(structuredData.headings)}
|
|
219
|
-
structuredData.contents = ${JSON.stringify(structuredData.contents)}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
240
|
|
|
223
|
-
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
async function generateFiles({ input, output, name: nameFn, per = 'file', cwd = process.cwd(), groupBy = 'none', ...options }) {
|
|
241
|
+
async function generateFiles(options) {
|
|
242
|
+
const { input, output, name: nameFn, per = 'operation', groupBy = 'none', cwd = process.cwd() } = options;
|
|
227
243
|
const outputDir = join(cwd, output);
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
244
|
+
const urlInputs = [];
|
|
245
|
+
const fileInputs = [];
|
|
246
|
+
for (const v of typeof input === 'string' ? [
|
|
247
|
+
input
|
|
248
|
+
] : input){
|
|
249
|
+
if (isUrl(v)) {
|
|
250
|
+
urlInputs.push(v);
|
|
251
|
+
} else {
|
|
252
|
+
fileInputs.push(v);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
const resolvedInputs = [
|
|
256
|
+
...await fg.glob(fileInputs, {
|
|
257
|
+
cwd,
|
|
258
|
+
absolute: false
|
|
259
|
+
}),
|
|
260
|
+
...urlInputs
|
|
261
|
+
];
|
|
262
|
+
await Promise.all(resolvedInputs.map(async (pathOrUrl)=>{
|
|
233
263
|
if (per === 'file') {
|
|
234
|
-
let filename = parse(
|
|
264
|
+
let filename = isUrl(pathOrUrl) ? 'index' : parse(pathOrUrl).name;
|
|
235
265
|
if (nameFn) filename = nameFn('file', filename);
|
|
236
266
|
const outPath = join(outputDir, `${filename}.mdx`);
|
|
237
|
-
const result = await generateAll(
|
|
267
|
+
const result = await generateAll(pathOrUrl, options);
|
|
238
268
|
await write(outPath, result);
|
|
239
269
|
console.log(`Generated: ${outPath}`);
|
|
240
270
|
return;
|
|
241
271
|
}
|
|
242
272
|
if (per === 'operation') {
|
|
243
273
|
const metaFiles = new Set();
|
|
244
|
-
const results = await generateOperations(
|
|
274
|
+
const results = await generateOperations(pathOrUrl, options);
|
|
245
275
|
await Promise.all(results.map(async (result)=>{
|
|
246
276
|
let outPath;
|
|
247
277
|
if (!result.method.operationId) return;
|
|
@@ -267,7 +297,7 @@ async function generateFiles({ input, output, name: nameFn, per = 'file', cwd =
|
|
|
267
297
|
}));
|
|
268
298
|
return;
|
|
269
299
|
}
|
|
270
|
-
const results = await generateTags(
|
|
300
|
+
const results = await generateTags(pathOrUrl, options);
|
|
271
301
|
for (const result of results){
|
|
272
302
|
let tagName = result.tag;
|
|
273
303
|
tagName = nameFn?.('tag', tagName) ?? getFilename(tagName);
|
|
@@ -277,6 +307,9 @@ async function generateFiles({ input, output, name: nameFn, per = 'file', cwd =
|
|
|
277
307
|
}
|
|
278
308
|
}));
|
|
279
309
|
}
|
|
310
|
+
function isUrl(input) {
|
|
311
|
+
return input.startsWith('https://') || input.startsWith('http://');
|
|
312
|
+
}
|
|
280
313
|
function getFilenameFromRoute(path) {
|
|
281
314
|
return path.replaceAll('.', '/').split('/').filter((v)=>!v.startsWith('{') && !v.endsWith('}')).at(-1) ?? '';
|
|
282
315
|
}
|
package/dist/server/index.d.ts
CHANGED
|
@@ -181,25 +181,29 @@ interface RenderContext {
|
|
|
181
181
|
}
|
|
182
182
|
|
|
183
183
|
interface ApiPageProps extends Pick<RenderContext, 'generateCodeSamples' | 'generateTypeScriptSchema'> {
|
|
184
|
-
document: OpenAPIV3.Document;
|
|
184
|
+
document: string | OpenAPIV3.Document;
|
|
185
185
|
/**
|
|
186
|
-
* An array of
|
|
186
|
+
* An array of operations
|
|
187
187
|
*/
|
|
188
|
-
operations:
|
|
189
|
-
path: string;
|
|
190
|
-
method: OpenAPIV3.HttpMethods;
|
|
191
|
-
}[];
|
|
188
|
+
operations: Operation[];
|
|
192
189
|
hasHead: boolean;
|
|
193
190
|
renderer?: Partial<Renderer>;
|
|
194
191
|
}
|
|
192
|
+
interface Operation {
|
|
193
|
+
path: string;
|
|
194
|
+
method: OpenAPIV3.HttpMethods;
|
|
195
|
+
}
|
|
195
196
|
|
|
196
197
|
interface OpenAPIOptions extends Omit<Partial<ApiPageProps>, 'document'> {
|
|
197
|
-
|
|
198
|
+
/**
|
|
199
|
+
* @deprecated Pass document to `APIPage` instead
|
|
200
|
+
*/
|
|
201
|
+
documentOrPath?: string | OpenAPIV3.Document;
|
|
198
202
|
}
|
|
199
203
|
interface OpenAPIServer {
|
|
200
|
-
APIPage: FC<
|
|
204
|
+
APIPage: FC<ApiPageProps>;
|
|
201
205
|
}
|
|
202
|
-
declare function createOpenAPI(options
|
|
206
|
+
declare function createOpenAPI(options?: OpenAPIOptions): OpenAPIServer;
|
|
203
207
|
|
|
204
208
|
/**
|
|
205
209
|
* Source API Integration
|
package/dist/server/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
|
|
2
|
-
import Parser from '@apidevtools/json-schema-ref-parser';
|
|
3
2
|
import Slugger from 'github-slugger';
|
|
3
|
+
import Parser from '@apidevtools/json-schema-ref-parser';
|
|
4
4
|
import { createElement, Fragment, useMemo } from 'react';
|
|
5
5
|
import { sample } from 'openapi-sampler';
|
|
6
6
|
import { compile } from 'json-schema-to-typescript';
|
|
@@ -1001,8 +1001,17 @@ const defaultRenderer = {
|
|
|
1001
1001
|
APIPlayground
|
|
1002
1002
|
};
|
|
1003
1003
|
|
|
1004
|
-
|
|
1005
|
-
|
|
1004
|
+
const cache = new Map();
|
|
1005
|
+
async function APIPage(props) {
|
|
1006
|
+
const { operations, hasHead = true } = props;
|
|
1007
|
+
let document;
|
|
1008
|
+
if (typeof props.document === 'string') {
|
|
1009
|
+
const cached = cache.get(props.document);
|
|
1010
|
+
document = cached ?? await Parser.dereference(props.document);
|
|
1011
|
+
cache.set(props.document, document);
|
|
1012
|
+
} else {
|
|
1013
|
+
document = await Parser.dereference(props.document);
|
|
1014
|
+
}
|
|
1006
1015
|
const ctx = getContext(document, props);
|
|
1007
1016
|
return /*#__PURE__*/ jsx(ctx.renderer.Root, {
|
|
1008
1017
|
baseUrl: ctx.baseUrl,
|
|
@@ -1033,12 +1042,11 @@ function getContext(document, options) {
|
|
|
1033
1042
|
};
|
|
1034
1043
|
}
|
|
1035
1044
|
|
|
1036
|
-
function createOpenAPI(options) {
|
|
1037
|
-
const document = Parser.dereference(options.documentOrPath);
|
|
1045
|
+
function createOpenAPI(options = {}) {
|
|
1038
1046
|
return {
|
|
1039
|
-
APIPage
|
|
1047
|
+
APIPage (props) {
|
|
1040
1048
|
return /*#__PURE__*/ jsx(APIPage, {
|
|
1041
|
-
|
|
1049
|
+
...options,
|
|
1042
1050
|
...props
|
|
1043
1051
|
});
|
|
1044
1052
|
}
|
|
@@ -1078,8 +1086,13 @@ function getBadgeColor(method) {
|
|
|
1078
1086
|
*/ const attachFile = (node, file)=>{
|
|
1079
1087
|
if (!file) return node;
|
|
1080
1088
|
const data = file.data.data;
|
|
1081
|
-
|
|
1082
|
-
|
|
1089
|
+
let method;
|
|
1090
|
+
if ('_openapi' in data && typeof data._openapi === 'object') {
|
|
1091
|
+
const meta = data._openapi;
|
|
1092
|
+
method = meta.method;
|
|
1093
|
+
}
|
|
1094
|
+
if (method) {
|
|
1095
|
+
const color = getBadgeColor(method);
|
|
1083
1096
|
node.name = /*#__PURE__*/ jsxs(Fragment$1, {
|
|
1084
1097
|
children: [
|
|
1085
1098
|
node.name,
|
|
@@ -1089,7 +1102,7 @@ function getBadgeColor(method) {
|
|
|
1089
1102
|
className: 'ms-auto text-nowrap',
|
|
1090
1103
|
color
|
|
1091
1104
|
}),
|
|
1092
|
-
children:
|
|
1105
|
+
children: method
|
|
1093
1106
|
})
|
|
1094
1107
|
]
|
|
1095
1108
|
});
|
|
@@ -64,7 +64,7 @@ function useSchemaContext() {
|
|
|
64
64
|
return ctx;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
const APIPlayground = dynamic(()=>import('./playground-client-
|
|
67
|
+
const APIPlayground = dynamic(()=>import('./playground-client-itvkUjgt.js').then((mod)=>mod.APIPlayground));
|
|
68
68
|
function Root({ children, baseUrl, className, ...props }) {
|
|
69
69
|
return /*#__PURE__*/ jsx("div", {
|
|
70
70
|
className: cn('flex flex-col gap-24 text-sm text-fd-muted-foreground', className),
|
|
@@ -87,6 +87,7 @@ function CopyRouteButton({ className, route, ...props }) {
|
|
|
87
87
|
className
|
|
88
88
|
})),
|
|
89
89
|
onClick: onCopy,
|
|
90
|
+
"aria-label": "Copy route path",
|
|
90
91
|
...props,
|
|
91
92
|
children: checked ? /*#__PURE__*/ jsx(Check, {
|
|
92
93
|
className: "size-3"
|
package/dist/ui/index.js
CHANGED
|
@@ -3,8 +3,8 @@ import { cn } from 'fumadocs-ui/components/api';
|
|
|
3
3
|
import { Fragment } from 'react';
|
|
4
4
|
import { Accordions, Accordion } from 'fumadocs-ui/components/accordion';
|
|
5
5
|
import { cva } from 'class-variance-authority';
|
|
6
|
-
import { C as CopyRouteButton } from './client-client-
|
|
7
|
-
export { A as APIPlayground, R as Root, u as useSchemaContext } from './client-client-
|
|
6
|
+
import { C as CopyRouteButton } from './client-client-34yX5eij.js';
|
|
7
|
+
export { A as APIPlayground, R as Root, u as useSchemaContext } from './client-client-34yX5eij.js';
|
|
8
8
|
|
|
9
9
|
const badgeVariants = cva('rounded border px-1.5 py-1 text-xs font-medium leading-[12px]', {
|
|
10
10
|
variants: {
|
|
@@ -6,7 +6,7 @@ import { FormProvider, Controller, useFormContext, useFieldArray, useForm, useWa
|
|
|
6
6
|
import useSWRImmutable from 'swr/immutable';
|
|
7
7
|
import { Accordions, Accordion } from 'fumadocs-ui/components/accordion';
|
|
8
8
|
import { cn, buttonVariants } from 'fumadocs-ui/components/api';
|
|
9
|
-
import { u as useSchemaContext, a as useApiContext, S as SchemaContext } from './client-client-
|
|
9
|
+
import { u as useSchemaContext, a as useApiContext, S as SchemaContext } from './client-client-34yX5eij.js';
|
|
10
10
|
import { Slot } from '@radix-ui/react-slot';
|
|
11
11
|
import { cva } from 'class-variance-authority';
|
|
12
12
|
import { CircleCheckIcon, CircleXIcon, ChevronDown, ChevronUp, Check, Trash2, Plus } from 'lucide-react';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fumadocs-openapi",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"description": "Generate MDX docs for your OpenAPI spec",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"NextJs",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"dist"
|
|
45
45
|
],
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@apidevtools/json-schema-ref-parser": "^11.
|
|
47
|
+
"@apidevtools/json-schema-ref-parser": "^11.7.0",
|
|
48
48
|
"@mdx-js/mdx": "^3.0.1",
|
|
49
49
|
"@radix-ui/react-select": "^2.1.1",
|
|
50
50
|
"@radix-ui/react-slot": "^1.1.0",
|
|
@@ -54,21 +54,21 @@
|
|
|
54
54
|
"github-slugger": "^2.0.0",
|
|
55
55
|
"js-yaml": "^4.1.0",
|
|
56
56
|
"json-schema-to-typescript": "^15.0.0",
|
|
57
|
-
"lucide-react": "^0.
|
|
57
|
+
"lucide-react": "^0.427.0",
|
|
58
58
|
"openapi-sampler": "^1.5.1",
|
|
59
|
-
"react-hook-form": "^7.52.
|
|
59
|
+
"react-hook-form": "^7.52.2",
|
|
60
60
|
"remark": "^15.0.0",
|
|
61
|
-
"shiki": "^1.
|
|
61
|
+
"shiki": "^1.12.1",
|
|
62
62
|
"swr": "^2.2.5",
|
|
63
|
-
"fumadocs-core": "13.2.
|
|
64
|
-
"fumadocs-ui": "13.2.
|
|
63
|
+
"fumadocs-core": "13.2.2",
|
|
64
|
+
"fumadocs-ui": "13.2.2"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
67
67
|
"@types/js-yaml": "^4.0.9",
|
|
68
68
|
"@types/node": "20.14.12",
|
|
69
69
|
"@types/openapi-sampler": "^1.0.3",
|
|
70
70
|
"@types/react": "^18.3.3",
|
|
71
|
-
"bunchee": "^5.3.
|
|
71
|
+
"bunchee": "^5.3.2",
|
|
72
72
|
"next": "^14.2.5",
|
|
73
73
|
"openapi-types": "^12.1.3",
|
|
74
74
|
"eslint-config-custom": "0.0.0",
|