@gitbook/react-openapi 1.0.2 → 1.0.4

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.
Files changed (72) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/OpenAPICodeSample.jsx +17 -16
  3. package/dist/OpenAPIDisclosure.d.ts +2 -1
  4. package/dist/OpenAPIDisclosure.jsx +1 -1
  5. package/dist/OpenAPIDisclosureGroup.d.ts +1 -1
  6. package/dist/OpenAPIDisclosureGroup.jsx +2 -2
  7. package/dist/OpenAPIOperation.jsx +21 -7
  8. package/dist/OpenAPIPath.d.ts +3 -2
  9. package/dist/OpenAPIPath.jsx +4 -15
  10. package/dist/OpenAPIRequestBody.jsx +1 -1
  11. package/dist/OpenAPIResponse.jsx +1 -1
  12. package/dist/OpenAPIResponseExample.jsx +6 -5
  13. package/dist/OpenAPIResponses.d.ts +1 -1
  14. package/dist/OpenAPIResponses.jsx +2 -2
  15. package/dist/OpenAPISchema.d.ts +5 -1
  16. package/dist/OpenAPISchema.jsx +72 -61
  17. package/dist/OpenAPISchemaName.d.ts +5 -3
  18. package/dist/OpenAPISchemaName.jsx +25 -4
  19. package/dist/OpenAPISecurities.jsx +2 -2
  20. package/dist/OpenAPITabs.d.ts +3 -3
  21. package/dist/OpenAPITabs.jsx +17 -14
  22. package/dist/ScalarApiButton.jsx +1 -1
  23. package/dist/code-samples.js +239 -17
  24. package/dist/contentTypeChecks.d.ts +9 -0
  25. package/dist/contentTypeChecks.js +27 -0
  26. package/dist/generateSchemaExample.js +2 -1
  27. package/dist/resolveOpenAPIOperation.d.ts +3 -3
  28. package/dist/resolveOpenAPIOperation.js +1 -1
  29. package/dist/stringifyOpenAPI.d.ts +1 -1
  30. package/dist/stringifyOpenAPI.js +8 -2
  31. package/dist/tsconfig.build.tsbuildinfo +1 -1
  32. package/dist/types.d.ts +14 -2
  33. package/dist/util/server.d.ts +9 -0
  34. package/dist/util/server.js +44 -0
  35. package/dist/utils.d.ts +2 -2
  36. package/dist/utils.js +7 -6
  37. package/package.json +3 -8
  38. package/src/InteractiveSection.tsx +4 -4
  39. package/src/OpenAPICodeSample.tsx +20 -19
  40. package/src/OpenAPIDisclosure.tsx +4 -3
  41. package/src/OpenAPIDisclosureGroup.tsx +5 -5
  42. package/src/OpenAPIOperation.tsx +32 -10
  43. package/src/OpenAPIOperationContext.tsx +1 -1
  44. package/src/OpenAPIPath.tsx +11 -10
  45. package/src/OpenAPIRequestBody.tsx +2 -2
  46. package/src/OpenAPIResponse.tsx +3 -3
  47. package/src/OpenAPIResponseExample.tsx +7 -6
  48. package/src/OpenAPIResponses.tsx +4 -4
  49. package/src/OpenAPISchema.test.ts +5 -5
  50. package/src/OpenAPISchema.tsx +134 -73
  51. package/src/OpenAPISchemaName.tsx +40 -7
  52. package/src/OpenAPISecurities.tsx +3 -3
  53. package/src/OpenAPITabs.tsx +23 -17
  54. package/src/ScalarApiButton.tsx +3 -3
  55. package/src/code-samples.test.ts +594 -2
  56. package/src/code-samples.ts +238 -17
  57. package/src/contentTypeChecks.ts +35 -0
  58. package/src/generateSchemaExample.ts +22 -18
  59. package/src/json2xml.test.ts +1 -1
  60. package/src/resolveOpenAPIOperation.test.ts +6 -6
  61. package/src/resolveOpenAPIOperation.ts +7 -7
  62. package/src/stringifyOpenAPI.ts +13 -2
  63. package/src/types.ts +11 -1
  64. package/src/util/server.test.ts +58 -0
  65. package/src/util/server.ts +47 -0
  66. package/src/utils.ts +9 -5
  67. package/dist/OpenAPIServerURL.d.ts +0 -11
  68. package/dist/OpenAPIServerURL.jsx +0 -67
  69. package/dist/OpenAPIServerURLVariable.d.ts +0 -8
  70. package/dist/OpenAPIServerURLVariable.jsx +0 -8
  71. package/src/OpenAPIServerURL.tsx +0 -73
  72. package/src/OpenAPIServerURLVariable.tsx +0 -14
package/CHANGELOG.md CHANGED
@@ -1,5 +1,29 @@
1
1
  # @gitbook/react-openapi
