Compare commits

...

9 Commits

Author SHA1 Message Date
Samy Pessé 32a73b55d4 Version Packages (#2403)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-25 15:12:18 +02:00
Samy Pessé 0426312d6c Reset to first tab when tabs change in an InteractiveSection (#2407) 2024-07-25 15:09:21 +02:00
Samy Pessé ede2335fb3 Fix x-codeSamples: false not working at the single operation level (#2408) 2024-07-25 14:59:30 +02:00
Amrit Kahlon 709f1a1ccb Update Scalar Api Client to new version (#2406)
Co-authored-by: marclave <marc@scalar.com>
Co-authored-by: Samy Pessé <samypesse@gmail.com>
2024-07-25 10:25:50 +02:00
Samy Pessé 24b785cbfb Update shiki to fix diff code highlighting (#2338) 2024-07-25 09:33:42 +02:00
Samy Pessé acc3f2f418 Fix Scalar proxy failing on Cloudflare (#2402) 2024-07-24 11:41:35 +02:00
Scott Cazan d4a653d6a9 Use SpaceURL in getURL function to for cross-space searches (#2399) 2024-07-23 12:07:32 +02:00
Samy Pessé 7e74d25447 Version Packages (#2397)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-07-22 16:26:53 +02:00
Samy Pessé 3445db41ce Fix packages not including all files (#2396) 2024-07-22 16:20:06 +02:00
23 changed files with 178 additions and 204 deletions
BIN
View File
Binary file not shown.
+3
View File
@@ -23,5 +23,8 @@
"@changesets/cli": "^2.27.7", "@changesets/cli": "^2.27.7",
"prettier": "^3.0.3", "prettier": "^3.0.3",
"turbo": "^2.0.9" "turbo": "^2.0.9"
},
"patchedDependencies": {
"@vercel/next@4.0.15": "patches/@vercel%2Fnext@4.0.15.patch"
} }
} }
+23
View File
@@ -1,5 +1,28 @@
# gitbook # gitbook
## 0.3.0
### Minor Changes
- 24b785c: Update shiki for code block syntax highlighting, with support for more languages and fixes for diffs. It also patches the deployment on Cloudflare to support edge functions larger than 4MB.
### Patch Changes
- acc3f2f: Fix error with the "Try it" of OpenAPI block because of the Scalar proxy failing on Cloudflare with the `cache` option
- Updated dependencies [709f1a1]
- Updated dependencies [ede2335]
- Updated dependencies [0426312]
- @gitbook/react-openapi@0.6.0
## 0.2.2
### Patch Changes
- Updated dependencies [3445db4]
- @gitbook/react-contentkit@0.5.0
- @gitbook/react-openapi@0.5.0
- @gitbook/react-math@0.5.0
## 0.2.1 ## 0.2.1
### Patch Changes ### Patch Changes
+2 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "gitbook", "name": "gitbook",
"version": "0.2.1", "version": "0.3.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev", "dev": "next dev",
@@ -55,7 +55,7 @@
"remark-rehype": "^11.1.0", "remark-rehype": "^11.1.0",
"rison": "^0.1.1", "rison": "^0.1.1",
"server-only": "^0.0.1", "server-only": "^0.0.1",
"shiki": "^1.2.0", "shiki": "^1.11.1",
"tailwind-merge": "^2.2.0", "tailwind-merge": "^2.2.0",
"tailwind-shades": "^1.1.2", "tailwind-shades": "^1.1.2",
"unified": "^11.0.4", "unified": "^11.0.4",
@@ -30,7 +30,7 @@ export async function POST(req: NextRequest) {
// no-cors, *cors, same-origin // no-cors, *cors, same-origin
// mode: 'cors', // Not supported on Cloudflare Workers // mode: 'cors', // Not supported on Cloudflare Workers
// *default, no-cache, reload, force-cache, only-if-cached // *default, no-cache, reload, force-cache, only-if-cached
cache: 'no-cache', // cache: 'no-cache', // Not supported on Cloudflare Workers
// include, *same-origin, omit // include, *same-origin, omit
// credentials: 'include', // Not supported on Cloudflare Workers // credentials: 'include', // Not supported on Cloudflare Workers
headers: requestBody.headers, headers: requestBody.headers,
@@ -9,6 +9,9 @@
--shiki-token-string-expression: #6a4906; --shiki-token-string-expression: #6a4906;
--shiki-token-punctuation: theme('colors.pomegranate.700/.92'); --shiki-token-punctuation: theme('colors.pomegranate.700/.92');
--shiki-token-link: theme('colors.dark.DEFAULT'); --shiki-token-link: theme('colors.dark.DEFAULT');
--shiki-token-inserted: #22863a;
--shiki-token-deleted: #b31d28;
--shiki-token-changed: #8250df;
} }
html.dark { html.dark {
@@ -22,4 +25,7 @@ html.dark {
--shiki-token-string-expression: theme('colors.light.4'); --shiki-token-string-expression: theme('colors.light.4');
--shiki-token-punctuation: #acc6ee; --shiki-token-punctuation: #acc6ee;
--shiki-token-link: theme('colors.pomegranate.400'); --shiki-token-link: theme('colors.pomegranate.400');
--shiki-token-inserted: #85e89d;
--shiki-token-deleted: #fdaeb7;
--shiki-token-changed: #56b6c2;
} }
@@ -34,7 +34,7 @@ export async function OpenAPI(props: BlockProps<DocumentBlockSwagger>) {
async function OpenAPIBody(props: BlockProps<DocumentBlockSwagger>) { async function OpenAPIBody(props: BlockProps<DocumentBlockSwagger>) {
const { block, context } = props; const { block, context } = props;
const { data, error } = await fetchOpenAPIBlock(block, context.resolveContentRef); const { data, specUrl, error } = await fetchOpenAPIBlock(block, context.resolveContentRef);
if (error) { if (error) {
return ( return (
@@ -46,7 +46,7 @@ async function OpenAPIBody(props: BlockProps<DocumentBlockSwagger>) {
); );
} }
if (!data) { if (!data || !specUrl) {
return null; return null;
} }
@@ -60,6 +60,7 @@ async function OpenAPIBody(props: BlockProps<DocumentBlockSwagger>) {
}, },
CodeBlock: PlainCodeBlock, CodeBlock: PlainCodeBlock,
defaultInteractiveOpened: context.mode === 'print', defaultInteractiveOpened: context.mode === 'print',
specUrl,
}} }}
className="openapi-block" className="openapi-block"
/> />
@@ -1,4 +1,7 @@
@import '@scalar/api-client-react/style.css';
.light .scalar-modal-layout, .light .scalar-modal-layout,
.light .scalar-app,
.light .scalar { .light .scalar {
--scalar-color-1: color-mix( --scalar-color-1: color-mix(
in srgb, in srgb,
@@ -50,8 +53,13 @@
--scalar-button-1: rgb(49 53 56); --scalar-button-1: rgb(49 53 56);
--scalar-button-1-color: #fff; --scalar-button-1-color: #fff;
--scalar-button-1-hover: rgb(28 31 33); --scalar-button-1-hover: rgb(28 31 33);
--scalar-shadow-1: 0 1px 3px 0 rgba(0, 0, 0, 0.11);
--scalar-shadow-2: rgba(0, 0, 0, 0.08) 0px 13px 20px 0px, rgba(0, 0, 0, 0.08) 0px 3px 8px 0px,
#eeeeed 0px 0 0 1px;
} }
.dark .scalar-modal-layout, .dark .scalar-modal-layout,
.dark .scalar-app,
.dark .scalar { .dark .scalar {
--scalar-color-1: color-mix( --scalar-color-1: color-mix(
in srgb, in srgb,
@@ -102,8 +110,13 @@
--scalar-button-1: #f6f6f6; --scalar-button-1: #f6f6f6;
--scalar-button-1-color: #000; --scalar-button-1-color: #000;
--scalar-button-1-hover: #e7e7e7; --scalar-button-1-hover: #e7e7e7;
--scalar-shadow-1: 0 1px 3px 0 rgb(0, 0, 0, 0.1);
--scalar-shadow-2: rgba(15, 15, 15, 0.2) 0px 3px 6px, rgba(15, 15, 15, 0.4) 0px 9px 24px,
0 0 0 1px rgba(255, 255, 255, 0.1);
} }
.scalar-modal-layout, .scalar-modal-layout,
.scalar-app,
.scalar { .scalar {
--scalar-font: initial; --scalar-font: initial;
--scalar-font-code: var(--font-mono); --scalar-font-code: var(--font-mono);
@@ -165,7 +178,7 @@
.scalar-api-client__close:hover { .scalar-api-client__close:hover {
cursor: pointer; cursor: pointer;
} }
.scalar .scalar-app { .scalar .scalar-app-layout {
background: var(--scalar-background-3); background: var(--scalar-background-3);
height: calc(100dvh - 100px); height: calc(100dvh - 100px);
max-width: 1280px; max-width: 1280px;
@@ -202,23 +215,6 @@
cursor: pointer; cursor: pointer;
animation: scalardrawerexitfadein 0.35s forwards; animation: scalardrawerexitfadein 0.35s forwards;
} }
.scalar .scalar-app-exit:before {
content: '\00d7';
font-family: sans-serif;
position: absolute;
top: 0;
right: 0;
font-size: 30px;
font-weight: 100;
line-height: 50px;
right: 12px;
text-align: center;
color: white;
opacity: 0.6;
}
.scalar .scalar-app-exit:hover:before {
opacity: 1;
}
@keyframes scalardrawerexitfadein { @keyframes scalardrawerexitfadein {
from { from {
opacity: 0; opacity: 0;
@@ -305,11 +301,6 @@
scrollbar-width: thin; scrollbar-width: thin;
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
} }
@supports (-moz-appearance: none) {
.scalar .custom-scroll {
padding-right: 12px;
}
}
.scalar .custom-scroll:hover { .scalar .custom-scroll:hover {
scrollbar-color: rgba(0, 0, 0, 0.24) transparent; scrollbar-color: rgba(0, 0, 0, 0.24) transparent;
} }
@@ -347,3 +338,18 @@
padding-right: 12px; padding-right: 12px;
} }
} }
.dark .scalar .client-wrapper-bg-color {
background: linear-gradient(
color-mix(in srgb, var(--tw-bg-base) 6%, transparent) 1%,
color-mix(in srgb, var(--scalar-background-1) 30%, black) 9%
);
}
.light .scalar .client-wrapper-bg-color {
background-color: var(--scalar-background-2) !important;
}
.scalar .gitbook-show {
display: block !important;
}
.scalar .gitbook-hidden {
display: none !important;
}
@@ -266,7 +266,7 @@ function transformSectionsAndPage(args: {
type: 'page', type: 'page',
id: item.id, id: item.id,
title: item.title, title: item.title,
href: getURL(item.path), href: getURL(item.path, spaceURL),
spaceTitle: space?.title, spaceTitle: space?.title,
}; };
+4 -4
View File
@@ -19,12 +19,12 @@ export async function fetchOpenAPIBlock(
block: DocumentBlockSwagger, block: DocumentBlockSwagger,
resolveContentRef: (ref: ContentRef) => Promise<ResolvedContentRef | null>, resolveContentRef: (ref: ContentRef) => Promise<ResolvedContentRef | null>,
): Promise< ): Promise<
| { data: OpenAPIOperationData | null; error?: undefined } | { data: OpenAPIOperationData | null; specUrl: string | null; error?: undefined }
| { error: OpenAPIFetchError; data?: undefined } | { error: OpenAPIFetchError; data?: undefined; specUrl?: undefined }
> { > {
const resolved = block.data.ref ? await resolveContentRef(block.data.ref) : null; const resolved = block.data.ref ? await resolveContentRef(block.data.ref) : null;
if (!resolved || !block.data.path || !block.data.method) { if (!resolved || !block.data.path || !block.data.method) {
return { data: null }; return { data: null, specUrl: null };
} }
try { try {
@@ -37,7 +37,7 @@ export async function fetchOpenAPIBlock(
fetcher, fetcher,
); );
return { data }; return { data, specUrl: resolved.href };
} catch (error) { } catch (error) {
if (error instanceof OpenAPIFetchError) { if (error instanceof OpenAPIFetchError) {
return { error }; return { error };
+6
View File
@@ -1,5 +1,11 @@
# @gitbook/react-contentkit # @gitbook/react-contentkit
## 0.5.0
### Minor Changes
- 3445db4: Fix files published in the NPM packages by defining "files" in "package.json"
## 0.4.0 ## 0.4.0
### Minor Changes ### Minor Changes
+8 -2
View File
@@ -1,6 +1,6 @@
{ {
"name": "@gitbook/react-contentkit", "name": "@gitbook/react-contentkit",
"version": "0.4.0", "version": "0.5.0",
"exports": { "exports": {
".": { ".": {
"types": "./dist/index.d.ts", "types": "./dist/index.d.ts",
@@ -23,5 +23,11 @@
"build": "tsc", "build": "tsc",
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"dev": "tsc -w" "dev": "tsc -w"
} },
"files": [
"dist",
"src",
"README.md",
"CHANGELOG.md"
]
} }
+6
View File
@@ -1,5 +1,11 @@
# @gitbook/react-math # @gitbook/react-math
## 0.5.0
### Minor Changes
- 3445db4: Fix files published in the NPM packages by defining "files" in "package.json"
## 0.4.0 ## 0.4.0
### Minor Changes ### Minor Changes
+9 -2
View File
@@ -7,7 +7,7 @@
"default": "./dist/index.js" "default": "./dist/index.js"
} }
}, },
"version": "0.4.0", "version": "0.5.0",
"dependencies": { "dependencies": {
"object-hash": "^3.0.0" "object-hash": "^3.0.0"
}, },
@@ -22,5 +22,12 @@
"build": "tsc", "build": "tsc",
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"dev": "tsc -w" "dev": "tsc -w"
} },
"files": [
"dist",
"src",
"css",
"README.md",
"CHANGELOG.md"
]
} }
+17
View File
@@ -1,5 +1,22 @@
# @gitbook/react-openapi # @gitbook/react-openapi
## 0.6.0
### Minor Changes
- 709f1a1: Update Scalar to the latest version, with faster performances and an improved experience
### Patch Changes
- ede2335: Fix x-codeSamples: false not working at the single operation level
- 0426312: Fix tabs being empty for code samples when they are updated dynamically
## 0.5.0
### Minor Changes
- 3445db4: Fix files published in the NPM packages by defining "files" in "package.json"
## 0.4.0 ## 0.4.0
### Minor Changes ### Minor Changes
+9 -4
View File
@@ -7,10 +7,9 @@
"default": "./dist/index.js" "default": "./dist/index.js"
} }
}, },
"version": "0.4.0", "version": "0.6.0",
"dependencies": { "dependencies": {
"@scalar/api-client-react": "^0.3.7", "@scalar/api-client-react": "1.0.5",
"@scalar/oas-utils": "0.1.6",
"classnames": "^2.5.1", "classnames": "^2.5.1",
"flatted": "^3.2.9", "flatted": "^3.2.9",
"openapi-types": "^12.1.3", "openapi-types": "^12.1.3",
@@ -30,5 +29,11 @@
"typecheck": "tsc --noEmit", "typecheck": "tsc --noEmit",
"unit": "bun test", "unit": "bun test",
"dev": "tsc -w" "dev": "tsc -w"
} },
"files": [
"dist",
"src",
"README.md",
"CHANGELOG.md"
]
} }
@@ -3,6 +3,12 @@
import classNames from 'classnames'; import classNames from 'classnames';
import React from 'react'; import React from 'react';
interface InteractiveSectionTab {
key: string;
label: string;
body: React.ReactNode;
}
/** /**
* To optimize rendering, most of the components are server-components, * To optimize rendering, most of the components are server-components,
* and the interactiveness is mainly handled by a few key components like this one. * and the interactiveness is mainly handled by a few key components like this one.
@@ -19,11 +25,7 @@ export function InteractiveSection(props: {
toggleOpenIcon?: React.ReactNode; toggleOpenIcon?: React.ReactNode;
toggleCloseIcon?: React.ReactNode; toggleCloseIcon?: React.ReactNode;
/** Tabs of content to display */ /** Tabs of content to display */
tabs?: Array<{ tabs?: Array<InteractiveSectionTab>;
key: string;
label: string;
body: React.ReactNode;
}>;
/** Default tab to have opened */ /** Default tab to have opened */
defaultTab?: string; defaultTab?: string;
/** Content of the header */ /** Content of the header */
@@ -48,9 +50,9 @@ export function InteractiveSection(props: {
} = props; } = props;
const [opened, setOpened] = React.useState(defaultOpened); const [opened, setOpened] = React.useState(defaultOpened);
const [selectedTab, setSelectedTab] = React.useState(defaultTab); const [selectedTabKey, setSelectedTab] = React.useState(defaultTab);
const selectedTab: InteractiveSectionTab | undefined =
const tabBody = tabs.find((tab) => tab.key === selectedTab)?.body; tabs.find((tab) => tab.key === selectedTabKey) ?? tabs[0];
return ( return (
<div <div
@@ -94,7 +96,7 @@ export function InteractiveSection(props: {
'openapi-select', 'openapi-select',
`${className}-tabs-select`, `${className}-tabs-select`,
)} )}
value={selectedTab} value={selectedTab.key}
onChange={(event) => { onChange={(event) => {
setSelectedTab(event.target.value); setSelectedTab(event.target.value);
setOpened(true); setOpened(true);
@@ -107,7 +109,7 @@ export function InteractiveSection(props: {
))} ))}
</select> </select>
) : null} ) : null}
{(children || tabBody) && toggeable ? ( {(children || selectedTab?.body) && toggeable ? (
<button <button
className={classNames('openapi-section-toggle', `${className}-toggle`)} className={classNames('openapi-section-toggle', `${className}-toggle`)}
onClick={() => setOpened(!opened)} onClick={() => setOpened(!opened)}
@@ -117,10 +119,10 @@ export function InteractiveSection(props: {
) : null} ) : null}
</div> </div>
</div> </div>
{(!toggeable || opened) && (children || tabBody) ? ( {(!toggeable || opened) && (children || selectedTab?.body) ? (
<div className={classNames('openapi-section-body', `${className}-body`)}> <div className={classNames('openapi-section-body', `${className}-body`)}>
{children} {children}
{tabBody} {selectedTab?.body}
</div> </div>
) : null} ) : null}
{overlay} {overlay}
@@ -1,7 +1,7 @@
import * as React from 'react'; import * as React from 'react';
import { CodeSampleInput, codeSampleGenerators } from './code-samples'; import { CodeSampleInput, codeSampleGenerators } from './code-samples';
import { OpenAPIOperationData, toJSON } from './fetchOpenAPIOperation'; import { OpenAPIOperationData } from './fetchOpenAPIOperation';
import { generateMediaTypeExample } from './generateSchemaExample'; import { generateMediaTypeExample } from './generateSchemaExample';
import { InteractiveSection } from './InteractiveSection'; import { InteractiveSection } from './InteractiveSection';
import { getServersURL } from './OpenAPIServerURL'; import { getServersURL } from './OpenAPIServerURL';
@@ -52,7 +52,7 @@ export function OpenAPICodeSample(props: {
}> = null; }> = null;
(['x-custom-examples', 'x-code-samples', 'x-codeSamples'] as const).forEach((key) => { (['x-custom-examples', 'x-code-samples', 'x-codeSamples'] as const).forEach((key) => {
const customSamples = data.operation[key]; const customSamples = data.operation[key];
if (customSamples) { if (customSamples && Array.isArray(customSamples)) {
customCodeSamples = customSamples.map((sample) => ({ customCodeSamples = customSamples.map((sample) => ({
key: `redocly-${sample.lang}`, key: `redocly-${sample.lang}`,
label: sample.label, label: sample.label,
@@ -61,16 +61,15 @@ export function OpenAPICodeSample(props: {
} }
}); });
const samples = customCodeSamples ?? (data['x-codeSamples'] !== false ? autoCodeSamples : []); // Code samples can be disabled at the top-level or at the operation level
// If code samples are defined at the operation level, it will override the top-level setting
const codeSamplesDisabled =
data['x-codeSamples'] === false || data.operation['x-codeSamples'] === false;
const samples = customCodeSamples ?? (!codeSamplesDisabled ? autoCodeSamples : []);
if (samples.length === 0) { if (samples.length === 0) {
return null; return null;
} }
async function fetchOperationData() {
'use server';
return toJSON(data);
}
return ( return (
<InteractiveSection <InteractiveSection
header="Request" header="Request"
@@ -78,7 +77,7 @@ export function OpenAPICodeSample(props: {
tabs={samples} tabs={samples}
overlay={ overlay={
data['x-hideTryItPanel'] || data.operation['x-hideTryItPanel'] ? null : ( data['x-hideTryItPanel'] || data.operation['x-hideTryItPanel'] ? null : (
<ScalarApiButton fetchOperationData={fetchOperationData} /> <ScalarApiButton />
) )
} }
/> />
@@ -7,8 +7,8 @@ import { OpenAPICodeSample } from './OpenAPICodeSample';
import { OpenAPIResponseExample } from './OpenAPIResponseExample'; import { OpenAPIResponseExample } from './OpenAPIResponseExample';
import { OpenAPIServerURL } from './OpenAPIServerURL'; import { OpenAPIServerURL } from './OpenAPIServerURL';
import { OpenAPISpec } from './OpenAPISpec'; import { OpenAPISpec } from './OpenAPISpec';
import { ScalarApiClient } from './ScalarApiButton';
import { OpenAPIClientContext, OpenAPIContextProps } from './types'; import { OpenAPIClientContext, OpenAPIContextProps } from './types';
import { ApiClientModalProvider } from '@scalar/api-client-react';
/** /**
* Display an interactive OpenAPI operation. * Display an interactive OpenAPI operation.
@@ -23,11 +23,15 @@ export function OpenAPIOperation(props: {
const clientContext: OpenAPIClientContext = { const clientContext: OpenAPIClientContext = {
defaultInteractiveOpened: context.defaultInteractiveOpened, defaultInteractiveOpened: context.defaultInteractiveOpened,
specUrl: context.specUrl,
icons: context.icons, icons: context.icons,
}; };
return ( return (
<ScalarApiClient> <ApiClientModalProvider
configuration={{ spec: { url: context.specUrl } }}
initialRequest={{ path: data.path, method: data.method }}
>
<div className={classNames('openapi-operation', className)}> <div className={classNames('openapi-operation', className)}>
<div className="openapi-intro"> <div className="openapi-intro">
<h2 className="openapi-summary">{operation.summary}</h2> <h2 className="openapi-summary">{operation.summary}</h2>
@@ -61,6 +65,6 @@ export function OpenAPIOperation(props: {
</div> </div>
</div> </div>
</div> </div>
</ScalarApiClient> </ApiClientModalProvider>
); );
} }
+5 -138
View File
@@ -1,44 +1,17 @@
'use client'; 'use client';
import {
Cookie, import { useApiClientModal } from '@scalar/api-client-react';
getHarRequest,
getParametersFromOperation,
type TransformedOperation,
getRequestFromOperation,
Query,
Header,
RequestBody,
} from '@scalar/oas-utils';
import React from 'react'; import React from 'react';
import { OpenAPIOperationData, fromJSON } from './fetchOpenAPIOperation';
const ApiClientReact = React.lazy(async () => {
const mod = await import('@scalar/api-client-react');
return { default: mod.ApiClientReact };
});
const ScalarContext = React.createContext<
(fetchOperationData: () => Promise<OpenAPIOperationData>) => void
>(() => {});
/** /**
* Button which launches the Scalar API Client * Button which launches the Scalar API Client
*/ */
export function ScalarApiButton(props: { export function ScalarApiButton() {
fetchOperationData: () => Promise<OpenAPIOperationData>; const client = useApiClientModal();
}) {
const { fetchOperationData } = props;
const open = React.useContext(ScalarContext);
return ( return (
<div className="scalar scalar-activate"> <div className="scalar scalar-activate">
<button <button className="scalar-activate-button" onClick={() => client?.open()}>
className="scalar-activate-button"
onClick={() => {
open(fetchOperationData);
}}
>
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="12" fill="none"> <svg xmlns="http://www.w3.org/2000/svg" width="10" height="12" fill="none">
<path <path
stroke="currentColor" stroke="currentColor"
@@ -51,109 +24,3 @@ export function ScalarApiButton(props: {
</div> </div>
); );
} }
/**
* Wrap the rendering with a context to open the scalar modal.
*/
export function ScalarApiClient(props: { children: React.ReactNode }) {
const { children } = props;
const [active, setActive] = React.useState<null | {
operationData: OpenAPIOperationData | null;
}>(null);
const proxy = '/~scalar/proxy';
const open = React.useCallback(
async (fetchOperationData: () => Promise<OpenAPIOperationData>) => {
setActive({ operationData: null });
const operationData = fromJSON(await fetchOperationData());
setActive({ operationData });
},
[],
);
const onClose = React.useCallback(() => {
setActive(null);
}, []);
const request = React.useMemo(() => {
const operationData = active?.operationData;
if (!operationData) {
return null;
}
const operationId =
operationData.operation.operationId ?? operationData.method + operationData.path;
const operation = {
...operationData,
httpVerb: operationData.method,
pathParameters: operationData.operation.parameters,
} as TransformedOperation;
const variables = getParametersFromOperation(operation, 'path', false);
const request = getHarRequest(
{
url: operationData.path,
},
getRequestFromOperation(
{
...operation,
information: {
requestBody: operationData.operation.requestBody as RequestBody,
},
},
{ requiredOnly: false },
),
);
return {
id: operationId,
type: operationData.method,
path: operationData.path,
variables,
cookies: request.cookies.map((cookie: Cookie) => {
return { ...cookie, enabled: true };
}),
query: request.queryString.map((queryString: Query) => {
const query: typeof queryString & { required?: boolean } = queryString;
return { ...queryString, enabled: query.required ?? true };
}),
headers: request.headers.map((header: Header) => {
return { ...header, enabled: true };
}),
url: operationData.servers[0]?.url,
body: request.postData?.text,
};
}, [active]);
return (
<ScalarContext.Provider value={open}>
{children}
{active ? (
<div className="scalar">
<div className="scalar-container">
<div className="scalar-app">
<React.Suspense fallback={<ScalarLoading />}>
<ApiClientReact
close={onClose}
proxy={proxy}
isOpen={true}
request={request}
/>
</React.Suspense>
</div>
<div onClick={() => onClose()} className="scalar-app-exit"></div>
</div>
</div>
) : null}
</ScalarContext.Provider>
);
}
function ScalarLoading() {
return <div className="scalar-app-loading">Loading...</div>;
}
@@ -43,7 +43,7 @@ export interface OpenAPICustomSpecProperties {
*/ */
export interface OpenAPICustomOperationProperties { export interface OpenAPICustomOperationProperties {
'x-code-samples'?: OpenAPICustomCodeSample[]; 'x-code-samples'?: OpenAPICustomCodeSample[];
'x-codeSamples'?: OpenAPICustomCodeSample[]; 'x-codeSamples'?: OpenAPICustomCodeSample[] | false;
'x-custom-examples'?: OpenAPICustomCodeSample[]; 'x-custom-examples'?: OpenAPICustomCodeSample[];
/** /**
+3
View File
@@ -10,6 +10,9 @@ export interface OpenAPIClientContext {
chevronRight: React.ReactNode; chevronRight: React.ReactNode;
}; };
/** Spec url foor the Scalar Api Client */
specUrl: string;
/** /**
* Force all sections to be opened by default. * Force all sections to be opened by default.
* @default false * @default false
+13
View File
@@ -0,0 +1,13 @@
diff --git a/dist/index.js b/dist/index.js
index 7f9eaa2526e5fad42420f590bb733e5670766e63..302274144d28dde2b9ba8f9018281d2867f79299 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -9484,7 +9484,7 @@ var import_path = require("path");
// src/constants.ts
var KIB = 1024;
var MIB = 1024 * KIB;
-var EDGE_FUNCTION_SIZE_LIMIT = 4 * MIB;
+var EDGE_FUNCTION_SIZE_LIMIT = 10 * MIB;
var MAX_UNCOMPRESSED_LAMBDA_SIZE = 250 * MIB;
var LAMBDA_RESERVED_UNCOMPRESSED_SIZE = 2.5 * MIB;
var LAMBDA_RESERVED_COMPRESSED_SIZE = 250 * KIB;