@andesine/pages 0.0.0-stage → 0.6.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/CHANGELOG.md +103 -0
- package/LICENSE +21 -0
- package/README.md +92 -2
- package/dist/answers.d.ts +6 -0
- package/dist/astro/content.astro +118 -0
- package/dist/astro/middleware.js +39 -0
- package/dist/astro/middleware.js.map +1 -0
- package/dist/astro/routes/answers.js +129 -0
- package/dist/astro/routes/answers.js.map +1 -0
- package/dist/astro/routes/entry-pages.js +22 -0
- package/dist/astro/routes/entry-pages.js.map +1 -0
- package/dist/astro/routes/llms-full.js +12 -0
- package/dist/astro/routes/llms-full.js.map +1 -0
- package/dist/astro/routes/llms.js +12 -0
- package/dist/astro/routes/llms.js.map +1 -0
- package/dist/astro/routes/markdown-alias.js +14 -0
- package/dist/astro/routes/markdown-alias.js.map +1 -0
- package/dist/astro/routes/markdown.js +12 -0
- package/dist/astro/routes/markdown.js.map +1 -0
- package/dist/astro/routes/not-found.astro +12 -0
- package/dist/astro/routes/robots.js +9 -0
- package/dist/astro/routes/robots.js.map +1 -0
- package/dist/astro/routes/search.js +42 -0
- package/dist/astro/routes/search.js.map +1 -0
- package/dist/astro/routes/sitemap.js +12 -0
- package/dist/astro/routes/sitemap.js.map +1 -0
- package/dist/astro/routes/skill.js +13 -0
- package/dist/astro/routes/skill.js.map +1 -0
- package/dist/astro/routes/skills.js +24 -0
- package/dist/astro/routes/skills.js.map +1 -0
- package/dist/astro/routes/social.js +91 -0
- package/dist/astro/routes/social.js.map +1 -0
- package/dist/astro/routes/static.astro +53 -0
- package/dist/astro/routes/well-known-llms.js +2 -0
- package/dist/astro.d.ts +34 -0
- package/dist/astro.js +60 -0
- package/dist/astro.js.map +1 -0
- package/dist/chunks/assets-D6WJmZ05.js +21 -0
- package/dist/chunks/assets-D6WJmZ05.js.map +1 -0
- package/dist/chunks/catalog-DU4BUrpw.js +28 -0
- package/dist/chunks/catalog-DU4BUrpw.js.map +1 -0
- package/dist/chunks/config-CuH5JSI4.js +184 -0
- package/dist/chunks/config-CuH5JSI4.js.map +1 -0
- package/dist/chunks/files-BxqiQzFj.js +62 -0
- package/dist/chunks/files-BxqiQzFj.js.map +1 -0
- package/dist/chunks/hash-D4piIIQ6.js +11 -0
- package/dist/chunks/hash-D4piIIQ6.js.map +1 -0
- package/dist/chunks/index-D8wL2B5s.d.ts +571 -0
- package/dist/chunks/index-vsu3hISM.d.ts +62 -0
- package/dist/chunks/limits-Ppc7BQPG.js +45 -0
- package/dist/chunks/limits-Ppc7BQPG.js.map +1 -0
- package/dist/chunks/markdown-DKJSQxR2.js +42 -0
- package/dist/chunks/markdown-DKJSQxR2.js.map +1 -0
- package/dist/chunks/mdx-components-CUUDTapN.d.ts +9 -0
- package/dist/chunks/normalize-DG5nxOLm.js +361 -0
- package/dist/chunks/normalize-DG5nxOLm.js.map +1 -0
- package/dist/chunks/paths-75QgA3Qs.js +16 -0
- package/dist/chunks/paths-75QgA3Qs.js.map +1 -0
- package/dist/chunks/prepare-lnuw_ycM.js +219 -0
- package/dist/chunks/prepare-lnuw_ycM.js.map +1 -0
- package/dist/chunks/read-DCv1lmcM.js +57 -0
- package/dist/chunks/read-DCv1lmcM.js.map +1 -0
- package/dist/chunks/request-DOuBHGQs.js +92 -0
- package/dist/chunks/request-DOuBHGQs.js.map +1 -0
- package/dist/chunks/response-CtzaKMWH.js +15 -0
- package/dist/chunks/response-CtzaKMWH.js.map +1 -0
- package/dist/chunks/site-DY-uZ0PP.js +419 -0
- package/dist/chunks/site-DY-uZ0PP.js.map +1 -0
- package/dist/chunks/skill-CBTGUHQH.js +85 -0
- package/dist/chunks/skill-CBTGUHQH.js.map +1 -0
- package/dist/chunks/sources-Cm6NdIen.js +236 -0
- package/dist/chunks/sources-Cm6NdIen.js.map +1 -0
- package/dist/chunks/stored-CabomV-C.js +354 -0
- package/dist/chunks/stored-CabomV-C.js.map +1 -0
- package/dist/chunks/stored-CcEfvCQH.js +475 -0
- package/dist/chunks/stored-CcEfvCQH.js.map +1 -0
- package/dist/chunks/types-DBzuXfSe.d.ts +53 -0
- package/dist/chunks/view-C-9ZM1zK.js +745 -0
- package/dist/chunks/view-C-9ZM1zK.js.map +1 -0
- package/dist/chunks/view-Dlf_VRI7.d.ts +151 -0
- package/dist/client.d.ts +73 -0
- package/dist/client.js +295 -0
- package/dist/client.js.map +1 -0
- package/dist/collections.d.ts +7 -0
- package/dist/collections.js +215 -0
- package/dist/collections.js.map +1 -0
- package/dist/entry-pages.d.ts +10 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +38 -0
- package/dist/index.js.map +1 -0
- package/dist/integration.d.ts +16 -0
- package/dist/integration.js +435 -0
- package/dist/integration.js.map +1 -0
- package/dist/llms-full.d.ts +5 -0
- package/dist/llms.d.ts +5 -0
- package/dist/markdown-alias.d.ts +7 -0
- package/dist/markdown.d.ts +7 -0
- package/dist/middleware.d.ts +8 -0
- package/dist/robots.d.ts +5 -0
- package/dist/runtime.d.ts +81 -0
- package/dist/runtime.js +56 -0
- package/dist/runtime.js.map +1 -0
- package/dist/scripts/restore-navigation.js +1 -0
- package/dist/search.d.ts +6 -0
- package/dist/sitemap.d.ts +5 -0
- package/dist/skill.d.ts +5 -0
- package/dist/skills.d.ts +10 -0
- package/dist/social.d.ts +7 -0
- package/dist/well-known-llms.d.ts +2 -0
- package/package.json +103 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stored-CabomV-C.js","names":[],"sources":["../../src/content/fragments.ts","../../src/content/visibility.ts","../../src/content/markdown.ts","../../src/sources/andesine/load.ts","../../src/sources/andesine/stored.ts"],"sourcesContent":["import type { ContentNode } from \"@andesine/converters\";\n\ninterface FragmentSource {\n content: unknown;\n fragments: Record<string, { name?: string; content: unknown } | undefined>;\n}\n\ninterface EntryFragments {\n body: ContentNode;\n summary?: ContentNode;\n aside?: ContentNode;\n}\n\ntype SlotName = \"summary\" | \"aside\";\n\nconst slotNames: SlotName[] = [\"summary\", \"aside\"];\nconst contentTypes = new Set([\"image\", \"element\", \"horizontalRule\", \"codeBlock\", \"table\"]);\n\n/** Empty fragments have only empty paragraphs. */\nconst hasContent = (node: ContentNode): boolean => {\n return (\n Boolean(node.text?.trim()) ||\n contentTypes.has(node.type) ||\n (node.content ?? []).some(hasContent)\n );\n};\n/**\n * Splits an entry into the page body and the `summary` and `aside` fragments, which the layout\n * shows in their own places. Other named fragments stay in the body.\n */\nconst splitFragments = (entry: FragmentSource): EntryFragments => {\n const document = entry.content as ContentNode;\n const slots = slotNames.flatMap((name) => {\n const fragment = entry.fragments[name];\n\n return fragment\n ? [{ name, label: fragment.name, content: fragment.content as ContentNode }]\n : [];\n });\n const labels = new Set(slots.map((slot) => slot.label));\n const isSlot = (node: ContentNode): boolean => {\n return node.type === \"fragment\" && labels.has(String(node.attrs?.name));\n };\n const result: EntryFragments = {\n body: { ...document, content: (document.content ?? []).filter((node) => !isSlot(node)) }\n };\n\n for (const slot of slots) {\n if (hasContent(slot.content)) result[slot.name] = slot.content;\n }\n\n return result;\n};\n\nexport { splitFragments };\nexport type { EntryFragments };\n","interface Tag {\n start: number;\n end: number;\n /** The audience of an opening tag; undefined for a closing tag. */\n audience?: Audience;\n}\n\ntype Audience = \"agents\" | \"humans\";\n\nconst tagPattern = /<Visibility\\s+for=([\"'])(agents|humans)\\1\\s*>|<\\/Visibility\\s*>/g;\n\n/** Ranges of fenced and inline code, where tags are only text. */\nconst findCode = (source: string): Array<[number, number]> => {\n const ranges: Array<[number, number]> = [];\n\n let fence: { marker: string; start: number } | undefined;\n let offset = 0;\n\n for (const line of source.split(\"\\n\")) {\n const marker = /^\\s{0,3}(`{3,}|~{3,})/.exec(line)?.[1];\n const end = offset + line.length;\n\n if (fence) {\n const closesFence = marker?.[0] === fence.marker[0] && marker.length >= fence.marker.length;\n\n if (closesFence) {\n ranges.push([fence.start, end]);\n fence = undefined;\n }\n } else if (marker) {\n fence = { marker, start: offset };\n } else {\n for (const match of line.matchAll(/`+[^`]*`+/g)) {\n ranges.push([offset + match.index, offset + match.index + match[0].length]);\n }\n }\n\n offset = end + 1;\n }\n\n if (fence) ranges.push([fence.start, source.length]);\n\n return ranges;\n};\n/** Removes the indent that all lines share, as JSX children are often indented. */\nconst dedent = (text: string): string => {\n const lines = text.split(\"\\n\");\n const indents = lines\n .filter((line) => line.trim())\n .map((line) => /^[ \\t]*/.exec(line)![0].length);\n const indent = Math.min(...indents);\n\n return indents.length ? lines.map((line) => line.slice(indent)).join(\"\\n\") : text;\n};\n/**\n * Keeps the `<Visibility>` blocks of one audience, without their tags, and removes the others.\n * Tags in code stay. Blocks cannot be nested.\n */\nconst filterVisibility = (source: string, audience: Audience): string => {\n const code = findCode(source);\n const tags: Tag[] = [...source.matchAll(tagPattern)]\n .map((match) => {\n return {\n start: match.index,\n end: match.index + match[0].length,\n audience: match[2] as Audience | undefined\n };\n })\n .filter((tag) => !code.some(([start, end]) => tag.start >= start && tag.end <= end));\n\n let result = \"\";\n let position = 0;\n\n for (let index = 0; index < tags.length; index++) {\n const open = tags[index]!;\n const close = tags[index + 1];\n const isBlock = open.audience !== undefined && close !== undefined && !close.audience;\n\n if (!isBlock) {\n throw new Error(\"Each <Visibility> needs a closing tag, and blocks cannot be nested.\");\n }\n\n result += source.slice(position, open.start);\n result += open.audience === audience ? dedent(source.slice(open.end, close.start)) : \"\";\n position = close.end;\n index++;\n }\n\n return `${result}${source.slice(position)}`.replace(/\\n{3,}/g, \"\\n\\n\");\n};\n\nexport { filterVisibility };\nexport type { Audience };\n","import type { ContentNode } from \"@andesine/converters\";\nimport { toMDX } from \"@andesine/converters/mdx\";\nimport { filterVisibility } from \"./visibility\";\n\ninterface MarkdownOptions {\n imageURL(node: ContentNode): Promise<string>;\n /** Maps content links to absolute URLs. */\n linkURL(href: string): string;\n}\n\nconst rewriteLinks = (node: ContentNode, linkURL: (href: string) => string): ContentNode => {\n const props = node.attrs?.props as Record<string, unknown> | undefined;\n const href = props?.href;\n const isLinkedCard =\n node.type === \"element\" && node.attrs?.name === \"Card\" && typeof href === \"string\";\n\n return {\n ...node,\n attrs: isLinkedCard ? { ...node.attrs, props: { ...props, href: linkURL(href) } } : node.attrs,\n marks: node.marks?.map((mark) => {\n return mark.type === \"link\" && typeof mark.attrs?.href === \"string\"\n ? { ...mark, attrs: { ...mark.attrs, href: linkURL(mark.attrs.href) } }\n : mark;\n }),\n content: node.content?.map((child) => rewriteLinks(child, linkURL))\n };\n};\n/**\n * Converts Andesine documents to the page's Markdown alternative. Elements become MDX\n * components, like in MDX files.\n */\nconst toPageMarkdown = async (\n documents: ContentNode[],\n options: MarkdownOptions\n): Promise<string> => {\n const parts = await Promise.all(\n documents.map((document) => {\n return toMDX(rewriteLinks(document, options.linkURL), {\n title: \"omit\",\n properties: \"omit\",\n imageURL: options.imageURL,\n encode: {\n elements: {\n // Agents get the content of agent blocks, without the tags.\n Visibility: (node, context) => {\n return (node.attrs?.props as { for?: string } | undefined)?.for === \"agents\"\n ? context.children(node)\n : null;\n }\n }\n }\n });\n })\n );\n\n return parts\n .map((part) => part.trim())\n .filter(Boolean)\n .join(\"\\n\\n\");\n};\nconst toAbsolute = (target: string, base: URL): string => {\n const isAbsolute = /^[a-z][\\w+.-]*:/i.test(target);\n\n return isAbsolute || target.startsWith(\"{\") ? target : new URL(target, base).href;\n};\n/** Makes link and image targets absolute, outside of inline code. */\nconst rewriteLine = (line: string, base: URL): string => {\n return line\n .split(/(`+[^`]*`+)/)\n .map((part, index) => {\n return index % 2\n ? part\n : part\n .replace(/(\\]\\()(<[^>]*>|[^)\\s]+)/g, (_, start: string, target: string) => {\n const wrapped = target.startsWith(\"<\");\n const url = toAbsolute(wrapped ? target.slice(1, -1) : target, base);\n\n return `${start}${wrapped ? `<${url}>` : url}`;\n })\n .replace(\n /^(\\s{0,3}\\[[^\\]]+\\]:\\s*)(<[^>]*>|\\S+)/,\n (_, start: string, target: string) => {\n const wrapped = target.startsWith(\"<\");\n const url = toAbsolute(wrapped ? target.slice(1, -1) : target, base);\n\n return `${start}${wrapped ? `<${url}>` : url}`;\n }\n )\n .replace(\n /\\b(href|src)=([\"'])([^\"']+)\\2/g,\n (_, name: string, quote: string, target: string) => {\n return `${name}=${quote}${toAbsolute(target, base)}${quote}`;\n }\n );\n })\n .join(\"\");\n};\n/**\n * Prepares the source of a file page as its Markdown alternative. It keeps the content for\n * agents, removes the leading MDX `import` and `export` statements, which only work in the\n * build, and makes links absolute.\n */\nconst toFileMarkdown = (body = \"\", pageURL: URL): string => {\n let fence: string | undefined;\n\n return filterVisibility(body, \"agents\")\n .replace(/^(?:(?:import|export)\\s[\\s\\S]*?(?:\\n\\s*\\n|$))+/, \"\")\n .split(\"\\n\")\n .map((line) => {\n const marker = /^\\s{0,3}(`{3,}|~{3,})/.exec(line)?.[1];\n\n if (fence) {\n const closesFence = marker?.[0] === fence[0] && marker.length >= fence.length;\n\n if (closesFence) fence = undefined;\n\n return line;\n }\n\n if (marker) {\n fence = marker;\n\n return line;\n }\n\n return rewriteLine(line, pageURL);\n })\n .join(\"\\n\")\n .trim();\n};\n\nexport { toPageMarkdown, toFileMarkdown };\n","import {\n toStructuredContent,\n type PublishedAsset,\n type PublishedCollection,\n type PublishedEntryContent\n} from \"@andesine/sdk\";\nimport type { ContentNode } from \"@andesine/converters\";\nimport type { AndesineSourceConfig } from \"../../config\";\nimport { splitFragments } from \"../../content/fragments\";\nimport { toPageMarkdown } from \"../../content/markdown\";\nimport { prepareContent, type HighlightOptions } from \"../../content/prepare\";\nimport { toHref, toSegments } from \"../../routing\";\nimport type { SourceData, SourceNode, SourcePage } from \"../types\";\nimport type { AssetStore } from \"./assets\";\n\ninterface EntryMetadata {\n description?: string;\n searchHidden: boolean;\n toc: boolean;\n layout: \"docs\" | \"wide\";\n}\n\ninterface LoadOptions {\n base: string;\n /** The site URL, for absolute links in Markdown alternatives. */\n site: string;\n assets: AssetStore;\n highlight: HighlightOptions;\n}\n\ninterface TreeEntry {\n entry: PublishedCollection[\"entries\"][number];\n collection: PublishedCollection;\n}\n\ntype HrefResolver = (slugPath: string) => string;\n\nconst isIndex = (slugPath: string): boolean => slugPath.endsWith(\"/index\");\n/** Reads the standard documentation properties. Missing properties use their defaults. */\nconst readMetadata = (entry: PublishedEntryContent): EntryMetadata => {\n const properties = toStructuredContent(entry).properties as Record<string, unknown>;\n const text = (key: string): string | undefined => {\n const value = properties[key];\n\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n };\n const flag = (key: string, fallback: boolean): boolean => {\n const value = properties[key];\n\n return typeof value === \"boolean\" ? value : fallback;\n };\n\n return {\n description: text(\"description\"),\n searchHidden: flag(\"searchHidden\", false),\n toc: flag(\"toc\", true),\n layout: text(\"layout\") === \"wide\" ? \"wide\" : \"docs\"\n };\n};\n/**\n * Returns the site URL of a published slug path, relative to the source's root collection. An\n * `index` entry has its collection's URL, like an `index` file.\n */\nconst createHrefResolver = (\n source: AndesineSourceConfig,\n base: string,\n rootSlugPath: string\n): HrefResolver => {\n const label = `Source \"${source.id}\"`;\n const prefix = [...toSegments(base, \"Site base\"), ...toSegments(source.mount, `${label} mount`)];\n const root = toSegments(rootSlugPath, `${label} root`);\n\n return (slugPath) => {\n const segments = toSegments(slugPath, label).slice(root.length);\n\n return toHref(prefix, isIndex(slugPath) ? segments.slice(0, -1) : segments);\n };\n};\n/** Lists the entries of a collection and its descendants, with their collections. */\nconst listTreeEntries = (collection: PublishedCollection): TreeEntry[] => {\n return [\n ...collection.entries.map((entry) => ({ entry, collection })),\n ...collection.collections.flatMap(listTreeEntries)\n ];\n};\n/** An `index` entry takes its collection's name, so its page is not titled \"Index\". */\nconst getTitle = ({ entry, collection }: TreeEntry): string => {\n return isIndex(entry.slugPath) ? collection.name : entry.name;\n};\n/** Prepares the content of published entries as pages. */\nconst createAndesinePages = async (\n source: AndesineSourceConfig,\n tree: PublishedCollection,\n entries: PublishedEntryContent[],\n options: LoadOptions\n): Promise<SourcePage[]> => {\n const label = `Source \"${source.id}\"`;\n const toPageHref = createHrefResolver(source, options.base, tree.slugPath);\n const treeEntries = new Map(listTreeEntries(tree).map((item) => [item.entry.id, item]));\n // Content links use the name or slug paths of published entries.\n const links = new Map(\n [...treeEntries.values()].flatMap(({ entry }) => {\n const href = toPageHref(entry.slugPath);\n\n return [\n [entry.path, href],\n [entry.slugPath, href]\n ];\n })\n );\n const linkURL = (href: string): string => {\n const [, path = \"\", suffix = \"\"] = /^([^?#]*)(.*)$/s.exec(href) ?? [];\n\n return links.has(path) ? `${links.get(path)}${suffix}` : href;\n };\n\n return Promise.all(\n entries.map(async (entry): Promise<SourcePage> => {\n const data = readMetadata(entry);\n const treeEntry = treeEntries.get(entry.id);\n const findAsset = (assetID: unknown): PublishedAsset => {\n const asset = entry.assets.find(\n (item) => item.assetID === assetID && item.variant === \"display\"\n );\n\n if (!asset) throw new Error(`${label}, entry ${entry.id}: image ${assetID} is missing.`);\n\n return asset;\n };\n const href = toPageHref(entry.slugPath);\n const pageURL = new URL(href, options.site);\n const fragments = splitFragments(entry);\n const imageURL = async (image: ContentNode): Promise<string> => {\n return options.assets.resolve(findAsset(image.attrs?.assetID), entry.id);\n };\n const prepare = (document?: ContentNode) => {\n return (\n document && prepareContent(document, { imageURL, linkURL, highlight: options.highlight })\n );\n };\n const [[body, summary, aside], markdown] = await Promise.all([\n Promise.all([\n prepare(fragments.body)!,\n prepare(fragments.summary),\n prepare(fragments.aside)\n ]),\n toPageMarkdown(\n [fragments.summary, fragments.body, fragments.aside].filter((item) => item !== undefined),\n {\n imageURL: async (image) => new URL(await imageURL(image), pageURL).href,\n linkURL: (link) => new URL(linkURL(link), pageURL).href\n }\n )\n ]).catch((error: Error) => {\n throw new Error(`${label}, entry ${entry.id}: ${error.message}`);\n });\n\n return {\n sourceID: source.id,\n id: entry.id,\n href,\n title: treeEntry ? getTitle(treeEntry) : entry.name,\n description: data.description,\n toc: data.toc,\n layout: data.layout,\n searchHidden: data.searchHidden,\n markdown,\n updatedAt: entry.version.createdAt,\n content: {\n type: \"andesine\",\n ...body,\n iconCSS: [body, summary, aside].map((item) => item?.iconCSS ?? \"\").join(\"\"),\n summary: summary?.nodes,\n aside: aside?.nodes\n }\n };\n })\n );\n};\n/**\n * Maps a publication tree to navigation, like the app's explorer: collections first, then\n * entries. The pages come from the same snapshot as the tree, so each entry has one.\n */\nconst createAndesineSource = (\n source: AndesineSourceConfig,\n tree: PublishedCollection,\n base: string,\n prepared: SourcePage[]\n): SourceData => {\n const toPageHref = createHrefResolver(source, base, tree.slugPath);\n // Copies, so changes to a page, e.g. operation links, never change the stored publication.\n const pagesByID = new Map(prepared.map((page) => [page.id, { ...page }]));\n const pages = listTreeEntries(tree).map((item) => pagesByID.get(item.entry.id)!);\n const toNode = (page: SourcePage): SourceNode => {\n return { id: `${source.id}:${page.id}`, label: page.title, page };\n };\n // Published entries are in ascending rank; the explorer shows them in descending rank.\n const build = (collection: PublishedCollection): SourceNode[] => {\n const groups = collection.collections.flatMap((child): SourceNode[] => {\n const landing = child.entries.find((entry) => isIndex(entry.slugPath));\n const children = build(child);\n const node: SourceNode = {\n id: `${source.id}:${child.id}`,\n label: child.name,\n page: landing && pagesByID.get(landing.id),\n children\n };\n\n return node.page || children.length ? [node] : [];\n });\n // The root's index page is a normal page; other index pages belong to their group.\n const isRoot = collection === tree;\n const leaves = [...collection.entries]\n .reverse()\n .filter((entry) => isRoot || !isIndex(entry.slugPath))\n .map((entry) => toNode(pagesByID.get(entry.id)!));\n\n return [...groups, ...leaves];\n };\n\n return {\n id: source.id,\n href: toPageHref(tree.slugPath),\n pages,\n navigation: build(tree)\n };\n};\n\nexport { createAndesineSource, createAndesinePages };\nexport type { LoadOptions };\n","import type { PublishedCollection } from \"@andesine/sdk\";\nimport { getCollection } from \"astro:content\";\nimport type { AndesineSourceConfig } from \"../../config\";\nimport type { SourceData, SourcePage } from \"../types\";\nimport { createAndesineSource } from \"./load\";\n\ninterface StoredSource {\n tree: PublishedCollection;\n pages: SourcePage[];\n}\n\nconst recordID = \"source\";\n\n/** Reads a publication that the build loaded. */\nconst loadAndesineSource = async (\n source: AndesineSourceConfig,\n base: string\n): Promise<SourceData> => {\n const [record] = await getCollection(source.id);\n const stored = record?.data as StoredSource | undefined;\n\n if (!stored) throw new Error(`Source \"${source.id}\": the build did not load the publication.`);\n\n return createAndesineSource(source, stored.tree, base, stored.pages);\n};\n\nexport { recordID, loadAndesineSource };\nexport type { StoredSource };\n"],"mappings":"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"}
|
|
@@ -0,0 +1,475 @@
|
|
|
1
|
+
import { n as toSegments, t as toHref } from "./paths-75QgA3Qs.js";
|
|
2
|
+
import { i as toLine, r as toLabel } from "./markdown-DKJSQxR2.js";
|
|
3
|
+
import { getCollection } from "astro:content";
|
|
4
|
+
//#region src/sources/openapi/labels.ts
|
|
5
|
+
const constraintLabels = {
|
|
6
|
+
minimum: "Minimum",
|
|
7
|
+
maximum: "Maximum",
|
|
8
|
+
exclusiveMinimum: "Greater than",
|
|
9
|
+
exclusiveMaximum: "Less than",
|
|
10
|
+
multipleOf: "Multiple of",
|
|
11
|
+
minLength: "Min length",
|
|
12
|
+
maxLength: "Max length",
|
|
13
|
+
pattern: "Pattern",
|
|
14
|
+
minItems: "Min items",
|
|
15
|
+
maxItems: "Max items",
|
|
16
|
+
uniqueItems: "Unique items",
|
|
17
|
+
minProperties: "Min properties",
|
|
18
|
+
maxProperties: "Max properties"
|
|
19
|
+
};
|
|
20
|
+
const statusLabels = {
|
|
21
|
+
"200": "OK",
|
|
22
|
+
"201": "Created",
|
|
23
|
+
"202": "Accepted",
|
|
24
|
+
"204": "No Content",
|
|
25
|
+
"301": "Moved Permanently",
|
|
26
|
+
"302": "Found",
|
|
27
|
+
"304": "Not Modified",
|
|
28
|
+
"400": "Bad Request",
|
|
29
|
+
"401": "Unauthorized",
|
|
30
|
+
"403": "Forbidden",
|
|
31
|
+
"404": "Not Found",
|
|
32
|
+
"405": "Method Not Allowed",
|
|
33
|
+
"409": "Conflict",
|
|
34
|
+
"410": "Gone",
|
|
35
|
+
"412": "Precondition Failed",
|
|
36
|
+
"413": "Content Too Large",
|
|
37
|
+
"415": "Unsupported Media Type",
|
|
38
|
+
"422": "Unprocessable Content",
|
|
39
|
+
"429": "Too Many Requests",
|
|
40
|
+
"500": "Internal Server Error",
|
|
41
|
+
"502": "Bad Gateway",
|
|
42
|
+
"503": "Service Unavailable",
|
|
43
|
+
"504": "Gateway Timeout",
|
|
44
|
+
"1XX": "Informational",
|
|
45
|
+
"2XX": "Success",
|
|
46
|
+
"3XX": "Redirection",
|
|
47
|
+
"4XX": "Client Error",
|
|
48
|
+
"5XX": "Server Error",
|
|
49
|
+
"default": "Other responses"
|
|
50
|
+
};
|
|
51
|
+
/** A schema's type, e.g. `string (date-time)` or `array of Pet`. `formatName` formats names. */
|
|
52
|
+
const toTypeLabel = (schema, formatName = (name) => name) => {
|
|
53
|
+
if (schema.ref) return formatName(schema.ref);
|
|
54
|
+
const types = (schema.type ?? []).map((type) => {
|
|
55
|
+
if (type === "array" && schema.items) return `array of ${toTypeLabel(schema.items, formatName)}`;
|
|
56
|
+
return schema.format && type !== "null" ? `${type} (${schema.format})` : type;
|
|
57
|
+
});
|
|
58
|
+
if (types.length) return types.join(" or ");
|
|
59
|
+
if (schema.oneOf) return "one of";
|
|
60
|
+
if (schema.anyOf) return "any of";
|
|
61
|
+
if (schema.allOf) return "all of";
|
|
62
|
+
return schema.const === void 0 ? "any" : "constant";
|
|
63
|
+
};
|
|
64
|
+
/** Allowed values, defaults, and limits of a schema. */
|
|
65
|
+
const toFacts = (schema) => {
|
|
66
|
+
const json = (value) => JSON.stringify(value);
|
|
67
|
+
return [
|
|
68
|
+
...schema.enum ? [{
|
|
69
|
+
label: "One of",
|
|
70
|
+
values: schema.enum.map(json)
|
|
71
|
+
}] : [],
|
|
72
|
+
...schema.const === void 0 ? [] : [{
|
|
73
|
+
label: "Value",
|
|
74
|
+
values: [json(schema.const)]
|
|
75
|
+
}],
|
|
76
|
+
...schema.default === void 0 ? [] : [{
|
|
77
|
+
label: "Default",
|
|
78
|
+
values: [json(schema.default)]
|
|
79
|
+
}],
|
|
80
|
+
...Object.entries(schema.constraints ?? {}).map(([key, value]) => {
|
|
81
|
+
return {
|
|
82
|
+
label: constraintLabels[key] ?? key,
|
|
83
|
+
values: [json(value)]
|
|
84
|
+
};
|
|
85
|
+
})
|
|
86
|
+
];
|
|
87
|
+
};
|
|
88
|
+
/** A security scheme's kind, e.g. `http, bearer, JWT` or `apiKey, header X-API-Key`. */
|
|
89
|
+
const toSchemeLabel = (scheme) => {
|
|
90
|
+
const place = scheme.in && scheme.name ? `${scheme.in} ${scheme.name}` : void 0;
|
|
91
|
+
return [
|
|
92
|
+
scheme.type,
|
|
93
|
+
scheme.scheme,
|
|
94
|
+
scheme.bearerFormat,
|
|
95
|
+
place
|
|
96
|
+
].filter(Boolean).join(", ");
|
|
97
|
+
};
|
|
98
|
+
/** An operation's summary, or its method and path without one. */
|
|
99
|
+
const toOperationTitle = (operation) => {
|
|
100
|
+
return operation.summary ?? `${operation.method.toUpperCase()} ${operation.path}`;
|
|
101
|
+
};
|
|
102
|
+
/** The text of a response status, e.g. `Not Found` for `404`. */
|
|
103
|
+
const toStatusLabel = (status) => {
|
|
104
|
+
return statusLabels[status.toUpperCase()] ?? statusLabels[status];
|
|
105
|
+
};
|
|
106
|
+
//#endregion
|
|
107
|
+
//#region src/sources/openapi/model.ts
|
|
108
|
+
/** Resolves a reference; the annotations set with it replace the target's. */
|
|
109
|
+
const resolveSchema = (schema, model, seen = []) => {
|
|
110
|
+
if (!schema.ref) return schema;
|
|
111
|
+
if (seen.includes(schema.ref)) return void 0;
|
|
112
|
+
const target = model.schemas[schema.ref];
|
|
113
|
+
const resolved = target && resolveSchema(target, model, [...seen, schema.ref]);
|
|
114
|
+
return resolved && {
|
|
115
|
+
...resolved,
|
|
116
|
+
...schema,
|
|
117
|
+
ref: void 0
|
|
118
|
+
};
|
|
119
|
+
};
|
|
120
|
+
/** Combines `allOf` details for display; field expansion still follows the original schema. */
|
|
121
|
+
const resolveSchemaDetails = (schema, model, seen = []) => {
|
|
122
|
+
const target = resolveSchema(schema, model);
|
|
123
|
+
const path = schema.ref ? [...seen, schema.ref] : seen;
|
|
124
|
+
if (!target || schema.ref && seen.includes(schema.ref)) return void 0;
|
|
125
|
+
return [...(target.allOf ?? []).flatMap((part) => {
|
|
126
|
+
return resolveSchemaDetails(part, model, path) ?? [];
|
|
127
|
+
}), target].reduce((details, part) => {
|
|
128
|
+
return {
|
|
129
|
+
...details,
|
|
130
|
+
...part,
|
|
131
|
+
type: part.type ?? details.type,
|
|
132
|
+
constraints: {
|
|
133
|
+
...details.constraints,
|
|
134
|
+
...part.constraints
|
|
135
|
+
},
|
|
136
|
+
deprecated: details.deprecated || part.deprecated,
|
|
137
|
+
readOnly: details.readOnly || part.readOnly,
|
|
138
|
+
writeOnly: details.writeOnly || part.writeOnly
|
|
139
|
+
};
|
|
140
|
+
}, {});
|
|
141
|
+
};
|
|
142
|
+
/** Required names apply across `allOf` branches, but not to nested objects or array items. */
|
|
143
|
+
const getRequiredNames = (schema, model, seen = []) => {
|
|
144
|
+
if (schema.ref && seen.includes(schema.ref)) return [];
|
|
145
|
+
const target = resolveSchema(schema, model);
|
|
146
|
+
const path = schema.ref ? [...seen, schema.ref] : seen;
|
|
147
|
+
return [...target?.required ?? [], ...(target?.allOf ?? []).flatMap((part) => getRequiredNames(part, model, path))];
|
|
148
|
+
};
|
|
149
|
+
//#endregion
|
|
150
|
+
//#region src/sources/openapi/markdown.ts
|
|
151
|
+
const locations = [
|
|
152
|
+
["path", "Path"],
|
|
153
|
+
["query", "Query"],
|
|
154
|
+
["header", "Header"],
|
|
155
|
+
["cookie", "Cookie"]
|
|
156
|
+
];
|
|
157
|
+
/** A description as one sentence line, so facts can follow it. */
|
|
158
|
+
const toSentence = (description) => {
|
|
159
|
+
const line = toLine(description);
|
|
160
|
+
return /[.!?:]$/.test(line) ? line : `${line}.`;
|
|
161
|
+
};
|
|
162
|
+
const typeLabel = (schema) => toTypeLabel(schema, (name) => `\`${name}\``);
|
|
163
|
+
/** Values, defaults, and limits of a schema, as sentences. */
|
|
164
|
+
const toFactLines = (...schemas) => {
|
|
165
|
+
return [...new Map(schemas.flatMap(toFacts).map((fact) => [fact.label, fact])).values()].map((fact) => `${fact.label}: ${fact.values.map((value) => `\`${value}\``).join(", ")}.`);
|
|
166
|
+
};
|
|
167
|
+
/**
|
|
168
|
+
* Writes schemas as nested lists. A named schema expands once for each page; later uses show
|
|
169
|
+
* its name only, so recursive schemas stay finite.
|
|
170
|
+
*/
|
|
171
|
+
const createSchemaWriter = (model) => {
|
|
172
|
+
const expanded = /* @__PURE__ */ new Set();
|
|
173
|
+
const lines = [];
|
|
174
|
+
const resolve = (schema) => {
|
|
175
|
+
if (!schema.ref) return schema;
|
|
176
|
+
if (expanded.has(schema.ref)) return void 0;
|
|
177
|
+
expanded.add(schema.ref);
|
|
178
|
+
return resolveSchema(schema, model);
|
|
179
|
+
};
|
|
180
|
+
const writeField = (name, required, schemas, depth, overrides = {}) => {
|
|
181
|
+
const targets = schemas.flatMap((schema) => resolveSchemaDetails(schema, model) ?? []);
|
|
182
|
+
const flags = [
|
|
183
|
+
schemas.map((schema) => typeLabel(schema.ref ? schema : resolveSchemaDetails(schema, model) ?? schema)).filter((type) => type !== "any").at(-1) ?? "any",
|
|
184
|
+
required ? "required" : "optional",
|
|
185
|
+
(overrides.deprecated || targets.some((target) => target.deprecated)) && "deprecated",
|
|
186
|
+
targets.some((target) => target.readOnly) && "read-only",
|
|
187
|
+
targets.some((target) => target.writeOnly) && "write-only"
|
|
188
|
+
].filter(Boolean);
|
|
189
|
+
const description = overrides.description ?? targets.map((target) => target.description).filter((description) => description !== void 0).at(-1);
|
|
190
|
+
const text = [description && toSentence(description), ...toFactLines(...targets)];
|
|
191
|
+
lines.push(`${" ".repeat(depth)}- \`${name}\` (${flags.join(", ")})${text.some(Boolean) ? `: ${text.filter(Boolean).join(" ")}` : ""}`);
|
|
192
|
+
writeChildren(schemas, depth + 1);
|
|
193
|
+
};
|
|
194
|
+
/** Collects all definitions before writing a field, so later `allOf` details are retained. */
|
|
195
|
+
const writeChildren = (schemas, depth, required = /* @__PURE__ */ new Set()) => {
|
|
196
|
+
const fields = /* @__PURE__ */ new Map();
|
|
197
|
+
const variants = [];
|
|
198
|
+
const requiredNames = /* @__PURE__ */ new Set([...required, ...schemas.flatMap((schema) => getRequiredNames(schema, model))]);
|
|
199
|
+
const collect = (schema, required) => {
|
|
200
|
+
const target = resolve(schema);
|
|
201
|
+
const requiredNames = /* @__PURE__ */ new Set([...required, ...getRequiredNames(schema, model)]);
|
|
202
|
+
const properties = [...target?.properties ?? [], ...typeof target?.additionalProperties === "object" ? [{
|
|
203
|
+
name: "{key}",
|
|
204
|
+
required: false,
|
|
205
|
+
schema: target.additionalProperties
|
|
206
|
+
}] : []];
|
|
207
|
+
if (!target) return;
|
|
208
|
+
properties.forEach((property) => {
|
|
209
|
+
const field = fields.get(property.name) ?? {
|
|
210
|
+
name: property.name,
|
|
211
|
+
required: false,
|
|
212
|
+
schemas: []
|
|
213
|
+
};
|
|
214
|
+
field.required ||= property.required || requiredNames.has(property.name);
|
|
215
|
+
field.schemas.push(property.schema);
|
|
216
|
+
fields.set(property.name, field);
|
|
217
|
+
});
|
|
218
|
+
if (target.items) collect(target.items, /* @__PURE__ */ new Set());
|
|
219
|
+
target.allOf?.forEach((part) => collect(part, requiredNames));
|
|
220
|
+
for (const [key, label] of [["oneOf", "One of"], ["anyOf", "Any of"]]) target[key]?.forEach((option, index) => {
|
|
221
|
+
variants.push({
|
|
222
|
+
schema: option,
|
|
223
|
+
label,
|
|
224
|
+
index,
|
|
225
|
+
required: requiredNames
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
};
|
|
229
|
+
schemas.forEach((schema) => collect(schema, requiredNames));
|
|
230
|
+
fields.forEach((field) => writeField(field.name, field.required, field.schemas, depth));
|
|
231
|
+
variants.forEach(({ schema, label, index, required }) => {
|
|
232
|
+
const target = resolveSchemaDetails(schema, model);
|
|
233
|
+
const name = schema.ref ? `\`${schema.ref}\`` : `${schema.title ?? `Option ${index + 1}`} (${typeLabel(target ?? schema)})`;
|
|
234
|
+
const facts = target ? toFactLines(target) : [];
|
|
235
|
+
lines.push(`${" ".repeat(depth)}- ${label}: ${name}${facts.length ? `. ${facts.join(" ")}` : ""}`);
|
|
236
|
+
writeChildren([schema], depth + 1, required);
|
|
237
|
+
});
|
|
238
|
+
};
|
|
239
|
+
return {
|
|
240
|
+
/** Writes one field and its nested fields, e.g. a parameter. */
|
|
241
|
+
field: (name, required, schema, overrides) => {
|
|
242
|
+
const start = lines.length;
|
|
243
|
+
writeField(name, required, [schema], 0, overrides);
|
|
244
|
+
return lines.splice(start).join("\n");
|
|
245
|
+
},
|
|
246
|
+
/** Writes the fields of a schema, or its type when it has no fields. */
|
|
247
|
+
write: (schema) => {
|
|
248
|
+
const start = lines.length;
|
|
249
|
+
writeChildren([schema], 0);
|
|
250
|
+
const fields = lines.splice(start);
|
|
251
|
+
const target = resolveSchemaDetails(schema, model);
|
|
252
|
+
const type = typeLabel(schema.ref ? schema : target ?? schema);
|
|
253
|
+
return [
|
|
254
|
+
type === "object" ? "" : `Type: ${type}.`,
|
|
255
|
+
target?.description,
|
|
256
|
+
...target ? toFactLines(target) : [],
|
|
257
|
+
fields.join("\n")
|
|
258
|
+
].filter(Boolean).join("\n\n");
|
|
259
|
+
}
|
|
260
|
+
};
|
|
261
|
+
};
|
|
262
|
+
const toMediaMarkdown = (media, writer) => {
|
|
263
|
+
return [`Content type: \`${media.type}\``, ...media.schema ? [writer.write(media.schema)] : []];
|
|
264
|
+
};
|
|
265
|
+
const toSecurityMarkdown = (operation, model) => {
|
|
266
|
+
if (!operation.security.length) return [];
|
|
267
|
+
const items = operation.security.map((requirement) => {
|
|
268
|
+
return `- ${Object.entries(requirement).map(([id, scopes]) => {
|
|
269
|
+
const scheme = model.securitySchemes.find((item) => item.id === id);
|
|
270
|
+
const kind = scheme ? toSchemeLabel(scheme) : "";
|
|
271
|
+
return `\`${id}\`${kind ? ` (${kind})` : ""}${scopes.length ? `, scopes: ${scopes.join(", ")}` : ""}`;
|
|
272
|
+
}).join(" and ") || "No authentication"}`;
|
|
273
|
+
});
|
|
274
|
+
return ["## Authentication", items.length > 1 ? `Use one of:\n\n${items.join("\n")}` : items[0]];
|
|
275
|
+
};
|
|
276
|
+
const toOperationMarkdown = (operation, options) => {
|
|
277
|
+
const writer = createSchemaWriter(options.model);
|
|
278
|
+
const parameters = locations.flatMap(([location, label]) => {
|
|
279
|
+
const items = operation.parameters.filter((parameter) => parameter.in === location);
|
|
280
|
+
return items.length ? [`### ${label}`, items.map((parameter) => {
|
|
281
|
+
return writer.field(parameter.name, parameter.required, parameter.schema ?? {}, {
|
|
282
|
+
description: parameter.description,
|
|
283
|
+
deprecated: parameter.deprecated
|
|
284
|
+
});
|
|
285
|
+
}).join("\n")] : [];
|
|
286
|
+
});
|
|
287
|
+
const body = operation.requestBody;
|
|
288
|
+
const responses = operation.responses.flatMap((response) => {
|
|
289
|
+
return [
|
|
290
|
+
`### ${response.status}`,
|
|
291
|
+
...response.description ? [response.description] : [],
|
|
292
|
+
...response.headers.length ? ["#### Headers", response.headers.map((header) => {
|
|
293
|
+
return writer.field(header.name, header.required, header.schema ?? {}, { description: header.description });
|
|
294
|
+
}).join("\n")] : [],
|
|
295
|
+
...response.contents.flatMap((media) => toMediaMarkdown(media, writer))
|
|
296
|
+
];
|
|
297
|
+
});
|
|
298
|
+
const server = operation.servers[0]?.url.replace(/\/$/, "") ?? "";
|
|
299
|
+
return [
|
|
300
|
+
`\`${operation.method.toUpperCase()} ${server}${operation.path}\``,
|
|
301
|
+
...operation.deprecated ? ["> This operation is deprecated."] : [],
|
|
302
|
+
...operation.description ? [operation.description] : [],
|
|
303
|
+
...toSecurityMarkdown(operation, options.model),
|
|
304
|
+
...parameters.length ? ["## Parameters", ...parameters] : [],
|
|
305
|
+
...body ? [
|
|
306
|
+
"## Request body",
|
|
307
|
+
...body.description ? [body.description] : [],
|
|
308
|
+
body.required ? "The body is required." : "The body is optional.",
|
|
309
|
+
...body.contents.flatMap((media) => toMediaMarkdown(media, writer))
|
|
310
|
+
] : [],
|
|
311
|
+
...responses.length ? ["## Responses", ...responses] : []
|
|
312
|
+
].join("\n\n");
|
|
313
|
+
};
|
|
314
|
+
const toOperationLinks = (operations, options) => {
|
|
315
|
+
return operations.map((operation) => {
|
|
316
|
+
const href = options.toURL(options.links.operations[operation.id]);
|
|
317
|
+
return `- [${toLabel(toOperationTitle(operation))}](${href}): \`${operation.method.toUpperCase()} ${operation.path}\``;
|
|
318
|
+
}).join("\n");
|
|
319
|
+
};
|
|
320
|
+
const toTagMarkdown = (tag, options) => {
|
|
321
|
+
const operations = options.model.operations.filter((operation) => {
|
|
322
|
+
return operation.tags[0] === tag.name;
|
|
323
|
+
});
|
|
324
|
+
return [
|
|
325
|
+
...tag.description ? [tag.description] : [],
|
|
326
|
+
"## Operations",
|
|
327
|
+
toOperationLinks(operations, options)
|
|
328
|
+
].join("\n\n");
|
|
329
|
+
};
|
|
330
|
+
const toOverviewMarkdown = (options) => {
|
|
331
|
+
const { model } = options;
|
|
332
|
+
const servers = model.servers.map((server) => {
|
|
333
|
+
return `- \`${server.url}\`${server.description ? `: ${toLine(server.description)}` : ""}`;
|
|
334
|
+
});
|
|
335
|
+
const schemes = model.securitySchemes.map((scheme) => {
|
|
336
|
+
return `- \`${scheme.id}\` (${toSchemeLabel(scheme)})${scheme.description ? `: ${toLine(scheme.description)}` : ""}`;
|
|
337
|
+
});
|
|
338
|
+
return [
|
|
339
|
+
...model.description ? [model.description] : [],
|
|
340
|
+
...servers.length ? ["## Servers", servers.join("\n")] : [],
|
|
341
|
+
...schemes.length ? ["## Authentication", schemes.join("\n")] : []
|
|
342
|
+
].join("\n\n");
|
|
343
|
+
};
|
|
344
|
+
/** The Markdown of an overview, tag, or operation page. */
|
|
345
|
+
const toOpenAPIMarkdown = (content, toURL) => {
|
|
346
|
+
const options = {
|
|
347
|
+
model: content.model,
|
|
348
|
+
links: content.links,
|
|
349
|
+
toURL
|
|
350
|
+
};
|
|
351
|
+
if (content.operation) return toOperationMarkdown(content.operation, options);
|
|
352
|
+
if (content.tag) return toTagMarkdown(content.tag, options);
|
|
353
|
+
return toOverviewMarkdown(options);
|
|
354
|
+
};
|
|
355
|
+
//#endregion
|
|
356
|
+
//#region src/sources/openapi/load.ts
|
|
357
|
+
/** Makes a URL segment, e.g. `schemaVersions.list` becomes `schema-versions-list`. */
|
|
358
|
+
const toSlug = (value) => {
|
|
359
|
+
return value.replace(/(\p{Ll}|\d)(\p{Lu})/gu, "$1-$2").toLowerCase().replace(/[^\p{L}\p{N}]+/gu, "-").replace(/^-|-$/g, "");
|
|
360
|
+
};
|
|
361
|
+
const createLinks = (source, model, base) => {
|
|
362
|
+
const prefix = [...toSegments(base, "Site base"), ...toSegments(source.mount, `Source "${source.id}" mount`)];
|
|
363
|
+
const href = toHref(prefix);
|
|
364
|
+
const used = /* @__PURE__ */ new Set([href]);
|
|
365
|
+
/** Adds a number to a slug while its URL is in use, e.g. `list-2`. */
|
|
366
|
+
const toUniqueSlug = (parents, slug) => {
|
|
367
|
+
let result = slug;
|
|
368
|
+
for (let index = 2; used.has(toHref(prefix, [...parents, result])); index++) result = `${slug}-${index}`;
|
|
369
|
+
used.add(toHref(prefix, [...parents, result]));
|
|
370
|
+
return result;
|
|
371
|
+
};
|
|
372
|
+
const tagSlugs = new Map(model.tags.map((tag) => [tag.name, toUniqueSlug([], toSlug(tag.name) || "tag")]));
|
|
373
|
+
return {
|
|
374
|
+
href,
|
|
375
|
+
links: {
|
|
376
|
+
operations: Object.fromEntries(model.operations.map((operation) => {
|
|
377
|
+
const tag = operation.tags[0] && tagSlugs.get(operation.tags[0]);
|
|
378
|
+
const slug = toSlug(operation.id) || toSlug(`${operation.method} ${operation.path}`);
|
|
379
|
+
const parents = tag ? [tag] : [];
|
|
380
|
+
const name = tag && slug.startsWith(`${tag}-`) ? slug.slice(tag.length + 1) : slug;
|
|
381
|
+
return [operation.id, toHref(prefix, [...parents, toUniqueSlug(parents, name)])];
|
|
382
|
+
})),
|
|
383
|
+
tags: Object.fromEntries([...tagSlugs].map(([name, slug]) => [name, toHref(prefix, [slug])]))
|
|
384
|
+
}
|
|
385
|
+
};
|
|
386
|
+
};
|
|
387
|
+
/**
|
|
388
|
+
* Maps an API model to pages and navigation: an overview page from the API description,
|
|
389
|
+
* servers, and authentication schemes, tags as groups with their descriptions as landing
|
|
390
|
+
* pages, and one page for each operation.
|
|
391
|
+
*/
|
|
392
|
+
const createOpenAPISource = (source, model, options) => {
|
|
393
|
+
const { href, links } = createLinks(source, model, options.base);
|
|
394
|
+
const toPage = (id, pageHref, title, parts) => {
|
|
395
|
+
const pageURL = new URL(pageHref, options.site);
|
|
396
|
+
const content = {
|
|
397
|
+
type: "openapi",
|
|
398
|
+
model,
|
|
399
|
+
links,
|
|
400
|
+
...parts
|
|
401
|
+
};
|
|
402
|
+
return {
|
|
403
|
+
sourceID: source.id,
|
|
404
|
+
id,
|
|
405
|
+
href: pageHref,
|
|
406
|
+
title,
|
|
407
|
+
toc: true,
|
|
408
|
+
layout: parts.operation ? "reference" : "docs",
|
|
409
|
+
searchHidden: false,
|
|
410
|
+
markdown: toOpenAPIMarkdown(content, (url) => new URL(url, pageURL).href),
|
|
411
|
+
content
|
|
412
|
+
};
|
|
413
|
+
};
|
|
414
|
+
const overview = Boolean(model.description || model.servers.length || model.securitySchemes.length) ? toPage("overview", href, model.title, {}) : void 0;
|
|
415
|
+
const operationPages = new Map(model.operations.map((operation) => {
|
|
416
|
+
const page = toPage(`operation:${operation.id}`, links.operations[operation.id], toOperationTitle(operation), { operation });
|
|
417
|
+
return [operation.id, page];
|
|
418
|
+
}));
|
|
419
|
+
const toLeaf = (operation) => {
|
|
420
|
+
const page = operationPages.get(operation.id);
|
|
421
|
+
return {
|
|
422
|
+
id: `${source.id}:${page.id}`,
|
|
423
|
+
label: page.title,
|
|
424
|
+
page,
|
|
425
|
+
method: operation.method
|
|
426
|
+
};
|
|
427
|
+
};
|
|
428
|
+
const groups = model.tags.map((tag) => {
|
|
429
|
+
const page = source.tagPages && tag.description ? toPage(`tag:${tag.name}`, links.tags[tag.name], tag.label, { tag }) : void 0;
|
|
430
|
+
return {
|
|
431
|
+
id: `${source.id}:tag:${tag.name}`,
|
|
432
|
+
label: tag.label,
|
|
433
|
+
page,
|
|
434
|
+
children: model.operations.filter((operation) => operation.tags[0] === tag.name).map(toLeaf)
|
|
435
|
+
};
|
|
436
|
+
});
|
|
437
|
+
const untagged = model.operations.filter((operation) => !operation.tags.length).map(toLeaf);
|
|
438
|
+
const navigation = [
|
|
439
|
+
...overview ? [{
|
|
440
|
+
id: `${source.id}:overview`,
|
|
441
|
+
label: "Overview",
|
|
442
|
+
page: overview
|
|
443
|
+
}] : [],
|
|
444
|
+
...groups,
|
|
445
|
+
...untagged
|
|
446
|
+
];
|
|
447
|
+
const pages = [
|
|
448
|
+
...overview ? [overview] : [],
|
|
449
|
+
...groups.flatMap((group) => group.page ? [group.page] : []),
|
|
450
|
+
...operationPages.values()
|
|
451
|
+
];
|
|
452
|
+
return {
|
|
453
|
+
id: source.id,
|
|
454
|
+
href,
|
|
455
|
+
pages,
|
|
456
|
+
navigation
|
|
457
|
+
};
|
|
458
|
+
};
|
|
459
|
+
//#endregion
|
|
460
|
+
//#region src/sources/openapi/stored.ts
|
|
461
|
+
const recordID = "spec";
|
|
462
|
+
/** Reads an API model that the build loaded. The model changes only when the spec loads again. */
|
|
463
|
+
const loadOpenAPIModel = async (source) => {
|
|
464
|
+
const [record] = await getCollection(source.id);
|
|
465
|
+
const stored = record?.data;
|
|
466
|
+
if (!stored) throw new Error(`Source "${source.id}": the build did not load the spec.`);
|
|
467
|
+
return stored.model;
|
|
468
|
+
};
|
|
469
|
+
const loadOpenAPISource = async (source, options) => {
|
|
470
|
+
return createOpenAPISource(source, await loadOpenAPIModel(source), options);
|
|
471
|
+
};
|
|
472
|
+
//#endregion
|
|
473
|
+
export { toOpenAPIMarkdown as a, resolveSchemaDetails as c, toSchemeLabel as d, toStatusLabel as f, createLinks as i, toFacts as l, loadOpenAPISource as n, getRequiredNames as o, toTypeLabel as p, recordID as r, resolveSchema as s, loadOpenAPIModel as t, toOperationTitle as u };
|
|
474
|
+
|
|
475
|
+
//# sourceMappingURL=stored-CcEfvCQH.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stored-CcEfvCQH.js","names":[],"sources":["../../src/sources/openapi/labels.ts","../../src/sources/openapi/model.ts","../../src/sources/openapi/markdown.ts","../../src/sources/openapi/load.ts","../../src/sources/openapi/stored.ts"],"sourcesContent":["import type { ApiOperation, ApiSchema, ApiSecurityScheme } from \"./model\";\n\ninterface Fact {\n label: string;\n /** Values as JSON, e.g. `\"dog\"` or `100`. */\n values: string[];\n}\n\nconst constraintLabels: Record<string, string> = {\n minimum: \"Minimum\",\n maximum: \"Maximum\",\n exclusiveMinimum: \"Greater than\",\n exclusiveMaximum: \"Less than\",\n multipleOf: \"Multiple of\",\n minLength: \"Min length\",\n maxLength: \"Max length\",\n pattern: \"Pattern\",\n minItems: \"Min items\",\n maxItems: \"Max items\",\n uniqueItems: \"Unique items\",\n minProperties: \"Min properties\",\n maxProperties: \"Max properties\"\n};\nconst statusLabels: Record<string, string> = {\n \"200\": \"OK\",\n \"201\": \"Created\",\n \"202\": \"Accepted\",\n \"204\": \"No Content\",\n \"301\": \"Moved Permanently\",\n \"302\": \"Found\",\n \"304\": \"Not Modified\",\n \"400\": \"Bad Request\",\n \"401\": \"Unauthorized\",\n \"403\": \"Forbidden\",\n \"404\": \"Not Found\",\n \"405\": \"Method Not Allowed\",\n \"409\": \"Conflict\",\n \"410\": \"Gone\",\n \"412\": \"Precondition Failed\",\n \"413\": \"Content Too Large\",\n \"415\": \"Unsupported Media Type\",\n \"422\": \"Unprocessable Content\",\n \"429\": \"Too Many Requests\",\n \"500\": \"Internal Server Error\",\n \"502\": \"Bad Gateway\",\n \"503\": \"Service Unavailable\",\n \"504\": \"Gateway Timeout\",\n \"1XX\": \"Informational\",\n \"2XX\": \"Success\",\n \"3XX\": \"Redirection\",\n \"4XX\": \"Client Error\",\n \"5XX\": \"Server Error\",\n \"default\": \"Other responses\"\n};\n\n/** A schema's type, e.g. `string (date-time)` or `array of Pet`. `formatName` formats names. */\nconst toTypeLabel = (\n schema: ApiSchema,\n formatName: (name: string) => string = (name) => name\n): string => {\n if (schema.ref) return formatName(schema.ref);\n\n const types = (schema.type ?? []).map((type) => {\n if (type === \"array\" && schema.items) {\n return `array of ${toTypeLabel(schema.items, formatName)}`;\n }\n\n return schema.format && type !== \"null\" ? `${type} (${schema.format})` : type;\n });\n\n if (types.length) return types.join(\" or \");\n if (schema.oneOf) return \"one of\";\n if (schema.anyOf) return \"any of\";\n if (schema.allOf) return \"all of\";\n\n return schema.const === undefined ? \"any\" : \"constant\";\n};\n/** Allowed values, defaults, and limits of a schema. */\nconst toFacts = (schema: ApiSchema): Fact[] => {\n const json = (value: unknown): string => JSON.stringify(value);\n\n return [\n ...(schema.enum ? [{ label: \"One of\", values: schema.enum.map(json) }] : []),\n ...(schema.const === undefined ? [] : [{ label: \"Value\", values: [json(schema.const)] }]),\n ...(schema.default === undefined ? [] : [{ label: \"Default\", values: [json(schema.default)] }]),\n ...Object.entries(schema.constraints ?? {}).map(([key, value]) => {\n return { label: constraintLabels[key] ?? key, values: [json(value)] };\n })\n ];\n};\n/** A security scheme's kind, e.g. `http, bearer, JWT` or `apiKey, header X-API-Key`. */\nconst toSchemeLabel = (scheme: ApiSecurityScheme): string => {\n const place = scheme.in && scheme.name ? `${scheme.in} ${scheme.name}` : undefined;\n\n return [scheme.type, scheme.scheme, scheme.bearerFormat, place].filter(Boolean).join(\", \");\n};\n/** An operation's summary, or its method and path without one. */\nconst toOperationTitle = (operation: ApiOperation): string => {\n return operation.summary ?? `${operation.method.toUpperCase()} ${operation.path}`;\n};\n/** The text of a response status, e.g. `Not Found` for `404`. */\nconst toStatusLabel = (status: string): string | undefined => {\n return statusLabels[status.toUpperCase()] ?? statusLabels[status];\n};\n\nexport { toTypeLabel, toFacts, toSchemeLabel, toOperationTitle, toStatusLabel };\nexport type { Fact };\n","interface ApiModel {\n title: string;\n version: string;\n /** Markdown. */\n description?: string;\n servers: ApiServer[];\n securitySchemes: ApiSecurityScheme[];\n /** Tags in the order of the spec's `tags`, then in order of first use. */\n tags: ApiTag[];\n operations: ApiOperation[];\n /** Named schemas, which `ApiSchema.ref` points to. */\n schemas: Record<string, ApiSchema>;\n}\n\ninterface ApiServer {\n /** Absolute URL with server variables resolved. */\n url: string;\n description?: string;\n}\n\ninterface ApiSecurityScheme {\n id: string;\n type: string;\n /** Markdown. */\n description?: string;\n /** For `http` schemes, e.g. `bearer`. */\n scheme?: string;\n bearerFormat?: string;\n /** For `apiKey` schemes: the name and place of the key. */\n name?: string;\n in?: string;\n}\n\ninterface ApiTag {\n name: string;\n label: string;\n /** Markdown. */\n description?: string;\n}\n\ninterface ApiOperation {\n /** The `operationId`, or `{method}-{path}` without one. */\n id: string;\n method: string;\n path: string;\n summary?: string;\n /** Markdown. */\n description?: string;\n deprecated: boolean;\n tags: string[];\n parameters: ApiParameter[];\n requestBody?: ApiRequestBody;\n responses: ApiResponse[];\n /** Alternative requirements; each maps scheme IDs to scopes. Empty means no authentication. */\n security: Array<Record<string, string[]>>;\n servers: ApiServer[];\n /** From `x-codeSamples` or `x-code-samples`. */\n codeSamples: ApiCodeSample[];\n /** The `x-` fields of the operation. */\n extensions: Record<string, unknown>;\n}\n\ninterface ApiParameter {\n name: string;\n in: \"path\" | \"query\" | \"header\" | \"cookie\";\n required: boolean;\n deprecated: boolean;\n /** Markdown. */\n description?: string;\n schema?: ApiSchema;\n examples: ApiExample[];\n /** The media type of a parameter with `content`, whose values are written in that type. */\n mediaType?: string;\n /** How values are written, e.g. `form` or `deepObject`; unset for the default of the place. */\n style?: string;\n explode?: boolean;\n}\n\ninterface ApiRequestBody {\n required: boolean;\n /** Markdown. */\n description?: string;\n contents: ApiMediaType[];\n}\n\ninterface ApiResponse {\n /** A status code, a range such as `4XX`, or `default`. */\n status: string;\n /** Markdown. */\n description?: string;\n headers: ApiHeader[];\n contents: ApiMediaType[];\n}\n\ninterface ApiHeader {\n name: string;\n required: boolean;\n /** Markdown. */\n description?: string;\n schema?: ApiSchema;\n}\n\ninterface ApiMediaType {\n type: string;\n schema?: ApiSchema;\n examples: ApiExample[];\n encoding?: Record<string, ApiEncoding>;\n}\n\ninterface ApiEncoding {\n contentType?: string;\n style?: string;\n explode?: boolean;\n}\n\ninterface ApiExample {\n name?: string;\n summary?: string;\n value: unknown;\n}\n\ninterface ApiCodeSample {\n lang: string;\n label: string;\n source: string;\n}\n\n/** A JSON Schema with 3.0 and 3.1 differences removed, e.g. `nullable` is a `null` type. */\ninterface ApiSchema {\n /**\n * The name of a schema in `ApiModel.schemas`. Only annotations can be set with it: the\n * description, default, examples, and the deprecated, read-only, and write-only flags.\n */\n ref?: string;\n type?: string[];\n format?: string;\n /** OpenAPI 3.1 content of a string, e.g. `image/png` for a file. */\n contentMediaType?: string;\n contentEncoding?: string;\n title?: string;\n /** Markdown. */\n description?: string;\n enum?: unknown[];\n const?: unknown;\n default?: unknown;\n examples?: unknown[];\n deprecated?: boolean;\n readOnly?: boolean;\n writeOnly?: boolean;\n required?: string[];\n properties?: ApiProperty[];\n additionalProperties?: ApiSchema | boolean;\n items?: ApiSchema;\n allOf?: ApiSchema[];\n oneOf?: ApiSchema[];\n anyOf?: ApiSchema[];\n not?: ApiSchema;\n discriminator?: { propertyName: string; mapping?: Record<string, string> };\n /** Validation keywords, such as `minimum` or `pattern`. */\n constraints?: Record<string, unknown>;\n}\n\ninterface ApiProperty {\n name: string;\n required: boolean;\n schema: ApiSchema;\n}\n\n/** Resolves a reference; the annotations set with it replace the target's. */\nconst resolveSchema = (\n schema: ApiSchema,\n model: ApiModel,\n seen: string[] = []\n): ApiSchema | undefined => {\n if (!schema.ref) return schema;\n if (seen.includes(schema.ref)) return undefined;\n\n const target = model.schemas[schema.ref];\n const resolved = target && resolveSchema(target, model, [...seen, schema.ref]);\n\n return resolved && { ...resolved, ...schema, ref: undefined };\n};\n\n/** Combines `allOf` details for display; field expansion still follows the original schema. */\nconst resolveSchemaDetails = (\n schema: ApiSchema,\n model: ApiModel,\n seen: string[] = []\n): ApiSchema | undefined => {\n const target = resolveSchema(schema, model);\n const path = schema.ref ? [...seen, schema.ref] : seen;\n\n if (!target || (schema.ref && seen.includes(schema.ref))) return undefined;\n\n const parts = (target.allOf ?? []).flatMap((part) => {\n return resolveSchemaDetails(part, model, path) ?? [];\n });\n\n return [...parts, target].reduce<ApiSchema>((details, part) => {\n return {\n ...details,\n ...part,\n type: part.type ?? details.type,\n constraints: { ...details.constraints, ...part.constraints },\n deprecated: details.deprecated || part.deprecated,\n readOnly: details.readOnly || part.readOnly,\n writeOnly: details.writeOnly || part.writeOnly\n };\n }, {});\n};\n\n/** Required names apply across `allOf` branches, but not to nested objects or array items. */\nconst getRequiredNames = (schema: ApiSchema, model: ApiModel, seen: string[] = []): string[] => {\n if (schema.ref && seen.includes(schema.ref)) return [];\n\n const target = resolveSchema(schema, model);\n const path = schema.ref ? [...seen, schema.ref] : seen;\n\n return [\n ...(target?.required ?? []),\n ...(target?.allOf ?? []).flatMap((part) => getRequiredNames(part, model, path))\n ];\n};\n\nexport { resolveSchema, resolveSchemaDetails, getRequiredNames };\nexport type {\n ApiModel,\n ApiServer,\n ApiSecurityScheme,\n ApiTag,\n ApiOperation,\n ApiParameter,\n ApiRequestBody,\n ApiResponse,\n ApiHeader,\n ApiMediaType,\n ApiEncoding,\n ApiExample,\n ApiCodeSample,\n ApiSchema,\n ApiProperty\n};\n","import { toLabel, toLine } from \"../../output/markdown\";\nimport type { OpenAPIContent } from \"../types\";\nimport { toFacts, toOperationTitle, toSchemeLabel, toTypeLabel } from \"./labels\";\nimport {\n resolveSchema,\n resolveSchemaDetails,\n getRequiredNames,\n type ApiMediaType,\n type ApiModel,\n type ApiOperation,\n type ApiParameter,\n type ApiSchema,\n type ApiTag\n} from \"./model\";\n\ninterface OpenAPILinks {\n /** URL paths by operation ID. */\n operations: Record<string, string>;\n /** URL paths of tag landing pages by tag name. */\n tags: Record<string, string>;\n}\n\ninterface MarkdownOptions {\n model: ApiModel;\n links: OpenAPILinks;\n /** Maps a URL path to the URL in the output, e.g. an absolute URL. */\n toURL(href: string): string;\n}\n\n/** Parameter details that override their schema's. */\ninterface FieldOverrides {\n description?: string;\n deprecated?: boolean;\n}\n\ninterface FieldSchemas {\n name: string;\n required: boolean;\n schemas: ApiSchema[];\n}\n\ninterface SchemaVariant {\n schema: ApiSchema;\n label: string;\n index: number;\n required: Set<string>;\n}\n\ntype ToURL = MarkdownOptions[\"toURL\"];\n\nconst locations: Array<[ApiParameter[\"in\"], string]> = [\n [\"path\", \"Path\"],\n [\"query\", \"Query\"],\n [\"header\", \"Header\"],\n [\"cookie\", \"Cookie\"]\n];\n\n/** A description as one sentence line, so facts can follow it. */\nconst toSentence = (description: string): string => {\n const line = toLine(description);\n\n return /[.!?:]$/.test(line) ? line : `${line}.`;\n};\nconst typeLabel = (schema: ApiSchema): string => toTypeLabel(schema, (name) => `\\`${name}\\``);\n/** Values, defaults, and limits of a schema, as sentences. */\nconst toFactLines = (...schemas: ApiSchema[]): string[] => {\n const facts = new Map(schemas.flatMap(toFacts).map((fact) => [fact.label, fact]));\n\n return [...facts.values()].map(\n (fact) => `${fact.label}: ${fact.values.map((value) => `\\`${value}\\``).join(\", \")}.`\n );\n};\n/**\n * Writes schemas as nested lists. A named schema expands once for each page; later uses show\n * its name only, so recursive schemas stay finite.\n */\nconst createSchemaWriter = (model: ApiModel) => {\n const expanded = new Set<string>();\n const lines: string[] = [];\n const resolve = (schema: ApiSchema): ApiSchema | undefined => {\n if (!schema.ref) return schema;\n if (expanded.has(schema.ref)) return undefined;\n\n expanded.add(schema.ref);\n\n return resolveSchema(schema, model);\n };\n const writeField = (\n name: string,\n required: boolean,\n schemas: ApiSchema[],\n depth: number,\n overrides: FieldOverrides = {}\n ) => {\n const targets = schemas.flatMap((schema) => resolveSchemaDetails(schema, model) ?? []);\n const flags = [\n schemas\n .map((schema) =>\n typeLabel(schema.ref ? schema : (resolveSchemaDetails(schema, model) ?? schema))\n )\n .filter((type) => type !== \"any\")\n .at(-1) ?? \"any\",\n required ? \"required\" : \"optional\",\n (overrides.deprecated || targets.some((target) => target.deprecated)) && \"deprecated\",\n targets.some((target) => target.readOnly) && \"read-only\",\n targets.some((target) => target.writeOnly) && \"write-only\"\n ].filter(Boolean);\n const description =\n overrides.description ??\n targets\n .map((target) => target.description)\n .filter((description) => description !== undefined)\n .at(-1);\n const text = [description && toSentence(description), ...toFactLines(...targets)];\n\n lines.push(\n `${\" \".repeat(depth)}- \\`${name}\\` (${flags.join(\", \")})${text.some(Boolean) ? `: ${text.filter(Boolean).join(\" \")}` : \"\"}`\n );\n writeChildren(schemas, depth + 1);\n };\n /** Collects all definitions before writing a field, so later `allOf` details are retained. */\n const writeChildren = (\n schemas: ApiSchema[],\n depth: number,\n required = new Set<string>()\n ): void => {\n const fields = new Map<string, FieldSchemas>();\n const variants: SchemaVariant[] = [];\n const requiredNames = new Set([\n ...required,\n ...schemas.flatMap((schema) => getRequiredNames(schema, model))\n ]);\n const collect = (schema: ApiSchema, required: Set<string>): void => {\n const target = resolve(schema);\n const requiredNames = new Set([...required, ...getRequiredNames(schema, model)]);\n const properties = [\n ...(target?.properties ?? []),\n ...(typeof target?.additionalProperties === \"object\"\n ? [{ name: \"{key}\", required: false, schema: target.additionalProperties }]\n : [])\n ];\n\n if (!target) return;\n\n properties.forEach((property) => {\n const field = fields.get(property.name) ?? {\n name: property.name,\n required: false,\n schemas: []\n };\n\n field.required ||= property.required || requiredNames.has(property.name);\n field.schemas.push(property.schema);\n fields.set(property.name, field);\n });\n\n if (target.items) collect(target.items, new Set());\n\n target.allOf?.forEach((part) => collect(part, requiredNames));\n\n for (const [key, label] of [\n [\"oneOf\", \"One of\"],\n [\"anyOf\", \"Any of\"]\n ] as const) {\n target[key]?.forEach((option, index) => {\n variants.push({ schema: option, label, index, required: requiredNames });\n });\n }\n };\n\n schemas.forEach((schema) => collect(schema, requiredNames));\n fields.forEach((field) => writeField(field.name, field.required, field.schemas, depth));\n variants.forEach(({ schema, label, index, required }) => {\n const target = resolveSchemaDetails(schema, model);\n const name = schema.ref\n ? `\\`${schema.ref}\\``\n : `${schema.title ?? `Option ${index + 1}`} (${typeLabel(target ?? schema)})`;\n const facts = target ? toFactLines(target) : [];\n\n lines.push(\n `${\" \".repeat(depth)}- ${label}: ${name}${facts.length ? `. ${facts.join(\" \")}` : \"\"}`\n );\n writeChildren([schema], depth + 1, required);\n });\n };\n\n return {\n /** Writes one field and its nested fields, e.g. a parameter. */\n field: (\n name: string,\n required: boolean,\n schema: ApiSchema,\n overrides?: FieldOverrides\n ): string => {\n const start = lines.length;\n\n writeField(name, required, [schema], 0, overrides);\n\n return lines.splice(start).join(\"\\n\");\n },\n /** Writes the fields of a schema, or its type when it has no fields. */\n write: (schema: ApiSchema): string => {\n const start = lines.length;\n\n writeChildren([schema], 0);\n\n const fields = lines.splice(start);\n const target = resolveSchemaDetails(schema, model);\n const type = typeLabel(schema.ref ? schema : (target ?? schema));\n\n return [\n type === \"object\" ? \"\" : `Type: ${type}.`,\n target?.description,\n ...(target ? toFactLines(target) : []),\n fields.join(\"\\n\")\n ]\n .filter(Boolean)\n .join(\"\\n\\n\");\n }\n };\n};\nconst toMediaMarkdown = (\n media: ApiMediaType,\n writer: ReturnType<typeof createSchemaWriter>\n): string[] => {\n return [`Content type: \\`${media.type}\\``, ...(media.schema ? [writer.write(media.schema)] : [])];\n};\nconst toSecurityMarkdown = (operation: ApiOperation, model: ApiModel): string[] => {\n if (!operation.security.length) return [];\n\n const items = operation.security.map((requirement) => {\n const schemes = Object.entries(requirement).map(([id, scopes]) => {\n const scheme = model.securitySchemes.find((item) => item.id === id);\n const kind = scheme ? toSchemeLabel(scheme) : \"\";\n\n return `\\`${id}\\`${kind ? ` (${kind})` : \"\"}${scopes.length ? `, scopes: ${scopes.join(\", \")}` : \"\"}`;\n });\n\n return `- ${schemes.join(\" and \") || \"No authentication\"}`;\n });\n\n return [\"## Authentication\", items.length > 1 ? `Use one of:\\n\\n${items.join(\"\\n\")}` : items[0]!];\n};\nconst toOperationMarkdown = (operation: ApiOperation, options: MarkdownOptions): string => {\n const writer = createSchemaWriter(options.model);\n const parameters = locations.flatMap(([location, label]) => {\n const items = operation.parameters.filter((parameter) => parameter.in === location);\n\n return items.length\n ? [\n `### ${label}`,\n items\n .map((parameter) => {\n return writer.field(parameter.name, parameter.required, parameter.schema ?? {}, {\n description: parameter.description,\n deprecated: parameter.deprecated\n });\n })\n .join(\"\\n\")\n ]\n : [];\n });\n const body = operation.requestBody;\n const responses = operation.responses.flatMap((response) => {\n return [\n `### ${response.status}`,\n ...(response.description ? [response.description] : []),\n ...(response.headers.length\n ? [\n \"#### Headers\",\n response.headers\n .map((header) => {\n return writer.field(header.name, header.required, header.schema ?? {}, {\n description: header.description\n });\n })\n .join(\"\\n\")\n ]\n : []),\n ...response.contents.flatMap((media) => toMediaMarkdown(media, writer))\n ];\n });\n\n const server = operation.servers[0]?.url.replace(/\\/$/, \"\") ?? \"\";\n\n return [\n `\\`${operation.method.toUpperCase()} ${server}${operation.path}\\``,\n ...(operation.deprecated ? [\"> This operation is deprecated.\"] : []),\n ...(operation.description ? [operation.description] : []),\n ...toSecurityMarkdown(operation, options.model),\n ...(parameters.length ? [\"## Parameters\", ...parameters] : []),\n ...(body\n ? [\n \"## Request body\",\n ...(body.description ? [body.description] : []),\n body.required ? \"The body is required.\" : \"The body is optional.\",\n ...body.contents.flatMap((media) => toMediaMarkdown(media, writer))\n ]\n : []),\n ...(responses.length ? [\"## Responses\", ...responses] : [])\n ].join(\"\\n\\n\");\n};\nconst toOperationLinks = (operations: ApiOperation[], options: MarkdownOptions): string => {\n return operations\n .map((operation) => {\n const href = options.toURL(options.links.operations[operation.id]!);\n\n return `- [${toLabel(toOperationTitle(operation))}](${href}): \\`${operation.method.toUpperCase()} ${operation.path}\\``;\n })\n .join(\"\\n\");\n};\nconst toTagMarkdown = (tag: ApiTag, options: MarkdownOptions): string => {\n const operations = options.model.operations.filter((operation) => {\n return operation.tags[0] === tag.name;\n });\n\n return [\n ...(tag.description ? [tag.description] : []),\n \"## Operations\",\n toOperationLinks(operations, options)\n ].join(\"\\n\\n\");\n};\nconst toOverviewMarkdown = (options: MarkdownOptions): string => {\n const { model } = options;\n const servers = model.servers.map((server) => {\n return `- \\`${server.url}\\`${server.description ? `: ${toLine(server.description)}` : \"\"}`;\n });\n const schemes = model.securitySchemes.map((scheme) => {\n return `- \\`${scheme.id}\\` (${toSchemeLabel(scheme)})${scheme.description ? `: ${toLine(scheme.description)}` : \"\"}`;\n });\n\n return [\n ...(model.description ? [model.description] : []),\n ...(servers.length ? [\"## Servers\", servers.join(\"\\n\")] : []),\n ...(schemes.length ? [\"## Authentication\", schemes.join(\"\\n\")] : [])\n ].join(\"\\n\\n\");\n};\n\n/** The Markdown of an overview, tag, or operation page. */\nconst toOpenAPIMarkdown = (content: OpenAPIContent, toURL: ToURL): string => {\n const options = { model: content.model, links: content.links, toURL };\n\n if (content.operation) return toOperationMarkdown(content.operation, options);\n if (content.tag) return toTagMarkdown(content.tag, options);\n\n return toOverviewMarkdown(options);\n};\n\nexport { toOpenAPIMarkdown };\nexport type { OpenAPILinks, MarkdownOptions };\n","import type { OpenAPISourceConfig } from \"../../config\";\nimport { toHref, toSegments } from \"../../routing\";\nimport type { OpenAPIContent, SourceData, SourceNode, SourcePage } from \"../types\";\nimport { toOperationTitle } from \"./labels\";\nimport { toOpenAPIMarkdown, type OpenAPILinks } from \"./markdown\";\nimport type { ApiModel, ApiOperation } from \"./model\";\n\ninterface LoadOptions {\n base: string;\n /** The site URL, for absolute links in Markdown alternatives. */\n site: string;\n}\n\n/** Makes a URL segment, e.g. `schemaVersions.list` becomes `schema-versions-list`. */\nconst toSlug = (value: string): string => {\n return value\n .replace(/(\\p{Ll}|\\d)(\\p{Lu})/gu, \"$1-$2\")\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}]+/gu, \"-\")\n .replace(/^-|-$/g, \"\");\n};\nconst createLinks = (source: OpenAPISourceConfig, model: ApiModel, base: string) => {\n const prefix = [\n ...toSegments(base, \"Site base\"),\n ...toSegments(source.mount, `Source \"${source.id}\" mount`)\n ];\n const href = toHref(prefix);\n const used = new Set([href]);\n /** Adds a number to a slug while its URL is in use, e.g. `list-2`. */\n const toUniqueSlug = (parents: string[], slug: string): string => {\n let result = slug;\n\n for (let index = 2; used.has(toHref(prefix, [...parents, result])); index++) {\n result = `${slug}-${index}`;\n }\n\n used.add(toHref(prefix, [...parents, result]));\n\n return result;\n };\n const tagSlugs = new Map(\n model.tags.map((tag) => [tag.name, toUniqueSlug([], toSlug(tag.name) || \"tag\")])\n );\n const links: OpenAPILinks = {\n operations: Object.fromEntries(\n model.operations.map((operation) => {\n const tag = operation.tags[0] && tagSlugs.get(operation.tags[0]);\n const slug = toSlug(operation.id) || toSlug(`${operation.method} ${operation.path}`);\n // `entries.get` in the `entries` tag becomes `entries/get/`.\n const parents = tag ? [tag] : [];\n const name = tag && slug.startsWith(`${tag}-`) ? slug.slice(tag.length + 1) : slug;\n\n return [operation.id, toHref(prefix, [...parents, toUniqueSlug(parents, name)])];\n })\n ),\n tags: Object.fromEntries([...tagSlugs].map(([name, slug]) => [name, toHref(prefix, [slug])]))\n };\n\n return { href, links };\n};\n/**\n * Maps an API model to pages and navigation: an overview page from the API description,\n * servers, and authentication schemes, tags as groups with their descriptions as landing\n * pages, and one page for each operation.\n */\nconst createOpenAPISource = (\n source: OpenAPISourceConfig,\n model: ApiModel,\n options: LoadOptions\n): SourceData => {\n const { href, links } = createLinks(source, model, options.base);\n const toPage = (\n id: string,\n pageHref: string,\n title: string,\n parts: Pick<OpenAPIContent, \"operation\" | \"tag\">\n ): SourcePage => {\n const pageURL = new URL(pageHref, options.site);\n const content: OpenAPIContent = { type: \"openapi\", model, links, ...parts };\n\n return {\n sourceID: source.id,\n id,\n href: pageHref,\n title,\n toc: true,\n // Operation pages show their examples next to the fields, in place of the ToC.\n layout: parts.operation ? \"reference\" : \"docs\",\n searchHidden: false,\n markdown: toOpenAPIMarkdown(content, (url) => new URL(url, pageURL).href),\n content\n };\n };\n const hasOverview = Boolean(\n model.description || model.servers.length || model.securitySchemes.length\n );\n const overview = hasOverview ? toPage(\"overview\", href, model.title, {}) : undefined;\n const operationPages = new Map(\n model.operations.map((operation) => {\n const page = toPage(\n `operation:${operation.id}`,\n links.operations[operation.id]!,\n toOperationTitle(operation),\n { operation }\n );\n\n return [operation.id, page];\n })\n );\n const toLeaf = (operation: ApiOperation): SourceNode => {\n const page = operationPages.get(operation.id)!;\n\n return { id: `${source.id}:${page.id}`, label: page.title, page, method: operation.method };\n };\n const groups = model.tags.map((tag): SourceNode => {\n const page =\n source.tagPages && tag.description\n ? toPage(`tag:${tag.name}`, links.tags[tag.name]!, tag.label, { tag })\n : undefined;\n\n return {\n id: `${source.id}:tag:${tag.name}`,\n label: tag.label,\n page,\n children: model.operations.filter((operation) => operation.tags[0] === tag.name).map(toLeaf)\n };\n });\n const untagged = model.operations.filter((operation) => !operation.tags.length).map(toLeaf);\n const navigation = [\n ...(overview ? [{ id: `${source.id}:overview`, label: \"Overview\", page: overview }] : []),\n ...groups,\n ...untagged\n ];\n const pages = [\n ...(overview ? [overview] : []),\n ...groups.flatMap((group) => (group.page ? [group.page] : [])),\n ...operationPages.values()\n ];\n\n return { id: source.id, href, pages, navigation };\n};\n\nexport { createLinks, createOpenAPISource };\n","import { getCollection } from \"astro:content\";\nimport type { OpenAPISourceConfig } from \"../../config\";\nimport type { SourceData } from \"../types\";\nimport { createOpenAPISource } from \"./load\";\nimport type { ApiModel } from \"./model\";\n\ninterface StoredSpec {\n model: ApiModel;\n}\n\nconst recordID = \"spec\";\n\n/** Reads an API model that the build loaded. The model changes only when the spec loads again. */\nconst loadOpenAPIModel = async (source: OpenAPISourceConfig): Promise<ApiModel> => {\n const [record] = await getCollection(source.id);\n const stored = record?.data as StoredSpec | undefined;\n\n if (!stored) throw new Error(`Source \"${source.id}\": the build did not load the spec.`);\n\n return stored.model;\n};\nconst loadOpenAPISource = async (\n source: OpenAPISourceConfig,\n options: { base: string; site: string }\n): Promise<SourceData> => {\n return createOpenAPISource(source, await loadOpenAPIModel(source), options);\n};\n\nexport { recordID, loadOpenAPIModel, loadOpenAPISource };\nexport type { StoredSpec };\n"],"mappings":"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"}
|