docusaurus-theme-openapi-docs 3.0.0-beta.3 → 3.0.0-beta.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.
Files changed (115) hide show
  1. package/lib/markdown/utils.d.ts +2 -1
  2. package/lib/theme/ApiDemoPanel/ApiCodeBlock/ExpandButton/index.d.ts +13 -0
  3. package/lib/theme/ApiDemoPanel/ApiCodeBlock/ExpandButton/index.js +199 -124
  4. package/lib/theme/ApiExplorer/Accept/index.d.ts +2 -2
  5. package/lib/theme/ApiExplorer/ApiCodeBlock/Container/index.d.ts +4 -0
  6. package/lib/theme/ApiExplorer/ApiCodeBlock/Container/index.js +25 -19
  7. package/lib/theme/ApiExplorer/ApiCodeBlock/Content/Element.d.ts +4 -0
  8. package/lib/theme/ApiExplorer/ApiCodeBlock/Content/Element.js +27 -16
  9. package/lib/theme/ApiExplorer/ApiCodeBlock/Content/String.d.ts +4 -0
  10. package/lib/theme/ApiExplorer/ApiCodeBlock/Content/String.js +115 -96
  11. package/lib/theme/ApiExplorer/ApiCodeBlock/CopyButton/index.d.ts +3 -0
  12. package/lib/theme/ApiExplorer/ApiCodeBlock/CopyButton/index.js +115 -54
  13. package/lib/theme/ApiExplorer/ApiCodeBlock/ExitButton/index.d.ts +6 -0
  14. package/lib/theme/ApiExplorer/ApiCodeBlock/ExitButton/index.js +41 -30
  15. package/lib/theme/ApiExplorer/ApiCodeBlock/ExpandButton/index.d.ts +14 -0
  16. package/lib/theme/ApiExplorer/ApiCodeBlock/ExpandButton/index.js +200 -120
  17. package/lib/theme/ApiExplorer/ApiCodeBlock/Line/index.d.ts +3 -0
  18. package/lib/theme/ApiExplorer/ApiCodeBlock/Line/index.js +36 -24
  19. package/lib/theme/ApiExplorer/ApiCodeBlock/WordWrapButton/index.d.ts +7 -0
  20. package/lib/theme/ApiExplorer/ApiCodeBlock/WordWrapButton/index.js +35 -28
  21. package/lib/theme/ApiExplorer/ApiCodeBlock/index.d.ts +3 -0
  22. package/lib/theme/ApiExplorer/ApiCodeBlock/index.js +72 -14
  23. package/lib/theme/ApiExplorer/Authorization/index.d.ts +2 -2
  24. package/lib/theme/ApiExplorer/Body/index.d.ts +2 -2
  25. package/lib/theme/ApiExplorer/Body/index.js +8 -1
  26. package/lib/theme/ApiExplorer/CodeSnippets/code-snippets-types.d.ts +21 -0
  27. package/lib/theme/ApiExplorer/CodeSnippets/code-snippets-types.js +8 -0
  28. package/lib/theme/ApiExplorer/CodeSnippets/index.d.ts +4 -14
  29. package/lib/theme/ApiExplorer/CodeSnippets/index.js +87 -8
  30. package/lib/theme/ApiExplorer/CodeSnippets/languages.d.ts +2 -0
  31. package/lib/theme/ApiExplorer/CodeSnippets/languages.js +32 -0
  32. package/lib/theme/ApiExplorer/CodeSnippets/languages.json +0 -96
  33. package/lib/theme/ApiExplorer/CodeTabs/_CodeTabs.scss +14 -0
  34. package/lib/theme/ApiExplorer/CodeTabs/index.d.ts +14 -0
  35. package/lib/theme/ApiExplorer/CodeTabs/index.js +130 -78
  36. package/lib/theme/ApiExplorer/ContentType/index.d.ts +2 -2
  37. package/lib/theme/ApiExplorer/Export/index.d.ts +2 -2
  38. package/lib/theme/ApiExplorer/FloatingButton/index.d.ts +1 -1
  39. package/lib/theme/ApiExplorer/FormFileUpload/index.d.ts +2 -2
  40. package/lib/theme/ApiExplorer/FormItem/index.d.ts +1 -1
  41. package/lib/theme/ApiExplorer/FormMultiSelect/index.d.ts +1 -1
  42. package/lib/theme/ApiExplorer/FormSelect/index.d.ts +1 -1
  43. package/lib/theme/ApiExplorer/FormTextInput/index.d.ts +1 -1
  44. package/lib/theme/ApiExplorer/MethodEndpoint/index.d.ts +2 -2
  45. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.d.ts +2 -2
  46. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.d.ts +2 -2
  47. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.d.ts +2 -2
  48. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.d.ts +2 -2
  49. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.d.ts +2 -2
  50. package/lib/theme/ApiExplorer/ParamOptions/index.d.ts +2 -2
  51. package/lib/theme/ApiExplorer/Request/index.d.ts +2 -2
  52. package/lib/theme/ApiExplorer/Response/index.d.ts +2 -2
  53. package/lib/theme/ApiExplorer/SecuritySchemes/index.d.ts +2 -2
  54. package/lib/theme/ApiExplorer/Server/index.d.ts +2 -2
  55. package/lib/theme/ApiExplorer/index.d.ts +2 -2
  56. package/lib/theme/ApiExplorer/index.js +1 -1
  57. package/lib/theme/ApiItem/index.d.ts +2 -2
  58. package/lib/theme/ApiItem/index.js +4 -3
  59. package/lib/theme/ApiItem/store.d.ts +4 -4
  60. package/lib/theme/ApiLogo/index.d.ts +2 -2
  61. package/lib/theme/ApiTabs/index.d.ts +7 -0
  62. package/lib/theme/ApiTabs/index.js +155 -97
  63. package/lib/theme/DiscriminatorTabs/index.d.ts +3 -0
  64. package/lib/theme/DiscriminatorTabs/index.js +146 -94
  65. package/lib/theme/Markdown/index.js +37 -0
  66. package/lib/theme/MimeTabs/index.d.ts +6 -0
  67. package/lib/theme/MimeTabs/index.js +163 -114
  68. package/lib/theme/OperationTabs/_OperationTabs.scss +68 -0
  69. package/lib/theme/OperationTabs/index.d.ts +3 -0
  70. package/lib/theme/OperationTabs/index.js +232 -0
  71. package/lib/theme/ParamsItem/index.d.ts +22 -0
  72. package/lib/theme/ParamsItem/index.js +154 -109
  73. package/lib/theme/ResponseSamples/index.d.ts +8 -0
  74. package/lib/theme/ResponseSamples/index.js +18 -13
  75. package/lib/theme/SchemaItem/index.d.ts +12 -0
  76. package/lib/theme/SchemaItem/index.js +123 -89
  77. package/lib/theme/SchemaTabs/index.d.ts +3 -0
  78. package/lib/theme/SchemaTabs/index.js +142 -91
  79. package/lib/theme/styles.scss +1 -0
  80. package/package.json +4 -4
  81. package/src/markdown/utils.ts +4 -2
  82. package/src/theme/ApiDemoPanel/ApiCodeBlock/ExpandButton/{index.js → index.tsx} +21 -8
  83. package/src/theme/ApiExplorer/ApiCodeBlock/Container/{index.js → index.tsx} +6 -3
  84. package/src/theme/ApiExplorer/ApiCodeBlock/Content/{Element.js → Element.tsx} +5 -1
  85. package/src/theme/ApiExplorer/ApiCodeBlock/Content/{String.js → String.tsx} +4 -4
  86. package/src/theme/ApiExplorer/ApiCodeBlock/CopyButton/{index.js → index.tsx} +8 -3
  87. package/src/theme/ApiExplorer/ApiCodeBlock/ExitButton/{index.js → index.tsx} +9 -1
  88. package/src/theme/ApiExplorer/ApiCodeBlock/ExpandButton/{index.js → index.tsx} +12 -2
  89. package/src/theme/ApiExplorer/ApiCodeBlock/Line/{index.js → index.tsx} +2 -1
  90. package/src/theme/ApiExplorer/ApiCodeBlock/WordWrapButton/{index.js → index.tsx} +11 -1
  91. package/src/theme/ApiExplorer/ApiCodeBlock/{index.js → index.tsx} +10 -5
  92. package/src/theme/ApiExplorer/Body/index.tsx +3 -1
  93. package/src/theme/ApiExplorer/CodeSnippets/code-snippets-types.ts +55 -0
  94. package/src/theme/ApiExplorer/CodeSnippets/index.tsx +94 -21
  95. package/src/theme/ApiExplorer/CodeSnippets/languages.json +0 -96
  96. package/src/theme/ApiExplorer/CodeSnippets/languages.ts +37 -0
  97. package/src/theme/ApiExplorer/CodeTabs/_CodeTabs.scss +14 -0
  98. package/src/theme/ApiExplorer/CodeTabs/{index.js → index.tsx} +57 -25
  99. package/src/theme/ApiExplorer/index.tsx +1 -1
  100. package/src/theme/ApiItem/index.tsx +3 -4
  101. package/src/theme/ApiLogo/index.tsx +1 -1
  102. package/src/theme/ApiTabs/{index.js → index.tsx} +63 -25
  103. package/src/theme/DiscriminatorTabs/{index.js → index.tsx} +57 -24
  104. package/src/theme/Markdown/index.js +37 -0
  105. package/src/theme/MimeTabs/{index.js → index.tsx} +58 -26
  106. package/src/theme/OperationTabs/_OperationTabs.scss +68 -0
  107. package/src/theme/OperationTabs/index.tsx +216 -0
  108. package/src/theme/ParamsItem/{index.js → index.tsx} +28 -13
  109. package/src/theme/ResponseSamples/{index.js → index.tsx} +10 -1
  110. package/src/theme/SchemaItem/{index.js → index.tsx} +18 -9
  111. package/src/theme/SchemaTabs/{index.js → index.tsx} +56 -25
  112. package/src/theme/styles.scss +1 -0
  113. package/src/theme-classic.d.ts +69 -2
  114. package/src/theme-openapi.d.ts +4 -0
  115. package/tsconfig.json +4 -1
