diff --git a/.changeset/tender-grapes-walk.md b/.changeset/tender-grapes-walk.md new file mode 100644 index 000000000..d15a2843c --- /dev/null +++ b/.changeset/tender-grapes-walk.md @@ -0,0 +1,7 @@ +--- +"@gitbook/openapi-parser": patch +"@gitbook/react-openapi": patch +"gitbook": patch +--- + +Support expand-all options for OpenAPI diff --git a/packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPIOperation.tsx b/packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPIOperation.tsx index 7694f94dc..634b59b10 100644 --- a/packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPIOperation.tsx +++ b/packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPIOperation.tsx @@ -50,6 +50,10 @@ async function OpenAPIOperationBody(props: BlockProps props, specUrl: publicURL, context: context.contentContext, + expandAllResponses: + data.operation['x-expandAllResponses'] ?? data['x-expandAllResponses'], + expandAllModelSections: + data.operation['x-expandAllModelSections'] ?? data['x-expandAllModelSections'], })} className="openapi-block" /> diff --git a/packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPISchemas.tsx b/packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPISchemas.tsx index ec90eead5..c0fd2ce08 100644 --- a/packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPISchemas.tsx +++ b/packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPISchemas.tsx @@ -46,12 +46,13 @@ async function OpenAPISchemasBody(props: BlockProps) { return ( diff --git a/packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPIWebhook.tsx b/packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPIWebhook.tsx index 3225ee1da..2c6b21946 100644 --- a/packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPIWebhook.tsx +++ b/packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPIWebhook.tsx @@ -52,6 +52,10 @@ async function OpenAPIWebhookBody(props: BlockProps) { props, specUrl: publicURL, context: context.contentContext, + expandAllResponses: + data.operation['x-expandAllResponses'] ?? data['x-expandAllResponses'], + expandAllModelSections: + data.operation['x-expandAllModelSections'] ?? data['x-expandAllModelSections'], })} className="openapi-block" /> diff --git a/packages/gitbook/src/components/DocumentView/OpenAPI/context.tsx b/packages/gitbook/src/components/DocumentView/OpenAPI/context.tsx index b6eaee797..289ab699a 100644 --- a/packages/gitbook/src/components/DocumentView/OpenAPI/context.tsx +++ b/packages/gitbook/src/components/DocumentView/OpenAPI/context.tsx @@ -24,8 +24,10 @@ export function getOpenAPIContext(args: { props: BlockProps; specUrl: string | null; context: GitBookAnyContext | undefined; + expandAllResponses?: boolean; + expandAllModelSections?: boolean; }): OpenAPIContextInput { - const { props, specUrl, context } = args; + const { props, specUrl, context, expandAllResponses, expandAllModelSections } = args; const { block } = props; const customizationLocale = context ? getSpaceLocale(context) : DEFAULT_LOCALE; @@ -91,7 +93,8 @@ export function getOpenAPIContext(args: { }} /> ), - defaultInteractiveOpened: props.context.mode === 'print', + expandAllResponses: expandAllResponses || props.context.mode === 'print', + expandAllModelSections: expandAllModelSections || props.context.mode === 'print', id: block.meta?.id, blockKey: block.key, locale, diff --git a/packages/gitbook/src/lib/openapi/resolveOpenAPISchemasBlock.ts b/packages/gitbook/src/lib/openapi/resolveOpenAPISchemasBlock.ts index 1e3dd1131..030023e69 100644 --- a/packages/gitbook/src/lib/openapi/resolveOpenAPISchemasBlock.ts +++ b/packages/gitbook/src/lib/openapi/resolveOpenAPISchemasBlock.ts @@ -1,5 +1,5 @@ -import { OpenAPIParseError, type OpenAPISchema } from '@gitbook/openapi-parser'; -import { resolveOpenAPISchemas } from '@gitbook/react-openapi'; +import { OpenAPIParseError } from '@gitbook/openapi-parser'; +import { type OpenAPISchemasData, resolveOpenAPISchemas } from '@gitbook/react-openapi'; import { fetchOpenAPIFilesystem } from './fetch'; import type { OpenAPISchemasBlock, @@ -7,9 +7,7 @@ import type { ResolveOpenAPIBlockResult, } from './types'; -type ResolveOpenAPISchemasBlockResult = ResolveOpenAPIBlockResult<{ - schemas: OpenAPISchema[]; -}>; +type ResolveOpenAPISchemasBlockResult = ResolveOpenAPIBlockResult; const weakmap = new WeakMap>(); diff --git a/packages/openapi-parser/src/types.ts b/packages/openapi-parser/src/types.ts index 13edbc0ea..cde56d09a 100644 --- a/packages/openapi-parser/src/types.ts +++ b/packages/openapi-parser/src/types.ts @@ -23,6 +23,16 @@ export interface OpenAPICustomSpecProperties { */ 'x-enable-proxy'?: boolean; + /** + * If `true`, all response sections will be expanded by default. + */ + 'x-expandAllResponses'?: boolean; + + /** + * If `true`, all model/schema sections will be expanded by default. + */ + 'x-expandAllModelSections'?: boolean; + /** * Description in HTML format. */ @@ -75,6 +85,16 @@ export interface OpenAPICustomOperationProperties { */ 'x-enable-proxy'?: boolean; + /** + * If `true`, all response sections will be expanded by default. + */ + 'x-expandAllResponses'?: boolean; + + /** + * If `true`, all model/schema sections will be expanded by default. + */ + 'x-expandAllModelSections'?: boolean; + /** * Stability of the operation. * @enum 'experimental' | 'alpha' | 'beta' diff --git a/packages/react-openapi/src/OpenAPIResponse.tsx b/packages/react-openapi/src/OpenAPIResponse.tsx index 9dbfa293d..cae583741 100644 --- a/packages/react-openapi/src/OpenAPIResponse.tsx +++ b/packages/react-openapi/src/OpenAPIResponse.tsx @@ -43,6 +43,7 @@ export function OpenAPIResponse(props: { /> } icon={context.icons.plus} + defaultExpanded={context.expandAllModelSections} label={(isExpanded) => tString( context.translation, diff --git a/packages/react-openapi/src/OpenAPIResponses.tsx b/packages/react-openapi/src/OpenAPIResponses.tsx index 0ac47d8cd..0af72cb24 100644 --- a/packages/react-openapi/src/OpenAPIResponses.tsx +++ b/packages/react-openapi/src/OpenAPIResponses.tsx @@ -107,11 +107,19 @@ export function OpenAPIResponses(props: { const state = useResponseExamplesState(context.blockKey, groups[0]?.key); + const expandAll = context.expandAllResponses; + const expandedKeys = expandAll + ? new Set(groups.map((g) => g.key)) + : state.key + ? new Set([state.key]) + : new Set(); + return ( { const key = keys.values().next().value ?? null; state.setKey(key); diff --git a/packages/react-openapi/src/OpenAPISchema.tsx b/packages/react-openapi/src/OpenAPISchema.tsx index 1cf3f2215..0b6c4a83b 100644 --- a/packages/react-openapi/src/OpenAPISchema.tsx +++ b/packages/react-openapi/src/OpenAPISchema.tsx @@ -130,6 +130,7 @@ function OpenAPISchemaProperty( label={(isExpanded) => getDisclosureLabel({ schema: effectiveSchema, isExpanded, context }) } + defaultExpanded={context.expandAllModelSections} > {content} @@ -408,6 +409,7 @@ function OpenAPISchemaAlternative(props: { icon={context.icons.plus} header={} label={(isExpanded) => getDisclosureLabel({ schema, isExpanded, context })} + defaultExpanded={context.expandAllModelSections} > getDisclosureLabel({ schema, isExpanded, context })} + defaultExpanded={context.expandAllModelSections} >
diff --git a/packages/react-openapi/src/schemas/OpenAPISchemas.tsx b/packages/react-openapi/src/schemas/OpenAPISchemas.tsx index 3185d8036..5d71e2022 100644 --- a/packages/react-openapi/src/schemas/OpenAPISchemas.tsx +++ b/packages/react-openapi/src/schemas/OpenAPISchemas.tsx @@ -1,4 +1,3 @@ -import type { OpenAPISchema } from '@gitbook/openapi-parser'; import clsx from 'classnames'; import { OpenAPIExample } from '../OpenAPIExample'; import { OpenAPIRootSchema } from '../OpenAPISchemaServer'; @@ -11,20 +10,22 @@ import { import { t } from '../translate'; import { getExampleFromSchema } from '../util/example'; import { OpenAPISchemaItem } from './OpenAPISchemaItem'; +import type { OpenAPISchemasData } from './resolveOpenAPISchemas'; /** * OpenAPI Schemas component. */ export function OpenAPISchemas(props: { className?: string; - schemas: OpenAPISchema[]; + data: OpenAPISchemasData; context: OpenAPIContextInput; /** * Whether to show the schema directly if there is only one. */ grouped?: boolean; }) { - const { schemas, context: contextInput, grouped, className } = props; + const { data, context: contextInput, grouped, className } = props; + const { schemas } = data; const firstSchema = schemas[0]; diff --git a/packages/react-openapi/src/schemas/resolveOpenAPISchemas.ts b/packages/react-openapi/src/schemas/resolveOpenAPISchemas.ts index 5497468f1..01e74fe7f 100644 --- a/packages/react-openapi/src/schemas/resolveOpenAPISchemas.ts +++ b/packages/react-openapi/src/schemas/resolveOpenAPISchemas.ts @@ -1,7 +1,16 @@ -import type { Filesystem, OpenAPISchema, OpenAPIV3xDocument } from '@gitbook/openapi-parser'; +import type { + Filesystem, + OpenAPICustomSpecProperties, + OpenAPISchema, + OpenAPIV3xDocument, +} from '@gitbook/openapi-parser'; import { filterSelectedOpenAPISchemas } from '@gitbook/openapi-parser'; import { dereferenceFilesystem } from '../dereference'; +export type OpenAPISchemasData = Pick & { + schemas: OpenAPISchema[]; +}; + /** * Resolve an OpenAPI schemas from a file and compile it to a more usable format. * Schemas are extracted from the OpenAPI components.schemas @@ -11,9 +20,7 @@ export async function resolveOpenAPISchemas( options: { schemas: string[]; } -): Promise<{ - schemas: OpenAPISchema[]; -} | null> { +): Promise { const { schemas: selectedSchemas } = options; const schema = await dereferenceFilesystem(filesystem); @@ -24,5 +31,11 @@ export async function resolveOpenAPISchemas( return null; } - return { schemas }; + return { + schemas, + 'x-expandAllModelSections': + typeof schema['x-expandAllModelSections'] === 'boolean' + ? schema['x-expandAllModelSections'] + : undefined, + }; }