docusaurus-theme-openapi-docs 1.5.1 → 1.6.0

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 (40) hide show
  1. package/lib/index.js +2 -11
  2. package/lib/markdown/utils.js +18 -1
  3. package/lib/theme/ApiDemoPanel/Curl/index.js +36 -9
  4. package/lib/theme/ApiDemoPanel/Curl/styles.module.css +5 -0
  5. package/lib/theme/ApiDemoPanel/Request/index.js +3 -2
  6. package/lib/theme/ApiDemoPanel/SecuritySchemes/index.js +195 -9
  7. package/lib/theme/ApiLogo/index.js +24 -1
  8. package/lib/theme/ParamsItem/index.js +33 -6
  9. package/lib/theme/SchemaItem/index.js +26 -12
  10. package/lib/theme/SchemaItem/styles.module.css +5 -0
  11. package/lib/theme/SchemaTabs/index.js +2 -2
  12. package/lib/theme/SchemaTabs/styles.module.css +5 -0
  13. package/lib/theme/styles.css +57 -2
  14. package/lib-next/index.js +2 -13
  15. package/lib-next/markdown/utils.js +17 -1
  16. package/lib-next/theme/ApiDemoPanel/Curl/index.js +37 -8
  17. package/lib-next/theme/ApiDemoPanel/Curl/styles.module.css +5 -0
  18. package/lib-next/theme/ApiDemoPanel/Request/index.js +4 -2
  19. package/lib-next/theme/ApiDemoPanel/SecuritySchemes/index.js +210 -9
  20. package/lib-next/theme/ApiLogo/index.js +35 -9
  21. package/lib-next/theme/ParamsItem/index.js +33 -6
  22. package/lib-next/theme/SchemaItem/index.js +26 -12
  23. package/lib-next/theme/SchemaItem/styles.module.css +5 -0
  24. package/lib-next/theme/SchemaTabs/index.js +2 -2
  25. package/lib-next/theme/SchemaTabs/styles.module.css +5 -0
  26. package/lib-next/theme/styles.css +57 -2
  27. package/package.json +8 -7
  28. package/src/index.ts +3 -13
  29. package/src/markdown/utils.ts +18 -1
  30. package/src/theme/ApiDemoPanel/Curl/index.tsx +36 -8
  31. package/src/theme/ApiDemoPanel/Curl/styles.module.css +5 -0
  32. package/src/theme/ApiDemoPanel/Request/index.tsx +4 -2
  33. package/src/theme/ApiDemoPanel/SecuritySchemes/index.tsx +213 -9
  34. package/src/theme/ApiLogo/index.tsx +37 -10
  35. package/src/theme/ParamsItem/index.js +33 -6
  36. package/src/theme/SchemaItem/index.js +26 -12
  37. package/src/theme/SchemaItem/styles.module.css +5 -0
  38. package/src/theme/SchemaTabs/index.js +2 -2
  39. package/src/theme/SchemaTabs/styles.module.css +5 -0
  40. package/src/theme/styles.css +57 -2
@@ -8,6 +8,8 @@
8
8
  import React from "react";
9
9
 
10
10
  import CodeBlock from "@theme/CodeBlock";
11
+ import SchemaTabs from "@theme/SchemaTabs";
12
+ import TabItem from "@theme/TabItem";
11
13
  /* eslint-disable import/no-extraneous-dependencies*/
12
14
  import { createDescription } from "docusaurus-theme-openapi-docs/lib/markdown/createDescription";
13
15
  /* eslint-disable import/no-extraneous-dependencies*/
@@ -16,7 +18,10 @@ import {
16
18
  getSchemaName,
17
19
  } from "docusaurus-theme-openapi-docs/lib/markdown/schema";
18
20
  /* eslint-disable import/no-extraneous-dependencies*/
19
- import { guard } from "docusaurus-theme-openapi-docs/lib/markdown/utils";
21
+ import {
22
+ guard,
23
+ toString,
24
+ } from "docusaurus-theme-openapi-docs/lib/markdown/utils";
20
25
  import ReactMarkdown from "react-markdown";
21
26
  import rehypeRaw from "rehype-raw";
22
27
 
