11import type React from 'react'
2+ import { getHighlighter , highlight } from 'fumadocs-core/highlight'
23import type { Root } from 'fumadocs-core/page-tree'
34import { findNeighbour } from 'fumadocs-core/page-tree'
45import type { ApiPageProps } from 'fumadocs-openapi/ui'
@@ -17,6 +18,8 @@ import { Heading } from '@/components/ui/heading'
1718import { ResponseSection } from '@/components/ui/response-section'
1819import { i18n } from '@/lib/i18n'
1920import { getApiSpecContent , getAuthenticatedCodeSamples , openapi } from '@/lib/openapi'
21+ import { curlJsonBodyGrammar } from '@/lib/shiki-curl-json'
22+ import { simShikiOptions } from '@/lib/shiki-theme'
2023import { type PageData , source } from '@/lib/source'
2124import { DOCS_BASE_URL } from '@/lib/urls'
2225
@@ -69,9 +72,40 @@ function stripLocalePrefix(url: string, lang: string): string {
6972 return url
7073}
7174
75+ /**
76+ * Renders the API reference's request and response samples through the docs' own `CodeBlock`
77+ * rather than fumadocs-openapi's built-in one, so those blocks get the emcn copy control
78+ * instead of fumadocs' lucide clipboard. Mirrors the default renderer — same `highlight` call,
79+ * same `Pre` component, same `my-0` — differing only in which shell wraps the result.
80+ *
81+ * One asymmetry: `highlight` resolves fumadocs' shared `defaultShikiFactory`, while the renderer
82+ * this replaces uses whatever `shiki` factory the page was configured with. They are the same
83+ * object because that factory is also the default; passing a custom one would be honored on API
84+ * markdown and ignored here.
85+ */
86+ async function ApiCodeBlock ( { lang, code } : { lang : string ; code : string } ) {
87+ // Registers the injection on the shared highlighter `highlight` resolves; an injection is a
88+ // property of the highlighter, not a per-call option. Idempotent — already-loaded grammars are
89+ // skipped.
90+ await getHighlighter ( 'js' , { langs : [ curlJsonBodyGrammar ] } )
91+ return (
92+ < CodeBlock className = 'my-0' >
93+ { await highlight ( code , { lang, ...simShikiOptions , components : { pre : Pre } } ) }
94+ </ CodeBlock >
95+ )
96+ }
97+
7298const APIPage = createAPIPage ( openapi , {
99+ renderCodeBlock : ( props ) => < ApiCodeBlock { ...props } /> ,
73100 playground : { enabled : false } ,
74101 generateCodeSamples : getAuthenticatedCodeSamples ,
102+ /**
103+ * fumadocs-openapi highlights its request and response samples through its own Shiki
104+ * instance, not the MDX pipeline, so it does not inherit `source.config.ts`. Left alone,
105+ * every API reference page renders `github-light` / `github-dark` while the rest of the docs
106+ * render the platform palette.
107+ */
108+ shikiOptions : simShikiOptions ,
75109 client : {
76110 operation : { APIExampleSelector } ,
77111 } ,
0 commit comments