fumadocs-openapi
Version:
Generate MDX docs for your OpenAPI spec
136 lines (134 loc) • 4.57 kB
JavaScript
import { createMethod } from "../utils/schema.js";
import { defaultAdapters } from "../requests/media/adapter.js";
import { Operation } from "./operation/index.js";
import { ApiProviderLazy } from "./contexts/api.lazy.js";
import Slugger from "github-slugger";
import * as JsxRuntime from "react/jsx-runtime";
import { jsx, jsxs } from "react/jsx-runtime";
import { CodeBlock, Pre } from "fumadocs-ui/components/codeblock";
import { highlight } from "fumadocs-core/highlight";
import { Heading } from "fumadocs-ui/components/heading";
import { rehypeCode } from "fumadocs-core/mdx-plugins/rehype-code";
import { remarkGfm } from "fumadocs-core/mdx-plugins/remark-gfm";
import defaultMdxComponents from "fumadocs-ui/mdx";
import { remark } from "remark";
import remarkRehype from "remark-rehype";
import { toJsxRuntime } from "hast-util-to-jsx-runtime";
//#region src/ui/api-page.tsx
function createAPIPage(server, options = {}) {
let processor;
function createMarkdownProcessor() {
function rehypeReact() {
this.compiler = (tree, file) => {
return toJsxRuntime(tree, {
development: false,
filePath: file.path,
...JsxRuntime,
components: defaultMdxComponents
});
};
}
return remark().use(remarkGfm).use(remarkRehype).use(rehypeCode, {
langs: [],
lazy: true
}).use(rehypeReact);
}
return async function APIPageWrapper({ document, ...props }) {
let processed;
if (typeof document === "string") processed = await server.getSchema(document);
else processed = await document;
const { dereferenced } = processed;
const servers = dereferenced.servers && dereferenced.servers.length > 0 ? dereferenced.servers : [{ url: "/" }];
const slugger = new Slugger();
const ctx = {
schema: processed,
proxyUrl: server.options.proxyUrl,
...options,
servers,
mediaAdapters: {
...defaultAdapters,
...options.mediaAdapters
},
slugger,
renderHeading(depth, text, props$1) {
const id = slugger.slug(text);
return /* @__PURE__ */ jsx(Heading, {
id,
as: `h${depth}`,
...props$1,
children: text
}, id);
},
async renderMarkdown(text) {
processor ??= createMarkdownProcessor();
return (await processor.process({ value: text })).result;
},
async renderCodeBlock(lang, code) {
return /* @__PURE__ */ jsx(CodeBlock, {
className: "my-0",
children: await highlight(code, {
lang,
...options.shikiOptions,
components: { pre: (props$1) => /* @__PURE__ */ jsx(Pre, { ...props$1 }) }
})
});
}
};
return /* @__PURE__ */ jsx(APIPage, {
...props,
ctx
});
};
}
async function APIPage({ showTitle: hasHead = false, showDescription, operations, webhooks, ctx }) {
const { dereferenced } = ctx.schema;
let { renderPageLayout } = ctx.content ?? {};
renderPageLayout ??= (slots) => /* @__PURE__ */ jsxs("div", {
className: "flex flex-col gap-24 text-sm @container",
children: [slots.operations?.map((op) => op.children), slots.webhooks?.map((op) => op.children)]
});
const content = await renderPageLayout({
operations: operations?.map((item) => {
const pathItem = dereferenced.paths?.[item.path];
if (!pathItem) throw new Error(`[Fumadocs OpenAPI] Path not found in OpenAPI schema: ${item.path}`);
const operation = pathItem[item.method];
if (!operation) throw new Error(`[Fumadocs OpenAPI] Method ${item.method} not found in operation: ${item.path}`);
return {
item,
children: /* @__PURE__ */ jsx(Operation, {
method: createMethod(item.method, pathItem, operation),
path: item.path,
ctx,
showTitle: hasHead,
showDescription
}, `${item.path}:${item.method}`)
};
}),
webhooks: webhooks?.map((item) => {
const webhook = dereferenced.webhooks?.[item.name];
if (!webhook) throw new Error(`[Fumadocs OpenAPI] Webhook not found in OpenAPI schema: ${item.name}`);
const hook = webhook[item.method];
if (!hook) throw new Error(`[Fumadocs OpenAPI] Method ${item.method} not found in webhook: ${item.name}`);
return {
item,
children: /* @__PURE__ */ jsx(Operation, {
type: "webhook",
method: createMethod(item.method, webhook, hook),
ctx,
path: `/${item.name}`,
showTitle: hasHead,
showDescription
}, `${item.name}:${item.method}`)
};
})
}, ctx);
return /* @__PURE__ */ jsx(ApiProviderLazy, {
servers: ctx.servers,
shikiOptions: ctx.shikiOptions,
client: ctx.client ?? {},
children: content
});
}
//#endregion
export { createAPIPage };
//# sourceMappingURL=api-page.js.map