mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-25 04:20:02 +00:00
Chore: migrate other packages
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'fumadocs-typescript': minor
|
||||
'fumadocs-openapi': minor
|
||||
---
|
||||
|
||||
Bump deps
|
||||
@@ -93,13 +93,19 @@ export function createRehypeCode<
|
||||
}>),
|
||||
) {
|
||||
async function initTransformer(_options?: Options) {
|
||||
const { highlighter, options } =
|
||||
typeof highlighterFactory === 'function'
|
||||
? await highlighterFactory(_options)
|
||||
: {
|
||||
highlighter: await highlighterFactory.getOrInit(),
|
||||
options: (_options ?? {}) as RehypeCodeOptionsCommon,
|
||||
};
|
||||
let highlighter: HighlighterCore;
|
||||
let options: RehypeCodeOptionsCommon;
|
||||
if (typeof highlighterFactory === 'function') {
|
||||
const out = await highlighterFactory(_options);
|
||||
highlighter = out.highlighter;
|
||||
options = out.options;
|
||||
} else {
|
||||
// TODO: When newer Shiki supported it, register lang alias dynamically instead of creating new instance
|
||||
highlighter = _options?.langAlias
|
||||
? await highlighterFactory.init(_options)
|
||||
: await highlighterFactory.getOrInit();
|
||||
options = (_options ?? {}) as RehypeCodeOptionsCommon;
|
||||
}
|
||||
|
||||
const transformers = options.transformers ? [...options.transformers] : [];
|
||||
transformers.unshift({
|
||||
|
||||
@@ -83,6 +83,7 @@
|
||||
"fumadocs-core": "workspace:*",
|
||||
"fumadocs-ui": "workspace:*",
|
||||
"json-schema-typed": "^8.0.2",
|
||||
"shiki": "^4.0.2",
|
||||
"tailwindcss": "^4.2.1",
|
||||
"tsconfig": "workspace:*",
|
||||
"tsdown": "0.21.2"
|
||||
@@ -90,13 +91,17 @@
|
||||
"peerDependencies": {
|
||||
"@scalar/api-client-react": "*",
|
||||
"@types/react": "*",
|
||||
"fumadocs-core": "^16.5.0",
|
||||
"fumadocs-ui": "^16.5.0",
|
||||
"fumadocs-core": "^16.7.0",
|
||||
"fumadocs-ui": "^16.7.0",
|
||||
"json-schema-typed": "*",
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0"
|
||||
"react-dom": "^19.2.0",
|
||||
"shiki": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"shiki": {
|
||||
"optional": true
|
||||
},
|
||||
"json-schema-typed": {
|
||||
"optional": true
|
||||
},
|
||||
|
||||
@@ -15,7 +15,6 @@ import type { FetchResult } from '@/playground/fetcher';
|
||||
import type { SecurityEntry } from '@/playground/index';
|
||||
import { getStatusInfo } from './status-info';
|
||||
import { joinURL, resolveRequestData, resolveServerUrl, withBase } from '@/utils/url';
|
||||
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock.core';
|
||||
import { MethodLabel } from '@/ui/components/method-label';
|
||||
import { useQuery } from '@/utils/use-query';
|
||||
import {
|
||||
@@ -52,6 +51,7 @@ import {
|
||||
import { objectGet, objectSet, stringifyFieldKey } from '@fumari/stf/lib/utils';
|
||||
import { FieldInput, FieldSet, JsonInput, ObjectInput } from './components/inputs';
|
||||
import type { ParameterObject } from '@/types';
|
||||
import { ClientCodeBlock } from '@/ui/components/codeblock';
|
||||
|
||||
export interface FormValues extends Record<string, unknown> {
|
||||
path: Record<string, unknown>;
|
||||
@@ -696,7 +696,6 @@ function Route({ route, ...props }: ComponentProps<'div'> & { route: string }) {
|
||||
|
||||
function DefaultResultDisplay({ data, reset }: { data: FetchResult; reset: () => void }) {
|
||||
const statusInfo = useMemo(() => getStatusInfo(data.status), [data.status]);
|
||||
const { shikiOptions } = useApiContext();
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-3 mt-2 px-3 py-2 border-y bg-fd-secondary text-fd-secondary-foreground">
|
||||
@@ -715,10 +714,9 @@ function DefaultResultDisplay({ data, reset }: { data: FetchResult; reset: () =>
|
||||
</div>
|
||||
<p className="text-sm text-fd-muted-foreground">{data.status}</p>
|
||||
{data.data !== undefined && (
|
||||
<DynamicCodeBlock
|
||||
<ClientCodeBlock
|
||||
lang={typeof data.data === 'string' && data.data.length > 50000 ? 'text' : data.type}
|
||||
code={typeof data.data === 'string' ? data.data : JSON.stringify(data.data, null, 2)}
|
||||
options={shikiOptions}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any -- rehype-react without types */
|
||||
import Slugger from 'github-slugger';
|
||||
import type { Awaitable, DistributiveOmit, MethodInformation, RenderContext } from '@/types';
|
||||
import type { Awaitable, MethodInformation, RenderContext } from '@/types';
|
||||
import type { NoReference } from '@/utils/schema';
|
||||
import type { ProcessedDocument } from '@/utils/process-document';
|
||||
import { defaultAdapters, MediaAdapter } from '@/requests/media/adapter';
|
||||
import type { FC, HTMLAttributes, ReactNode } from 'react';
|
||||
import { highlight, type CoreHighlightOptions } from 'fumadocs-core/highlight/core';
|
||||
import type { OpenAPIServer } from '@/server';
|
||||
import type { APIPageClientOptions } from './client';
|
||||
import { Heading } from 'fumadocs-ui/components/heading';
|
||||
@@ -20,10 +19,11 @@ import { CodeBlock, Pre } from 'fumadocs-ui/components/codeblock';
|
||||
import type { SchemaUIOptions } from './schema';
|
||||
import type { ResponseTab } from './operation/response-tabs';
|
||||
import type { ExampleRequestItem } from './operation/request-tabs';
|
||||
import type { ResolvedShikiConfig } from 'fumadocs-core/highlight/config';
|
||||
import { APIPage, type ApiPageProps, type OperationItem, type WebhookItem } from './api-page';
|
||||
import type { CodeUsageGeneratorRegistry, InlineCodeUsageGenerator } from '@/requests/generators';
|
||||
import type { JSONSchema } from 'json-schema-typed';
|
||||
import type { BundledTheme, CodeOptionsThemes, CodeToHastOptionsCommon } from 'shiki';
|
||||
import { highlightHast, type ShikiFactory } from 'fumadocs-core/highlight/shiki';
|
||||
|
||||
export interface GenerateTypeScriptDefinitionsContext extends RenderContext {
|
||||
operation: NoReference<MethodInformation>;
|
||||
@@ -75,9 +75,9 @@ export interface CreateAPIPageOptions {
|
||||
*/
|
||||
generateCodeSamples?: (method: MethodInformation) => Awaitable<InlineCodeUsageGenerator[]>;
|
||||
|
||||
shiki: ResolvedShikiConfig;
|
||||
shiki: ShikiFactory;
|
||||
renderMarkdown?: (md: string) => ReactNode;
|
||||
shikiOptions?: DistributiveOmit<CoreHighlightOptions, 'config' | 'lang' | 'components'>;
|
||||
shikiOptions: Omit<CodeToHastOptionsCommon, 'lang'> & CodeOptionsThemes<BundledTheme>;
|
||||
|
||||
/**
|
||||
* Show full response schema instead of only example response & Typescript definitions.
|
||||
@@ -233,6 +233,8 @@ export function createAPIPage(
|
||||
.use(createRehypeCode(options.shiki), {
|
||||
langs: [],
|
||||
lazy: true,
|
||||
defaultColor: false,
|
||||
...options.shikiOptions,
|
||||
})
|
||||
.use(rehypeReact);
|
||||
}
|
||||
@@ -293,10 +295,13 @@ export function createAPIPage(
|
||||
return options.renderCodeBlock({ lang, code });
|
||||
}
|
||||
|
||||
const rendered = await highlight(code, {
|
||||
const hast = await highlightHast(await options.shiki.getOrInit(), code, {
|
||||
lang,
|
||||
defaultColor: false,
|
||||
...options.shikiOptions,
|
||||
config: options.shiki,
|
||||
});
|
||||
const rendered = toJsxRuntime(hast, {
|
||||
...JsxRuntime,
|
||||
components: {
|
||||
pre: Pre,
|
||||
},
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
'use client';
|
||||
import {
|
||||
DynamicCodeBlock,
|
||||
type DynamicCodeblockProps,
|
||||
} from 'fumadocs-ui/components/dynamic-codeblock.core';
|
||||
import { useApiContext } from '../contexts/api';
|
||||
import { createContext, type ReactNode, use } from 'react';
|
||||
import type { ShikiFactory } from 'fumadocs-core/highlight/shiki';
|
||||
|
||||
const CodeBlockContext = createContext<ShikiFactory | null>(null);
|
||||
|
||||
export function ClientCodeBlock(props: Omit<DynamicCodeblockProps, 'highlighter' | 'options'>) {
|
||||
const { shikiOptions } = useApiContext();
|
||||
const ctx = use(CodeBlockContext);
|
||||
if (!ctx)
|
||||
throw new Error(
|
||||
'Missing Shiki context, please wrap your <APIPage /> component under <ClientCodeBlockProvider />',
|
||||
);
|
||||
|
||||
return <DynamicCodeBlock highlighter={() => ctx.getOrInit()} options={shikiOptions} {...props} />;
|
||||
}
|
||||
|
||||
export function ClientCodeBlockProvider({
|
||||
factory,
|
||||
children,
|
||||
}: {
|
||||
factory: ShikiFactory;
|
||||
children: ReactNode;
|
||||
}) {
|
||||
return <CodeBlockContext value={factory}>{children}</CodeBlockContext>;
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
'use client';
|
||||
import * as base from 'fumadocs-core/highlight/core/client';
|
||||
import { configDefault } from 'fumadocs-core/highlight';
|
||||
import type { ReactNode } from 'react';
|
||||
import { ClientCodeBlockProvider } from './components/codeblock';
|
||||
import { defaultShikiFactory } from 'fumadocs-core/highlight/shiki/full';
|
||||
|
||||
export function ShikiConfigProvider({ children }: { children: ReactNode }) {
|
||||
const config = base.useShikiConfigOptional() ?? configDefault;
|
||||
return <base.ShikiConfigProvider config={config}>{children}</base.ShikiConfigProvider>;
|
||||
export function FullProvider({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<ClientCodeBlockProvider factory={defaultShikiFactory}>{children}</ClientCodeBlockProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import type { OpenAPIServer } from '@/server';
|
||||
import * as base from './base';
|
||||
import { configDefault } from 'fumadocs-core/highlight';
|
||||
import { ApiPageProps } from './api-page';
|
||||
import { ShikiConfigProvider } from './full.client';
|
||||
import type { ApiPageProps } from './api-page';
|
||||
import { defaultShikiFactory } from 'fumadocs-core/highlight/shiki/full';
|
||||
import { FullProvider } from './full.client';
|
||||
|
||||
export type CreateAPIPageOptions = Partial<base.CreateAPIPageOptions>;
|
||||
|
||||
export function createAPIPage(server: OpenAPIServer, options: CreateAPIPageOptions = {}) {
|
||||
const APIPage = base.createAPIPage(server, {
|
||||
shiki: configDefault,
|
||||
shiki: defaultShikiFactory,
|
||||
shikiOptions: { themes: { light: 'github-light', dark: 'github-dark' } },
|
||||
async generateTypeScriptDefinitions(schema, ctx) {
|
||||
if (typeof schema !== 'object') return;
|
||||
const { compile } = await import('@fumari/json-schema-ts');
|
||||
@@ -29,9 +30,9 @@ export function createAPIPage(server: OpenAPIServer, options: CreateAPIPageOptio
|
||||
|
||||
return function APIPageFull(props: ApiPageProps) {
|
||||
return (
|
||||
<ShikiConfigProvider>
|
||||
<FullProvider>
|
||||
<APIPage {...props} />
|
||||
</ShikiConfigProvider>
|
||||
</FullProvider>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ import {
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
} from '@/ui/components/select';
|
||||
import { DynamicCodeBlock } from 'fumadocs-ui/components/dynamic-codeblock.core';
|
||||
import { useState, useEffect, useMemo, createContext, ReactNode, useRef, use } from 'react';
|
||||
import type { ExampleRequestItem } from '../request-tabs';
|
||||
import type { RawRequestData, RequestData } from '@/requests/types';
|
||||
import type { CodeUsageGenerator } from '@/requests/generators';
|
||||
import { ClientCodeBlock } from '@/ui/components/codeblock';
|
||||
|
||||
export type ExampleUpdateListener = (data: RawRequestData, encoded: RequestData) => void;
|
||||
|
||||
@@ -135,7 +135,7 @@ export function UsageTab({
|
||||
lang,
|
||||
_client,
|
||||
}: Pick<CodeUsageGenerator, 'lang' | '_client'> & { id: string }) {
|
||||
const { shikiOptions, mediaAdapters, codeUsages } = useApiContext();
|
||||
const { mediaAdapters, codeUsages } = useApiContext();
|
||||
const {
|
||||
examples,
|
||||
example: selectedExampleId,
|
||||
@@ -186,5 +186,5 @@ export function UsageTab({
|
||||
|
||||
if (!code) return null;
|
||||
|
||||
return <DynamicCodeBlock lang={lang} code={code} options={shikiOptions} />;
|
||||
return <ClientCodeBlock lang={lang} code={code} />;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { RenderContext } from '@/types';
|
||||
import { processDocument } from '@/utils/process-document';
|
||||
import { configDefault } from 'fumadocs-core/highlight';
|
||||
import { defaultShikiFactory } from 'fumadocs-core/highlight/shiki/full';
|
||||
import Slugger from 'github-slugger';
|
||||
|
||||
export async function renderContextFrom(input: string): Promise<RenderContext> {
|
||||
@@ -11,7 +11,8 @@ export async function renderContextFrom(input: string): Promise<RenderContext> {
|
||||
generateTypeScriptDefinitions() {
|
||||
return '';
|
||||
},
|
||||
shiki: configDefault,
|
||||
shiki: defaultShikiFactory,
|
||||
shikiOptions: { theme: 'github-light' },
|
||||
renderCodeBlock(_lang, code) {
|
||||
return code;
|
||||
},
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
"fumadocs-core": "workspace:*",
|
||||
"fumadocs-ui": "workspace:*",
|
||||
"mdast-util-mdx": "^3.0.0",
|
||||
"shiki": "^4.0.2",
|
||||
"tsconfig": "workspace:*",
|
||||
"tsdown": "0.21.2",
|
||||
"typescript": "^5.9.3",
|
||||
@@ -69,12 +70,16 @@
|
||||
"@types/hast": "*",
|
||||
"@types/mdast": "*",
|
||||
"@types/react": "*",
|
||||
"fumadocs-core": "^16.5.0",
|
||||
"fumadocs-ui": "^16.5.0",
|
||||
"fumadocs-core": "^16.7.0",
|
||||
"fumadocs-ui": "^16.7.0",
|
||||
"react": "*",
|
||||
"shiki": "*",
|
||||
"typescript": "*"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"shiki": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/estree": {
|
||||
"optional": true
|
||||
},
|
||||
|
||||
@@ -3,13 +3,12 @@ import type { Nodes } from 'hast';
|
||||
import type { Transformer } from 'unified';
|
||||
import type { Expression, ExpressionStatement, ObjectExpression } from 'estree';
|
||||
import { createGenerator, type DocEntry, type Generator } from '@/lib/base';
|
||||
import { type MarkdownRenderer, markdownRenderer } from '@/markdown';
|
||||
import { type MarkdownRenderer, markdownRenderer, type ShikiOptions } from '@/markdown';
|
||||
import { valueToEstree } from 'estree-util-value-to-estree';
|
||||
import { visit } from 'unist-util-visit';
|
||||
import { type BaseTypeTableProps, type GenerateTypeTableOptions } from '@/lib/type-table';
|
||||
import { toEstree } from 'hast-util-to-estree';
|
||||
import { type ParameterTag, parseTags } from '@/lib/parse-tags';
|
||||
import type { ResolvedShikiConfig } from 'fumadocs-core/highlight/config';
|
||||
import type { MdxJsxAttribute, MdxJsxExpressionAttribute, MdxJsxFlowElement } from 'mdast-util-mdx';
|
||||
import type { VFile } from 'vfile';
|
||||
|
||||
@@ -118,7 +117,7 @@ export interface RemarkAutoTypeTableOptions {
|
||||
/**
|
||||
* config for Shiki when using default `renderMarkdown` & `renderType`.
|
||||
*/
|
||||
shiki?: ResolvedShikiConfig;
|
||||
shiki?: ShikiOptions;
|
||||
renderMarkdown?: MarkdownRenderer['renderMarkdownToHast'];
|
||||
renderType?: MarkdownRenderer['renderTypeToHast'];
|
||||
|
||||
|
||||
@@ -1,33 +1,35 @@
|
||||
import type { ElementContent, Nodes } from 'hast';
|
||||
import { remark } from 'remark';
|
||||
import { remarkGfm } from 'fumadocs-core/mdx-plugins/remark-gfm';
|
||||
import { createRehypeCode } from 'fumadocs-core/mdx-plugins/rehype-code.core';
|
||||
import { rehypeCode } from 'fumadocs-core/mdx-plugins/rehype-code';
|
||||
import remarkRehype from 'remark-rehype';
|
||||
import { highlightHast } from 'fumadocs-core/highlight/core';
|
||||
import { configDefault } from 'fumadocs-core/highlight';
|
||||
import { highlightHast } from 'fumadocs-core/highlight';
|
||||
import type { CodeToHastOptionsCommon, CodeOptionsThemes, BundledTheme } from 'shiki';
|
||||
|
||||
export interface MarkdownRenderer {
|
||||
renderTypeToHast: (type: string) => Nodes | Promise<Nodes>;
|
||||
renderMarkdownToHast: (md: string) => Nodes | Promise<Nodes>;
|
||||
}
|
||||
|
||||
export function markdownRenderer(shiki = configDefault): MarkdownRenderer {
|
||||
export type ShikiOptions = Omit<CodeToHastOptionsCommon, 'lang'> & CodeOptionsThemes<BundledTheme>;
|
||||
|
||||
export function markdownRenderer(options?: ShikiOptions): MarkdownRenderer {
|
||||
const processor = remark()
|
||||
.use(remarkGfm)
|
||||
.use(remarkRehype)
|
||||
.use(createRehypeCode(shiki), {
|
||||
lazy: true,
|
||||
.use(rehypeCode, {
|
||||
langs: ['ts', 'tsx'],
|
||||
// disable default transformers & meta parser
|
||||
transformers: [],
|
||||
parseMetaString: undefined,
|
||||
...options,
|
||||
});
|
||||
return {
|
||||
async renderTypeToHast(type) {
|
||||
const nodes = await highlightHast(type, {
|
||||
config: shiki,
|
||||
lang: 'ts',
|
||||
structure: 'inline',
|
||||
...options,
|
||||
});
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { type ParameterNode, type TypeNode, TypeTable } from 'fumadocs-ui/components/type-table';
|
||||
import { type Jsx, toJsxRuntime } from 'hast-util-to-jsx-runtime';
|
||||
import * as runtime from 'react/jsx-runtime';
|
||||
import { toJsxRuntime } from 'hast-util-to-jsx-runtime';
|
||||
import * as JsxRuntime from 'react/jsx-runtime';
|
||||
import defaultMdxComponents from 'fumadocs-ui/mdx';
|
||||
import 'server-only';
|
||||
import type { ComponentProps, ReactNode } from 'react';
|
||||
@@ -8,14 +8,13 @@ import { type BaseTypeTableProps, type GenerateTypeTableOptions } from '@/lib/ty
|
||||
import { type Generator } from '@/lib/base';
|
||||
import type { Nodes } from 'hast';
|
||||
import { parseTags } from '@/lib/parse-tags';
|
||||
import type { ResolvedShikiConfig } from 'fumadocs-core/highlight/config';
|
||||
import { markdownRenderer } from '@/markdown';
|
||||
import { markdownRenderer, type ShikiOptions } from '@/markdown';
|
||||
|
||||
export interface AutoTypeTableProps extends BaseTypeTableProps, ComponentProps<'div'> {
|
||||
generator: Generator;
|
||||
|
||||
/** Shiki configuration when using default `renderMarkdown` & `renderType` */
|
||||
shiki?: ResolvedShikiConfig;
|
||||
shiki?: ShikiOptions;
|
||||
options?: GenerateTypeTableOptions;
|
||||
|
||||
renderMarkdown?: (md: string) => Promise<ReactNode>;
|
||||
@@ -82,9 +81,7 @@ export async function AutoTypeTable({
|
||||
|
||||
function toJsx(hast: Nodes) {
|
||||
return toJsxRuntime(hast, {
|
||||
Fragment: runtime.Fragment,
|
||||
jsx: runtime.jsx as Jsx,
|
||||
jsxs: runtime.jsxs as Jsx,
|
||||
...JsxRuntime,
|
||||
components: { ...defaultMdxComponents, img: undefined },
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user