@gitbook/react-openapi 1.1.4 → 1.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/OpenAPICodeSample.jsx +21 -0
- package/dist/OpenAPICopyButton.d.ts +4 -0
- package/dist/OpenAPICopyButton.jsx +32 -0
- package/dist/OpenAPIOperation.jsx +1 -1
- package/dist/OpenAPIPath.d.ts +1 -2
- package/dist/OpenAPIPath.jsx +32 -30
- package/dist/OpenAPIResponseExample.jsx +5 -8
- package/dist/OpenAPITabs.d.ts +1 -1
- package/dist/OpenAPITabs.jsx +9 -2
- package/dist/ScalarApiButton.jsx +2 -2
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/OpenAPICodeSample.tsx +32 -0
- package/src/OpenAPICopyButton.tsx +54 -0
- package/src/OpenAPIOperation.tsx +1 -1
- package/src/OpenAPIPath.tsx +40 -42
- package/src/OpenAPIResponseExample.tsx +30 -33
- package/src/OpenAPITabs.tsx +13 -4
- package/src/ScalarApiButton.tsx +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,7 @@ var __assign = (this && this.__assign) || function () {
|
|
|
10
10
|
return __assign.apply(this, arguments);
|
|
11
11
|
};
|
|
12
12
|
import { OpenAPITabs, OpenAPITabsList, OpenAPITabsPanels } from './OpenAPITabs';
|
|
13
|
+
import { ScalarApiButton } from './ScalarApiButton';
|
|
13
14
|
import { StaticSection } from './StaticSection';
|
|
14
15
|
import { codeSampleGenerators } from './code-samples';
|
|
15
16
|
import { generateMediaTypeExample, generateSchemaExample } from './generateSchemaExample';
|
|
@@ -73,6 +74,7 @@ export function OpenAPICodeSample(props) {
|
|
|
73
74
|
code: generator.generate(input),
|
|
74
75
|
syntax: generator.syntax,
|
|
75
76
|
}),
|
|
77
|
+
footer: <OpenAPICodeSampleFooter data={data} context={context}/>,
|
|
76
78
|
}); });
|
|
77
79
|
// Use custom samples if defined
|
|
78
80
|
var customCodeSamples = null;
|
|
@@ -92,6 +94,7 @@ export function OpenAPICodeSample(props) {
|
|
|
92
94
|
code: sample.source,
|
|
93
95
|
syntax: sample.lang,
|
|
94
96
|
}),
|
|
97
|
+
footer: <OpenAPICodeSampleFooter data={data} context={context}/>,
|
|
95
98
|
}); });
|
|
96
99
|
}
|
|
97
100
|
});
|
|
@@ -108,6 +111,21 @@ export function OpenAPICodeSample(props) {
|
|
|
108
111
|
</StaticSection>
|
|
109
112
|
</OpenAPITabs>);
|
|
110
113
|
}
|
|
114
|
+
function OpenAPICodeSampleFooter(props) {
|
|
115
|
+
var data = props.data, context = props.context;
|
|
116
|
+
var method = data.method, path = data.path;
|
|
117
|
+
var specUrl = context.specUrl;
|
|
118
|
+
var hideTryItPanel = data['x-hideTryItPanel'] || data.operation['x-hideTryItPanel'];
|
|
119
|
+
if (hideTryItPanel) {
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
if (!validateHttpMethod(method)) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
return (<div className="openapi-codesample-footer">
|
|
126
|
+
<ScalarApiButton method={method} path={path} specUrl={specUrl}/>
|
|
127
|
+
</div>);
|
|
128
|
+
}
|
|
111
129
|
function getSecurityHeaders(securities) {
|
|
112
130
|
var _a;
|
|
113
131
|
var _b, _c;
|
|
@@ -146,3 +164,6 @@ function getSecurityHeaders(securities) {
|
|
|
146
164
|
}
|
|
147
165
|
}
|
|
148
166
|
}
|
|
167
|
+
function validateHttpMethod(method) {
|
|
168
|
+
return ['get', 'post', 'put', 'delete', 'patch', 'head', 'options', 'trace'].includes(method);
|
|
169
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Button, Tooltip, TooltipTrigger } from 'react-aria-components';
|
|
4
|
+
export function OpenAPICopyButton(props) {
|
|
5
|
+
var value = props.value;
|
|
6
|
+
var children = props.children, onPress = props.onPress, className = props.className;
|
|
7
|
+
var _a = useState(false), copied = _a[0], setCopied = _a[1];
|
|
8
|
+
var _b = useState(false), isOpen = _b[0], setIsOpen = _b[1];
|
|
9
|
+
var handleCopy = function () {
|
|
10
|
+
if (!value)
|
|
11
|
+
return;
|
|
12
|
+
navigator.clipboard.writeText(value).then(function () {
|
|
13
|
+
setIsOpen(true);
|
|
14
|
+
setCopied(true);
|
|
15
|
+
setTimeout(function () {
|
|
16
|
+
setCopied(false);
|
|
17
|
+
}, 2000);
|
|
18
|
+
});
|
|
19
|
+
};
|
|
20
|
+
return (<TooltipTrigger isOpen={isOpen} onOpenChange={setIsOpen} closeDelay={200} delay={200}>
|
|
21
|
+
<Button type="button" preventFocusOnPress onPress={function (e) {
|
|
22
|
+
handleCopy();
|
|
23
|
+
onPress === null || onPress === void 0 ? void 0 : onPress(e);
|
|
24
|
+
}} className={"openapi-copy-button ".concat(className)} {...props}>
|
|
25
|
+
{children}
|
|
26
|
+
</Button>
|
|
27
|
+
|
|
28
|
+
<Tooltip isOpen={isOpen} onOpenChange={setIsOpen} placement="top" offset={4} className="openapi-tooltip">
|
|
29
|
+
{copied ? 'Copied' : 'Copy to clipboard'}{' '}
|
|
30
|
+
</Tooltip>
|
|
31
|
+
</TooltipTrigger>);
|
|
32
|
+
}
|
|
@@ -25,6 +25,7 @@ export function OpenAPIOperation(props) {
|
|
|
25
25
|
title: operation.summary,
|
|
26
26
|
})
|
|
27
27
|
: null}
|
|
28
|
+
<OpenAPIPath data={data} context={context}/>
|
|
28
29
|
{operation.deprecated && <div className="openapi-deprecated">Deprecated</div>}
|
|
29
30
|
</div>
|
|
30
31
|
<div className="openapi-columns">
|
|
@@ -37,7 +38,6 @@ export function OpenAPIOperation(props) {
|
|
|
37
38
|
{'.'}
|
|
38
39
|
</div>) : null}
|
|
39
40
|
<OpenAPIOperationDescription operation={operation} context={context}/>
|
|
40
|
-
<OpenAPIPath data={data} context={context}/>
|
|
41
41
|
<OpenAPISpec data={data} context={clientContext}/>
|
|
42
42
|
</div>
|
|
43
43
|
<div className="openapi-column-preview">
|
package/dist/OpenAPIPath.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type React from 'react';
|
|
2
1
|
import type { OpenAPIContextProps, OpenAPIOperationData } from './types';
|
|
3
2
|
/**
|
|
4
3
|
* Display the path of an operation.
|
|
@@ -6,4 +5,4 @@ import type { OpenAPIContextProps, OpenAPIOperationData } from './types';
|
|
|
6
5
|
export declare function OpenAPIPath(props: {
|
|
7
6
|
data: OpenAPIOperationData;
|
|
8
7
|
context: OpenAPIContextProps;
|
|
9
|
-
}):
|
|
8
|
+
}): import("react").JSX.Element;
|
package/dist/OpenAPIPath.jsx
CHANGED
|
@@ -1,47 +1,49 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { OpenAPICopyButton } from './OpenAPICopyButton';
|
|
2
|
+
import { getDefaultServerURL } from './util/server';
|
|
2
3
|
/**
|
|
3
4
|
* Display the path of an operation.
|
|
4
5
|
*/
|
|
5
6
|
export function OpenAPIPath(props) {
|
|
6
|
-
var data = props.data
|
|
7
|
-
var method = data.method, path = data.path;
|
|
8
|
-
var
|
|
9
|
-
var
|
|
7
|
+
var data = props.data;
|
|
8
|
+
var method = data.method, path = data.path, operation = data.operation;
|
|
9
|
+
var server = getDefaultServerURL(data.servers);
|
|
10
|
+
var formattedPath = formatPath(path);
|
|
10
11
|
return (<div className="openapi-path">
|
|
11
12
|
<div className={"openapi-method openapi-method-".concat(method)}>{method}</div>
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
|
|
14
|
+
<OpenAPICopyButton value={server + path} className="openapi-path-title" data-deprecated={operation.deprecated}>
|
|
15
|
+
<span className="openapi-path-server">{server}</span>
|
|
16
|
+
{formattedPath}
|
|
17
|
+
</OpenAPICopyButton>
|
|
16
18
|
</div>);
|
|
17
19
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
// Format the path to highlight placeholders
|
|
20
|
+
/**
|
|
21
|
+
* Format the path by wrapping placeholders in <span> tags.
|
|
22
|
+
*/
|
|
22
23
|
function formatPath(path) {
|
|
23
24
|
// Matches placeholders like {id}, {userId}, etc.
|
|
24
|
-
var regex = /\{(\w+)\}
|
|
25
|
+
var regex = /\{\s*(\w+)\s*\}|:\w+/g;
|
|
25
26
|
var parts = [];
|
|
26
27
|
var lastIndex = 0;
|
|
27
|
-
//
|
|
28
|
-
path.replace(regex, function (match,
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
//Wrap the variables in <span> tags and maintain either {variable} or :variable
|
|
29
|
+
path.replace(regex, function (match, _, offset) {
|
|
30
|
+
if (offset > lastIndex) {
|
|
31
|
+
parts.push(path.slice(lastIndex, offset));
|
|
32
|
+
}
|
|
33
|
+
parts.push(<span key={offset} className="openapi-path-variable">
|
|
34
|
+
{match}
|
|
35
|
+
</span>);
|
|
31
36
|
lastIndex = offset + match.length;
|
|
32
37
|
return match;
|
|
33
38
|
});
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
var formattedPath = parts.
|
|
38
|
-
if (typeof part === 'string'
|
|
39
|
-
|
|
40
|
-
/
|
|
41
|
-
</span>);
|
|
39
|
+
if (lastIndex < path.length) {
|
|
40
|
+
parts.push(path.slice(lastIndex));
|
|
41
|
+
}
|
|
42
|
+
var formattedPath = parts.map(function (part, index) {
|
|
43
|
+
if (typeof part === 'string') {
|
|
44
|
+
return <span key={index}>{part}</span>;
|
|
42
45
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return <span>{formattedPath}</span>;
|
|
46
|
+
return part;
|
|
47
|
+
});
|
|
48
|
+
return formattedPath;
|
|
47
49
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Markdown } from './Markdown';
|
|
1
2
|
import { OpenAPITabs, OpenAPITabsList, OpenAPITabsPanels } from './OpenAPITabs';
|
|
2
3
|
import { StaticSection } from './StaticSection';
|
|
3
4
|
import { generateSchemaExample } from './generateSchemaExample';
|
|
@@ -32,35 +33,31 @@ export function OpenAPIResponseExample(props) {
|
|
|
32
33
|
}
|
|
33
34
|
return Number(a) - Number(b);
|
|
34
35
|
});
|
|
35
|
-
var tabs = responses
|
|
36
|
-
.map(function (_a) {
|
|
36
|
+
var tabs = responses.map(function (_a) {
|
|
37
37
|
var key = _a[0], responseObject = _a[1];
|
|
38
38
|
var description = resolveDescription(responseObject);
|
|
39
39
|
if (checkIsReference(responseObject)) {
|
|
40
40
|
return {
|
|
41
41
|
key: key,
|
|
42
42
|
label: key,
|
|
43
|
-
description: description,
|
|
44
43
|
body: (<OpenAPIExample example={getExampleFromReference(responseObject)} context={context} syntax="json"/>),
|
|
44
|
+
footer: description ? <Markdown source={description}/> : undefined,
|
|
45
45
|
};
|
|
46
46
|
}
|
|
47
47
|
if (!responseObject.content || Object.keys(responseObject.content).length === 0) {
|
|
48
48
|
return {
|
|
49
49
|
key: key,
|
|
50
50
|
label: key,
|
|
51
|
-
description: description,
|
|
52
51
|
body: <OpenAPIEmptyResponseExample />,
|
|
52
|
+
footer: description ? <Markdown source={description}/> : undefined,
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
55
|
return {
|
|
56
56
|
key: key,
|
|
57
57
|
label: key,
|
|
58
|
-
description: resolveDescription(responseObject),
|
|
59
58
|
body: <OpenAPIResponse context={context} content={responseObject.content}/>,
|
|
59
|
+
footer: description ? <Markdown source={description}/> : undefined,
|
|
60
60
|
};
|
|
61
|
-
})
|
|
62
|
-
.filter(function (val) {
|
|
63
|
-
return Boolean(val);
|
|
64
61
|
});
|
|
65
62
|
if (tabs.length === 0) {
|
|
66
63
|
return null;
|
package/dist/OpenAPITabs.d.ts
CHANGED
package/dist/OpenAPITabs.jsx
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
import { createContext, useContext, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { Tab, TabList, TabPanel, Tabs } from 'react-aria-components';
|
|
4
4
|
import { useEventCallback } from 'usehooks-ts';
|
|
5
|
-
import { Markdown } from './Markdown';
|
|
6
5
|
import { getOrCreateTabStoreByKey } from './useSyncedTabsGlobalState';
|
|
7
6
|
var OpenAPITabsContext = createContext(null);
|
|
8
7
|
function useOpenAPITabsContext() {
|
|
@@ -105,6 +104,14 @@ export function OpenAPITabsPanels() {
|
|
|
105
104
|
var key = selectedTab.key.toString();
|
|
106
105
|
return (<TabPanel key={key} id={key} className="openapi-tabs-panel">
|
|
107
106
|
{selectedTab.body}
|
|
108
|
-
{selectedTab.
|
|
107
|
+
{selectedTab.footer ? (<OpenAPITabsPanelFooter>{selectedTab.footer}</OpenAPITabsPanelFooter>) : null}
|
|
109
108
|
</TabPanel>);
|
|
110
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* The OpenAPI Tabs panel footer component.
|
|
112
|
+
* This component should be used as a child of the OpenAPITabs component.
|
|
113
|
+
*/
|
|
114
|
+
function OpenAPITabsPanelFooter(props) {
|
|
115
|
+
var children = props.children;
|
|
116
|
+
return <div className="openapi-tabs-footer">{children}</div>;
|
|
117
|
+
}
|
package/dist/ScalarApiButton.jsx
CHANGED
|
@@ -16,10 +16,10 @@ export function ScalarApiButton(props) {
|
|
|
16
16
|
(_b = (_a = controllerRef.current) === null || _a === void 0 ? void 0 : _a.openClient) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
17
17
|
setIsOpen(true);
|
|
18
18
|
}}>
|
|
19
|
-
|
|
19
|
+
Test it
|
|
20
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 12" fill="currentColor">
|
|
20
21
|
<path stroke="currentColor" strokeWidth="1.5" d="M1 10.05V1.43c0-.2.2-.31.37-.22l7.26 4.08c.17.1.17.33.01.43l-7.26 4.54a.25.25 0 0 1-.38-.21Z"/>
|
|
21
22
|
</svg>
|
|
22
|
-
Test it
|
|
23
23
|
</button>
|
|
24
24
|
|
|
25
25
|
{isOpen &&
|