@@ -14,6 +14,7 @@ import FormSelect from "@theme/ApiExplorer/FormSelect";
14
14
  import FormTextInput from "@theme/ApiExplorer/FormTextInput";
15
15
  import LiveApp from "@theme/ApiExplorer/LiveEditor";
16
16
  import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
17
+ import Markdown from "@theme/Markdown";
17
18
  import SchemaTabs from "@theme/SchemaTabs";
18
19
  import TabItem from "@theme/TabItem";
19
20
  import { RequestBodyObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
@@ -303,6 +304,7 @@ function Body({
303
304
  </TabItem>
304
305
  {/* @ts-ignore */}
305
306
  <TabItem label="Example" value="example">
307
+ {example.summary && <Markdown children={example.summary} />}
306
308
  {exampleBody && (
307
309
  <LiveApp
308
310
  action={dispatch}
@@ -340,7 +342,7 @@ function Body({
340
342
  value={example.label}
341
343
  key={example.label}
342
344
  >
343
- {example.summary && <p>{example.summary}</p>}
345
+ {example.summary && <Markdown children={example.summary} />}
344
346
  {example.body && (
345
347
  <LiveApp action={dispatch} language={language}>
346
348
  {example.body}
@@ -0,0 +1,55 @@
1
+ /* ============================================================================
2
+ * Copyright (c) Palo Alto Networks
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ * ========================================================================== */
7
+
8
+ // https://github.com/github-linguist/linguist/blob/master/lib/linguist/popular.yml
9
+ export type CodeSampleLanguage =
10
+ | "C"
11
+ | "C#"
12
+ | "C++"
13
+ | "CoffeeScript"
14
+ | "CSS"
15
+ | "Dart"
16
+ | "DM"
17
+ | "Elixir"
18
+ | "Go"
19
+ | "Groovy"
20
+ | "HTML"
21
+ | "Java"
22
+ | "JavaScript"
23
+ | "Kotlin"
24
+ | "Objective-C"
25
+ | "Perl"
26
+ | "PHP"
27
+ | "PowerShell"
28
+ | "Python"
29
+ | "Ruby"
30
+ | "Rust"
31
+ | "Scala"
32
+ | "Shell"
33
+ | "Swift"
34
+ | "TypeScript";
35
+
36
+ export interface Language {
37
+ highlight: string;
38
+ language: string;
39
+ codeSampleLanguage: CodeSampleLanguage;
40
+ logoClass: string;
41
+ variant: string;
42
+ variants: string[];
43
+ options?: { [key: string]: boolean };
44
+ sample?: string;
45
+ samples?: string[];
46
+ samplesSources?: string[];
47
+ samplesLabels?: string[];
48
+ }
49
+
50
+ // https://redocly.com/docs/api-reference-docs/specification-extensions/x-code-samples
51
+ export interface CodeSample {
52
+ source: string;
53
+ lang: CodeSampleLanguage;
54
+ label?: string;
55
+ }
@@ -16,20 +16,14 @@ import CodeTabs from "@theme/ApiExplorer/CodeTabs";
16
16
  import { useTypedSelector } from "@theme/ApiItem/hooks";
17
17
  import merge from "lodash/merge";
18
18
 
19
- export interface Language {
20
- highlight: string;
21
- language: string;
22
- logoClass: string;
23
- variant: string;
24
- variants: string[];
25
- options: { [key: string]: boolean };
26
- source?: string;
27
- }
19
+ import { CodeSample, Language } from "./code-snippets-types";
20
+ import { mergeCodeSampleLanguage } from "./languages";
28
21
 
29
22
  export const languageSet: Language[] = [
30
23
  {
31
24
  highlight: "bash",
32
25
  language: "curl",
26
+ codeSampleLanguage: "Shell",
33
27
  logoClass: "bash",
34
28
  options: {
35
29
  longFormat: false,
@@ -42,6 +36,7 @@ export const languageSet: Language[] = [
42
36
  {
43
37
  highlight: "python",
44
38
  language: "python",
39
+ codeSampleLanguage: "Python",
45
40
  logoClass: "python",
46
41
  options: {
47
42
  followRedirect: true,
@@ -53,6 +48,7 @@ export const languageSet: Language[] = [
53
48
  {
54
49
  highlight: "go",
55
50
  language: "go",
51
+ codeSampleLanguage: "Go",
56
52
  logoClass: "go",
57
53
  options: {
58
54
  followRedirect: true,
@@ -64,6 +60,7 @@ export const languageSet: Language[] = [
64
60
  {
65
61
  highlight: "javascript",
66
62
  language: "nodejs",
63
+ codeSampleLanguage: "JavaScript",
67
64
  logoClass: "nodejs",
68
65
  options: {
69
66
  ES6_enabled: true,
@@ -71,11 +68,12 @@ export const languageSet: Language[] = [
71
68
  trimRequestBody: true,
72
69
  },
73
70
  variant: "axios",
74
- variants: ["axios", "native", "request", "unirest"],
71
+ variants: ["axios", "native"],
75
72
  },
76
73
  {
77
74
  highlight: "ruby",
78
75
  language: "ruby",
76
+ codeSampleLanguage: "Ruby",
79
77
  logoClass: "ruby",
80
78
  options: {
81
79
  followRedirect: true,
@@ -87,6 +85,7 @@ export const languageSet: Language[] = [
87
85
  {
88
86
  highlight: "csharp",
89
87
  language: "csharp",
88
+ codeSampleLanguage: "C#",
90
89
  logoClass: "csharp",
91
90
  options: {
92
91
  followRedirect: true,
@@ -98,6 +97,7 @@ export const languageSet: Language[] = [
98
97
  {
99
98
  highlight: "php",
100
99
  language: "php",
100
+ codeSampleLanguage: "PHP",
101
101
  logoClass: "php",
102
102
  options: {
103
103
  followRedirect: true,
@@ -109,6 +109,7 @@ export const languageSet: Language[] = [
109
109
  {
110
110
  highlight: "java",
111
111
  language: "java",
112
+ codeSampleLanguage: "Java",
112
113
  logoClass: "java",
113
114
  options: {
114
115
  followRedirect: true,
@@ -120,6 +121,7 @@ export const languageSet: Language[] = [
120
121
  {
121
122
  highlight: "powershell",
122
123
  language: "powershell",
124
+ codeSampleLanguage: "PowerShell",
123
125
  logoClass: "powershell",
124
126
  options: {
125
127
  followRedirect: true,
@@ -132,10 +134,10 @@ export const languageSet: Language[] = [
132
134
 
133
135
  export interface Props {
134
136
  postman: sdk.Request;
135
- codeSamples: any; // TODO: Type this...
137
+ codeSamples: CodeSample[];
136
138
  }
137
139
 
138
- function CodeTab({ children, hidden, className, onClick }: any): JSX.Element {
140
+ function CodeTab({ children, hidden, className }: any): JSX.Element {
139
141
  return (
140
142
  <div role="tabpanel" className={className} {...{ hidden }}>
141
143
  {children}
@@ -165,7 +167,6 @@ function CodeSnippets({ postman, codeSamples }: Props) {
165
167
  const langs = [
166
168
  ...((siteConfig?.themeConfig?.languageTabs as Language[] | undefined) ??
167
169
  languageSet),
168
- ...codeSamples,
169
170
  ];
170
171
 
171
172
  // Filter languageSet by user-defined langs
@@ -176,14 +177,18 @@ function CodeSnippets({ postman, codeSamples }: Props) {
176
177
  });
177
178
 
178
179
  // Merge user-defined langs into languageSet
179
- const mergedLangs = merge(filteredLanguageSet, langs);
180
+ const mergedLangs = mergeCodeSampleLanguage(
181
+ merge(filteredLanguageSet, langs),
182
+ codeSamples
183
+ );
180
184
 
181
185
  // Read defaultLang from localStorage
182
186
  const defaultLang: Language[] = mergedLangs.filter(
183
187
  (lang) =>
184
188
  lang.language === localStorage.getItem("docusaurus.tab.code-samples")
185
189
  );
186
- const [selectedVariant, setSelectedVariant] = useState();
190
+ const [selectedVariant, setSelectedVariant] = useState<string | undefined>();
191
+ const [selectedSample, setSelectedSample] = useState<string | undefined>();
187
192
  const [language, setLanguage] = useState(() => {
188
193
  // Return first index if only 1 user-defined language exists
189
194
  if (mergedLangs.length === 1) {
@@ -192,9 +197,23 @@ function CodeSnippets({ postman, codeSamples }: Props) {
192
197
  // Fall back to language in localStorage or first user-defined language
193
198
  return defaultLang[0] ?? mergedLangs[0];
194
199
  });
195
- const [codeText, setCodeText] = useState("");
200
+ const [codeText, setCodeText] = useState<string>("");
201
+ const [codeSampleCodeText, setCodeSampleCodeText] = useState<string>("");
196
202
 
197
203
  useEffect(() => {
204
+ // initial active language is custom code sample
205
+ if (
206
+ language &&
207
+ language.sample &&
208
+ language.samples &&
209
+ language.samplesSources
210
+ ) {
211
+ const sampleIndex = language.samples.findIndex(
212
+ (smp) => smp === language.sample
213
+ );
214
+ setCodeSampleCodeText(language.samplesSources[sampleIndex]);
215
+ }
216
+
198
217
  if (language && !!language.options) {
199
218
  const postmanRequest = buildPostmanRequest(postman, {
200
219
  queryParams,
@@ -219,8 +238,6 @@ function CodeSnippets({ postman, codeSamples }: Props) {
219
238
  setCodeText(snippet);
220
239
  }
221
240
  );
222
- } else if (language && !!language.source) {
223
- setCodeText(language.source);
224
241
  } else if (language && !language.options) {
225
242
  const langSource = mergedLangs.filter(
226
243
  (lang) => lang.language === language.language
@@ -271,8 +288,8 @@ function CodeSnippets({ postman, codeSamples }: Props) {
271
288
  auth,
272
289
  mergedLangs,
273
290
  ]);
274
-
275
- useEffect(() => {
291
+ // no dependencies was intentionlly set for this particular hook. it's safe as long as if conditions are set
292
+ useEffect(function onSelectedVariantUpdate() {
276
293
  if (selectedVariant && selectedVariant !== language.variant) {
277
294
  const postmanRequest = buildPostmanRequest(postman, {
278
295
  queryParams,
@@ -300,6 +317,22 @@ function CodeSnippets({ postman, codeSamples }: Props) {
300
317
  }
301
318
  });
302
319
 
320
+ // no dependencies was intentionlly set for this particular hook. it's safe as long as if conditions are set
321
+ // eslint-disable-next-line react-hooks/exhaustive-deps
322
+ useEffect(function onSelectedSampleUpdate() {
323
+ if (
324
+ language.samples &&
325
+ language.samplesSources &&
326
+ selectedSample &&
327
+ selectedSample !== language.sample
328
+ ) {
329
+ const sampleIndex = language.samples.findIndex(
330
+ (smp) => smp === selectedSample
331
+ );
332
+ setCodeSampleCodeText(language.samplesSources[sampleIndex]);
333
+ }
334
+ });
335
+
303
336
  if (language === undefined) {
304
337
  return null;
305
338
  }
@@ -324,6 +357,46 @@ function CodeSnippets({ postman, codeSamples }: Props) {
324
357
  className: `openapi-tabs__code-item--${lang.logoClass}`,
325
358
  }}
326
359
  >
360
+ {lang.samples && (
361
+ <CodeTabs
362
+ className="openapi-tabs__code-container-inner"
363
+ action={{
364
+ setLanguage: setLanguage,
365
+ setSelectedSample: setSelectedSample,
366
+ }}
367
+ includeSample={true}
368
+ currentLanguage={lang.language}
369
+ defaultValue={selectedSample}
370
+ lazy
371
+ >
372
+ {lang.samples.map((sample, index) => {
373
+ return (
374
+ <CodeTab
375
+ value={sample}
376
+ label={
377
+ lang.samplesLabels
378
+ ? lang.samplesLabels[index]
379
+ : sample
380
+ }
381
+ key={`${lang.language}-${lang.sample}`}
382
+ attributes={{
383
+ className: `openapi-tabs__code-item--sample`,
384
+ }}
385
+ >
386
+ {/* @ts-ignore */}
387
+ <ApiCodeBlock
388
+ language={lang.highlight}
389
+ className="openapi-explorer__code-block"
390
+ showLineNumbers={true}
391
+ >
392
+ {codeSampleCodeText}
393
+ </ApiCodeBlock>
394
+ </CodeTab>
395
+ );
396
+ })}
397
+ </CodeTabs>
398
+ )}
399
+
327
400
  <CodeTabs
328
401
  className="openapi-tabs__code-container-inner"
329
402
  action={{
@@ -335,7 +408,7 @@ function CodeSnippets({ postman, codeSamples }: Props) {
335
408
  defaultValue={selectedVariant}
336
409
  lazy
337
410
  >
338
- {lang.variants.map((variant) => {
411
+ {lang.variants.map((variant, index) => {
339
412
  return (
340
413
  <CodeTab
341
414
  value={variant.toLowerCase()}
@@ -635,102 +635,6 @@
635
635
  "description": "Modifies code snippet to incorporate ES6 (EcmaScript) features"
636
636
  }
637
637
  ]
638
- },
639
- {
640
- "key": "Request",
641
- "options": [
642
- {
643
- "name": "Set indentation count",
644
- "id": "indentCount",
645
- "type": "positiveInteger",
646
- "default": 2,
647
- "description": "Set the number of indentation characters to add per code level"
648
- },
649
- {
650
- "name": "Set indentation type",
651
- "id": "indentType",
652
- "type": "enum",
653
- "availableOptions": ["Tab", "Space"],
654
- "default": "Space",
655
- "description": "Select the character used to indent lines of code"
656
- },
657
- {
658
- "name": "Set request timeout",
659
- "id": "requestTimeout",
660
- "type": "positiveInteger",
661
- "default": 0,
662
- "description": "Set number of milliseconds the request should wait for a response before timing out (use 0 for infinity)"
663
- },
664
- {
665
- "name": "Follow redirects",
666
- "id": "followRedirect",
667
- "type": "boolean",
668
- "default": true,
669
- "description": "Automatically follow HTTP redirects"
670
- },
671
- {
672
- "name": "Trim request body fields",
673
- "id": "trimRequestBody",
674
- "type": "boolean",
675
- "default": false,
676
- "description": "Remove white space and additional lines that may affect the server's response"
677
- },
678
- {
679
- "name": "Enable ES6 features",
680
- "id": "ES6_enabled",
681
- "type": "boolean",
682
- "default": false,
683
- "description": "Modifies code snippet to incorporate ES6 (EcmaScript) features"
684
- }
685
- ]
686
- },
687
- {
688
- "key": "Unirest",
689
- "options": [
690
- {
691
- "name": "Set indentation count",
692
- "id": "indentCount",
693
- "type": "positiveInteger",
694
- "default": 2,
695
- "description": "Set the number of indentation characters to add per code level"
696
- },
697
- {
698
- "name": "Set indentation type",
699
- "id": "indentType",
700
- "type": "enum",
701
- "availableOptions": ["Tab", "Space"],
702
- "default": "Space",
703
- "description": "Select the character used to indent lines of code"
704
- },
705
- {
706
- "name": "Set request timeout",
707
- "id": "requestTimeout",
708
- "type": "positiveInteger",
709
- "default": 0,
710
- "description": "Set number of milliseconds the request should wait for a response before timing out (use 0 for infinity)"
711
- },
712
- {
713
- "name": "Follow redirects",
714
- "id": "followRedirect",
715
- "type": "boolean",
716
- "default": true,
717
- "description": "Automatically follow HTTP redirects"
718
- },
719
- {
720
- "name": "Trim request body fields",
721
- "id": "trimRequestBody",
722
- "type": "boolean",
723
- "default": false,
724
- "description": "Remove white space and additional lines that may affect the server's response"
725
- },
726
- {
727
- "name": "Enable ES6 features",
728
- "id": "ES6_enabled",
729
- "type": "boolean",
730
- "default": false,
731
- "description": "Modifies code snippet to incorporate ES6 (EcmaScript) features"
732
- }
733
- ]
734
638
  }
735
639
  ]
736
640
  },
@@ -0,0 +1,37 @@
1
+ /* ============================================================================
2
+ * Copyright (c) Palo Alto Networks
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ * ========================================================================== */
7
+
8
+ import { CodeSample, Language } from "./code-snippets-types";
9
+
10
+ export function mergeCodeSampleLanguage(
11
+ languages: Language[],
12
+ codeSamples: CodeSample[]
13
+ ): Language[] {
14
+ return languages.map((language) => {
15
+ const languageCodeSamples = codeSamples.filter(
16
+ ({ lang }) => lang === language.codeSampleLanguage
17
+ );
18
+
19
+ if (languageCodeSamples.length) {
20
+ const samples = languageCodeSamples.map(({ lang }) => lang);
21
+ const samplesLabels = languageCodeSamples.map(
22
+ ({ label, lang }) => label || lang
23
+ );
24
+ const samplesSources = languageCodeSamples.map(({ source }) => source);
25
+
26
+ return {
27
+ ...language,
28
+ sample: samples[0],
29
+ samples,
30
+ samplesSources,
31
+ samplesLabels,
32
+ };
33
+ }
34
+
35
+ return language;
36
+ });
37
+ }
@@ -96,6 +96,20 @@ body[class="ReactModal__Body--open"] {
96
96
  padding-right: 0.5rem !important;
97
97
  }
98
98
 
99
+ .openapi-tabs__code-item--sample {
100
+ color: var(--ifm-color-secondary);
101
+
102
+ &.active {
103
+ border-color: var(--ifm-toc-border-color);
104
+ }
105
+ }
106
+
107
+ .openapi-tabs__code-item--sample > span {
108
+ padding-top: unset !important;
109
+ padding-left: 0.5rem !important;
110
+ padding-right: 0.5rem !important;
111
+ }
112
+
99
113
  .openapi-tabs__code-item--python {
100
114
  color: var(--ifm-color-success);
101
115
 
@@ -5,34 +5,55 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- import React, { cloneElement } from "react";
8
+ import React, { cloneElement, ReactElement } from "react";
9
9
 
10
10
  import {
11
+ sanitizeTabsChildren,
12
+ type TabProps,
11
13
  useScrollPositionBlocker,
12
14
  useTabs,
13
15
  } from "@docusaurus/theme-common/internal";
16
+ import { TabItemProps } from "@docusaurus/theme-common/lib/utils/tabsUtils";
14
17
  import useIsBrowser from "@docusaurus/useIsBrowser";
15
- import { languageSet } from "@theme/ApiExplorer/CodeSnippets";
18
+ import { Language, languageSet } from "@theme/ApiExplorer/CodeSnippets";
16
19
  import clsx from "clsx";
17
20
 
21
+ export interface Props {
22
+ action: {
23
+ [key: string]: React.Dispatch<any>;
24
+ };
25
+ currentLanguage: Language;
26
+ includeVariant: boolean;
27
+ }
28
+
29
+ export interface TabListProps extends Props, TabProps {
30
+ includeSample?: boolean;
31
+ }
32
+
18
33
  function TabList({
19
34
  action,
20
35
  currentLanguage,
21
36
  includeVariant,
37
+ includeSample,
22
38
  className,
23
39
  block,
24
40
  selectedValue,
25
41
  selectValue,
26
42
  tabValues,
27
- }) {
28
- const tabRefs = [];
43
+ }: TabListProps & ReturnType<typeof useTabs>) {
44
+ const tabRefs: (HTMLLIElement | null)[] = [];
29
45
  const { blockElementScrollPositionUntilNextRender } =
30
46
  useScrollPositionBlocker();
31
47
 
32
- const handleTabChange = (event) => {
48
+ const handleTabChange = (
49
+ event:
50
+ | React.FocusEvent<HTMLLIElement>
51
+ | React.MouseEvent<HTMLLIElement>
52
+ | React.KeyboardEvent<HTMLLIElement>
53
+ ) => {
33
54
  const newTab = event.currentTarget;
34
55
  const newTabIndex = tabRefs.indexOf(newTab);
35
- const newTabValue = tabValues[newTabIndex].value;
56
+ const newTabValue = tabValues[newTabIndex]!.value;
36
57
 
37
58
  if (newTabValue !== selectedValue) {
38
59
  blockElementScrollPositionUntilNextRender(newTab);
@@ -40,25 +61,30 @@ function TabList({
40
61
  }
41
62
 
42
63
  if (action) {
43
- let newLanguage;
64
+ let newLanguage: Language;
44
65
  if (currentLanguage && includeVariant) {
45
66
  newLanguage = languageSet.filter(
46
- (lang) => lang.language === currentLanguage
67
+ (lang: Language) => lang.language === currentLanguage
47
68
  )[0];
48
69
  newLanguage.variant = newTabValue;
49
70
  action.setSelectedVariant(newTabValue.toLowerCase());
50
71
  } else {
51
72
  newLanguage = languageSet.filter(
52
- (lang) => lang.language === newTabValue
73
+ (lang: Language) => lang.language === newTabValue
53
74
  )[0];
54
75
  action.setSelectedVariant(newLanguage.variant.toLowerCase());
55
76
  }
77
+ if (currentLanguage && includeSample) {
78
+ newLanguage.sample = newTabValue;
79
+ action.setSelectedSample(newTabValue.toLowerCase());
80
+ }
56
81
  action.setLanguage(newLanguage);
57
82
  }
58
83
  };
59
84
 
60
- const handleKeydown = (event) => {
61
- let focusElement = null;
85
+ const handleKeydown = (event: React.KeyboardEvent<HTMLLIElement>) => {
86
+ let focusElement: HTMLLIElement | null = null;
87
+
62
88
  switch (event.key) {
63
89
  case "Enter": {
64
90
  handleTabChange(event);
@@ -66,17 +92,18 @@ function TabList({
66
92
  }
67
93
  case "ArrowRight": {
68
94
  const nextTab = tabRefs.indexOf(event.currentTarget) + 1;
69
- focusElement = tabRefs[nextTab] ?? tabRefs[0];
95
+ focusElement = tabRefs[nextTab] ?? tabRefs[0]!;
70
96
  break;
71
97
  }
72
98
  case "ArrowLeft": {
73
99
  const prevTab = tabRefs.indexOf(event.currentTarget) - 1;
74
- focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1];
100
+ focusElement = tabRefs[prevTab] ?? tabRefs[tabRefs.length - 1]!;
75
101
  break;
76
102
  }
77
103
  default:
78
104
  break;
79
105
  }
106
+
80
107
  focusElement?.focus();
81
108
  };
82
109
 
@@ -107,7 +134,7 @@ function TabList({
107
134
  className={clsx(
108
135
  "tabs__item",
109
136
  "openapi-tabs__code-item",
110
- attributes?.className,
137
+ attributes?.className as string,
111
138
  {
112
139
  active: selectedValue === value,
113
140
  }
@@ -120,11 +147,16 @@ function TabList({
120
147
  );
121
148
  }
122
149
 
123
- function TabContent({ lazy, children, selectedValue }) {
124
- // eslint-disable-next-line no-param-reassign
125
- children = Array.isArray(children) ? children : [children];
150
+ function TabContent({
151
+ lazy,
152
+ children,
153
+ selectedValue,
154
+ }: TabProps & ReturnType<typeof useTabs>): React.JSX.Element | null {
155
+ const childTabs = (Array.isArray(children) ? children : [children]).filter(
156
+ Boolean
157
+ ) as ReactElement<TabItemProps>[];
126
158
  if (lazy) {
127
- const selectedTabItem = children.find(
159
+ const selectedTabItem = childTabs.find(
128
160
  (tabItem) => tabItem.props.value === selectedValue
129
161
  );
130
162
  if (!selectedTabItem) {
@@ -135,7 +167,7 @@ function TabContent({ lazy, children, selectedValue }) {
135
167
  }
136
168
  return (
137
169
  <div className="margin-top--md openapi-tabs__code-content">
138
- {children.map((tabItem, i) =>
170
+ {childTabs.map((tabItem, i) =>
139
171
  cloneElement(tabItem, {
140
172
  key: i,
141
173
  hidden: tabItem.props.value !== selectedValue,
@@ -145,15 +177,13 @@ function TabContent({ lazy, children, selectedValue }) {
145
177
  );
146
178
  }
147
179
 
148
- function TabsComponent(props) {
180
+ function TabsComponent(props: TabProps & Props): React.JSX.Element {
149
181
  const tabs = useTabs(props);
150
182
  const { className } = props;
151
183
 
152
184
  return (
153
185
  <div
154
- className={clsx("tabs-container openapi-tabs__code-container", {
155
- [className]: className,
156
- })}
186
+ className={clsx("tabs-container openapi-tabs__code-container", className)}
157
187
  >
158
188
  <TabList {...props} {...tabs} />
159
189
  <TabContent {...props} {...tabs} />
@@ -161,7 +191,7 @@ function TabsComponent(props) {
161
191
  );
162
192
  }
163
193
 
164
- export default function CodeTabs(props) {
194
+ export default function CodeTabs(props: TabProps & Props): React.JSX.Element {
165
195
  const isBrowser = useIsBrowser();
166
196
  return (
167
197
  <TabsComponent
@@ -169,6 +199,8 @@ export default function CodeTabs(props) {
169
199
  // Temporary fix for https://github.com/facebook/docusaurus/issues/5653
170
200
  key={String(isBrowser)}
171
201
  {...props}
172
- />
202
+ >
203
+ {sanitizeTabsChildren(props.children)}
204
+ </TabsComponent>
173
205
  );
174
206
  }