@@ -3,19 +3,82 @@ import { OpenAPITabs, OpenAPITabsList, OpenAPITabsPanels } from './OpenAPITabs';
3
3
import { ScalarApiButton } from './ScalarApiButton' ;
4
4
import { StaticSection } from './StaticSection' ;
5
5
import { type CodeSampleInput , codeSampleGenerators } from './code-samples' ;
6
- import { generateMediaTypeExample , generateSchemaExample } from './generateSchemaExample' ;
6
+ import { generateMediaTypeExamples , generateSchemaExample } from './generateSchemaExample' ;
7
7
import { stringifyOpenAPI } from './stringifyOpenAPI' ;
8
8
import type { OpenAPIContextProps , OpenAPIOperationData } from './types' ;
9
9
import { getDefaultServerURL } from './util/server' ;
10
10
import { checkIsReference , createStateKey } from './utils' ;
11
11
12
+ const CUSTOM_CODE_SAMPLES_KEYS = [ 'x-custom-examples' , 'x-code-samples' , 'x-codeSamples' ] as const ;
13
+
12
14
/**
13
15
* Display code samples to execute the operation.
14
16
* It supports the Redocly custom syntax as well (https://redocly.com/docs/api-reference-docs/specification-extensions/x-code-samples/)
15
17
*/
16
18
export function OpenAPICodeSample ( props : {
17
19
data : OpenAPIOperationData ;
18
20
context : OpenAPIContextProps ;
21
+ } ) {
22
+ const { data } = props ;
23
+
24
+ // If code samples are disabled at operation level, we don't display the code samples.
25
+ if ( data . operation [ 'x-codeSamples' ] === false ) {
26
+ return null ;
27
+ }
28
+
29
+ const customCodeSamples = getCustomCodeSamples ( props ) ;
30
+
31
+ // If code samples are disabled at the top-level and not custom code samples are defined,
32
+ // we don't display the code samples.
33
+ if ( data [ 'x-codeSamples' ] === false && ! customCodeSamples ) {
34
+ return null ;
35
+ }
36
+
37
+ const samples = customCodeSamples ?? generateCodeSamples ( props ) ;
38
+
39
+ if ( samples . length === 0 ) {
40
+ return null ;
41
+ }
42
+
43
+ return (
44
+ < OpenAPITabs stateKey = { createStateKey ( 'codesample' ) } items = { samples } >
45
+ < StaticSection header = { < OpenAPITabsList /> } className = "openapi-codesample" >
46
+ < OpenAPITabsPanels />
47
+ </ StaticSection >
48
+ </ OpenAPITabs >
49
+ ) ;
50
+ }
51
+
52
+ function OpenAPICodeSampleFooter ( props : {
53
+ data : OpenAPIOperationData ;
54
+ context : OpenAPIContextProps ;
55
+ } ) {
56
+ const { data, context } = props ;
57
+ const { method, path } = data ;
58
+ const { specUrl } = context ;
59
+ const hideTryItPanel = data [ 'x-hideTryItPanel' ] || data . operation [ 'x-hideTryItPanel' ] ;
60
+
61
+ if ( hideTryItPanel ) {
62
+ return null ;
63
+ }
64
+
65
+ if ( ! validateHttpMethod ( method ) ) {
66
+ return null ;
67
+ }
68
+
69
+ return (
70
+ < div className = "openapi-codesample-footer" >
71
+ < ScalarApiButton method = { method } path = { path } specUrl = { specUrl } />
72
+ </ div >
73
+ ) ;
74
+ }
75
+
76
+ /**
77
+ * Generate code samples for the operation.
78
+ */
79
+ function generateCodeSamples ( props : {
80
+ data : OpenAPIOperationData ;
81
+ context : OpenAPIContextProps ;
19
82
} ) {
20
83
const { data, context } = props ;
21
84
@@ -56,13 +119,17 @@ export function OpenAPICodeSample(props: {
56
119
: undefined ;
57
120
const requestBodyContent = requestBodyContentEntries ?. [ 0 ] ;
58
121
122
+ const requestBodyExamples = requestBodyContent
123
+ ? generateMediaTypeExamples ( requestBodyContent [ 1 ] )
124
+ : [ ] ;
125
+
59
126
const input : CodeSampleInput = {
60
127
url :
61
128
getDefaultServerURL ( data . servers ) +
62
129
data . path +
63
130
( searchParams . size ? `?${ searchParams . toString ( ) } ` : '' ) ,
64
131
method : data . method ,
65
- body : requestBodyContent ? generateMediaTypeExample ( requestBodyContent [ 1 ] ) : undefined ,
132
+ body : requestBodyExamples [ 0 ] ?. value ,
66
133
headers : {
67
134
...getSecurityHeaders ( data . securities ) ,
68
135
...headersObject ,
@@ -74,7 +141,7 @@ export function OpenAPICodeSample(props: {
74
141
} ,
75
142
} ;
76
143
77
- const autoCodeSamples = codeSampleGenerators . map ( ( generator ) => ( {
144
+ return codeSampleGenerators . map ( ( generator ) => ( {
78
145
key : `default-${ generator . id } ` ,
79
146
label : generator . label ,
80
147
body : context . renderCodeBlock ( {
@@ -83,14 +150,24 @@ export function OpenAPICodeSample(props: {
83
150
} ) ,
84
151
footer : < OpenAPICodeSampleFooter data = { data } context = { context } /> ,
85
152
} ) ) ;
153
+ }
154
+
155
+ /**
156
+ * Get custom code samples for the operation.
157
+ */
158
+ function getCustomCodeSamples ( props : {
159
+ data : OpenAPIOperationData ;
160
+ context : OpenAPIContextProps ;
161
+ } ) {
162
+ const { data, context } = props ;
86
163
87
- // Use custom samples if defined
88
164
let customCodeSamples : null | Array < {
89
165
key : string ;
90
166
label : string ;
91
167
body : React . ReactNode ;
92
168
} > = null ;
93
- ( [ 'x-custom-examples' , 'x-code-samples' , 'x-codeSamples' ] as const ) . forEach ( ( key ) => {
169
+
170
+ CUSTOM_CODE_SAMPLES_KEYS . forEach ( ( key ) => {
94
171
const customSamples = data . operation [ key ] ;
95
172
if ( customSamples && Array . isArray ( customSamples ) ) {
96
173
customCodeSamples = customSamples
@@ -102,7 +179,7 @@ export function OpenAPICodeSample(props: {
102
179
) ;
103
180
} )
104
181
. map ( ( sample , index ) => ( {
105
- key : `redocly -${ sample . lang } -${ index } ` ,
182
+ key : `custom-sample -${ sample . lang } -${ index } ` ,
106
183
label : sample . label ,
107
184
body : context . renderCodeBlock ( {
108
185
code : sample . source ,
@@ -113,47 +190,7 @@ export function OpenAPICodeSample(props: {
113
190
}
114
191
} ) ;
115
192
116
- // Code samples can be disabled at the top-level or at the operation level
117
- // If code samples are defined at the operation level, it will override the top-level setting
118
- const codeSamplesDisabled =
119
- data [ 'x-codeSamples' ] === false || data . operation [ 'x-codeSamples' ] === false ;
120
- const samples = customCodeSamples ?? ( ! codeSamplesDisabled ? autoCodeSamples : [ ] ) ;
121
-
122
- if ( samples . length === 0 ) {
123
- return null ;
124
- }
125
-
126
- return (
127
- < OpenAPITabs stateKey = { createStateKey ( 'codesample' ) } items = { samples } >
128
- < StaticSection header = { < OpenAPITabsList /> } className = "openapi-codesample" >
129
- < OpenAPITabsPanels />
130
- </ StaticSection >
131
- </ OpenAPITabs >
132
- ) ;
133
- }
134
-
135
- function OpenAPICodeSampleFooter ( props : {
136
- data : OpenAPIOperationData ;
137
- context : OpenAPIContextProps ;
138
- } ) {
139
- const { data, context } = props ;
140
- const { method, path } = data ;
141
- const { specUrl } = context ;
142
- const hideTryItPanel = data [ 'x-hideTryItPanel' ] || data . operation [ 'x-hideTryItPanel' ] ;
143
-
144
- if ( hideTryItPanel ) {
145
- return null ;
146
- }
147
-
148
- if ( ! validateHttpMethod ( method ) ) {
149
- return null ;
150
- }
151
-
152
- return (
153
- < div className = "openapi-codesample-footer" >
154
- < ScalarApiButton method = { method } path = { path } specUrl = { specUrl } />
155
- </ div >
156
- ) ;
193
+ return customCodeSamples ;
157
194
}
158
195
159
196
function getSecurityHeaders ( securities : OpenAPIOperationData [ 'securities' ] ) : {
0 commit comments