docusaurus-theme-openapi-docs 2.0.3 → 2.1.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 (58) hide show
  1. package/lib/markdown/utils.d.ts +2 -2
  2. package/lib/markdown/utils.js +4 -4
  3. package/lib/markdown/utils.test.d.ts +1 -0
  4. package/lib/markdown/utils.test.js +43 -0
  5. package/lib/theme/ApiExplorer/Accept/index.d.ts +2 -2
  6. package/lib/theme/ApiExplorer/Authorization/index.d.ts +2 -2
  7. package/lib/theme/ApiExplorer/Authorization/slice.d.ts +1 -1
  8. package/lib/theme/ApiExplorer/Body/index.d.ts +2 -2
  9. package/lib/theme/ApiExplorer/Body/slice.d.ts +3 -3
  10. package/lib/theme/ApiExplorer/CodeSnippets/code-snippets-types.d.ts +21 -0
  11. package/lib/theme/ApiExplorer/CodeSnippets/code-snippets-types.js +8 -0
  12. package/lib/theme/ApiExplorer/CodeSnippets/index.d.ts +4 -14
  13. package/lib/theme/ApiExplorer/CodeSnippets/index.js +86 -8
  14. package/lib/theme/ApiExplorer/CodeSnippets/languages.d.ts +3 -0
  15. package/lib/theme/ApiExplorer/CodeSnippets/languages.js +48 -0
  16. package/lib/theme/ApiExplorer/CodeTabs/_CodeTabs.scss +14 -0
  17. package/lib/theme/ApiExplorer/CodeTabs/index.js +10 -1
  18. package/lib/theme/ApiExplorer/ContentType/index.d.ts +2 -2
  19. package/lib/theme/ApiExplorer/Export/index.d.ts +2 -2
  20. package/lib/theme/ApiExplorer/FloatingButton/index.d.ts +1 -1
  21. package/lib/theme/ApiExplorer/FormFileUpload/index.d.ts +2 -2
  22. package/lib/theme/ApiExplorer/FormItem/index.d.ts +1 -1
  23. package/lib/theme/ApiExplorer/FormMultiSelect/index.d.ts +1 -1
  24. package/lib/theme/ApiExplorer/FormSelect/index.d.ts +1 -1
  25. package/lib/theme/ApiExplorer/FormTextInput/index.d.ts +1 -1
  26. package/lib/theme/ApiExplorer/MethodEndpoint/index.d.ts +2 -2
  27. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.d.ts +2 -2
  28. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.d.ts +2 -2
  29. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.d.ts +2 -2
  30. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.d.ts +2 -2
  31. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.d.ts +2 -2
  32. package/lib/theme/ApiExplorer/ParamOptions/index.d.ts +2 -2
  33. package/lib/theme/ApiExplorer/ParamOptions/slice.d.ts +1 -1
  34. package/lib/theme/ApiExplorer/Request/index.d.ts +2 -2
  35. package/lib/theme/ApiExplorer/Response/index.d.ts +2 -2
  36. package/lib/theme/ApiExplorer/SecuritySchemes/index.d.ts +2 -2
  37. package/lib/theme/ApiExplorer/Server/index.d.ts +2 -2
  38. package/lib/theme/ApiExplorer/buildPostmanRequest.d.ts +1 -1
  39. package/lib/theme/ApiExplorer/index.d.ts +2 -2
  40. package/lib/theme/ApiExplorer/index.js +1 -1
  41. package/lib/theme/ApiExplorer/storage-utils.d.ts +1 -1
  42. package/lib/theme/ApiItem/index.js +24 -0
  43. package/lib/theme/ApiItem/store.d.ts +6 -6
  44. package/lib/theme/SchemaItem/index.js +5 -8
  45. package/lib/types.d.ts +4 -4
  46. package/package.json +3 -3
  47. package/src/markdown/utils.test.ts +48 -0
  48. package/src/markdown/utils.ts +4 -4
  49. package/src/theme/ApiExplorer/CodeSnippets/code-snippets-types.ts +55 -0
  50. package/src/theme/ApiExplorer/CodeSnippets/index.tsx +94 -21
  51. package/src/theme/ApiExplorer/CodeSnippets/languages.ts +53 -0
  52. package/src/theme/ApiExplorer/CodeTabs/_CodeTabs.scss +14 -0
  53. package/src/theme/ApiExplorer/CodeTabs/index.js +10 -1
  54. package/src/theme/ApiExplorer/index.tsx +1 -1
  55. package/src/theme/ApiItem/index.tsx +20 -0
  56. package/src/theme/SchemaItem/index.js +5 -8
  57. package/lib/theme/ApiExplorer/CodeSnippets/languages.json +0 -1386
  58. package/src/theme/ApiExplorer/CodeSnippets/languages.json +0 -1386
