docusaurus-theme-openapi-docs 5.0.2 → 5.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 (137) hide show
  1. package/lib/markdown/schema.js +38 -15
  2. package/lib/markdown/schema.test.d.ts +1 -0
  3. package/lib/markdown/schema.test.js +86 -0
  4. package/lib/theme/ApiExplorer/ApiCodeBlock/Container/index.js +4 -2
  5. package/lib/theme/ApiExplorer/ApiCodeBlock/Content/String.js +9 -6
  6. package/lib/theme/ApiExplorer/ApiCodeBlock/Line/index.d.ts +1 -1
  7. package/lib/theme/ApiExplorer/ApiCodeBlock/index.d.ts +1 -1
  8. package/lib/theme/ApiExplorer/Authorization/index.js +9 -10
  9. package/lib/theme/ApiExplorer/Body/index.js +4 -5
  10. package/lib/theme/ApiExplorer/CodeSnippets/index.js +96 -61
  11. package/lib/theme/ApiExplorer/CodeSnippets/languages.js +12 -1
  12. package/lib/theme/ApiExplorer/CodeSnippets/languages.test.d.ts +1 -0
  13. package/lib/theme/ApiExplorer/CodeSnippets/languages.test.js +102 -0
  14. package/lib/theme/ApiExplorer/CodeTabs/index.d.ts +1 -1
  15. package/lib/theme/ApiExplorer/CodeTabs/index.js +6 -5
  16. package/lib/theme/ApiExplorer/Export/index.js +9 -2
  17. package/lib/theme/ApiExplorer/FormFileUpload/index.js +1 -2
  18. package/lib/theme/ApiExplorer/FormLabel/index.js +1 -2
  19. package/lib/theme/ApiExplorer/FormTextInput/index.js +1 -2
  20. package/lib/theme/ApiExplorer/LiveEditor/index.js +1 -2
  21. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.js +5 -3
  22. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.js +75 -4
  23. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.js +1 -2
  24. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.js +67 -4
  25. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.js +65 -1
  26. package/lib/theme/ApiExplorer/ParamOptions/index.js +2 -3
  27. package/lib/theme/ApiExplorer/Request/index.js +17 -18
  28. package/lib/theme/ApiExplorer/Response/index.js +54 -12
  29. package/lib/theme/ApiExplorer/SecuritySchemes/index.js +57 -50
  30. package/lib/theme/ApiExplorer/Server/index.js +2 -3
  31. package/lib/theme/ApiItem/index.js +59 -33
  32. package/lib/theme/ApiTabs/index.d.ts +1 -1
  33. package/lib/theme/ApiTabs/index.js +7 -7
  34. package/lib/theme/DiscriminatorTabs/index.d.ts +1 -1
  35. package/lib/theme/DiscriminatorTabs/index.js +6 -5
  36. package/lib/theme/Example/index.js +3 -4
  37. package/lib/theme/MimeTabs/index.d.ts +1 -1
  38. package/lib/theme/MimeTabs/index.js +6 -5
  39. package/lib/theme/OperationTabs/index.d.ts +1 -1
  40. package/lib/theme/OperationTabs/index.js +6 -5
  41. package/lib/theme/ParamsDetails/index.js +1 -2
  42. package/lib/theme/ParamsItem/index.js +7 -8
  43. package/lib/theme/RequestSchema/index.js +57 -57
  44. package/lib/theme/ResponseExamples/index.js +3 -4
  45. package/lib/theme/ResponseSchema/index.js +26 -24
  46. package/lib/theme/Schema/index.js +148 -27
  47. package/lib/theme/SchemaExpansion/_SchemaExpansion.scss +113 -0
  48. package/lib/theme/SchemaExpansion/context.d.ts +24 -0
  49. package/lib/theme/SchemaExpansion/context.js +187 -0
  50. package/lib/theme/SchemaExpansion/index.d.ts +4 -0
  51. package/lib/theme/SchemaExpansion/index.js +314 -0
  52. package/lib/theme/SchemaItem/index.js +9 -10
  53. package/lib/theme/SchemaTabs/index.d.ts +1 -1
  54. package/lib/theme/SchemaTabs/index.js +6 -5
  55. package/lib/theme/StatusCodes/index.js +2 -4
  56. package/lib/theme/TabItem/index.d.ts +5 -0
  57. package/lib/theme/TabItem/index.js +51 -0
  58. package/lib/theme/TabItem/styles.module.css +3 -0
  59. package/lib/theme/Tabs/index.d.ts +5 -0
  60. package/lib/theme/Tabs/index.js +148 -0
  61. package/lib/theme/Tabs/styles.module.css +7 -0
  62. package/lib/theme/styles.scss +1 -0
  63. package/lib/theme/translationIds.d.ts +1 -93
  64. package/lib/theme/translationIds.js +0 -109
  65. package/lib/theme/utils/codeBlockUtils.d.ts +28 -0
  66. package/lib/theme/utils/codeBlockUtils.js +223 -0
  67. package/lib/theme/utils/reactUtils.d.ts +1 -0
  68. package/lib/theme/utils/reactUtils.js +23 -0
  69. package/lib/theme/utils/scrollUtils.d.ts +7 -0
  70. package/lib/theme/utils/scrollUtils.js +175 -0
  71. package/lib/theme/utils/tabsUtils.d.ts +47 -0
  72. package/lib/theme/utils/tabsUtils.js +299 -0
  73. package/lib/theme/utils/useCodeWordWrap.d.ts +8 -0
  74. package/lib/theme/utils/useCodeWordWrap.js +84 -0
  75. package/lib/theme/utils/useMutationObserver.d.ts +3 -0
  76. package/lib/theme/utils/useMutationObserver.js +34 -0
  77. package/package.json +4 -4
  78. package/src/markdown/schema.test.ts +102 -0
  79. package/src/markdown/schema.ts +42 -15
  80. package/src/theme/ApiExplorer/ApiCodeBlock/Container/index.tsx +2 -1
  81. package/src/theme/ApiExplorer/ApiCodeBlock/Content/String.tsx +8 -7
  82. package/src/theme/ApiExplorer/ApiCodeBlock/Line/index.tsx +1 -1
  83. package/src/theme/ApiExplorer/ApiCodeBlock/index.tsx +1 -1
  84. package/src/theme/ApiExplorer/Authorization/index.tsx +9 -10
  85. package/src/theme/ApiExplorer/Body/index.tsx +7 -5
  86. package/src/theme/ApiExplorer/CodeSnippets/index.tsx +103 -59
  87. package/src/theme/ApiExplorer/CodeSnippets/languages.test.ts +109 -0
  88. package/src/theme/ApiExplorer/CodeSnippets/languages.ts +13 -1
  89. package/src/theme/ApiExplorer/CodeTabs/index.tsx +5 -5
  90. package/src/theme/ApiExplorer/Export/index.tsx +6 -2
  91. package/src/theme/ApiExplorer/FormFileUpload/index.tsx +1 -2
  92. package/src/theme/ApiExplorer/FormLabel/index.tsx +1 -2
  93. package/src/theme/ApiExplorer/FormTextInput/index.tsx +1 -2
  94. package/src/theme/ApiExplorer/LiveEditor/index.tsx +1 -2
  95. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.tsx +5 -3
  96. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.tsx +20 -4
  97. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.tsx +1 -2
  98. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.tsx +15 -4
  99. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.tsx +11 -1
  100. package/src/theme/ApiExplorer/ParamOptions/index.tsx +2 -3
  101. package/src/theme/ApiExplorer/Request/index.tsx +23 -18
  102. package/src/theme/ApiExplorer/Response/index.tsx +63 -9
  103. package/src/theme/ApiExplorer/SecuritySchemes/index.tsx +60 -52
  104. package/src/theme/ApiExplorer/Server/index.tsx +8 -3
  105. package/src/theme/ApiItem/index.tsx +43 -21
  106. package/src/theme/ApiTabs/index.tsx +8 -8
  107. package/src/theme/DiscriminatorTabs/index.tsx +6 -5
  108. package/src/theme/Example/index.tsx +3 -4
  109. package/src/theme/MimeTabs/index.tsx +9 -8
  110. package/src/theme/OperationTabs/index.tsx +5 -4
  111. package/src/theme/ParamsDetails/index.tsx +1 -2
  112. package/src/theme/ParamsItem/index.tsx +13 -8
  113. package/src/theme/RequestSchema/index.tsx +38 -40
  114. package/src/theme/ResponseExamples/index.tsx +3 -4
  115. package/src/theme/ResponseSchema/index.tsx +16 -17
  116. package/src/theme/Schema/index.tsx +156 -27
  117. package/src/theme/SchemaExpansion/_SchemaExpansion.scss +113 -0
  118. package/src/theme/SchemaExpansion/context.tsx +154 -0
  119. package/src/theme/SchemaExpansion/index.tsx +236 -0
  120. package/src/theme/SchemaItem/index.tsx +18 -10
  121. package/src/theme/SchemaTabs/index.tsx +6 -5
  122. package/src/theme/StatusCodes/index.tsx +2 -3
  123. package/src/theme/TabItem/index.tsx +61 -0
  124. package/src/theme/TabItem/styles.module.css +3 -0
  125. package/src/theme/Tabs/index.tsx +164 -0
  126. package/src/theme/Tabs/styles.module.css +7 -0
  127. package/src/theme/styles.scss +1 -0
  128. package/src/theme/translationIds.ts +37 -106
  129. package/src/theme/utils/codeBlockUtils.ts +296 -0
  130. package/src/theme/utils/reactUtils.ts +22 -0
  131. package/src/theme/utils/scrollUtils.tsx +153 -0
  132. package/src/theme/utils/tabsUtils.tsx +329 -0
  133. package/src/theme/utils/useCodeWordWrap.ts +110 -0
  134. package/src/theme/utils/useMutationObserver.ts +43 -0
  135. package/src/theme-classic.d.ts +0 -96
  136. package/src/types.d.ts +27 -0
  137. package/tsconfig.tsbuildinfo +1 -1
