1
- import type { OpenAPIV3_1 } from '@gitbook/openapi-parser' ;
2
- import type React from 'react' ;
3
- import { ScalarApiButton } from './ScalarApiButton' ;
1
+ import { OpenAPICopyButton } from './OpenAPICopyButton' ;
4
2
import type { OpenAPIContextProps , OpenAPIOperationData } from './types' ;
3
+ import { getDefaultServerURL } from './util/server' ;
5
4
6
5
/**
7
6
* Display the path of an operation.
@@ -10,63 +9,62 @@ export function OpenAPIPath(props: {
10
9
data : OpenAPIOperationData ;
11
10
context : OpenAPIContextProps ;
12
11
} ) {
13
- const { data, context } = props ;
14
- const { method, path } = data ;
15
- const { specUrl } = context ;
16
- const hideTryItPanel = data [ 'x-hideTryItPanel' ] || data . operation [ 'x-hideTryItPanel' ] ;
12
+ const { data } = props ;
13
+ const { method, path, operation } = data ;
14
+
15
+ const server = getDefaultServerURL ( data . servers ) ;
16
+ const formattedPath = formatPath ( path ) ;
17
17
18
18
return (
19
19
< div className = "openapi-path" >
20
20
< div className = { `openapi-method openapi-method-${ method } ` } > { method } </ div >
21
- < div className = "openapi-path-title" data-deprecated = { data . operation . deprecated } >
22
- < p > { formatPath ( path ) } </ p >
23
- </ div >
24
- { ! hideTryItPanel && validateHttpMethod ( method ) && (
25
- < ScalarApiButton method = { method } path = { path } specUrl = { specUrl } />
26
- ) }
21
+
22
+ < OpenAPICopyButton
23
+ value = { server + path }
24
+ className = "openapi-path-title"
25
+ data-deprecated = { operation . deprecated }
26
+ >
27
+ < span className = "openapi-path-server" > { server } </ span >
28
+ { formattedPath }
29
+ </ OpenAPICopyButton >
27
30
</ div >
28
31
) ;
29
32
}
30
33
31
- function validateHttpMethod ( method : string ) : method is OpenAPIV3_1 . HttpMethods {
32
- return [ 'get' , 'post' , 'put' , 'delete' , 'patch' , 'head' , 'options' , 'trace' ] . includes ( method ) ;
33
- }
34
-
35
- // Format the path to highlight placeholders
34
+ /**
35
+ * Format the path by wrapping placeholders in <span> tags.
36
+ */
36
37
function formatPath ( path : string ) {
37
38
// Matches placeholders like {id}, {userId}, etc.
38
- const regex = / \{ ( \w + ) \} / g;
39
+ const regex = / \{ \s * ( \w + ) \s * \} | : \w + / g;
39
40
40
41
const parts : ( string | React . JSX . Element ) [ ] = [ ] ;
41
42
let lastIndex = 0 ;
42
43
43
- // Replace placeholders with <em> tags
44
- path . replace ( regex , ( match , key , offset ) => {
45
- parts . push ( path . slice ( lastIndex , offset ) ) ;
46
- parts . push ( < em key = { key } > { `{${ key } }` } </ em > ) ;
44
+ //Wrap the variables in <span> tags and maintain either {variable} or :variable
45
+ path . replace ( regex , ( match , _ , offset ) => {
46
+ if ( offset > lastIndex ) {
47
+ parts . push ( path . slice ( lastIndex , offset ) ) ;
48
+ }
49
+ parts . push (
50
+ < span key = { offset } className = "openapi-path-variable" >
51
+ { match }
52
+ </ span >
53
+ ) ;
47
54
lastIndex = offset + match . length ;
48
55
return match ;
49
56
} ) ;
50
57
51
- // Push remaining text after the last placeholder
52
- parts . push ( path . slice ( lastIndex ) ) ;
53
-
54
- // Join parts with separators wrapped in <span>
55
- const formattedPath = parts . reduce (
56
- ( acc , part , index ) => {
57
- if ( typeof part === 'string' && index > 0 && part === '/' ) {
58
- acc . push (
59
- < span className = "openapi-path-separator" key = { `sep-${ index } ` } >
60
- /
61
- </ span >
62
- ) ;
63
- }
58
+ if ( lastIndex < path . length ) {
59
+ parts . push ( path . slice ( lastIndex ) ) ;
60
+ }
64
61
65
- acc . push ( part ) ;
66
- return acc ;
67
- } ,
68
- [ ] as ( string | React . JSX . Element ) [ ]
69
- ) ;
62
+ const formattedPath = parts . map ( ( part , index ) => {
63
+ if ( typeof part === 'string' ) {
64
+ return < span key = { index } > { part } </ span > ;
65
+ }
66
+ return part ;
67
+ } ) ;
70
68
71
- return < span > { formattedPath } </ span > ;
69
+ return formattedPath ;
72
70
}
0 commit comments