2
2
 
3
+ ## 1.0.4
4
+
5
+ ### Patch Changes
6
+
7
+ - 722f02e: Fix recursion in OpenAPISchemaAlternative
8
+ - Updated dependencies [0924259]
9
+ - @gitbook/openapi-parser@2.0.1
10
+
11
+ ## 1.0.3
12
+
13
+ ### Patch Changes
14
+
15
+ - dc2dbc5: Update OpenAPI code examples to support multiple content-type
16
+ - f1d1d2f: Return empty string if no server provided
17
+ - 05e1d8c: Hide x-gitbook-\* symbols in OpenAPI blocks
18
+ - b4a12d6: Fix circularRef in schema + examples OpenAPI
19
+ - 9f0de74: Fix ID not set when there is no operation summary
20
+ - da55fac: Render GitBook blocks in OpenAPI operation description
21
+ - Updated dependencies [c808bb1]
22
+ - Updated dependencies [e24206e]
23
+ - Updated dependencies [a054554]
24
+ - Updated dependencies [da55fac]
25
+ - @gitbook/openapi-parser@2.0.0
26
+
3
27
  ## 1.0.2
4
28
 
5
29
  ### Patch Changes
@@ -9,14 +9,13 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
+ import { InteractiveSection } from './InteractiveSection';
13
+ import { OpenAPITabs, OpenAPITabsList, OpenAPITabsPanels } from './OpenAPITabs';
12
14
  import { codeSampleGenerators } from './code-samples';
13
15
  import { generateMediaTypeExample, generateSchemaExample } from './generateSchemaExample';
14
- import { InteractiveSection } from './InteractiveSection';
15
- import { getServersURL } from './OpenAPIServerURL';
16
- import { createStateKey } from './utils';
17
16
  import { stringifyOpenAPI } from './stringifyOpenAPI';
18
- import { OpenAPITabs, OpenAPITabsList, OpenAPITabsPanels } from './OpenAPITabs';
19
- import { checkIsReference } from './utils';
17
+ import { getDefaultServerURL } from './util/server';
18
+ import { checkIsReference, createStateKey } from './utils';
20
19
  /**
21
20
  * Display code samples to execute the operation.
22
21
  * It supports the Redocly custom syntax as well (https://redocly.com/docs/api-reference-docs/specification-extensions/x-code-samples/)
@@ -52,15 +51,11 @@ export function OpenAPICodeSample(props) {
52
51
  : undefined;
53
52
  var requestBodyContent = requestBodyContentEntries === null || requestBodyContentEntries === void 0 ? void 0 : requestBodyContentEntries[0];
54
53
  var input = {
55
- url: getServersURL(data.servers) +
54
+ url: getDefaultServerURL(data.servers) +
56
55
  data.path +
57
56
  (searchParams.size ? "?".concat(searchParams.toString()) : ''),
58
57
  method: data.method,
59
- body: requestBodyContent
60
- ? generateMediaTypeExample(requestBodyContent[1], {
61
- omitEmptyAndOptionalProperties: true,
62
- })
63
- : undefined,
58
+ body: requestBodyContent ? generateMediaTypeExample(requestBodyContent[1]) : undefined,
64
59
  headers: __assign(__assign(__assign({}, getSecurityHeaders(data.securities)), headersObject), (requestBodyContent
65
60
  ? {
66
61
  'Content-Type': requestBodyContent[0],
@@ -70,7 +65,10 @@ export function OpenAPICodeSample(props) {
70
65
  var autoCodeSamples = codeSampleGenerators.map(function (generator) { return ({
71
66
  key: "default-".concat(generator.id),
72
67
  label: generator.label,
73
- body: <context.CodeBlock code={generator.generate(input)} syntax={generator.syntax}/>,
68
+ body: context.renderCodeBlock({
69
+ code: generator.generate(input),
70
+ syntax: generator.syntax,
71
+ }),
74
72
  }); });
75
73
  // Use custom samples if defined
76
74
  var customCodeSamples = null;
@@ -83,10 +81,13 @@ export function OpenAPICodeSample(props) {
83
81
  typeof sample.source === 'string' &&
84
82
  typeof sample.lang === 'string');
85
83
  })
86
- .map(function (sample) { return ({
87
- key: "redocly-".concat(sample.lang),
84
+ .map(function (sample, index) { return ({
85
+ key: "redocly-".concat(sample.lang, "-").concat(index),
88
86
  label: sample.label,
89
- body: <context.CodeBlock code={sample.source} syntax={sample.lang}/>,
87
+ body: context.renderCodeBlock({
88
+ code: sample.source,
89
+ syntax: sample.lang,
90
+ }),
90
91
  }); });
91
92
  }
92
93
  });
@@ -125,7 +126,7 @@ function getSecurityHeaders(securities) {
125
126
  scheme = 'Token';
126
127
  }
127
128
  return {
128
- Authorization: scheme + ' ' + format,
129
+ Authorization: "".concat(scheme, " ").concat(format),
129
130
  };
130
131
  }
131
132
  case 'apiKey': {
@@ -1,3 +1,4 @@
1
+ import type React from 'react';
1
2
  import type { OpenAPIClientContext } from './types';
2
3
  interface Props {
3
4
  context: OpenAPIClientContext;
@@ -8,5 +9,5 @@ interface Props {
8
9
  * Display an interactive OpenAPI disclosure.
9
10
  * The label is optional and defaults to "child attributes".
10
11
  */
