mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-20 17:43:24 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 11254e6ee8 |
@@ -5,6 +5,9 @@ import { checkIsReference, createStateKey, resolveDescription } from './utils';
|
||||
import { stringifyOpenAPI } from './stringifyOpenAPI';
|
||||
import { OpenAPITabs, OpenAPITabsList, OpenAPITabsPanels } from './OpenAPITabs';
|
||||
import { InteractiveSection } from './InteractiveSection';
|
||||
import { Markdown } from './Markdown';
|
||||
import React from 'react';
|
||||
import { OpenAPIResponseMultipleExample } from './OpenAPIResponseMultipleExample';
|
||||
|
||||
/**
|
||||
* Display an example of the response content.
|
||||
@@ -61,18 +64,20 @@ export function OpenAPIResponseExample(props: {
|
||||
};
|
||||
}
|
||||
|
||||
const example = handleUnresolvedReference(
|
||||
const examples = handleUnresolvedReference(
|
||||
(() => {
|
||||
const { examples, example } = mediaTypeObject;
|
||||
if (examples) {
|
||||
const key = Object.keys(examples)[0];
|
||||
if (key) {
|
||||
// @TODO handle multiple examples
|
||||
const firstExample = examples[key];
|
||||
if (firstExample) {
|
||||
return firstExample;
|
||||
}
|
||||
if (Array.isArray(examples)) {
|
||||
return examples.map((example) => ({
|
||||
value: example,
|
||||
}));
|
||||
}
|
||||
|
||||
return Object.entries(examples).map(([key, value]) => ({
|
||||
summary: key,
|
||||
value: value,
|
||||
}));
|
||||
}
|
||||
|
||||
if (example) {
|
||||
@@ -88,21 +93,23 @@ export function OpenAPIResponseExample(props: {
|
||||
})(),
|
||||
);
|
||||
|
||||
if (!examples || (Array.isArray(examples) && examples.length === 0)) {
|
||||
return {
|
||||
key: key,
|
||||
label: key,
|
||||
body: <OpenAPIEmptyResponseExample description={responseObject.description} />,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
key: key,
|
||||
label: key,
|
||||
description: resolveDescription(responseObject),
|
||||
body: example?.value ? (
|
||||
<context.CodeBlock
|
||||
code={
|
||||
typeof example.value === 'string'
|
||||
? example.value
|
||||
: stringifyOpenAPI(example.value, null, 2)
|
||||
}
|
||||
syntax="json"
|
||||
body: (
|
||||
<OpenAPIResponseExampleBody
|
||||
examples={examples}
|
||||
context={context}
|
||||
description={responseObject.description}
|
||||
/>
|
||||
) : (
|
||||
<OpenAPIEmptyResponseExample />
|
||||
),
|
||||
};
|
||||
})
|
||||
@@ -123,17 +130,62 @@ export function OpenAPIResponseExample(props: {
|
||||
);
|
||||
}
|
||||
|
||||
function OpenAPIEmptyResponseExample() {
|
||||
function OpenAPIEmptyResponseExample(props: { description?: string }) {
|
||||
const { description } = props;
|
||||
|
||||
return (
|
||||
<pre className="openapi-response-example-empty">
|
||||
<p>No body</p>
|
||||
</pre>
|
||||
<>
|
||||
<pre className="openapi-response-example-empty">
|
||||
<p>No body</p>
|
||||
</pre>
|
||||
|
||||
{description ? <Markdown source={description} className="openapi-tabs-footer" /> : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
function OpenAPIResponseExampleBody(props: {
|
||||
examples: OpenAPIV3.ExampleObject[] | OpenAPIV3.ExampleObject;
|
||||
context: OpenAPIContextProps;
|
||||
description?: string;
|
||||
}) {
|
||||
const { examples, context, description } = props;
|
||||
|
||||
if (!Array.isArray(examples)) {
|
||||
return (
|
||||
<>
|
||||
<context.CodeBlock
|
||||
code={
|
||||
typeof examples.value === 'string'
|
||||
? examples.value
|
||||
: stringifyOpenAPI(examples.value, null, 2)
|
||||
}
|
||||
syntax="json"
|
||||
/>
|
||||
|
||||
{description ? (
|
||||
<Markdown source={description} className="openapi-tabs-footer" />
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (examples.length === 0) {
|
||||
return <OpenAPIEmptyResponseExample />;
|
||||
}
|
||||
|
||||
return <OpenAPIResponseMultipleExample examples={examples} context={context} />;
|
||||
}
|
||||
|
||||
function handleUnresolvedReference(
|
||||
input: OpenAPIV3.ExampleObject | null,
|
||||
): OpenAPIV3.ExampleObject | null {
|
||||
input: OpenAPIV3.ExampleObject | OpenAPIV3.ExampleObject[] | null,
|
||||
): OpenAPIV3.ExampleObject | OpenAPIV3.ExampleObject[] | null {
|
||||
if (Array.isArray(input)) {
|
||||
return input.map(
|
||||
(example) => handleUnresolvedReference(example) as OpenAPIV3.ExampleObject,
|
||||
);
|
||||
}
|
||||
|
||||
const isReference = checkIsReference(input?.value);
|
||||
|
||||
if (isReference) {
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { OpenAPIV3 } from '@scalar/openapi-types';
|
||||
import { OpenAPIContextProps } from './types';
|
||||
import { OpenAPIResponseMultipleExampleClient } from './OpenAPIResponseMultipleExampleClient';
|
||||
|
||||
export function OpenAPIResponseMultipleExample(props: {
|
||||
examples: OpenAPIV3.ExampleObject[];
|
||||
context: OpenAPIContextProps;
|
||||
}) {
|
||||
const { examples, context } = props;
|
||||
|
||||
return (
|
||||
<OpenAPIResponseMultipleExampleClient examples={examples}>
|
||||
<context.CodeBlock
|
||||
syntax="json"
|
||||
code=""
|
||||
// code={
|
||||
// typeof example?.value === 'string'
|
||||
// ? example?.value
|
||||
// : stringifyOpenAPI(example?.value, null, 2)
|
||||
// }
|
||||
/>
|
||||
{/* )} */}
|
||||
</OpenAPIResponseMultipleExampleClient>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
'use client';
|
||||
|
||||
import { OpenAPIV3 } from '@scalar/openapi-types';
|
||||
import React, { cloneElement, ReactNode } from 'react';
|
||||
|
||||
export function OpenAPIResponseMultipleExampleClient(props: {
|
||||
examples: OpenAPIV3.ExampleObject[];
|
||||
children: ReactNode;
|
||||
}) {
|
||||
const { examples, children: Comp } = props;
|
||||
|
||||
const examplesWithId = examples.map((example, index) => ({
|
||||
...example,
|
||||
id: `example-${index}`,
|
||||
}));
|
||||
|
||||
const [selectedExample, setSelectedExample] = React.useState(examplesWithId[0]);
|
||||
|
||||
const handleSelect = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
||||
const selected = examplesWithId.find((ex) => ex.id === e.target.value);
|
||||
|
||||
if (!selected) return;
|
||||
|
||||
setSelectedExample(selected);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{/* {typeof children === 'function' ? children({ example: selectedExample }) : children} */}
|
||||
|
||||
{cloneElement(Comp, { code: selectedExample?.value })}
|
||||
|
||||
<div className="openapi-tabs-footer">
|
||||
<select onChange={handleSelect} value={selectedExample?.id}>
|
||||
{examplesWithId.map((example, index) => (
|
||||
<option key={index} value={example.id}>
|
||||
{example.summary || `Example ${index + 1}`}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
||||
import { Key, Tab, TabList, TabPanel, Tabs, TabsProps } from 'react-aria-components';
|
||||
import { Markdown } from './Markdown';
|
||||
import { useSyncedTabsGlobalState } from './useSyncedTabsGlobalState';
|
||||
import { useIntersectionObserver } from 'usehooks-ts';
|
||||
|
||||
@@ -145,9 +144,6 @@ export function OpenAPITabsPanels() {
|
||||
className="openapi-tabs-panel"
|
||||
>
|
||||
{selectedTab.body}
|
||||
{selectedTab.description ? (
|
||||
<Markdown source={selectedTab.description} className="openapi-tabs-footer" />
|
||||
) : null}
|
||||
</TabPanel>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user