@@ -9,7 +9,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.getSchemaName = getSchemaName;
10
10
  exports.getQualifierMessage = getQualifierMessage;
11
11
  const Translate_1 = require("@docusaurus/Translate");
12
- const translationIds_1 = require("../theme/translationIds");
13
12
  /**
14
13
  * Extracts enum values from a schema, including when wrapped in allOf.
15
14
  */
@@ -42,13 +41,36 @@ function getTypeFromSchema(schema) {
42
41
  }
43
42
  return undefined;
44
43
  }
44
+ // OpenAPI 3.1 / JSON Schema 2020-12 allows `type` to be an array of type names
45
+ // (e.g. `["string", "null"]`). Normalize to a single name and a pretty-printed
46
+ // union form joined with ` | `.
47
+ function normalizeType(type) {
48
+ if (Array.isArray(type)) {
49
+ const filtered = type.filter((t) => typeof t === "string");
50
+ if (filtered.length === 0)
51
+ return { isUnion: false };
52
+ if (filtered.length === 1)
53
+ return { single: filtered[0], isUnion: false };
54
+ return { pretty: filtered.join(" | "), isUnion: true };
55
+ }
56
+ if (typeof type === "string")
57
+ return { single: type, isUnion: false };
58
+ return { isUnion: false };
59
+ }
45
60
  function prettyName(schema, circular) {
46
61
  // Handle enum-only schemas (valid in JSON Schema)
47
62
  // When enum is present without explicit type, treat as string
48
63
  if (schema.enum && !schema.type) {
49
64
  return "string";
50
65
  }
66
+ const t = normalizeType(schema.type);
51
67
  if (schema.format) {
68
+ if (t.single) {
69
+ return `${t.single}<${schema.format}>`;
70
+ }
71
+ if (t.isUnion) {
72
+ return `(${t.pretty})<${schema.format}>`;
73
+ }
52
74
  return schema.format;
53
75
  }
54
76
  if (schema.allOf) {
@@ -72,22 +94,23 @@ function prettyName(schema, circular) {
72
94
  if (schema.anyOf) {
73
95
  return "object";
74
96
  }
75
- if (schema.type === "object") {
76
- return schema.xml?.name ?? schema.type;
77
- // return schema.type;
97
+ if (t.single === "object") {
98
+ return schema.xml?.name ?? t.single;
78
99
  }
79
- if (schema.type === "array") {
80
- return schema.xml?.name ?? schema.type;
81
- // return schema.type;
100
+ if (t.single === "array") {
101
+ return schema.xml?.name ?? t.single;
82
102
  }
83
- if (Array.isArray(schema.type)) {
84
- return schema.type.join(" | ");
103
+ if (t.isUnion) {
104
+ return t.pretty;
85
105
  }
86
- return schema.title ?? schema.type;
106
+ return schema.title ?? t.single;
87
107
  }
88
108
  function getSchemaName(schema, circular) {
89
109
  if (schema.items) {
90
- return prettyName(schema.items, circular) + "[]";
110
+ const items = schema.items;
111
+ const inner = getSchemaName(items, circular);
112
+ const needsParens = Array.isArray(items.type) && items.type.length > 1;
113
+ return needsParens ? `(${inner})[]` : `${inner}[]`;
91
114
  }
92
115
  return prettyName(schema, circular) ?? "";
93
116
  }
@@ -106,7 +129,7 @@ function getQualifierMessage(schema) {
106
129
  return getQualifierMessage(schema.items);
107
130
  }
108
131
  let message = `**${(0, Translate_1.translate)({
109
- id: translationIds_1.OPENAPI_SCHEMA_ITEM.POSSIBLE_VALUES,
132
+ id: "theme.openapi.schemaItem.possibleValues",
110
133
  message: "Possible values:",
111
134
  })}** `;
112
135
  let qualifierGroups = [];
@@ -122,11 +145,11 @@ function getQualifierMessage(schema) {
122
145
  let minLength;
123
146
  let maxLength;
124
147
  const charactersMessage = (0, Translate_1.translate)({
125
- id: translationIds_1.OPENAPI_SCHEMA_ITEM.CHARACTERS,
148
+ id: "theme.openapi.schemaItem.characters",
126
149
  message: "characters",
127
150
  });
128
151
  const nonEmptyMessage = (0, Translate_1.translate)({
129
- id: translationIds_1.OPENAPI_SCHEMA_ITEM.NON_EMPTY,
152
+ id: "theme.openapi.schemaItem.nonEmpty",
130
153
  message: "non-empty",
131
154
  });
132
155
  if (schema.minLength && schema.minLength > 1) {
@@ -187,7 +210,7 @@ function getQualifierMessage(schema) {
187
210
  }
188
211
  if (schema.pattern) {
189
212
  const expressionMessage = (0, Translate_1.translate)({
190
- id: translationIds_1.OPENAPI_SCHEMA_ITEM.EXPRESSION,
213
+ id: "theme.openapi.schemaItem.expression",
191
214
  message: "Value must match regular expression",
192
215
  });
193
216
  qualifierGroups.push(`${expressionMessage} \`${schema.pattern}\``);
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ /* ============================================================================
3
+ * Copyright (c) Palo Alto Networks
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ * ========================================================================== */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ jest.mock("@docusaurus/Translate", () => ({
10
+ translate: ({ message }) => message,
11
+ }), { virtual: true });
12
+ const schema_1 = require("./schema");
13
+ describe("getSchemaName", () => {
14
+ it("returns the type for a primitive schema", () => {
15
+ expect((0, schema_1.getSchemaName)({ type: "string" })).toBe("string");
16
+ });
17
+ it("appends [] for an array of primitives", () => {
18
+ const schema = {
19
+ type: "array",
20
+ items: { type: "string" },
21
+ };
22
+ expect((0, schema_1.getSchemaName)(schema)).toBe("string[]");
23
+ });
24
+ it("appends [][] for an array of arrays of primitives", () => {
25
+ const schema = {
26
+ type: "array",
27
+ items: { type: "array", items: { type: "string" } },
28
+ };
29
+ expect((0, schema_1.getSchemaName)(schema)).toBe("string[][]");
30
+ });
31
+ it("appends [][] for an array of arrays of objects (issue #1114)", () => {
32
+ const schema = {
33
+ type: "array",
34
+ items: {
35
+ type: "array",
36
+ items: { type: "object", properties: { foo: { type: "string" } } },
37
+ },
38
+ };
39
+ expect((0, schema_1.getSchemaName)(schema)).toBe("object[][]");
40
+ });
41
+ it("handles three levels of array nesting", () => {
42
+ const schema = {
43
+ type: "array",
44
+ items: {
45
+ type: "array",
46
+ items: { type: "array", items: { type: "integer" } },
47
+ },
48
+ };
49
+ expect((0, schema_1.getSchemaName)(schema)).toBe("integer[][][]");
50
+ });
51
+ it("joins OpenAPI 3.1 type arrays with ` | ` (issue #950)", () => {
52
+ const schema = { type: ["string", "null"] };
53
+ expect((0, schema_1.getSchemaName)(schema)).toBe("string | null");
54
+ });
55
+ it("unwraps a single-element type array", () => {
56
+ const schema = { type: ["integer"] };
57
+ expect((0, schema_1.getSchemaName)(schema)).toBe("integer");
58
+ });
59
+ it("renders single type with format as `type<format>`", () => {
60
+ const schema = {
61
+ type: "string",
62
+ format: "uuid",
63
+ };
64
+ expect((0, schema_1.getSchemaName)(schema)).toBe("string<uuid>");
65
+ });
66
+ it("renders type union with format", () => {
67
+ const schema = {
68
+ type: ["string", "null"],
69
+ format: "uuid",
70
+ };
71
+ expect((0, schema_1.getSchemaName)(schema)).toBe("(string | null)<uuid>");
72
+ });
73
+ it("resolves type from an allOf wrapper that contains an enum", () => {
74
+ const schema = {
75
+ allOf: [{ type: "string", enum: ["a", "b"] }],
76
+ };
77
+ expect((0, schema_1.getSchemaName)(schema)).toBe("string");
78
+ });
79
+ it("renders array of items whose type is a union", () => {
80
+ const schema = {
81
+ type: "array",
82
+ items: { type: ["string", "null"] },
83
+ };
84
+ expect((0, schema_1.getSchemaName)(schema)).toBe("(string | null)[]");
85
+ });
86
+ });
@@ -14,11 +14,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.default = CodeBlockContainer;
15
15
  const react_1 = __importDefault(require("react"));
16
16
  const theme_common_1 = require("@docusaurus/theme-common");
17
- const internal_1 = require("@docusaurus/theme-common/internal");
18
17
  const clsx_1 = __importDefault(require("clsx"));
18
+ const codeBlockUtils_1 = require("@theme/utils/codeBlockUtils");
19
19
  function CodeBlockContainer({ as: As, ...props }) {
20
20
  const prismTheme = (0, theme_common_1.usePrismTheme)();
21
- const prismCssVariables = (0, internal_1.getPrismCssVariables)(prismTheme);
21
+ const prismCssVariables = (0, codeBlockUtils_1.getPrismCssVariables)(
22
+ prismTheme
23
+ );
22
24
  return react_1.default.createElement(
23
25
  As,
24
26
  // Polymorphic components are hard to type, without `oneOf` generics
@@ -14,7 +14,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
14
14
  exports.default = CodeBlockString;
15
15
  const react_1 = __importDefault(require("react"));
16
16
  const theme_common_1 = require("@docusaurus/theme-common");
17
- const internal_1 = require("@docusaurus/theme-common/internal");
18
17
  const Container_1 = __importDefault(
19
18
  require("@theme/ApiExplorer/ApiCodeBlock/Container")
20
19
  );
@@ -30,6 +29,8 @@ const WordWrapButton_1 = __importDefault(
30
29
  );
31
30
  const clsx_1 = __importDefault(require("clsx"));
32
31
  const prism_react_renderer_1 = require("prism-react-renderer");
32
+ const codeBlockUtils_1 = require("@theme/utils/codeBlockUtils");
33
+ const useCodeWordWrap_1 = require("@theme/utils/useCodeWordWrap");
33
34
  function CodeBlockString({
34
35
  children,
35
36
  className: blockClassName = "",
@@ -43,21 +44,23 @@ function CodeBlockString({
43
44
  } = (0, theme_common_1.useThemeConfig)();
44
45
  const language =
45
46
  languageProp ??
46
- (0, internal_1.parseLanguage)(blockClassName) ??
47
+ (0, codeBlockUtils_1.parseLanguage)(blockClassName) ??
47
48
  defaultLanguage;
48
49
  const prismTheme = (0, theme_common_1.usePrismTheme)();
49
- const wordWrap = (0, internal_1.useCodeWordWrap)();
50
+ const wordWrap = (0, useCodeWordWrap_1.useCodeWordWrap)();
50
51
  // We still parse the metastring in case we want to support more syntax in the
51
52
  // future. Note that MDX doesn't strip quotes when parsing metastring:
52
53
  // "title=\"xyz\"" => title: "\"xyz\""
53
- const title = (0, internal_1.parseCodeBlockTitle)(metastring) || titleProp;
54
- const { lineClassNames, code } = (0, internal_1.parseLines)(children, {
54
+ const title =
55
+ (0, codeBlockUtils_1.parseCodeBlockTitle)(metastring) || titleProp;
56
+ const { lineClassNames, code } = (0, codeBlockUtils_1.parseLines)(children, {
55
57
  metastring,
56
58
  language,
57
59
  magicComments,
58
60
  });
59
61
  const showLineNumbers =
60
- showLineNumbersProp ?? (0, internal_1.containsLineNumbers)(metastring);
62
+ showLineNumbersProp ??
63
+ (0, codeBlockUtils_1.containsLineNumbers)(metastring);
61
64
  return react_1.default.createElement(
62
65
  Container_1.default,
63
66
  {
@@ -1,3 +1,3 @@
1
1
  import React from "react";
2
- import { LineProps } from "@docusaurus/theme-common/internal";
2
+ import type { Props as LineProps } from "@theme/CodeBlock/Line";
3
3
  export default function CodeBlockLine({ line, classNames, showLineNumbers, getLineProps, getTokenProps, }: LineProps): React.JSX.Element;
@@ -1,3 +1,3 @@
1
1
  import React from "react";
2
- import { CodeBlockProps } from "@docusaurus/theme-common/internal";
2
+ import type { Props as CodeBlockProps } from "@theme/CodeBlock";
3
3
  export default function ApiCodeBlock({ children: rawChildren, ...props }: CodeBlockProps): React.JSX.Element;
@@ -19,7 +19,6 @@ const FormTextInput_1 = __importDefault(
19
19
  require("@theme/ApiExplorer/FormTextInput")
20
20
  );
21
21
  const hooks_1 = require("@theme/ApiItem/hooks");
22
- const translationIds_1 = require("@theme/translationIds");
23
22
  const slice_1 = require("./slice");
24
23
  function Authorization() {
25
24
  const data = (0, hooks_1.useTypedSelector)((state) => state.auth.data);
@@ -42,7 +41,7 @@ function Authorization() {
42
41
  null,
43
42
  react_1.default.createElement(FormSelect_1.default, {
44
43
  label: (0, Translate_1.translate)({
45
- id: translationIds_1.OPENAPI_AUTH.SECURITY_SCHEME,
44
+ id: "theme.openapi.auth.securityScheme",
46
45
  message: "Security Scheme",
47
46
  }),
48
47
  options: optionKeys,
@@ -59,11 +58,11 @@ function Authorization() {
59
58
  { key: a.key + "-bearer" },
60
59
  react_1.default.createElement(FormTextInput_1.default, {
61
60
  label: (0, Translate_1.translate)({
62
- id: translationIds_1.OPENAPI_AUTH.BEARER_TOKEN,
61
+ id: "theme.openapi.auth.bearerToken",
63
62
  message: "Bearer Token",
64
63
  }),
65
64
  placeholder: (0, Translate_1.translate)({
66
- id: translationIds_1.OPENAPI_AUTH.BEARER_TOKEN,
65
+ id: "theme.openapi.auth.bearerToken",
67
66
  message: "Bearer Token",
68
67
  }),
69
68
  password: true,
@@ -87,11 +86,11 @@ function Authorization() {
87
86
  { key: a.key + "-oauth2" },
88
87
  react_1.default.createElement(FormTextInput_1.default, {
89
88
  label: (0, Translate_1.translate)({
90
- id: translationIds_1.OPENAPI_AUTH.BEARER_TOKEN,
89
+ id: "theme.openapi.auth.bearerToken",
91
90
  message: "Bearer Token",
92
91
  }),
93
92
  placeholder: (0, Translate_1.translate)({
94
- id: translationIds_1.OPENAPI_AUTH.BEARER_TOKEN,
93
+ id: "theme.openapi.auth.bearerToken",
95
94
  message: "Bearer Token",
96
95
  }),
97
96
  password: true,
@@ -118,11 +117,11 @@ function Authorization() {
118
117
  null,
119
118
  react_1.default.createElement(FormTextInput_1.default, {
120
119
  label: (0, Translate_1.translate)({
121
- id: translationIds_1.OPENAPI_AUTH.USERNAME,
120
+ id: "theme.openapi.auth.username",
122
121
  message: "Username",
123
122
  }),
124
123
  placeholder: (0, Translate_1.translate)({
125
- id: translationIds_1.OPENAPI_AUTH.USERNAME,
124
+ id: "theme.openapi.auth.username",
126
125
  message: "Username",
127
126
  }),
128
127
  value: data[a.key].username ?? "",
@@ -143,11 +142,11 @@ function Authorization() {
143
142
  null,
144
143
  react_1.default.createElement(FormTextInput_1.default, {
145
144
  label: (0, Translate_1.translate)({
146
- id: translationIds_1.OPENAPI_AUTH.PASSWORD,
145
+ id: "theme.openapi.auth.password",
147
146
  message: "Password",
148
147
  }),
149
148
  placeholder: (0, Translate_1.translate)({
150
- id: translationIds_1.OPENAPI_AUTH.PASSWORD,
149
+ id: "theme.openapi.auth.password",
151
150
  message: "Password",
152
151
  }),
153
152
  password: true,
@@ -79,7 +79,6 @@ const hooks_1 = require("@theme/ApiItem/hooks");
79
79
  const Markdown_1 = __importDefault(require("@theme/Markdown"));
80
80
  const SchemaTabs_1 = __importDefault(require("@theme/SchemaTabs"));
81
81
  const TabItem_1 = __importDefault(require("@theme/TabItem"));
82
- const translationIds_1 = require("@theme/translationIds");
83
82
  const createSchemaExample_1 = require("docusaurus-plugin-openapi-docs/lib/openapi/createSchemaExample");
84
83
  const xml_formatter_1 = __importDefault(require("xml-formatter"));
85
84
  const FormBodyItem_1 = __importDefault(require("./FormBodyItem"));
@@ -340,7 +339,7 @@ function Body({
340
339
  placeholder:
341
340
  schema.description ||
342
341
  (0, Translate_1.translate)({
343
- id: translationIds_1.OPENAPI_REQUEST.BODY_TITLE,
342
+ id: "theme.openapi.request.body.title",
344
343
  message: "Body",
345
344
  }),
346
345
  onChange: (file) => {
@@ -373,7 +372,7 @@ function Body({
373
372
  TabItem_1.default,
374
373
  {
375
374
  label: (0, Translate_1.translate)({
376
- id: translationIds_1.OPENAPI_BODY.EXAMPLE_FROM_SCHEMA,
375
+ id: "theme.openapi.body.exampleFromSchema",
377
376
  message: "Example (from schema)",
378
377
  }),
379
378
  value: "Example (from schema)",
@@ -465,7 +464,7 @@ function Body({
465
464
  TabItem_1.default,
466
465
  {
467
466
  label: (0, Translate_1.translate)({
468
- id: translationIds_1.OPENAPI_BODY.EXAMPLE_FROM_SCHEMA,
467
+ id: "theme.openapi.body.exampleFromSchema",
469
468
  message: "Example (from schema)",
470
469
  }),
471
470
  value: "Example (from schema)",
@@ -517,7 +516,7 @@ function Body({
517
516
  TabItem_1.default,
518
517
  {
519
518
  label: (0, Translate_1.translate)({
520
- id: translationIds_1.OPENAPI_BODY.EXAMPLE_FROM_SCHEMA,
519
+ id: "theme.openapi.body.exampleFromSchema",
521
520
  message: "Example (from schema)",
522
521
  }),
523
522
  value: "Example (from schema)",
@@ -69,6 +69,7 @@ var __importDefault =
69
69
  Object.defineProperty(exports, "__esModule", { value: true });
70
70
  exports.languageSet = void 0;
71
71
  const react_1 = __importStar(require("react"));
72
+ const theme_common_1 = require("@docusaurus/theme-common");
72
73
  const useDocusaurusContext_1 = __importDefault(
73
74
  require("@docusaurus/useDocusaurusContext")
74
75
  );
@@ -94,6 +95,17 @@ function CodeTab({ children, hidden, className }) {
94
95
  children
95
96
  );
96
97
  }
98
+ /** Align with Docusaurus `<Tabs groupId="code-samples">` persisted tab value. */
99
+ function resolveOuterLanguageFromPersistedTab(persistedTab, langs) {
100
+ if (langs.length === 1) {
101
+ return langs[0];
102
+ }
103
+ const matched = langs.find((lang) => lang.language === persistedTab);
104
+ if (matched) {
105
+ return matched;
106
+ }
107
+ return langs[0];
108
+ }
97
109
  function CodeSnippets({
98
110
  postman,
99
111
  codeSamples,
@@ -163,43 +175,62 @@ function CodeSnippets({
163
175
  auth: cleanedAuth,
164
176
  encoding,
165
177
  });
178
+ const themeConfig = siteConfig.themeConfig;
179
+ const hideGeneratedSnippets =
180
+ themeConfig?.api?.hideGeneratedSnippets ?? false;
166
181
  // User-defined languages array
167
182
  // Can override languageSet, change order of langs, override options and variants
168
183
  const userDefinedLanguageSet =
169
184
  siteConfig?.themeConfig?.languageTabs ?? exports.languageSet;
170
- // Filter languageSet by user-defined langs
171
- const filteredLanguageSet = exports.languageSet.filter((ls) => {
172
- return userDefinedLanguageSet?.some((lang) => {
173
- return lang.language === ls.language;
185
+ const mergedLangs = (0, react_1.useMemo)(() => {
186
+ const filteredLanguageSet = exports.languageSet.filter((ls) => {
187
+ return userDefinedLanguageSet?.some((lang) => {
188
+ return lang.language === ls.language;
189
+ });
174
190
  });
175
- });
176
- // Merge user-defined langs into languageSet
177
- const mergedLangs = (0, languages_1.mergeCodeSampleLanguage)(
178
- (0, languages_1.mergeArraysbyLanguage)(
179
- userDefinedLanguageSet,
180
- filteredLanguageSet
181
- ),
182
- codeSamples
191
+ return (0, languages_1.mergeCodeSampleLanguage)(
192
+ (0, languages_1.mergeArraysbyLanguage)(
193
+ userDefinedLanguageSet,
194
+ filteredLanguageSet
195
+ ),
196
+ codeSamples
197
+ );
198
+ }, [userDefinedLanguageSet, codeSamples]);
199
+ const [persistedOuterTab] = (0, theme_common_1.useStorageSlot)(
200
+ "docusaurus.tab.code-samples"
183
201
  );
184
- // Read defaultLang from localStorage
185
- const defaultLang = mergedLangs.filter(
186
- (lang) =>
187
- lang.language === localStorage.getItem("docusaurus.tab.code-samples")
202
+ const initialOuterLanguage = (0, react_1.useMemo)(
203
+ () => resolveOuterLanguageFromPersistedTab(persistedOuterTab, mergedLangs),
204
+ [persistedOuterTab, mergedLangs]
188
205
  );
189
206
  const [selectedVariant, setSelectedVariant] = (0, react_1.useState)();
190
207
  const [selectedSample, setSelectedSample] = (0, react_1.useState)();
191
- const [language, setLanguage] = (0, react_1.useState)(() => {
192
- // Return first index if only 1 user-defined language exists
193
- if (mergedLangs.length === 1) {
194
- return mergedLangs[0];
195
- }
196
- // Fall back to language in localStorage or first user-defined language
197
- return defaultLang[0] ?? mergedLangs[0];
198
- });
208
+ const [language, setLanguage] = (0, react_1.useState)(() =>
209
+ resolveOuterLanguageFromPersistedTab(persistedOuterTab, mergedLangs)
210
+ );
211
+ (0, react_1.useEffect)(() => {
212
+ const next = resolveOuterLanguageFromPersistedTab(
213
+ persistedOuterTab,
214
+ mergedLangs
215
+ );
216
+ setLanguage((prev) => {
217
+ if (prev?.language !== next.language) {
218
+ return next;
219
+ }
220
+ return mergedLangs.find((l) => l.language === next.language) ?? next;
221
+ });
222
+ }, [persistedOuterTab, mergedLangs]);
199
223
  const [codeText, setCodeText] = (0, react_1.useState)("");
200
224
  const [codeSampleCodeText, setCodeSampleCodeText] = (0, react_1.useState)(
201
225
  () => (0, languages_1.getCodeSampleSourceFromLanguage)(language)
202
226
  );
227
+ // Reset selectedSample whenever the active language changes so the inner
228
+ // tab strip falls back to its first sample instead of trying to match an
229
+ // id that belongs to a different language's samples.
230
+ (0, react_1.useEffect)(() => {
231
+ setSelectedSample(language?.samples?.[0]);
232
+ // eslint-disable-next-line react-hooks/exhaustive-deps
233
+ }, [language?.language]);
203
234
  (0, react_1.useEffect)(() => {
204
235
  if (language && !!language.sample) {
205
236
  setCodeSampleCodeText(
@@ -305,7 +336,7 @@ function CodeSnippets({
305
336
  setSelectedSample: setSelectedSample,
306
337
  },
307
338
  languageSet: mergedLangs,
308
- defaultValue: defaultLang[0]?.language ?? mergedLangs[0].language,
339
+ defaultValue: initialOuterLanguage.language,
309
340
  lazy: true,
310
341
  },
311
342
  mergedLangs.map((lang) => {
@@ -330,7 +361,10 @@ function CodeSnippets({
330
361
  },
331
362
  includeSample: true,
332
363
  currentLanguage: lang,
333
- defaultValue: selectedSample,
364
+ defaultValue:
365
+ selectedSample && lang.samples.includes(selectedSample)
366
+ ? selectedSample
367
+ : lang.samples[0],
334
368
  languageSet: mergedLangs,
335
369
  lazy: true,
336
370
  },
@@ -342,7 +376,7 @@ function CodeSnippets({
342
376
  label: lang.samplesLabels
343
377
  ? lang.samplesLabels[index]
344
378
  : sample,
345
- key: `${lang.language}-${lang.sample}`,
379
+ key: `${lang.language}-${sample}`,
346
380
  attributes: {
347
381
  className: `openapi-tabs__code-item--sample`,
348
382
  },
@@ -359,43 +393,44 @@ function CodeSnippets({
359
393
  );
360
394
  })
361
395
  ),
362
- react_1.default.createElement(
363
- CodeTabs_1.default,
364
- {
365
- className: "openapi-tabs__code-container-inner",
366
- action: {
367
- setLanguage: setLanguage,
368
- setSelectedVariant: setSelectedVariant,
369
- },
370
- includeVariant: true,
371
- currentLanguage: lang,
372
- defaultValue: selectedVariant,
373
- languageSet: mergedLangs,
374
- lazy: true,
375
- },
376
- lang.variants.map((variant, index) => {
377
- return react_1.default.createElement(
378
- CodeTab,
379
- {
380
- value: variant.toLowerCase(),
381
- label: variant.toUpperCase(),
382
- key: `${lang.language}-${lang.variant}`,
383
- attributes: {
384
- className: `openapi-tabs__code-item--variant`,
385
- },
396
+ !(hideGeneratedSnippets && lang.samples?.length) &&
397
+ react_1.default.createElement(
398
+ CodeTabs_1.default,
399
+ {
400
+ className: "openapi-tabs__code-container-inner",
401
+ action: {
402
+ setLanguage: setLanguage,
403
+ setSelectedVariant: setSelectedVariant,
386
404
  },
387
- react_1.default.createElement(
388
- ApiCodeBlock_1.default,
405
+ includeVariant: true,
406
+ currentLanguage: lang,
407
+ defaultValue: selectedVariant,
408
+ languageSet: mergedLangs,
409
+ lazy: true,
410
+ },
411
+ lang.variants.map((variant, index) => {
412
+ return react_1.default.createElement(
413
+ CodeTab,
389
414
  {
390
- language: lang.highlight,
391
- className: "openapi-explorer__code-block",
392
- showLineNumbers: true,
415
+ value: variant.toLowerCase(),
416
+ label: variant.toUpperCase(),
417
+ key: `${lang.language}-${variant}`,
418
+ attributes: {
419
+ className: `openapi-tabs__code-item--variant`,
420
+ },
393
421
  },
394
- codeText
395
- )
396
- );
397
- })
398
- )
422
+ react_1.default.createElement(
423
+ ApiCodeBlock_1.default,
424
+ {
425
+ language: lang.highlight,
426
+ className: "openapi-explorer__code-block",
427
+ showLineNumbers: true,
428
+ },
429
+ codeText
430
+ )
431
+ );
432
+ })
433
+ )
399
434
  );
400
435
  })
401
436
  )
@@ -27,11 +27,22 @@ function mergeCodeSampleLanguage(languages, codeSamples) {
27
27
  ({ lang }) => lang === language.codeSampleLanguage
28
28
  );
29
29
  if (languageCodeSamples.length) {
30
- const samples = languageCodeSamples.map(({ lang }) => lang);
31
30
  const samplesLabels = languageCodeSamples.map(
32
31
  ({ label, lang }) => label || lang
33
32
  );
34
33
  const samplesSources = languageCodeSamples.map(({ source }) => source);
34
+ // Build a unique id per sample for use as the inner Tab's `value`.
35
+ // Prefer `${lang}-${label}`; fall back to `${lang}-${index}` when no
36
+ // label is provided. Defensively suffix with `-${index}` on collision
37
+ // so duplicate-label specs render two visually identical tabs instead
38
+ // of crashing Docusaurus's unique-value check.
39
+ const seen = new Set();
40
+ const samples = languageCodeSamples.map((cs, i) => {
41
+ const base = cs.label ? `${cs.lang}-${cs.label}` : `${cs.lang}-${i}`;
42
+ const id = seen.has(base) ? `${base}-${i}` : base;
43
+ seen.add(id);
44
+ return id;
45
+ });
35
46
  return {
36
47
  ...language,
37
48
  sample: samples[0],