mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-17 08:05:19 +00:00
Formatting
This commit is contained in:
@@ -55,16 +55,16 @@ async function OpenAPIBody(props: BlockProps<DocumentBlockSwagger>) {
|
||||
chevronDown: <Icon icon="chevron-down" />,
|
||||
chevronRight: <Icon icon="chevron-right" />,
|
||||
edit: <Icon icon="edit" />,
|
||||
clear: <Icon icon="x" />
|
||||
clear: <Icon icon="x" />,
|
||||
},
|
||||
CodeBlock: PlainCodeBlock,
|
||||
defaultInteractiveOpened: context.mode === 'print',
|
||||
id: block.meta?.id,
|
||||
blockKey: block.key
|
||||
blockKey: block.key,
|
||||
}}
|
||||
className="openapi-block"
|
||||
/>
|
||||
</OpenAPIContext>
|
||||
</OpenAPIContext>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,21 +1,38 @@
|
||||
'use client'
|
||||
'use client';
|
||||
|
||||
import { DocumentBlock } from "@gitbook/api";
|
||||
import { OpenAPIOperationData } from "@gitbook/react-openapi";
|
||||
import {OpenAPIContextProvider} from "@gitbook/react-openapi/client";
|
||||
import { DocumentBlock } from '@gitbook/api';
|
||||
import { OpenAPIOperationData } from '@gitbook/react-openapi';
|
||||
import { OpenAPIContextProvider } from '@gitbook/react-openapi/client';
|
||||
import { useRouter, useSearchParams } from 'next/navigation';
|
||||
import * as React from 'react';
|
||||
|
||||
export default function OpenAPIContext(props: { children: React.ReactNode; block: DocumentBlock; data: OpenAPIOperationData }) {
|
||||
export default function OpenAPIContext(props: {
|
||||
children: React.ReactNode;
|
||||
block: DocumentBlock;
|
||||
data: OpenAPIOperationData;
|
||||
}) {
|
||||
const { block, children, data } = props;
|
||||
const [isPending, startTransition] = React.useTransition();
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
return <OpenAPIContextProvider isPending={isPending} data={data} params={searchParams.get("block") === block.key ? Object.fromEntries(searchParams.entries()) : undefined} onUpdate={async (params) => {
|
||||
startTransition(() => {
|
||||
const queryParams = new URLSearchParams(params ?? '');
|
||||
router.replace(`?${queryParams}`, { scroll: false });
|
||||
})
|
||||
}}>{children}</OpenAPIContextProvider>
|
||||
}
|
||||
return (
|
||||
<OpenAPIContextProvider
|
||||
isPending={isPending}
|
||||
data={data}
|
||||
params={
|
||||
searchParams.get('block') === block.key
|
||||
? Object.fromEntries(searchParams.entries())
|
||||
: undefined
|
||||
}
|
||||
onUpdate={async (params) => {
|
||||
startTransition(() => {
|
||||
const queryParams = new URLSearchParams(params ?? '');
|
||||
router.replace(`?${queryParams}`, { scroll: false });
|
||||
});
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</OpenAPIContextProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -370,7 +370,9 @@
|
||||
@apply p-0.5 inline-flex text-dark/6 dark:text-light/6 hover:opacity-8;
|
||||
}
|
||||
|
||||
.openapi-edit-button { @apply p-0.5 ml-4 size-4; }
|
||||
.openapi-edit-button {
|
||||
@apply p-0.5 ml-4 size-4;
|
||||
}
|
||||
|
||||
.openapi-edit-button > * {
|
||||
@apply size-full;
|
||||
|
||||
@@ -1,34 +1,52 @@
|
||||
'use client'
|
||||
'use client';
|
||||
|
||||
import * as React from 'react';
|
||||
import { OpenAPIOperationData } from './fetchOpenAPIOperation';
|
||||
import { getServersURL } from './utils';
|
||||
|
||||
type OpenAPIContextProps = { isPending?: boolean; serverUrl?: string; state?: Record<string, string> | null, onUpdate: (params: Record<string, string> | null) => void; }
|
||||
type OpenAPIContextProps = {
|
||||
isPending?: boolean;
|
||||
serverUrl?: string;
|
||||
state?: Record<string, string> | null;
|
||||
onUpdate: (params: Record<string, string> | null) => void;
|
||||
};
|
||||
const OpenAPIContext = React.createContext<OpenAPIContextProps | null>(null);
|
||||
|
||||
export function useOpenAPIContext() {
|
||||
return React.useContext(OpenAPIContext);
|
||||
}
|
||||
|
||||
export function OpenAPIContextProvider(props: { children: React.ReactNode; data: OpenAPIOperationData; isPending?: boolean; params?: Record<string, string>; onUpdate: OpenAPIContextProps['onUpdate']; }) {
|
||||
export function OpenAPIContextProvider(props: {
|
||||
children: React.ReactNode;
|
||||
data: OpenAPIOperationData;
|
||||
isPending?: boolean;
|
||||
params?: Record<string, string>;
|
||||
onUpdate: OpenAPIContextProps['onUpdate'];
|
||||
}) {
|
||||
const { children, data, isPending, params, onUpdate } = props;
|
||||
|
||||
|
||||
const clientState = React.useMemo(() => {
|
||||
if (!params) { return null; }
|
||||
if (!params) {
|
||||
return null;
|
||||
}
|
||||
return parseClientStateModifiers(data, params);
|
||||
}, [data, params]);
|
||||
const serverUrl = getServersURL(data.servers, clientState ?? undefined)
|
||||
const serverUrl = getServersURL(data.servers, clientState ?? undefined);
|
||||
|
||||
return <OpenAPIContext.Provider value={{
|
||||
isPending,
|
||||
state: clientState,
|
||||
serverUrl,
|
||||
onUpdate
|
||||
}}>{children}</OpenAPIContext.Provider>
|
||||
return (
|
||||
<OpenAPIContext.Provider
|
||||
value={{
|
||||
isPending,
|
||||
state: clientState,
|
||||
serverUrl,
|
||||
onUpdate,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</OpenAPIContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function parseClientStateModifiers(data: OpenAPIOperationData, params: Record<string, string>) {
|
||||
if (!data) {
|
||||
return null;
|
||||
@@ -39,14 +57,16 @@ function parseClientStateModifiers(data: OpenAPIOperationData, params: Record<st
|
||||
? Math.max(0, Math.min(Number(serverQueryParam), data.servers.length - 1))
|
||||
: 0;
|
||||
const server = data.servers[serverIndex];
|
||||
return server ? Object.keys(server.variables ?? {}).reduce<Record<string, string>>(
|
||||
(result, key) => {
|
||||
const selection = params[key];
|
||||
if (!isNaN(Number(selection))) {
|
||||
result[key] = selection;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
{ server: `${serverIndex}`, edit: params['edit'] },
|
||||
) : null;
|
||||
}
|
||||
return server
|
||||
? Object.keys(server.variables ?? {}).reduce<Record<string, string>>(
|
||||
(result, key) => {
|
||||
const selection = params[key];
|
||||
if (!isNaN(Number(selection))) {
|
||||
result[key] = selection;
|
||||
}
|
||||
return result;
|
||||
},
|
||||
{ server: `${serverIndex}`, edit: params['edit'] },
|
||||
)
|
||||
: null;
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@ export function OpenAPIServerURL(props: {
|
||||
}) {
|
||||
const { path, servers, context } = props;
|
||||
const ctx = useOpenAPIContext();
|
||||
|
||||
|
||||
const serverIndex = !isNaN(Number(ctx?.state?.server)) ? Number(ctx?.state?.server) : 0;
|
||||
const server = servers[serverIndex];
|
||||
const parts = parseServerURL(server?.url ?? '');
|
||||
console.log({ ctxState: ctx?.state })
|
||||
console.log({ ctxState: ctx?.state });
|
||||
|
||||
return (
|
||||
<ServerURLForm context={context} servers={servers} serverIndex={serverIndex}>
|
||||
|
||||
@@ -21,7 +21,7 @@ export function ServerURLForm(props: {
|
||||
if (index !== serverIndex) {
|
||||
update({
|
||||
server: `${index}` ?? '0',
|
||||
...(ctx?.state?.edit ? { edit: 'true' } : undefined)
|
||||
...(ctx?.state?.edit ? { edit: 'true' } : undefined),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -37,12 +37,14 @@ export function ServerURLForm(props: {
|
||||
update({
|
||||
server: `${formData.get('server')}` ?? '0',
|
||||
...variables,
|
||||
...(ctx?.state?.edit ? { edit: 'true' } : undefined)
|
||||
...(ctx?.state?.edit ? { edit: 'true' } : undefined),
|
||||
});
|
||||
}
|
||||
|
||||
function update(variables?: Record<string, string>) {
|
||||
if (!context.blockKey) { return; }
|
||||
if (!context.blockKey) {
|
||||
return;
|
||||
}
|
||||
ctx?.onUpdate({
|
||||
block: context.blockKey,
|
||||
...variables,
|
||||
@@ -51,22 +53,42 @@ export function ServerURLForm(props: {
|
||||
|
||||
const isEditable = servers.length > 1 || server.variables;
|
||||
return (
|
||||
<form ref={formRef} onSubmit={e => { e.preventDefault(); updateServerVariables(new FormData(e.currentTarget)); }} className="contents">
|
||||
<form
|
||||
ref={formRef}
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
updateServerVariables(new FormData(e.currentTarget));
|
||||
}}
|
||||
className="contents"
|
||||
>
|
||||
<fieldset disabled={ctx?.isPending} className="contents">
|
||||
<input type="hidden" name="block" value={context.blockKey} />
|
||||
{children}
|
||||
{ctx?.state?.edit && servers.length > 1 ? (
|
||||
<ServerSelector
|
||||
servers={servers}
|
||||
currentIndex={serverIndex}
|
||||
onChange={switchServer}
|
||||
servers={servers}
|
||||
currentIndex={serverIndex}
|
||||
onChange={switchServer}
|
||||
/>
|
||||
) : null}
|
||||
{ isEditable ? <button className='openapi-edit-button ml-2' onClick={() => {
|
||||
const state = { ...ctx?.state };
|
||||
delete state.edit;
|
||||
update({ server: `${serverIndex}`, ...state, ...(ctx?.state?.edit ? undefined : { edit: 'true' }) });
|
||||
}} title={ctx?.state?.edit ? undefined : "Try different server options"} aria-label={ctx?.state?.edit ? "Clear" : "Edit"}>{ctx?.state?.edit ? context.icons.clear : context.icons.edit}</button> : null}
|
||||
{isEditable ? (
|
||||
<button
|
||||
className="openapi-edit-button ml-2"
|
||||
onClick={() => {
|
||||
const state = { ...ctx?.state };
|
||||
delete state.edit;
|
||||
update({
|
||||
server: `${serverIndex}`,
|
||||
...state,
|
||||
...(ctx?.state?.edit ? undefined : { edit: 'true' }),
|
||||
});
|
||||
}}
|
||||
title={ctx?.state?.edit ? undefined : 'Try different server options'}
|
||||
aria-label={ctx?.state?.edit ? 'Clear' : 'Edit'}
|
||||
>
|
||||
{ctx?.state?.edit ? context.icons.clear : context.icons.edit}
|
||||
</button>
|
||||
) : null}
|
||||
</fieldset>
|
||||
</form>
|
||||
);
|
||||
|
||||
@@ -16,7 +16,13 @@ export function OpenAPIServerURLVariable(props: {
|
||||
|
||||
if (variable.enum && variable.enum.length > 0) {
|
||||
if (!selectable) {
|
||||
return <span className={classNames('openapi-url-var')}>{!isNaN(Number(selectionIndex)) ? variable.enum[Number(selectionIndex)] : variable.default}</span>;
|
||||
return (
|
||||
<span className={classNames('openapi-url-var')}>
|
||||
{!isNaN(Number(selectionIndex))
|
||||
? variable.enum[Number(selectionIndex)]
|
||||
: variable.default}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -57,7 +57,7 @@ export function ScalarApiButton(props: {
|
||||
/**
|
||||
* Wrap the rendering with a context to open the scalar modal.
|
||||
*/
|
||||
export function ScalarApiClient(props: { children: React.ReactNode; }) {
|
||||
export function ScalarApiClient(props: { children: React.ReactNode }) {
|
||||
const { children } = props;
|
||||
|
||||
const ctx = useOpenAPIContext();
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
'use client';
|
||||
export {OpenAPIContextProvider} from './OpenAPIContextProvider';
|
||||
export { OpenAPIContextProvider } from './OpenAPIContextProvider';
|
||||
|
||||
@@ -12,7 +12,6 @@ export function createStateKey(key: string, scope?: string) {
|
||||
return scope ? `${scope}_${key}` : key;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the default URL for the server.
|
||||
*/
|
||||
@@ -20,7 +19,8 @@ export function getServersURL(
|
||||
servers: OpenAPIV3.ServerObject[],
|
||||
selectors?: Record<string, string>,
|
||||
): string {
|
||||
const serverIndex = selectors && !isNaN(Number(selectors.server)) ? Number(selectors.server) : 0;
|
||||
const serverIndex =
|
||||
selectors && !isNaN(Number(selectors.server)) ? Number(selectors.server) : 0;
|
||||
const server = servers[serverIndex];
|
||||
const parts = parseServerURL(server?.url ?? '');
|
||||
|
||||
@@ -48,4 +48,4 @@ export function parseServerURL(url: string) {
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user