@@ -25,6 +30,10 @@ import styles from "./styles.module.css";
25
30
  function ParamsItem({
26
31
  param: { description, example, examples, name, required, schema },
27
32
  }) {
33
+ if (!schema || !schema?.type) {
34
+ schema = { type: "any" };
35
+ }
36
+
28
37
  const renderSchemaName = guard(schema, (schema) => (
29
38
  <span className={styles.schemaName}> {getSchemaName(schema)}</span>
30
39
  ));
@@ -76,17 +85,35 @@ function ParamsItem({
76
85
  )
77
86
  );
78
87
 
79
- const renderExample = guard(example, (example) => (
80
- <div>{`Example: ${example}`}</div>
88
+ const renderExample = guard(toString(example), (example) => (
89
+ <div>
90
+ <strong>Example: </strong>
91
+ {example}
92
+ </div>
81
93
  ));
82
94
 
83
95
  const renderExamples = guard(examples, (examples) => {
84
96
  const exampleEntries = Object.entries(examples);
85
97
  return (
86
98
  <>
87
- {exampleEntries.map(([k, v]) => (
88
- <div>{`Example (${k}): ${v.value}`}</div>
89
- ))}
99
+ <strong>Examples:</strong>
100
+ <SchemaTabs>
101
+ {exampleEntries.map(([exampleName, exampleProperties]) => (
102
+ <TabItem value={exampleName} label={exampleName}>
103
+ {exampleProperties.summary && <p>{exampleProperties.summary}</p>}
104
+ {exampleProperties.description && (
105
+ <p>
106
+ <strong>Description: </strong>
107
+ <span>{exampleProperties.description}</span>
108
+ </p>
109
+ )}
110
+ <p>
111
+ <strong>Example: </strong>
112
+ <code>{exampleProperties.value}</code>
113
+ </p>
114
+ </TabItem>
115
+ ))}
116
+ </SchemaTabs>
90
117
  </>
91
118
  );
92
119
  });
@@ -11,7 +11,10 @@ import CodeBlock from "@theme/CodeBlock";
11
11
  /* eslint-disable import/no-extraneous-dependencies*/
12
12
  import { createDescription } from "docusaurus-theme-openapi-docs/lib/markdown/createDescription";
13
13
  /* eslint-disable import/no-extraneous-dependencies*/
14
- import { guard } from "docusaurus-theme-openapi-docs/lib/markdown/utils";
14
+ import {
15
+ guard,
16
+ toString,
17
+ } from "docusaurus-theme-openapi-docs/lib/markdown/utils";
15
18
  import ReactMarkdown from "react-markdown";
16
19
  import rehypeRaw from "rehype-raw";
17
20
 
@@ -23,11 +26,20 @@ function SchemaItem({
23
26
  name,
24
27
  qualifierMessage,
25
28
  required,
26
- deprecated,
27
- schemaDescription,
28
29
  schemaName,
29
- defaultValue,
30
+ schema,
30
31
  }) {
32
+ let deprecated;
33
+ let schemaDescription;
34
+ let defaultValue;
35
+ let nullable;
36
+ if (schema) {
37
+ deprecated = schema.deprecated;
38
+ schemaDescription = schema.description;
39
+ defaultValue = schema.default;
40
+ nullable = schema.nullable;
41
+ }
42
+
31
43
  const renderRequired = guard(
32
44
  Array.isArray(required) ? required.includes(name) : required,
33
45
  () => <strong className={styles.required}> required</strong>
@@ -37,6 +49,10 @@ function SchemaItem({
37
49
  <strong className={styles.deprecated}> deprecated</strong>
38
50
  ));
39
51
 
52
+ const renderNullable = guard(nullable, () => (
53
+ <strong className={styles.nullable}> nullable</strong>
54
+ ));
55
+
40
56
  const renderSchemaDescription = guard(schemaDescription, (description) => (
41
57
  <div>
42
58
  <ReactMarkdown
@@ -67,19 +83,17 @@ function SchemaItem({
67
83
  </div>
68
84
  ));
69
85
 
70
- const renderDefaultValue = guard(
71
- typeof defaultValue === "boolean" ? defaultValue.toString() : defaultValue,
72
- (value) => (
73
- <div className={styles.schemaQualifierMessage}>
74
- <ReactMarkdown children={`**Default value:** \`${value}\``} />
75
- </div>
76
- )
77
- );
86
+ const renderDefaultValue = guard(toString(defaultValue), (value) => (
87
+ <div className={styles.schemaQualifierMessage}>
88
+ <ReactMarkdown children={`**Default value:** \`${value}\``} />
89
+ </div>
90
+ ));
78
91
 
79
92
  const schemaContent = (
80
93
  <div>
81
94
  <strong className={deprecated && styles.strikethrough}>{name}</strong>
82
95
  <span className={styles.schemaName}> {schemaName}</span>
96
+ {renderNullable}
83
97
  {!deprecated && renderRequired}
84
98
  {renderDeprecated}
85
99
  {renderQualifierMessage}
@@ -28,6 +28,11 @@
28
28
  color: var(--openapi-deprecated);
29
29
  }
30
30
 
31
+ .nullable {
32
+ font-size: var(--ifm-code-font-size);
33
+ color: var(--openapi-nullable);
34
+ }
35
+
31
36
  .strikethrough {
32
37
  text-decoration: line-through;
33
38
  }
@@ -241,11 +241,11 @@ function SchemaTabsComponent(props) {
241
241
  (tabItem) => tabItem.props.value === defaultValue
242
242
  )[0],
243
243
  {
244
- className: "margin-vert--md",
244
+ className: styles.marginVertical,
245
245
  }
246
246
  )
247
247
  ) : (
248
- <div className="margin-vert--md">
248
+ <div className={styles.marginVertical}>
249
249
  {children.map((tabItem, i) =>
250
250
  cloneElement(tabItem, {
251
251
  key: i,
@@ -103,3 +103,8 @@
103
103
  width: 100%;
104
104
  }
105
105
  }
106
+
107
+ .marginVertical {
108
+ margin-top: 1rem !important;
109
+ margin-bottom: unset !important;
110
+ }
@@ -8,6 +8,7 @@
8
8
  :root {
9
9
  --openapi-required: var(--ifm-color-danger);
10
10
  --openapi-deprecated: var(--ifm-color-warning);
11
+ --openapi-nullable: var(--ifm-color-info);
11
12
  --openapi-code-blue: var(--ifm-color-info);
12
13
  --openapi-code-red: var(--ifm-color-danger);
13
14
  --openapi-code-orange: var(--ifm-color-warning);
@@ -77,10 +78,14 @@
77
78
 
78
79
  .theme-api-markdown details li {
79
80
  list-style: none;
80
- padding-bottom: 5px;
81
81
  padding-top: 5px;
82
82
  }
83
83
 
84
+ .theme-api-markdown .tabs__item {
85
+ padding-bottom: unset;
86
+ padding-top: unset;
87
+ }
88
+
84
89
  .theme-api-markdown details > div > div {
85
90
  padding-top: unset !important;
86
91
  border-top: unset !important;
@@ -244,6 +249,8 @@
244
249
  color: var(--ifm-color-success);
245
250
  padding-left: 1.4rem;
246
251
  padding-right: 1.4rem;
252
+ padding-top: 1rem !important;
253
+ padding-bottom: 1rem !important;
247
254
  }
248
255
 
249
256
  .code__tab--python.tabs__item--active {
@@ -268,6 +275,8 @@
268
275
  color: var(--ifm-color-info);
269
276
  padding-left: 1.4rem;
270
277
  padding-right: 1.4rem;
278
+ padding-top: 1rem !important;
279
+ padding-bottom: 1rem !important;
271
280
  }
272
281
 
273
282
  .code__tab--go.tabs__item--active {
@@ -292,6 +301,8 @@
292
301
  color: var(--ifm-color-warning);
293
302
  padding-left: 1.4rem;
294
303
  padding-right: 1.4rem;
304
+ padding-top: 1rem !important;
305
+ padding-bottom: 1rem !important;
295
306
  }
296
307
 
297
308
  .code__tab--javascript.tabs__item--active {
@@ -316,6 +327,8 @@
316
327
  color: var(--ifm-color-danger);
317
328
  padding-left: 1.4rem;
318
329
  padding-right: 1.4rem;
330
+ padding-top: 1rem !important;
331
+ padding-bottom: 1rem !important;
319
332
  }
320
333
 
321
334
  .code__tab--bash.tabs__item--active {
@@ -340,6 +353,8 @@
340
353
  color: var(--ifm-color-danger);
341
354
  padding-left: 1.4rem;
342
355
  padding-right: 1.4rem;
356
+ padding-top: 1rem !important;
357
+ padding-bottom: 1rem !important;
343
358
  }
344
359
 
345
360
  .code__tab--ruby.tabs__item--active {
@@ -364,6 +379,8 @@
364
379
  color: var(--ifm-color-gray-500);
365
380
  padding-left: 1.4rem;
366
381
  padding-right: 1.4rem;
382
+ padding-top: 1rem !important;
383
+ padding-bottom: 1rem !important;
367
384
  }
368
385
 
369
386
  .code__tab--csharp.tabs__item--active {
@@ -388,6 +405,8 @@
388
405
  color: var(--ifm-color-success);
389
406
  padding-left: 1.4rem;
390
407
  padding-right: 1.4rem;
408
+ padding-top: 1rem !important;
409
+ padding-bottom: 1rem !important;
391
410
  }
392
411
 
393
412
  .code__tab--nodejs.tabs__item--active {
@@ -412,6 +431,8 @@
412
431
  color: var(--ifm-color-gray-500);
413
432
  padding-left: 1.4rem;
414
433
  padding-right: 1.4rem;
434
+ padding-top: 1rem !important;
435
+ padding-bottom: 1rem !important;
415
436
  }
416
437
 
417
438
  .code__tab--php.tabs__item--active {
@@ -424,7 +445,41 @@
424
445
  overflow: auto;
425
446
  }
426
447
 
448
+ .code__tab--java::after {
449
+ content: "";
450
+ width: 28px;
451
+ height: 28px;
452
+ background: url("https://raw.githubusercontent.com/devicons/devicon/master/icons/java/java-original.svg");
453
+ margin-block: auto;
454
+ }
455
+
456
+ .code__tab--java {
457
+ color: var(--ifm-color-warning);
458
+ padding-left: 1.4rem;
459
+ padding-right: 1.4rem;
460
+ padding-top: 1rem !important;
461
+ padding-bottom: 1rem !important;
462
+ }
463
+
464
+ .code__tab--java.tabs__item--active {
465
+ border-bottom-color: var(--ifm-color-warning);
466
+ background-color: var(--ifm-color-emphasis-100);
467
+ }
468
+
469
+ .language-java {
470
+ max-height: 500px;
471
+ overflow: auto;
472
+ }
473
+
427
474
  /* Prism code styles */
428
- .prism-code.language-json {
475
+ .prism-code.language-java {
429
476
  white-space: pre !important;
430
477
  }
478
+
479
+ .openapi__logo {
480
+ width: 250px;
481
+ }
482
+
483
+ div:has(> ul.openapi-tabs__security-schemes) {
484
+ max-width: 100%;
485
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "docusaurus-theme-openapi-docs",
3
3
  "description": "OpenAPI theme for Docusaurus.",
4
- "version": "1.5.1",
4
+ "version": "1.6.0",
5
5
  "license": "MIT",
6
6
  "keywords": [
7
7
  "openapi",
@@ -31,8 +31,8 @@
31
31
  "format:lib-next": "prettier --config ../../.prettierrc.json --write \"lib-next/**/*.{js,ts,jsx,tsc}\""
32
32
  },
33
33
  "devDependencies": {
34
- "@docusaurus/module-type-aliases": "^2.0.1",
35
- "@docusaurus/types": "^2.0.1",
34
+ "@docusaurus/module-type-aliases": ">=2.0.1 <2.3.0",
35
+ "@docusaurus/types": ">=2.0.1 <2.3.0",
36
36
  "@types/concurrently": "^6.3.0",
37
37
  "@types/crypto-js": "^4.1.0",
38
38
  "@types/file-saver": "^2.0.5",
@@ -43,18 +43,19 @@
43
43
  "concurrently": "^5.2.0"
44
44
  },
45
45
  "dependencies": {
46
- "@docusaurus/theme-common": "^2.0.1",
46
+ "@docusaurus/theme-common": ">=2.0.1 <2.3.0",
47
47
  "@mdx-js/react": "^1.6.21",
48
- "@paloaltonetworks/postman-code-generators": "^1.1.12",
48
+ "@paloaltonetworks/postman-code-generators": "^1.1.15",
49
49
  "@paloaltonetworks/postman-collection": "^4.1.0",
50
50
  "@reduxjs/toolkit": "^1.7.1",
51
51
  "buffer": "^6.0.3",
52
52
  "clsx": "^1.1.1",
53
53
  "crypto-js": "^4.1.1",
54
- "docusaurus-plugin-openapi-docs": "^1.5.1",
54
+ "docusaurus-plugin-openapi-docs": "^1.6.0",
55
55
  "file-saver": "^2.0.5",
56
56
  "immer": "^9.0.7",
57
57
  "lodash": "^4.17.20",
58
+ "node-polyfill-webpack-plugin": "^2.0.1",
58
59
  "process": "^0.11.10",
59
60
  "react-live": "^3.1.1",
60
61
  "react-magic-dropzone": "^1.0.1",
@@ -73,5 +74,5 @@
73
74
  "engines": {
74
75
  "node": ">=14"
75
76
  },
76
- "gitHead": "11d2c2fdb2bc81048097b05bc65698777d54e456"
77
+ "gitHead": "937e6543af8c1575877a0ebe7c5732e5cffaa37d"
77
78
  }
package/src/index.ts CHANGED
@@ -8,7 +8,8 @@
8
8
  import path from "path";
9
9
 
10
10
  import type { Plugin } from "@docusaurus/types";
11
- import { ProvidePlugin } from "webpack";
11
+
12
+ const NodePolyfillPlugin = require("node-polyfill-webpack-plugin");
12
13
 
13
14
  export default function docusaurusThemeOpenAPI(): Plugin<void> {
14
15
  return {
@@ -29,18 +30,7 @@ export default function docusaurusThemeOpenAPI(): Plugin<void> {
29
30
 
30
31
  configureWebpack() {
31
32
  return {
32
- plugins: [
33
- new ProvidePlugin({
34
- Buffer: [require.resolve("buffer/"), "Buffer"],
35
- process: require.resolve("process/browser"),
36
- }),
37
- ],
38
- resolve: {
39
- fallback: {
40
- buffer: require.resolve("buffer/"),
41
- process: require.resolve("process/browser"),
42
- },
43
- },
33
+ plugins: [new NodePolyfillPlugin()],
44
34
  };
45
35
  },
46
36
  };
@@ -24,7 +24,7 @@ export function guard<T>(
24
24
  value: T | undefined | string,
25
25
  cb: (value: T) => Children
26
26
  ): string {
27
- if (value) {
27
+ if (value !== undefined) {
28
28
  const children = cb(value as T);
29
29
  return render(children);
30
30
  }
@@ -37,3 +37,20 @@ export function render(children: Children): string {
37
37
  }
38
38
  return children ?? "";
39
39
  }
40
+
41
+ export function toString(value: any): string | undefined {
42
+ // Return as-is if already string
43
+ if (typeof value === "string") {
44
+ return value;
45
+ }
46
+ // Return undefined if null or undefined
47
+ if (value == null) {
48
+ return undefined;
49
+ }
50
+ // Return formatted array if Array
51
+ if (Array.isArray(value)) {
52
+ return `[${value.join(", ")}]`;
53
+ }
54
+ // Coerce to string in all other cases,
55
+ return value + "";
56
+ }
@@ -15,6 +15,7 @@ import CodeTabs from "@theme/ApiDemoPanel/CodeTabs";
15
15
  import { useTypedSelector } from "@theme/ApiItem/hooks";
16
16
  import CodeBlock from "@theme/CodeBlock";
17
17
  import clsx from "clsx";
18
+ import merge from "lodash/merge";
18
19
 
19
20
  import styles from "./styles.module.css";
20
21
 
@@ -100,6 +101,16 @@ export const languageSet: Language[] = [
100
101
  },
101
102
  variant: "cURL",
102
103
  },
104
+ {
105
+ highlight: "java",
106
+ language: "java",
107
+ logoClass: "java",
108
+ options: {
109
+ followRedirect: true,
110
+ trimRequestBody: true,
111
+ },
112
+ variant: "OkHttp",
113
+ },
103
114
  ];
104
115
 
105
116
  export interface Props {
@@ -136,23 +147,37 @@ function Curl({ postman, codeSamples }: Props) {
136
147
 
137
148
  const auth = useTypedSelector((state: any) => state.auth);
138
149
 
139
- // TODO
150
+ // User-defined languages array
151
+ // Can override languageSet, change order of langs, override options and variants
140
152
  const langs = [
141
153
  ...((siteConfig?.themeConfig?.languageTabs as Language[] | undefined) ??
142
154
  languageSet),
143
155
  ...codeSamples,
144
156
  ];
145
157
 
146
- const defaultLang: Language[] = languageSet.filter(
158
+ // Filter languageSet by user-defined langs
159
+ const filteredLanguageSet = languageSet.filter((ls) => {
160
+ return langs.some((lang) => {
161
+ return lang.language === ls.language;
162
+ });
163
+ });
164
+
165
+ // Merge user-defined langs into languageSet
166
+ const mergedLangs = merge(filteredLanguageSet, langs);
167
+
168
+ // Read defaultLang from localStorage
169
+ const defaultLang: Language[] = mergedLangs.filter(
147
170
  (lang) =>
148
171
  lang.language === localStorage.getItem("docusaurus.tab.code-samples")
149
172
  );
150
173
 
151
174
  const [language, setLanguage] = useState(() => {
152
- if (langs.length === 1) {
153
- return langs[0];
175
+ // Return first index if only 1 user-defined language exists
176
+ if (mergedLangs.length === 1) {
177
+ return mergedLangs[0];
154
178
  }
155
- return defaultLang[0] ?? langs[0];
179
+ // Fall back to language in localStorage or first user-defined language
180
+ return defaultLang[0] ?? mergedLangs[0];
156
181
  });
157
182
 
158
183
  const [codeText, setCodeText] = useState("");
@@ -186,7 +211,7 @@ function Curl({ postman, codeSamples }: Props) {
186
211
  } else if (language && !!language.source) {
187
212
  setCodeText(language.source);
188
213
  } else if (language && !language.options) {
189
- const langSource = languageSet.filter(
214
+ const langSource = mergedLangs.filter(
190
215
  (lang) => lang.language === language.language
191
216
  );
192
217
 
@@ -233,6 +258,7 @@ function Curl({ postman, codeSamples }: Props) {
233
258
  queryParams,
234
259
  server,
235
260
  auth,
261
+ mergedLangs,
236
262
  ]);
237
263
 
238
264
  if (language === undefined) {
@@ -242,7 +268,7 @@ function Curl({ postman, codeSamples }: Props) {
242
268
  return (
243
269
  <>
244
270
  <CodeTabs groupId="code-samples" action={setLanguage}>
245
- {langs.map((lang) => {
271
+ {mergedLangs.map((lang) => {
246
272
  return (
247
273
  <CodeTab
248
274
  value={lang.language}
@@ -254,7 +280,9 @@ function Curl({ postman, codeSamples }: Props) {
254
280
  }
255
281
  attributes={{ className: `code__tab--${lang.logoClass}` }}
256
282
  >
257
- <CodeBlock language={lang.highlight}>{codeText}</CodeBlock>
283
+ <CodeBlock language={lang.highlight} className={styles.codeBlock}>
284
+ {codeText}
285
+ </CodeBlock>
258
286
  </CodeTab>
259
287
  );
260
288
  })}
@@ -82,3 +82,8 @@
82
82
  background: var(--ifm-menu-color-background-active);
83
83
  color: var(--ifm-menu-color-active);
84
84
  }
85
+
86
+ .codeBlock code {
87
+ max-width: revert;
88
+ max-height: revert;
89
+ }
@@ -25,7 +25,7 @@ function Request({ item }: { item: NonNullable<ApiItem> }) {
25
25
  const response = useTypedSelector((state: any) => state.response.value);
26
26
  const postman = new sdk.Request(item.postman);
27
27
  const metadata = useDoc();
28
- const { proxy } = metadata.frontMatter;
28
+ const { proxy, hide_send_button } = metadata.frontMatter;
29
29
 
30
30
  const params = {
31
31
  path: [] as ParameterObject[],
@@ -48,7 +48,9 @@ function Request({ item }: { item: NonNullable<ApiItem> }) {
48
48
  <summary>
49
49
  <div className={`details__request-summary`}>
50
50
  <h4>Request</h4>
51
- {item.servers && <Execute postman={postman} proxy={proxy} />}
51
+ {item.servers && !hide_send_button && (
52
+ <Execute postman={postman} proxy={proxy} />
53
+ )}
52
54
  </div>
53
55
  </summary>
54
56
  <div className={styles.optionsPanel}>