Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions portal-template/src/components/api-page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { createOpenAPIPage } from 'fumadocs-openapi/ui';
import { createCodeUsageGeneratorRegistry } from 'fumadocs-openapi/requests/generators';
import { CodeBlock } from './code-block';
import { renderExampleLayout } from './example-layout';
import { renderUsageTabs } from './usage-tabs';

export const OpenAPIPage = createOpenAPIPage({
// Without a registry of its own, Fumadocs registers and bundles every request generator it has.
codeUsages: createCodeUsageGeneratorRegistry(),
generateTypeScriptDefinitions: false,
components: { CodeBlock },
content: { renderAPIExampleLayout: renderExampleLayout, renderAPIExampleUsageTabs: renderUsageTabs }
});
9 changes: 9 additions & 0 deletions portal-template/src/components/code-block.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock.core';
import { useRenderContext } from 'fumadocs-openapi/ui';

// Fumadocs passes `JSON.stringify(example.value)`, which is undefined for an example with no `value`.
export function CodeBlock({ lang, code }: Readonly<{ lang: string; code: string | undefined }>) {
const { shiki, shikiOptions } = useRenderContext();
if (code === undefined) return null;
return <DynamicCodeBlock lang={lang} code={code} highlighter={() => shiki.getOrInit()} options={shikiOptions} />;
}
7 changes: 1 addition & 6 deletions portal-template/src/components/usage-tabs.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { useEffect, useState, type ReactNode } from 'react';
import { CodeBlockTab, CodeBlockTabs, CodeBlockTabsList, CodeBlockTabsTrigger } from 'fumadocs-ui/components/codeblock';
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock.core';
import { useOperationContext, useRenderContext, useServerContext } from 'fumadocs-openapi/ui';
import { pathnameFromRequest } from 'fumadocs-openapi/requests/generators';
import { curl } from 'fumadocs-openapi/requests/generators/curl';
import { joinURL, resolveServerUrl } from '@fumadocs/api-docs/utils/url';
import { CodeSample } from '@/lib/code-samples';
import { CodeBlock } from './code-block';
import { useExampleSelection } from './example-layout';

interface UsageTab {
Expand Down Expand Up @@ -68,11 +68,6 @@ function CurlCode() {
return <CodeBlock lang={curl.lang} code={curl.generate({ ...request, url }, { mediaAdapters, custom: null })} />;
}

function CodeBlock({ lang, code }: Readonly<{ lang: string; code: string }>) {
const { shiki, shikiOptions } = useRenderContext();
return <DynamicCodeBlock lang={lang} code={code} highlighter={() => shiki.getOrInit()} options={shikiOptions} />;
}

// Fumadocs reports the playground's edits to the selected example through its listeners.
function useSelectedRequest() {
const { examples, example, addListener, removeListener } = useOperationContext();
Expand Down
Loading