UNPKG

fumadocs-openapi

Version:

Generate MDX docs for your OpenAPI spec

95 lines (94 loc) 3.54 kB
import { dump } from 'js-yaml'; import Slugger from 'github-slugger'; import { idToTitle } from '../utils/id-to-title.js'; export function generateDocument(input, processed, pageProps, options, context) { const { frontmatter, includeDescription = false, addGeneratedComment = true, } = options; const out = []; const extend = frontmatter?.(options.title, options.description, context); const page = { ...pageProps, document: options.inlineDocument ? processed.downloaded : input, }; let meta; if (page.operations?.length === 1) { const operation = page.operations[0]; meta = { method: operation.method.toUpperCase(), route: operation.path, }; } const data = generateStaticData(processed.document, page); const banner = dump({ title: options.title, description: !includeDescription ? options.description : undefined, full: true, ...extend, _openapi: { ...meta, ...data, ...extend?._openapi, }, }).trim(); if (banner.length > 0) out.push(`---\n${banner}\n---`); if (addGeneratedComment !== false) { let commentContent = 'This file was generated by Fumadocs. Do not edit this file directly. Any changes should be made by running the generation command again.'; if (typeof addGeneratedComment === 'string') { commentContent = addGeneratedComment; } commentContent = commentContent.replaceAll('/', '\\/'); out.push(`{/* ${commentContent} */}`); } const imports = options.imports ?.map((item) => `import { ${item.names.join(', ')} } from ${JSON.stringify(item.from)};`) .join('\n'); if (imports) { out.push(imports); } if (options.description && includeDescription) out.push(options.description); out.push(pageContent(page)); return out.join('\n\n'); } function generateStaticData(dereferenced, props) { const slugger = new Slugger(); const toc = []; const structuredData = { headings: [], contents: [] }; for (const item of props.operations ?? []) { const operation = dereferenced.paths?.[item.path]?.[item.method]; if (!operation) continue; if (props.hasHead && operation.operationId) { const title = operation.summary ?? (operation.operationId ? idToTitle(operation.operationId) : item.path); const id = slugger.slug(title); toc.push({ depth: 2, title, url: `#${id}`, }); structuredData.headings.push({ content: title, id, }); } if (operation.description) structuredData.contents.push({ content: operation.description, heading: structuredData.headings.at(-1)?.id, }); } return { toc, structuredData }; } function pageContent(props) { // filter extra properties in props const operations = (props.operations ?? []).map((item) => ({ path: item.path, method: item.method, })); const webhooks = (props.webhooks ?? []).map((item) => ({ name: item.name, method: item.method, })); return `<APIPage document={${JSON.stringify(props.document)}} operations={${JSON.stringify(operations)}} webhooks={${JSON.stringify(webhooks)}} hasHead={${JSON.stringify(props.hasHead)}} />`; }