@@ -1,6 +1,6 @@
1
- /// <reference types="react" />
1
+ import React from "react";
2
2
  import { Param } from "@theme/ApiExplorer/ParamOptions/slice";
3
3
  export interface ParamProps {
4
4
  param: Param;
5
5
  }
6
- export default function ParamTextFormItem({ param }: ParamProps): JSX.Element;
6
+ export default function ParamTextFormItem({ param }: ParamProps): React.JSX.Element;
@@ -1,7 +1,7 @@
1
- /// <reference types="react" />
1
+ import React from "react";
2
2
  import { Param } from "./slice";
3
3
  export interface ParamProps {
4
4
  param: Param;
5
5
  }
6
- declare function ParamOptions(): JSX.Element;
6
+ declare function ParamOptions(): React.JSX.Element;
7
7
  export default ParamOptions;
@@ -1,6 +1,6 @@
1
1
  import { PayloadAction } from "@reduxjs/toolkit";
2
2
  import { ParameterObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
3
- export declare type Param = ParameterObject & {
3
+ export type Param = ParameterObject & {
4
4
  value?: string[] | string;
5
5
  };
6
6
  export interface State {
@@ -1,6 +1,6 @@
1
- /// <reference types="react" />
1
+ import React from "react";
2
2
  import { ApiItem } from "docusaurus-plugin-openapi-docs/src/types";
3
3
  declare function Request({ item }: {
4
4
  item: NonNullable<ApiItem>;
5
- }): JSX.Element | null;
5
+ }): React.JSX.Element | null;
6
6
  export default Request;
@@ -1,6 +1,6 @@
1
- /// <reference types="react" />
1
+ import React from "react";
2
2
  import { ApiItem } from "docusaurus-plugin-openapi-docs/src/types";
3
3
  declare function Response({ item }: {
4
4
  item: NonNullable<ApiItem>;
5
- }): JSX.Element | null;
5
+ }): React.JSX.Element | null;
6
6
  export default Response;
@@ -1,3 +1,3 @@
1
- /// <reference types="react" />
2
- declare function SecuritySchemes(props: any): JSX.Element | null;
1
+ import React from "react";
2
+ declare function SecuritySchemes(props: any): React.JSX.Element | null;
3
3
  export default SecuritySchemes;
@@ -1,3 +1,3 @@
1
- /// <reference types="react" />
2
- declare function Server(): JSX.Element | null;
1
+ import React from "react";
2
+ declare function Server(): React.JSX.Element | null;
3
3
  export default Server;
@@ -2,7 +2,7 @@ import sdk from "@paloaltonetworks/postman-collection";
2
2
  import { AuthState } from "@theme/ApiExplorer/Authorization/slice";
3
3
  import { Body } from "@theme/ApiExplorer/Body/slice";
