Skip to content

Commit f4469b2

Browse files
authored
Support OpenAPI one-operation-per-page mode (#4314)
1 parent 91b325c commit f4469b2

19 files changed

Lines changed: 156 additions & 25 deletions

.changeset/rich-chefs-dig.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@gitbook/react-openapi": patch
3+
"gitbook": patch
4+
---
5+
6+
Support OpenAPI one-operation-per-page mode

packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPIOperation.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ async function OpenAPIOperationBody(props: BlockProps<AnyOpenAPIOperationsBlock>
5454
data.operation['x-expandAllResponses'] ?? data['x-expandAllResponses'],
5555
expandAllModelSections:
5656
data.operation['x-expandAllModelSections'] ?? data['x-expandAllModelSections'],
57+
headless: block.type === 'openapi-operation' ? block.data.headless : undefined,
5758
})}
5859
className="openapi-block"
5960
/>

packages/gitbook/src/components/DocumentView/OpenAPI/OpenAPIWebhook.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ async function OpenAPIWebhookBody(props: BlockProps<OpenAPIWebhookBlock>) {
5656
data.operation['x-expandAllResponses'] ?? data['x-expandAllResponses'],
5757
expandAllModelSections:
5858
data.operation['x-expandAllModelSections'] ?? data['x-expandAllModelSections'],
59+
headless: block.data.headless,
5960
})}
6061
className="openapi-block"
6162
/>