11
- export declare function OpenAPIDisclosure({ context, children, label }: Props): JSX.Element;
12
+ export declare function OpenAPIDisclosure({ context, children, label }: Props): React.JSX.Element;
12
13
  export {};
@@ -21,7 +21,7 @@ export function OpenAPIDisclosure(_a) {
21
21
  }}>
22
22
  {context.icons.plus}
23
23
  <span>
24
- {"".concat(state.isExpanded ? 'Hide' : 'Show', " ").concat(label ? label : "child attributes")}
24
+ {"".concat(state.isExpanded ? 'Hide' : 'Show', " ").concat(label ? label : 'child attributes')}
25
25
  </span>
26
26
  </button>
27
27
 
@@ -11,7 +11,7 @@ type TDisclosureGroup = {
11
11
  body?: React.ReactNode;
12
12
  }[];
13
13
  };
14
- import { DisclosureGroupProps } from 'react-stately';
14
+ import { type DisclosureGroupProps } from 'react-stately';
15
15
  /**
16
16
  * Display an interactive OpenAPI disclosure group.
17
17
  */
@@ -9,9 +9,9 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
+ import { createContext, useContext, useRef, useState } from 'react';
12
13
  import { mergeProps, useButton, useDisclosure, useFocusRing, useId } from 'react-aria';
13
14
  import { useDisclosureGroupState, useDisclosureState, } from 'react-stately';
14
- import { createContext, useContext, useRef, useState } from 'react';
15
15
  var DisclosureGroupStateContext = createContext(null);
16
16
  /**
17
17
  * Display an interactive OpenAPI disclosure group.
@@ -70,7 +70,7 @@ function DisclosureItem(props) {
70
70
  {group.tabs.map(function (tab) { return (<option key={tab.id} value={tab.id}>
71
71
  {tab.label}
72
72
  </option>); })}
73
- </select>) : !!group.tabs[0] ? (<span>{group.tabs[0].label}</span>) : null}
73
+ </select>) : group.tabs[0] ? (<span>{group.tabs[0].label}</span>) : null}
74
74
  </div>) : null}
75
75
  </div>
76
76
 
@@ -1,9 +1,9 @@
1
1
  import clsx from 'clsx';
2
2
  import { Markdown } from './Markdown';
3
3
  import { OpenAPICodeSample } from './OpenAPICodeSample';
4
+ import { OpenAPIPath } from './OpenAPIPath';
4
5
  import { OpenAPIResponseExample } from './OpenAPIResponseExample';
5
6
  import { OpenAPISpec } from './OpenAPISpec';
6
- import { OpenAPIPath } from './OpenAPIPath';
7
7
  import { resolveDescription } from './utils';
8
8
  /**
9
9
  * Display an interactive OpenAPI operation.
@@ -17,9 +17,8 @@ export function OpenAPIOperation(props) {
17
17
  icons: context.icons,
18
18
  blockKey: context.blockKey,
19
19
  };
20
- var description = resolveDescription(operation);
21
20
  return (<div className={clsx('openapi-operation', className)}>
22
- <div className="openapi-summary">
21
+ <div className="openapi-summary" id={operation.summary ? undefined : context.id}>
23
22
  {operation.summary
24
23
  ? context.renderHeading({
25
24
  deprecated: (_a = operation.deprecated) !== null && _a !== void 0 ? _a : false,
@@ -35,11 +34,9 @@ export function OpenAPIOperation(props) {
35
34
  <span className="openapi-deprecated-sunset-date">
36
35
  {operation['x-deprecated-sunset']}
37
36
  </span>
38
- {"."}
39
- </div>) : null}
40
- {description ? (<div className="openapi-intro">
41
- <Markdown className="openapi-description" source={description}/>
37
+ {'.'}
42
38
  </div>) : null}
39
+ <OpenAPIOperationDescription operation={operation} context={context}/>
43
40
  <OpenAPIPath data={data} context={context}/>
44
41
  <OpenAPISpec data={data} context={clientContext}/>
45
42
  </div>
@@ -52,3 +49,20 @@ export function OpenAPIOperation(props) {
52
49
  </div>
53
50
  </div>);
54
51
  }
52
+ function OpenAPIOperationDescription(props) {
53
+ var operation = props.operation;
54
+ if (operation['x-gitbook-description-document']) {
55
+ return (<div className="openapi-intro">
56
+ {props.context.renderDocument({
57
+ document: operation['x-gitbook-description-document'],
58
+ })}
59
+ </div>);
60
+ }
61
+ var description = resolveDescription(operation);
62
+ if (!description) {
63
+ return null;
64
+ }
65
+ return (<div className="openapi-intro">
66
+ <Markdown className="openapi-description" source={description}/>
67
+ </div>);
68
+ }
@@ -1,8 +1,9 @@
1
- import type { OpenAPIOperationData, OpenAPIContextProps } from './types';
1
+ import type React from 'react';
2
+ import type { OpenAPIContextProps, OpenAPIOperationData } from './types';
2
3
  /**
3
4
  * Display the path of an operation.
4
5
  */
