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
34 changes: 34 additions & 0 deletions apps/docs/app/[lang]/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type React from 'react'
import { getHighlighter, highlight } from 'fumadocs-core/highlight'
import type { Root } from 'fumadocs-core/page-tree'
import { findNeighbour } from 'fumadocs-core/page-tree'
import type { ApiPageProps } from 'fumadocs-openapi/ui'
Expand All @@ -17,6 +18,8 @@ import { Heading } from '@/components/ui/heading'
import { ResponseSection } from '@/components/ui/response-section'
import { i18n } from '@/lib/i18n'
import { getApiSpecContent, getAuthenticatedCodeSamples, openapi } from '@/lib/openapi'
import { curlJsonBodyGrammar } from '@/lib/shiki-curl-json'
import { simShikiOptions } from '@/lib/shiki-theme'
import { type PageData, source } from '@/lib/source'
import { DOCS_BASE_URL } from '@/lib/urls'

Expand Down Expand Up @@ -69,9 +72,40 @@ function stripLocalePrefix(url: string, lang: string): string {
return url
}

/**
* Renders the API reference's request and response samples through the docs' own `CodeBlock`
* rather than fumadocs-openapi's built-in one, so those blocks get the emcn copy control
* instead of fumadocs' lucide clipboard. Mirrors the default renderer — same `highlight` call,
* same `Pre` component, same `my-0` — differing only in which shell wraps the result.
*
* One asymmetry: `highlight` resolves fumadocs' shared `defaultShikiFactory`, while the renderer
* this replaces uses whatever `shiki` factory the page was configured with. They are the same
* object because that factory is also the default; passing a custom one would be honored on API
* markdown and ignored here.
*/
async function ApiCodeBlock({ lang, code }: { lang: string; code: string }) {
// Registers the injection on the shared highlighter `highlight` resolves; an injection is a
// property of the highlighter, not a per-call option. Idempotent — already-loaded grammars are
// skipped.
await getHighlighter('js', { langs: [curlJsonBodyGrammar] })
return (
<CodeBlock className='my-0'>
{await highlight(code, { lang, ...simShikiOptions, components: { pre: Pre } })}
</CodeBlock>
)
}

const APIPage = createAPIPage(openapi, {
renderCodeBlock: (props) => <ApiCodeBlock {...props} />,
playground: { enabled: false },
generateCodeSamples: getAuthenticatedCodeSamples,
/**
* fumadocs-openapi highlights its request and response samples through its own Shiki
* instance, not the MDX pipeline, so it does not inherit `source.config.ts`. Left alone,
* every API reference page renders `github-light` / `github-dark` while the rest of the docs
* render the platform palette.
*/
shikiOptions: simShikiOptions,
client: {
operation: { APIExampleSelector },
},
Expand Down
14 changes: 2 additions & 12 deletions apps/docs/app/[lang]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { ReactNode } from 'react'
import { defineI18nUI } from 'fumadocs-ui/i18n'
import { DocsLayout } from 'fumadocs-ui/layouts/docs'
import { RootProvider } from 'fumadocs-ui/provider/next'
import { Geist_Mono, Inter } from 'next/font/google'
import { Inter } from 'next/font/google'
import { ThemeProvider } from 'next-themes'
import {
SidebarFolder,
Expand All @@ -25,12 +25,6 @@ const inter = Inter({
display: 'swap',
})

const geistMono = Geist_Mono({
subsets: ['latin'],
variable: '--font-geist-mono',
display: 'swap',
})

const { provider } = defineI18nUI(i18n, {
translations: {
en: {
Expand Down Expand Up @@ -85,11 +79,7 @@ export default async function Layout({ children, params }: LayoutProps) {
}

return (
<html
lang={lang}
className={`${inter.variable} ${geistMono.variable} ${season.variable}`}
suppressHydrationWarning
>
<html lang={lang} className={`${inter.variable} ${season.variable}`} suppressHydrationWarning>
<head>
<script
id='website-json-ld'
Expand Down
Loading
Loading