packages/gitbook/src/components/DocumentView/OpenAPI/context.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ export function getOpenAPIContext(args: {
2626
context: GitBookAnyContext | undefined;
2727
expandAllResponses?: boolean;
2828
expandAllModelSections?: boolean;
29+
headless?: boolean;
2930
}): OpenAPIContextInput {
30-
const { props, specUrl, context, expandAllResponses, expandAllModelSections } = args;
31+
const { props, specUrl, context, expandAllResponses, expandAllModelSections, headless } = args;
3132
const { block } = props;
3233

3334
const customizationLocale = context ? getSpaceLocale(context) : DEFAULT_LOCALE;
@@ -96,6 +97,7 @@ export function getOpenAPIContext(args: {
9697
),
9798
expandAllResponses: expandAllResponses || props.context.mode === 'print',
9899
expandAllModelSections: expandAllModelSections || props.context.mode === 'print',
100+
headless,
99101
id: block.meta?.id,
100102
blockKey: block.key,
101103
locale,

packages/gitbook/src/components/DocumentView/OpenAPI/style.css

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,17 @@
101101
/* Method Tags */
102102
.openapi-method,
103103
.openapi-statuscode {
104-
@apply rounded-md straight-corners:rounded-none circular-corners:rounded-lg uppercase font-mono items-center shrink-0 font-semibold text-[0.813rem] px-1 py-0.5 mr-2 text-tint-12/8 leading-tight align-middle inline-flex ring-1 ring-inset ring-tint-12/1 dark:ring-tint-1/1 whitespace-nowrap;
104+
@apply m-0 h-5 min-w-9 justify-center rounded-md text-xs straight-corners:rounded-none circular-corners:rounded-lg uppercase font-mono items-center shrink-0 font-semibold px-1.5 py-0.5 mr-2 text-tint-12/8 leading-tight align-middle inline-flex whitespace-nowrap;
105+
}
106+
107+
.openapi-method-small {}
108+
109+
.openapi-method-medium {
110+
@apply m-0 px-2.5 py-1 h-6 text-[0.813rem];
111+
}
112+
113+
.toclink .openapi-method {
114+
@apply text-[0.625rem] flex items-center justify-center;
105115
}
106116

107117
.openapi-method-get,
@@ -130,7 +140,8 @@
130140

131141
.openapi-method-head,
132142
.openapi-method-options,
133-
.openapi-method-trace {
143+
.openapi-method-trace,
144+
.openapi-method-hook {
134145
@apply bg-tint;
135146
}
136147

@@ -450,16 +461,12 @@
450461
@apply max-w-full overflow-hidden shrink pl-0.5 py-0.5;
451462
}
452463

453-
.openapi-response-examples-header .openapi-select > button .openapi-statuscode {
454-
@apply h-full;
455-
}
456-
457464
.openapi-codesample-header-content {
458465
@apply flex flex-row items-center justify-between h-fit p-2.5;
459466
}
460467

461468
.openapi-codesample-header-content .openapi-path {
462-
@apply flex items-center font-mono text-[0.813rem] gap-1 h-fit *:truncate overflow-x-auto min-w-0 max-w-full font-normal text-tint-strong;
469+
@apply flex items-center font-mono text-[0.813rem] gap-2 h-fit *:truncate overflow-x-auto min-w-0 max-w-full font-normal text-tint-strong;
463470
}
464471

465472
.openapi-codesample-header-content .openapi-path-title {
@@ -493,10 +500,6 @@
493500
@apply text-tint inline;
494501
}
495502

496-
.openapi-summary .openapi-path .openapi-method {
497-
@apply m-0 items-center flex px-2 py-1 h-6;
498-
}
499-
500503
.openapi-path-title {
501504
@apply flex-1 relative font-normal items-center gap-y-1 flex flex-wrap text-left overflow-x-auto font-mono text-tint-strong/10;
502505
@apply whitespace-nowrap md:whitespace-normal;

packages/gitbook/src/components/PageAside/ScrollSectionsList.tsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type { DocumentSection } from '@/lib/document-sections';
77
import { tcls } from '@/lib/tailwind';
88

99
import { useBodyLoaded } from '@/components/primitives';
10+
import { OpenAPIMethodBadge } from '@gitbook/react-openapi';
1011
import { HEADER_HEIGHT_DESKTOP } from '../layout';
1112

1213
/**
@@ -141,11 +142,11 @@ export function ScrollSectionsList({ sections }: { sections: DocumentSection[] }
141142
)}
142143
>
143144
{section.tag ? (
144-
<span
145-
className={`-mt-0.5 openapi-method text-xs! openapi-method-${section.tag.toLowerCase()}`}
146-
>
147-
{section.tag}
148-
</span>
145+
<OpenAPIMethodBadge
146+
method={section.tag}
147+
size="small"
148+
className="-mt-0.5"
149+
/>
149150
) : null}
150151

151152
<span

packages/gitbook/src/components/TableOfContents/PageDocumentItem.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { tcls } from '@/lib/tailwind';
44
import { SiteInsightsLinkPosition } from '@gitbook/api';
5+
import { OpenAPIMethodBadge } from '@gitbook/react-openapi';
56
import { Tag } from '../Tag';
67
import { PagesList } from './PagesList';
78
import { TOCPageIcon } from './TOCPageIcon';
@@ -41,7 +42,18 @@ export function PageDocumentItem(props: { page: ClientTOCPageDocument }) {
4142
icon={<TOCPageIcon page={page} />}
4243
tag={page.primaryTag ? <Tag tag={page.primaryTag} /> : null}
4344
>
44-
{page.title}
45+
{page.openAPIOperation ? (
46+
<span className="flex h-[1lh] shrink-0 items-center self-center">
47+
<OpenAPIMethodBadge
48+
method={page.openAPIOperation.method}
49+
short
50+
size="small"
51+
/>
52+
</span>
53+
) : null}
54+
<span className={page.openAPIOperation?.deprecated ? 'line-through' : undefined}>
55+
{page.title}
56+
</span>
4557
</ToggleableLinkItem>
4658
</li>
4759
);

packages/gitbook/src/components/TableOfContents/encodeClientTableOfContents.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { GitBookSiteContext } from '@/lib/context';
2+
import { getOpenAPIOperationPageProps } from '@/lib/openapi/computedSourceProps';
23
import { getPagePaths, hasPageVisibleDescendant } from '@/lib/pages';
34
import { resolveContentRef } from '@/lib/references';
45
import { getRevisionTags, resolveTag } from '@/lib/tags';
@@ -26,6 +27,7 @@ export type ClientTOCPageDocument = {
2627
pathnames: string[];
2728
descendants?: ClientTOCPage[];
2829
primaryTag?: RevisionTag;
30+
openAPIOperation?: { method: string; deprecated: boolean };
2931
};
3032

3133
export type ClientTOCPageGroup = {
@@ -83,6 +85,7 @@ export async function encodeClientTableOfContents(
8385
pathnames: getPagePaths(rootPages, page),
8486
descendants,
8587
primaryTag,
88+
openAPIOperation: getOpenAPIOperationPageProps(page),
8689
type: 'document',
8790
})
8891
);

packages/gitbook/src/components/TableOfContents/styles.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ export const ToCItemBaseStyles = [
33
'circular-corners:rounded-2xl rounded-md straight-corners:rounded-none p-1.5 pl-3',
44
'focus-visible:-outline-offset-2',
55
'before:contents[] before:-left-px before:absolute before:inset-y-0',
6-
'sidebar-list-line:rounded-l-none! sidebar-list-line:before:w-px [&+div_a]:sidebar-list-default:rounded-l-none [&+div_a]:pl-5 [&+div_a]:sidebar-list-default:before:w-px',
6+
'sidebar-list-line:rounded-l-none! sidebar-list-line:before:w-px [&+div_a]:sidebar-list-default:rounded-l-none has-[.openapi-method]:pl-3 [&+div_a]:pl-5 [&+div_a]:sidebar-list-default:before:w-px',
77
];
88

99
export const ToCLinkItemStyles = [
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import type { ComputedContentSourceDocumentOpenAPI, RevisionPageDocument } from '@gitbook/api';
2+
3+
/**
4+
* Get the method and deprecated state of a page generated by the OpenAPI
5+
* computed source in one-operation-per-page mode.
6+
*/
7+
export function getOpenAPIOperationPageProps(
8+
page: RevisionPageDocument
9+
): { method: string; deprecated: boolean } | undefined {
10+
if (!('computed' in page)) {
11+
return;
12+
}
13+
14+
const source = page.computed;
15+
if (source.type !== 'builtin:openapi') {
16+
return;
17+
}
18+
19+
const { props } = source as ComputedContentSourceDocumentOpenAPI;
20+
if (props.doc !== 'operation') {
21+
return;
22+
}
23+
24+
return {
25+
method: props.method,
26+
deprecated: props.deprecated === true,
27+
};
28+
}

0 commit comments

Comments
 (0)