5
6
  export declare function OpenAPIPath(props: {
6
7
  data: OpenAPIOperationData;
7
8
  context: OpenAPIContextProps;
8
- }): JSX.Element;
9
+ }): React.JSX.Element;
@@ -1,12 +1,3 @@
1
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
2
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
3
- if (ar || !(i in from)) {
4
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
5
- ar[i] = from[i];
6
- }
7
- }
8
- return to.concat(ar || Array.prototype.slice.call(from));
9
- };
10
1
  import { ScalarApiButton } from './ScalarApiButton';
11
2
  /**
12
3
  * Display the path of an operation.
@@ -41,14 +32,12 @@ function formatPath(path) {
41
32
  // Join parts with separators wrapped in <span>
42
33
  var formattedPath = parts.reduce(function (acc, part, index) {
43
34
  if (typeof part === 'string' && index > 0 && part === '/') {
44
- return __spreadArray(__spreadArray([], acc, true), [
45
- <span className="openapi-path-separator" key={"sep-".concat(index)}>
35
+ acc.push(<span className="openapi-path-separator" key={"sep-".concat(index)}>
46
36
  /
47
- </span>,
48
- part,
49
- ], false);
37
+ </span>);
50
38
  }
51
- return __spreadArray(__spreadArray([], acc, true), [part], false);
39
+ acc.push(part);
40
+ return acc;
52
41
  }, []);
53
42
  return <span>{formattedPath}</span>;
54
43
  }
@@ -1,5 +1,5 @@
1
- import { OpenAPIRootSchema } from './OpenAPISchema';
2
1
  import { InteractiveSection } from './InteractiveSection';
2
+ import { OpenAPIRootSchema } from './OpenAPISchema';
3
3
  import { checkIsReference } from './utils';
4
4
  /**
5
5
  * Display an interactive request body.
@@ -9,9 +9,9 @@ var __assign = (this && this.__assign) || function () {
9
9
  };
10
10
  return __assign.apply(this, arguments);
11
11
  };
12
+ import { OpenAPIDisclosure } from './OpenAPIDisclosure';
12
13
  import { OpenAPISchemaProperties } from './OpenAPISchema';
13
14
  import { parameterToProperty, resolveDescription } from './utils';
14
- import { OpenAPIDisclosure } from './OpenAPIDisclosure';
15
15
  /**
16
16
  * Display an interactive response body.
17
17
  */
@@ -1,8 +1,9 @@
1
- import { generateSchemaExample } from './generateSchemaExample';
2
- import { checkIsReference, createStateKey, resolveDescription } from './utils';
3
- import { OpenAPITabs, OpenAPITabsList, OpenAPITabsPanels } from './OpenAPITabs';
4
1
  import { InteractiveSection } from './InteractiveSection';
2
+ import { OpenAPITabs, OpenAPITabsList, OpenAPITabsPanels } from './OpenAPITabs';
3
+ import { generateSchemaExample } from './generateSchemaExample';
5
4
  import { json2xml } from './json2xml';
5
+ import { stringifyOpenAPI } from './stringifyOpenAPI';
6
+ import { checkIsReference, createStateKey, resolveDescription } from './utils';
6
7
  /**
7
8
  * Display an example of the response content.
8
9
  */
@@ -128,7 +129,7 @@ function OpenAPIExample(props) {
128
129
  if (code === null) {
129
130
  return <OpenAPIEmptyResponseExample />;
130
131
  }
131
- return <context.CodeBlock code={code} syntax={syntax}/>;
132
+ return context.renderCodeBlock({ code: code, syntax: syntax });
132
133
  }