4
4
  import { ParameterObject, ServerObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
5
- declare type Param = {
5
+ type Param = {
6
6
  value?: string | string[];
7
7
  } & ParameterObject;
8
8
  interface Options {
@@ -1,7 +1,7 @@
1
- /// <reference types="react" />
1
+ import React from "react";
2
2
  import { ApiItem } from "docusaurus-plugin-openapi-docs/src/types";
3
3
  declare function ApiExplorer({ item, infoPath, }: {
4
4
  item: NonNullable<ApiItem>;
5
5
  infoPath: string;
6
- }): JSX.Element;
6
+ }): React.JSX.Element;
7
7
  export default ApiExplorer;
@@ -32,7 +32,7 @@ function ApiExplorer({ item, infoPath }) {
32
32
  item.method !== "event" &&
33
33
  react_1.default.createElement(CodeSnippets_1.default, {
34
34
  postman: postman,
35
- codeSamples: item["x-code-samples"] ?? [],
35
+ codeSamples: item["x-codeSamples"] ?? [],
36
36
  }),
37
37
  react_1.default.createElement(Request_1.default, { item: item }),
38
38
  react_1.default.createElement(Response_1.default, { item: item })
@@ -1,4 +1,4 @@
1
1
  export declare function hashArray(arr: string[]): string;
2
- declare type Persistance = false | "localStorage" | "sessionStorage" | undefined;
2
+ type Persistance = false | "localStorage" | "sessionStorage" | undefined;
3
3
  export declare function createStorage(persistance: Persistance): Storage;
4
4
  export {};
@@ -40,6 +40,7 @@ function ApiItem(props) {
40
40
  const { frontMatter } = MDXComponent;
41
41
  const { info_path: infoPath } = frontMatter;
42
42
  let { api } = frontMatter;
43
+ const { schema } = frontMatter;
43
44
  // decompress and parse
44
45
  if (api) {
45
46
  api = JSON.parse(
@@ -163,6 +164,29 @@ function ApiItem(props) {
163
164
  )
164
165
  )
165
166
  );
167
+ } else if (schema) {
168
+ return react_1.default.createElement(
169
+ DocProvider,
170
+ { content: props.content },
171
+ react_1.default.createElement(
172
+ theme_common_1.HtmlClassNameProvider,
173
+ { className: docHtmlClassName },
174
+ react_1.default.createElement(Metadata_1.default, null),
175
+ react_1.default.createElement(
176
+ Layout_1.default,
177
+ null,
178
+ react_1.default.createElement(
179
+ "div",
180
+ { className: (0, clsx_1.default)("row", "theme-api-markdown") },
181
+ react_1.default.createElement(
182
+ "div",
183
+ { className: "col col--12" },
184
+ react_1.default.createElement(MDXComponent, null)
185
+ )
186
+ )
187
+ )
188
+ )
189
+ );
166
190
  }
167
191
  // Non-API docs
168
192
  return react_1.default.createElement(
@@ -7,8 +7,8 @@ declare const rootReducer: import("redux").Reducer<import("redux").CombinedState
7
7
  params: unknown;
8
8
  auth: unknown;
9
9
  }>, import("redux").Action<any>>;
10
- export declare type RootState = ReturnType<typeof rootReducer>;
11
- export declare const createStoreWithState: (preloadedState: RootState, middlewares: any[]) => import("@reduxjs/toolkit/dist/configureStore").ToolkitStore<import("redux").CombinedState<{
10
+ export type RootState = ReturnType<typeof rootReducer>;
11
+ export declare const createStoreWithState: (preloadedState: RootState, middlewares: any[]) => import("@reduxjs/toolkit/dist/configureStore").ToolkitStore<import("redux").EmptyObject & {
12
12
  accept: unknown;
13
13
  contentType: unknown;
14
14
  response: unknown;
@@ -16,7 +16,7 @@ export declare const createStoreWithState: (preloadedState: RootState, middlewar
16
16
  body: unknown;
17
17
  params: unknown;
18
18
  auth: unknown;
19
- }>, import("redux").Action<any>, import("@reduxjs/toolkit").MiddlewareArray<[import("@reduxjs/toolkit").ThunkMiddleware<import("redux").CombinedState<{
19
+ }, import("redux").Action<any>, import("@reduxjs/toolkit").MiddlewareArray<[import("@reduxjs/toolkit").ThunkMiddleware<import("redux").CombinedState<{
20
20
  accept: unknown;
21
21
  contentType: unknown;
22
22
  response: unknown;
@@ -25,7 +25,7 @@ export declare const createStoreWithState: (preloadedState: RootState, middlewar
25
25
  params: unknown;
26
26
  auth: unknown;
27
27
  }>, import("redux").AnyAction, undefined>, ...any[]]>>;
28
- export declare const createStoreWithoutState: (preloadedState: {}, middlewares: any[]) => import("@reduxjs/toolkit/dist/configureStore").ToolkitStore<import("redux").CombinedState<{
28
+ export declare const createStoreWithoutState: (preloadedState: {}, middlewares: any[]) => import("@reduxjs/toolkit/dist/configureStore").ToolkitStore<import("redux").EmptyObject & {
29
29
  accept: unknown;
30
30
  contentType: unknown;
31
31
  response: unknown;
@@ -33,7 +33,7 @@ export declare const createStoreWithoutState: (preloadedState: {}, middlewares:
33
33
  body: unknown;
34
34
  params: unknown;
35
35
  auth: unknown;
36
- }>, import("redux").Action<any>, import("@reduxjs/toolkit").MiddlewareArray<[import("@reduxjs/toolkit").ThunkMiddleware<import("redux").CombinedState<{
36
+ }, import("redux").Action<any>, import("@reduxjs/toolkit").MiddlewareArray<[import("@reduxjs/toolkit").ThunkMiddleware<import("redux").CombinedState<{
37
37
  accept: unknown;
38
38
  contentType: unknown;
39
39
  response: unknown;
@@ -42,5 +42,5 @@ export declare const createStoreWithoutState: (preloadedState: {}, middlewares:
42
42
  params: unknown;
43
43
  auth: unknown;
44
44
  }>, import("redux").AnyAction, undefined>, ...any[]]>>;
45
- export declare type AppDispatch = ReturnType<typeof createStoreWithState>["dispatch"];
45
+ export type AppDispatch = ReturnType<typeof createStoreWithState>["dispatch"];
46
46
  export {};
@@ -79,14 +79,11 @@ function SchemaItem({
79
79
  </div>
80
80
  ));
81
81
 
82
- const renderDefaultValue = guard(
83
- typeof defaultValue === "boolean" ? defaultValue.toString() : defaultValue,
84
- (value) => (
85
- <div className="">
86
- <ReactMarkdown children={`**Default value:** \`${value}\``} />
87
- </div>
88
- )
89
- );
82
+ const renderDefaultValue = guard(defaultValue, (value) => (
83
+ <div className="">
84
+ <ReactMarkdown children={`**Default value:** \`${value}\``} />
85
+ </div>
86
+ ));
90
87
 
91
88
  const schemaContent = (
92
89
  <div>
package/lib/types.d.ts CHANGED
@@ -9,8 +9,8 @@ export interface ThemeConfig {
9
9
  interface Map<T> {
10
10
  [key: string]: T;
11
11
  }
12
- export declare type JSONSchema = JSONSchema4 | JSONSchema6 | JSONSchema7;
13
- export declare type SchemaObject = Omit<JSONSchema, "type" | "allOf" | "oneOf" | "anyOf" | "not" | "items" | "properties" | "additionalProperties"> & {
12
+ export type JSONSchema = JSONSchema4 | JSONSchema6 | JSONSchema7;
13
+ export type SchemaObject = Omit<JSONSchema, "type" | "allOf" | "oneOf" | "anyOf" | "not" | "items" | "properties" | "additionalProperties"> & {
14
14
  type?: "string" | "number" | "integer" | "boolean" | "object" | "array";
15
15
  allOf?: SchemaObject[];
16
16
  oneOf?: SchemaObject[];
@@ -43,14 +43,14 @@ export interface ExternalDocumentationObject {
43
43
  description?: string;
44
44
  url: string;
45
45
  }
46
- export declare type FileChange = {
46
+ export type FileChange = {
47
47
  author?: string;
48
48
  /** Date can be any
49
49
  * [parsable date string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse).
50
50
  */
51
51
  date?: Date | string;
52
52
  };
53
- export declare type DocFrontMatter = {
53
+ export type DocFrontMatter = {
54
54
  /**
55
55
  * The last part of the doc ID (will be refactored in the future to be the
56
56
  * full ID instead)
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": "2.0.3",
4
+ "version": "2.1.0",
5
5
  "license": "MIT",
6
6
  "keywords": [
7
7
  "openapi",
@@ -43,7 +43,7 @@
43
43
  "clsx": "^1.1.1",
44
44
  "copy-text-to-clipboard": "^3.1.0",
45
45
  "crypto-js": "^4.1.1",
46
- "docusaurus-plugin-openapi-docs": "^2.0.3",
46
+ "docusaurus-plugin-openapi-docs": "^2.1.0",
47
47
  "docusaurus-plugin-sass": "^0.2.3",
48
48
  "file-saver": "^2.0.5",
49
49
  "lodash": "^4.17.20",
@@ -68,5 +68,5 @@
68
68
  "engines": {
69
69
  "node": ">=14"
70
70
  },
71
- "gitHead": "f6641c0ce01e3247a06ef8ddde7bafbe749d4ed1"
71
+ "gitHead": "9064dd22c8e18125f838fd88caba6364e5484b68"
72
72
  }
@@ -0,0 +1,48 @@
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 { guard } from "./utils";
9
+
10
+ describe("guard", () => {
11
+ it("should guard empty strings", () => {
12
+ const actual = guard("", (_) => {
13
+ throw new Error("Should not be called");
14
+ });
15
+ expect(actual).toBe("");
16
+ });
17
+
18
+ it("should guard undefined", () => {
19
+ const actual = guard(undefined, (value) => {
20
+ throw new Error("Should not be called");
21
+ });
22
+ expect(actual).toBe("");
23
+ });
24
+
25
+ it("should not guard strings", () => {
26
+ const actual = guard("hello", (value) => value);
27
+ expect(actual).toBe("hello");
28
+ });
29
+
30
+ it("should not guard numbers", () => {
31
+ const actual = guard(1, (value) => `${value}`);
32
+ expect(actual).toBe("1");
33
+ });
34
+
35
+ it("should not guard numbers equals to 0", () => {
36
+ const actual = guard(0, (value) => `${value}`);
37
+ expect(actual).toBe("0");
38
+ });
39
+
40
+ it("should not guard false booleans", () => {
41
+ const actual = guard(false, (value) => `${value}`);
42
+ expect(actual).toBe("false");
43
+ });
44
+ it("should not guard true booleans", () => {
45
+ const actual = guard(true, (value) => `${value}`);
46
+ expect(actual).toBe("true");
47
+ });
48
+ });
@@ -24,11 +24,11 @@ export function guard<T>(
24
24
  value: T | undefined | string,
25
25
  cb: (value: T) => Children
26
26
  ): string {
27
- if (!!value) {
28
- const children = cb(value as T);
29
- return render(children);
27
+ if (value === undefined || value === "") {
28
+ return "";
30
29
  }
31
- return "";
30
+ const children = cb(value as T);
31
+ return render(children);
32
32
  }
33
33
 
34
34
  export function render(children: Children): string {
@@ -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,17 @@ 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 {
21
+ getCodeSampleSourceFromLanguage,
22
+ mergeCodeSampleLanguage,
23
+ } from "./languages";
28
24
 
29
25
  export const languageSet: Language[] = [
30
26
  {
31
27
  highlight: "bash",
32
28
  language: "curl",
29
+ codeSampleLanguage: "Shell",
33
30
  logoClass: "bash",
34
31
  options: {
35
32
  longFormat: false,
@@ -42,6 +39,7 @@ export const languageSet: Language[] = [
42
39
  {
43
40
  highlight: "python",
44
41
  language: "python",
42
+ codeSampleLanguage: "Python",
45
43
  logoClass: "python",
46
44
  options: {
47
45
  followRedirect: true,
@@ -53,6 +51,7 @@ export const languageSet: Language[] = [
53
51
  {
54
52
  highlight: "go",
55
53
  language: "go",
54
+ codeSampleLanguage: "Go",
56
55
  logoClass: "go",
57
56
  options: {
58
57
  followRedirect: true,
@@ -64,6 +63,7 @@ export const languageSet: Language[] = [
64
63
  {
65
64
  highlight: "javascript",
66
65
  language: "nodejs",
66
+ codeSampleLanguage: "JavaScript",
67
67
  logoClass: "nodejs",
68
68
  options: {
69
69
  ES6_enabled: true,
@@ -71,11 +71,12 @@ export const languageSet: Language[] = [
71
71
  trimRequestBody: true,
72
72
  },
73
73
  variant: "axios",
74
- variants: ["axios", "native", "request", "unirest"],
74
+ variants: ["axios", "native"],
75
75
  },
76
76
  {
77
77
  highlight: "ruby",
78
78
  language: "ruby",
79
+ codeSampleLanguage: "Ruby",
79
80
  logoClass: "ruby",
80
81
  options: {
81
82
  followRedirect: true,
@@ -87,6 +88,7 @@ export const languageSet: Language[] = [
87
88
  {
88
89
  highlight: "csharp",
89
90
  language: "csharp",
91
+ codeSampleLanguage: "C#",
90
92
  logoClass: "csharp",
91
93
  options: {
92
94
  followRedirect: true,
@@ -98,6 +100,7 @@ export const languageSet: Language[] = [
98
100
  {
99
101
  highlight: "php",
100
102
  language: "php",
103
+ codeSampleLanguage: "PHP",
101
104
  logoClass: "php",
102
105
  options: {
103
106
  followRedirect: true,
@@ -109,6 +112,7 @@ export const languageSet: Language[] = [
109
112
  {
110
113
  highlight: "java",
111
114
  language: "java",
115
+ codeSampleLanguage: "Java",
112
116
  logoClass: "java",
113
117
  options: {
114
118
  followRedirect: true,
@@ -120,6 +124,7 @@ export const languageSet: Language[] = [
120
124
  {
121
125
  highlight: "powershell",
122
126
  language: "powershell",
127
+ codeSampleLanguage: "PowerShell",
123
128
  logoClass: "powershell",
124
129
  options: {
125
130
  followRedirect: true,
@@ -132,10 +137,10 @@ export const languageSet: Language[] = [
132
137
 
133
138
  export interface Props {
134
139
  postman: sdk.Request;
135
- codeSamples: any; // TODO: Type this...
140
+ codeSamples: CodeSample[];
136
141
  }
137
142
 
138
- function CodeTab({ children, hidden, className, onClick }: any): JSX.Element {
143
+ function CodeTab({ children, hidden, className }: any): JSX.Element {
139
144
  return (
140
145
  <div role="tabpanel" className={className} {...{ hidden }}>
141
146
  {children}
@@ -165,7 +170,6 @@ function CodeSnippets({ postman, codeSamples }: Props) {
165
170
  const langs = [
166
171
  ...((siteConfig?.themeConfig?.languageTabs as Language[] | undefined) ??
167
172
  languageSet),
168
- ...codeSamples,
169
173
  ];
170
174
 
171
175
  // Filter languageSet by user-defined langs
@@ -176,14 +180,18 @@ function CodeSnippets({ postman, codeSamples }: Props) {
176
180
  });
177
181
 
178
182
  // Merge user-defined langs into languageSet
179
- const mergedLangs = merge(filteredLanguageSet, langs);
183
+ const mergedLangs = mergeCodeSampleLanguage(
184
+ merge(filteredLanguageSet, langs),
185
+ codeSamples
186
+ );
180
187
 
181
188
  // Read defaultLang from localStorage
182
189
  const defaultLang: Language[] = mergedLangs.filter(
183
190
  (lang) =>
184
191
  lang.language === localStorage.getItem("docusaurus.tab.code-samples")
185
192
  );
186
- const [selectedVariant, setSelectedVariant] = useState();
193
+ const [selectedVariant, setSelectedVariant] = useState<string | undefined>();
194
+ const [selectedSample, setSelectedSample] = useState<string | undefined>();
187
195
  const [language, setLanguage] = useState(() => {
188
196
  // Return first index if only 1 user-defined language exists
189
197
  if (mergedLangs.length === 1) {
@@ -192,9 +200,16 @@ function CodeSnippets({ postman, codeSamples }: Props) {
192
200
  // Fall back to language in localStorage or first user-defined language
193
201
  return defaultLang[0] ?? mergedLangs[0];
194
202
  });
195
- const [codeText, setCodeText] = useState("");
203
+ const [codeText, setCodeText] = useState<string>("");
204
+ const [codeSampleCodeText, setCodeSampleCodeText] = useState<
205
+ string | (() => string)
206
+ >(() => getCodeSampleSourceFromLanguage(language));
196
207
 
197
208
  useEffect(() => {
209
+ if (language && !!language.sample) {
210
+ setCodeSampleCodeText(getCodeSampleSourceFromLanguage(language));
211
+ }
212
+
198
213
  if (language && !!language.options) {
199
214
  const postmanRequest = buildPostmanRequest(postman, {
200
215
  queryParams,
@@ -219,8 +234,6 @@ function CodeSnippets({ postman, codeSamples }: Props) {
219
234
  setCodeText(snippet);
220
235
  }
221
236
  );
222
- } else if (language && !!language.source) {
223
- setCodeText(language.source);
224
237
  } else if (language && !language.options) {
225
238
  const langSource = mergedLangs.filter(
226
239
  (lang) => lang.language === language.language
@@ -271,8 +284,8 @@ function CodeSnippets({ postman, codeSamples }: Props) {
271
284
  auth,
272
285
  mergedLangs,
273
286
  ]);
274
-
275
- useEffect(() => {
287
+ // no dependencies was intentionlly set for this particular hook. it's safe as long as if conditions are set
288
+ useEffect(function onSelectedVariantUpdate() {
276
289
  if (selectedVariant && selectedVariant !== language.variant) {
277
290
  const postmanRequest = buildPostmanRequest(postman, {
278
291
  queryParams,
@@ -300,6 +313,22 @@ function CodeSnippets({ postman, codeSamples }: Props) {
300
313
  }
301
314
  });
302
315
 
316
+ // no dependencies was intentionlly set for this particular hook. it's safe as long as if conditions are set
317
+ // eslint-disable-next-line react-hooks/exhaustive-deps
318
+ useEffect(function onSelectedSampleUpdate() {
319
+ if (
320
+ language.samples &&
321
+ language.samplesSources &&
322
+ selectedSample &&
323
+ selectedSample !== language.sample
324
+ ) {
325
+ const sampleIndex = language.samples.findIndex(
326
+ (smp) => smp === selectedSample
327
+ );
328
+ setCodeSampleCodeText(language.samplesSources[sampleIndex]);
329
+ }
330
+ });
331
+
303
332
  if (language === undefined) {
304
333
  return null;
305
334
  }
@@ -311,7 +340,9 @@ function CodeSnippets({ postman, codeSamples }: Props) {
311
340
  action={{
312
341
  setLanguage: setLanguage,
313
342
  setSelectedVariant: setSelectedVariant,
343
+ setSelectedSample: setSelectedSample,
314
344
  }}
345
+ languageSet={mergedLangs}
315
346
  lazy
316
347
  >
317
348
  {mergedLangs.map((lang) => {
@@ -324,6 +355,47 @@ function CodeSnippets({ postman, codeSamples }: Props) {
324
355
  className: `openapi-tabs__code-item--${lang.logoClass}`,
325
356
  }}
326
357
  >
358
+ {lang.samples && (
359
+ <CodeTabs
360
+ className="openapi-tabs__code-container-inner"
361
+ action={{
362
+ setLanguage: setLanguage,
363
+ setSelectedSample: setSelectedSample,
364
+ }}
365
+ includeSample={true}
366
+ currentLanguage={lang.language}
367
+ defaultValue={selectedSample}
368
+ languageSet={mergedLangs}
369
+ lazy
370
+ >
371
+ {lang.samples.map((sample, index) => {
372
+ return (
373
+ <CodeTab
374
+ value={sample}
375
+ label={
376
+ lang.samplesLabels
377
+ ? lang.samplesLabels[index]
378
+ : sample
379
+ }
380
+ key={`${lang.language}-${lang.sample}`}
381
+ attributes={{
382
+ className: `openapi-tabs__code-item--sample`,
383
+ }}
384
+ >
385
+ {/* @ts-ignore */}
386
+ <ApiCodeBlock
387
+ language={lang.highlight}
388
+ className="openapi-explorer__code-block"
389
+ showLineNumbers={true}
390
+ >
391
+ {codeSampleCodeText}
392
+ </ApiCodeBlock>
393
+ </CodeTab>
394
+ );
395
+ })}
396
+ </CodeTabs>
397
+ )}
398
+
327
399
  <CodeTabs
328
400
  className="openapi-tabs__code-container-inner"
329
401
  action={{
@@ -333,9 +405,10 @@ function CodeSnippets({ postman, codeSamples }: Props) {
333
405
  includeVariant={true}
334
406
  currentLanguage={lang.language}
335
407
  defaultValue={selectedVariant}
408
+ languageSet={mergedLangs}
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()}