133
134
  function stringifyExample(args) {
134
135
  var example = args.example, xml = args.xml;
@@ -141,7 +142,7 @@ function stringifyExample(args) {
141
142
  if (xml) {
142
143
  return json2xml(example.value);
143
144
  }
144
- return JSON.stringify(example.value, null, 2);
145
+ return stringifyOpenAPI(example.value, null, 2);
145
146
  }
146
147
  /**
147
148
  * Get the syntax from a media type.
@@ -1,5 +1,5 @@
1
1
  import type { OpenAPIV3, OpenAPIV3_1 } from '@gitbook/openapi-parser';
2
- import { OpenAPIClientContext } from './types';
2
+ import type { OpenAPIClientContext } from './types';
3
3
  /**
4
4
  * Display an interactive response body.
5
5
  */
@@ -1,7 +1,7 @@
1
- import { OpenAPIResponse } from './OpenAPIResponse';
2
1
  import { InteractiveSection } from './InteractiveSection';
3
- import { OpenAPIDisclosureGroup } from './OpenAPIDisclosureGroup';
4
2
  import { Markdown } from './Markdown';
3
+ import { OpenAPIDisclosureGroup } from './OpenAPIDisclosureGroup';
4
+ import { OpenAPIResponse } from './OpenAPIResponse';
5
5
  /**
6
6
  * Display an interactive response body.
7
7
  */
@@ -38,10 +38,14 @@ export declare function OpenAPISchemaEnum(props: {
38
38
  enumValues: any[];
39
39
  }): import("react").JSX.Element;
40
40
  export declare function OpenAPISchemaPresentation(props: OpenAPISchemaPropertyEntry): import("react").JSX.Element;
41
+ type OpenAPISchemaAlternatives = [
42
+ OpenAPIV3.SchemaObject[],
43
+ OpenAPIV3.DiscriminatorObject | undefined
44
+ ];
41
45
  /**
42
46
  * Get the alternatives to display for a schema.
43
47
  */
44
- export declare function getSchemaAlternatives(schema: OpenAPIV3.SchemaObject, ancestors?: Set<OpenAPIV3.SchemaObject>): null | [OpenAPIV3.SchemaObject[], OpenAPIV3.DiscriminatorObject | undefined];
48
+ export declare function getSchemaAlternatives(schema: OpenAPIV3.SchemaObject, ancestors?: Set<OpenAPIV3.SchemaObject>): null | OpenAPISchemaAlternatives;
45
49
  export declare function getSchemaTitle(schema: OpenAPIV3.SchemaObject,
46
50
  /** If the title is inferred in a oneOf with discriminator, we can use it to optimize the title */
47
51
  discriminator?: OpenAPIV3.DiscriminatorObject): string;
@@ -1,20 +1,11 @@
1
- var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
2
- if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
3
- if (ar || !(i in from)) {
4
- if (!ar) ar = Array.prototype.slice.call(from, 0, i);
5
- ar[i] = from[i];
6
- }
7
- }
8
- return to.concat(ar || Array.prototype.slice.call(from));
9
- };
10
1
  import clsx from 'clsx';
11
2
  import { useId } from 'react';
12
3
  import { InteractiveSection } from './InteractiveSection';
13
4
  import { Markdown } from './Markdown';
14
- import { checkIsReference, resolveDescription } from './utils';
15
- import { stringifyOpenAPI } from './stringifyOpenAPI';
16
- import { OpenAPISchemaName } from './OpenAPISchemaName';
17
5
  import { OpenAPIDisclosure } from './OpenAPIDisclosure';
6
+ import { OpenAPISchemaName } from './OpenAPISchemaName';
7
+ import { stringifyOpenAPI } from './stringifyOpenAPI';
8
+ import { checkIsReference, resolveDescription } from './utils';
18
9
  /**
19
10
  * Render a property of an OpenAPI schema.
20
11
  */
@@ -29,18 +20,16 @@ export function OpenAPISchemaProperty(props) {
29
20
  var alternatives = parentCircularRef
30
21
  ? null
31
22
  : getSchemaAlternatives(schema, new Set(circularRefs.keys()));
23
+ if ((_a = alternatives === null || alternatives === void 0 ? void 0 : alternatives[0]) === null || _a === void 0 ? void 0 : _a.length) {
24
+ return (<OpenAPISchemaAlternativesItem {...props} circularRefs={circularRefs} context={context} alternatives={alternatives} parentCircularRef={parentCircularRef}/>);
25
+ }
32
26
  if ((properties && properties.length > 0) || schema.type === 'object') {
33
27
  return (<InteractiveSection id={id} className={clsx('openapi-schema', className)}>
34
28
  <OpenAPISchemaPresentation {...props}/>
35
- {properties && properties.length > 0 ? (<OpenAPIDisclosure context={context}>
29
+ {properties && properties.length > 0 ? (<OpenAPIDisclosure context={context} label={getDisclosureLabel(schema)}>
36
30
  <OpenAPISchemaProperties properties={properties} circularRefs={circularRefs} context={context}/>
37
31
  </OpenAPIDisclosure>) : null}
38
- </InteractiveSection>);
39
- }
40
- if ((_a = alternatives === null || alternatives === void 0 ? void 0 : alternatives[0]) === null || _a === void 0 ? void 0 : _a.length) {
41
- return (<InteractiveSection id={id} className={clsx('openapi-schema', className)}>
42
- <OpenAPISchemaPresentation {...props}/>
43
- {alternatives[0].map(function (alternative, index) { return (<OpenAPISchemaAlternative key={"alternative-".concat(index)} schema={alternative} circularRefs={circularRefs} context={context}/>); })}
32
+ {parentCircularRef ? (<OpenAPISchemaCircularRef id={parentCircularRef} schema={schema}/>) : null}
44
33
  </InteractiveSection>);
45
34
  }
46
35
  return (<InteractiveSection id={id} className={clsx('openapi-schema', className)}>
@@ -83,12 +72,35 @@ export function OpenAPIRootSchema(props) {
83
72
  * for primitives, it renders the schema itself.
84
73
  */
85
74
  function OpenAPISchemaAlternative(props) {
75
+ var _a;
86
76
  var schema = props.schema, circularRefs = props.circularRefs, context = props.context;
87
77
  var id = useId();
88
78
  var subProperties = getSchemaProperties(schema);
89
- return (<OpenAPIDisclosure context={context}>
90
- <OpenAPISchemaProperties id={id} properties={subProperties !== null && subProperties !== void 0 ? subProperties : [{ schema: schema }]} circularRefs={subProperties ? new Map(circularRefs).set(schema, id) : circularRefs} context={context}/>
91
- </OpenAPIDisclosure>);
79
+ var description = resolveDescription(schema);
80
+ var alternatives = getSchemaAlternatives(schema, new Set(circularRefs === null || circularRefs === void 0 ? void 0 : circularRefs.keys()));
81
+ if (((_a = alternatives === null || alternatives === void 0 ? void 0 : alternatives[0]) === null || _a === void 0 ? void 0 : _a.length) && !(subProperties === null || subProperties === void 0 ? void 0 : subProperties.length)) {
82
+ return (<>
83
+ {description ? (<Markdown source={description} className="openapi-schema-description"/>) : null}
84
+ <OpenAPIDisclosure context={context} label={getDisclosureLabel(schema)}>
85
+ <OpenAPISchemaAlternativesItem schema={schema} circularRefs={circularRefs} context={context} alternatives={alternatives}/>
86
+ </OpenAPIDisclosure>
87
+ </>);
88
+ }
89
+ return (<>
90
+ {description ? (<Markdown source={description} className="openapi-schema-description"/>) : null}
91
+ <OpenAPIDisclosure context={context} label={getDisclosureLabel(schema)}>
92
+ <OpenAPISchemaProperties id={id} properties={subProperties !== null && subProperties !== void 0 ? subProperties : [{ schema: schema }]} circularRefs={subProperties ? new Map(circularRefs).set(schema, id) : circularRefs} context={context}/>
93
+ </OpenAPIDisclosure>
94
+ </>);
95
+ }
96
+ function OpenAPISchemaAlternativesItem(props) {
97
+ var id = useId();
98
+ var schema = props.schema, circularRefs = props.circularRefs, context = props.context, alternatives = props.alternatives, parentCircularRef = props.parentCircularRef;
99
+ return (<InteractiveSection id={id} className={clsx('openapi-schema')}>
100
+ <OpenAPISchemaPresentation {...props}/>
101
+ {alternatives[0].map(function (alternative, index) { return (<OpenAPISchemaAlternative key={"alternative-".concat(index)} schema={alternative} circularRefs={circularRefs} context={context}/>); })}
102
+ {parentCircularRef ? (<OpenAPISchemaCircularRef id={parentCircularRef} schema={schema}/>) : null}
103
+ </InteractiveSection>);
92
104
  }
93
105
  /**
94
106
  * Render a circular reference to a schema.
@@ -118,7 +130,7 @@ export function OpenAPISchemaEnum(props) {
118
130
  export function OpenAPISchemaPresentation(props) {
119
131
  var schema = props.schema, propertyName = props.propertyName, required = props.required;
120
132
  var shouldDisplayExample = function (schema) {
121
- return (typeof schema.example === 'string' ||
133
+ return ((typeof schema.example === 'string' && !!schema.example) ||
122
134
  typeof schema.example === 'number' ||
123
135
  typeof schema.example === 'boolean' ||
124
136
  (Array.isArray(schema.example) && schema.example.length > 0) ||
@@ -128,7 +140,7 @@ export function OpenAPISchemaPresentation(props) {
128
140
  };
129
141
  var description = resolveDescription(schema);
130
142
  return (<div className="openapi-schema-presentation">
131
- <OpenAPISchemaName type={getSchemaTitle(schema)} propertyName={propertyName} required={required} deprecated={schema.deprecated}/>
143
+ <OpenAPISchemaName schema={schema} type={getSchemaTitle(schema)} propertyName={propertyName} required={required}/>
132
144
  {schema['x-deprecated-sunset'] ? (<div className="openapi-deprecated-sunset openapi-schema-description openapi-markdown">
133
145
  Sunset date:{' '}
134
146
  <span className="openapi-deprecated-sunset-date">
@@ -137,12 +149,7 @@ export function OpenAPISchemaPresentation(props) {
137
149
  </div>) : null}
138
150
  {description ? (<Markdown source={description} className="openapi-schema-description"/>) : null}
139
151
  {shouldDisplayExample(schema) ? (<div className="openapi-schema-example">
140
- Example:{' '}
141
- <code>
142
- {typeof schema.example === 'string'
143
- ? schema.example
144
- : stringifyOpenAPI(schema.example)}
145
- </code>
152
+ Example: <code>{formatExample(schema.example)}</code>
146
153
  </div>) : null}
147
154
  {schema.pattern ? (<div className="openapi-schema-pattern">
148
155
  Pattern: <code>{schema.pattern}</code>
@@ -154,17 +161,6 @@ export function OpenAPISchemaPresentation(props) {
154
161
  * Get the sub-properties of a schema.
155
162
  */
156
163
  function getSchemaProperties(schema) {
157
- if (schema.allOf) {
158
- return schema.allOf.reduce(function (acc, subSchema) {
159
- var _a;
160
- var properties = (_a = getSchemaProperties(subSchema)) !== null && _a !== void 0 ? _a : [
161
- {
162
- schema: subSchema,
163
- },
164
- ];
165
- return __spreadArray(__spreadArray([], acc, true), properties, true);
166
- }, []);
167
- }
168
164
  // check array AND schema.items as this is sometimes null despite what the type indicates
169
165
  if (schema.type === 'array' && !!schema.items) {
170
166
  var items = schema.items;
@@ -172,6 +168,10 @@ function getSchemaProperties(schema) {
172
168
  if (itemProperties) {
173
169
  return itemProperties;
174
170
  }
171
+ // If the items are a primitive type, we don't need to display them
172
+ if (['string', 'number', 'boolean', 'integer'].includes(items.type) && !items.enum) {
173
+ return null;
174
+ }
175
175
  return [
176
176
  {
177
177
  propertyName: 'items',
@@ -217,8 +217,7 @@ export function getSchemaAlternatives(schema, ancestors) {
217
217
  return [flattenAlternatives('oneOf', schema.oneOf, downAncestors), schema.discriminator];
218
218
  }
219
219
  if (schema.allOf) {
220
- // allOf is managed in `getSchemaProperties`
221
- return null;
220
+ return [flattenAlternatives('allOf', schema.allOf, downAncestors), schema.discriminator];
222
221
  }
223
222
  return null;
224
223
  }
@@ -226,19 +225,18 @@ function flattenAlternatives(alternativeType, alternatives, ancestors) {
226
225
  return alternatives.reduce(function (acc, alternative) {
227
226
  var _a;
228
227
  if (!!alternative[alternativeType] && !ancestors.has(alternative)) {
229
- return __spreadArray(__spreadArray([], acc, true), (((_a = getSchemaAlternatives(alternative, ancestors)) === null || _a === void 0 ? void 0 : _a[0]) || []), true);
228
+ acc.push.apply(acc, (((_a = getSchemaAlternatives(alternative, ancestors)) === null || _a === void 0 ? void 0 : _a[0]) || []));
230
229
  }
231
- return __spreadArray(__spreadArray([], acc, true), [alternative], false);
230
+ else {
231
+ acc.push(alternative);
232
+ }
233
+ return acc;
232
234
  }, []);
233
235
  }
234
236
  export function getSchemaTitle(schema,
235
237
  /** If the title is inferred in a oneOf with discriminator, we can use it to optimize the title */
236
238
  discriminator) {
237
239
  var _a;
238
- if (schema.title) {
239
- // If the schema has a title, use it
240
- return schema.title;
241
- }
242
240
  // Try using the discriminator
243
241
  if ((discriminator === null || discriminator === void 0 ? void 0 : discriminator.propertyName) && schema.properties) {
244
242
  var discriminatorProperty = schema.properties[discriminator.propertyName];
@@ -266,7 +264,7 @@ discriminator) {
266
264
  type += " \u00B7 ".concat(schema.format);
267
265
  }
268
266
  }
269
- else if ('anyOf' in schema) {
267
+ if ('anyOf' in schema) {
270
268
  type = 'any of';
271
269
  }
272
270
  else if ('oneOf' in schema) {
@@ -278,17 +276,30 @@ discriminator) {
278
276
  else if ('not' in schema) {
279
277
  type = 'not';
280
278
  }
281
- if (schema.minimum || schema.minLength) {
282
- type += " \u00B7 min: ".concat(schema.minimum || schema.minLength);
283
- }
284
- if (schema.maximum || schema.maxLength) {
285
- type += " \u00B7 max: ".concat(schema.maximum || schema.maxLength);
286
- }
287
- if (schema.default) {
288
- type += " \u00B7 default: ".concat(schema.default);
279
+ return type;
280
+ }
281
+ function getDisclosureLabel(schema) {
282
+ var _a, _b;
283
+ if (schema.type === 'array' && !!schema.items) {
284
+ if (schema.items.oneOf) {
285
+ return 'available items';
286
+ }
287
+ // Fallback to "child attributes" for enums and objects
288
+ if (schema.items.enum || schema.items.type === 'object') {
289
+ return;
290
+ }
291
+ return (_b = (_a = schema.items.title) !== null && _a !== void 0 ? _a : schema.title) !== null && _b !== void 0 ? _b : getSchemaTitle(schema.items);
289
292
  }
290
- if (schema.nullable) {
291
- type = "".concat(type, " | nullable");
293
+ return schema.title;
294
+ }
295
+ function formatExample(example) {
296
+ if (typeof example === 'string') {
297
+ return example
298
+ .replace(/\n/g, ' ') // Replace newlines with spaces
299
+ .replace(/\s+/g, ' ') // Collapse multiple spaces/newlines into a single space
300
+ .replace(/([\{\}:,])\s+/g, '$1 ') // Ensure a space after {, }, :, and ,
301
+ .replace(/\s+([\{\}:,])/g, ' $1') // Ensure a space before {, }, :, and ,
302
+ .trim();
292
303
  }
293
- return type;
304
+ return stringifyOpenAPI(example);
294
305
  }
@@ -1,12 +1,14 @@
1
+ import type { OpenAPIV3 } from '@gitbook/openapi-parser';
2
+ import type React from 'react';
1
3
  interface OpenAPISchemaNameProps {
2
- propertyName?: string | JSX.Element;
4
+ schema?: OpenAPIV3.SchemaObject;
5
+ propertyName?: string | React.JSX.Element;
3
6
  required?: boolean;
4
7
  type?: string;
5
- deprecated?: boolean;
6
8
  }
7
9
  /**
8
10
  * Display the schema name row.
9
11
  * It includes the property name, type, required and deprecated status.
10
12
  */
11
- export declare function OpenAPISchemaName(props: OpenAPISchemaNameProps): JSX.Element;
13
+ export declare function OpenAPISchemaName(props: OpenAPISchemaNameProps): React.JSX.Element;
12
14
  export {};
@@ -3,13 +3,34 @@
3
3
  * It includes the property name, type, required and deprecated status.
4
4
  */
5
5
  export function OpenAPISchemaName(props) {
6
- var type = props.type, propertyName = props.propertyName, required = props.required, deprecated = props.deprecated;
6
+ var schema = props.schema, type = props.type, propertyName = props.propertyName, required = props.required;
7
+ var additionalItems = schema && getAdditionalItems(schema);
7
8
  return (<div className="openapi-schema-name">
8
- {propertyName ? (<span data-deprecated={deprecated} className="openapi-schema-propertyname">
9
+ {propertyName ? (<span data-deprecated={schema === null || schema === void 0 ? void 0 : schema.deprecated} className="openapi-schema-propertyname">
9
10
  {propertyName}
10
11
  </span>) : null}
11
- {type ? <span className="openapi-schema-type">{type}</span> : null}
12
+ <span>
13
+ {type ? <span className="openapi-schema-type">{type}</span> : null}
14
+ {additionalItems ? (<span className="openapi-schema-type">{additionalItems}</span>) : null}
15
+ </span>
12
16
  {required ? <span className="openapi-schema-required">required</span> : null}
13
- {deprecated ? <span className="openapi-deprecated">Deprecated</span> : null}
17
+ {(schema === null || schema === void 0 ? void 0 : schema.deprecated) ? <span className="openapi-deprecated">Deprecated</span> : null}
14
18
  </div>);
15
19
  }
20
+ function getAdditionalItems(schema) {
21
+ var additionalItems = '';
22
+ if (schema.minimum || schema.minLength) {
23
+ additionalItems += " \u00B7 min: ".concat(schema.minimum || schema.minLength);
24
+ }
25
+ if (schema.maximum || schema.maxLength) {
26
+ additionalItems += " \u00B7 max: ".concat(schema.maximum || schema.maxLength);
27
+ }
28
+ // If the schema has a default value, we display it
29
+ if (typeof schema.default !== 'undefined') {
30
+ additionalItems += " \u00B7 default: ".concat(schema.default);
31
+ }
32
+ if (schema.nullable) {
33
+ additionalItems = ' | nullable';
34
+ }
35
+ return additionalItems;
36
+ }