docusaurus-theme-openapi-docs 0.0.0-1252 → 0.0.0-1253
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.
- package/lib/theme/ApiExplorer/CodeSnippets/index.js +50 -36
- package/lib/theme/ApiExplorer/CodeSnippets/languages.js +12 -1
- package/lib/theme/ApiExplorer/CodeSnippets/languages.test.d.ts +1 -0
- package/lib/theme/ApiExplorer/CodeSnippets/languages.test.js +102 -0
- package/package.json +3 -3
- package/src/theme/ApiExplorer/CodeSnippets/index.tsx +55 -35
- package/src/theme/ApiExplorer/CodeSnippets/languages.test.ts +109 -0
- package/src/theme/ApiExplorer/CodeSnippets/languages.ts +13 -1
- package/src/types.d.ts +9 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -163,6 +163,9 @@ function CodeSnippets({
|
|
|
163
163
|
auth: cleanedAuth,
|
|
164
164
|
encoding,
|
|
165
165
|
});
|
|
166
|
+
const themeConfig = siteConfig.themeConfig;
|
|
167
|
+
const hideGeneratedSnippets =
|
|
168
|
+
themeConfig?.api?.hideGeneratedSnippets ?? false;
|
|
166
169
|
// User-defined languages array
|
|
167
170
|
// Can override languageSet, change order of langs, override options and variants
|
|
168
171
|
const userDefinedLanguageSet =
|
|
@@ -200,6 +203,13 @@ function CodeSnippets({
|
|
|
200
203
|
const [codeSampleCodeText, setCodeSampleCodeText] = (0, react_1.useState)(
|
|
201
204
|
() => (0, languages_1.getCodeSampleSourceFromLanguage)(language)
|
|
202
205
|
);
|
|
206
|
+
// Reset selectedSample whenever the active language changes so the inner
|
|
207
|
+
// tab strip falls back to its first sample instead of trying to match an
|
|
208
|
+
// id that belongs to a different language's samples.
|
|
209
|
+
(0, react_1.useEffect)(() => {
|
|
210
|
+
setSelectedSample(language?.samples?.[0]);
|
|
211
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
212
|
+
}, [language?.language]);
|
|
203
213
|
(0, react_1.useEffect)(() => {
|
|
204
214
|
if (language && !!language.sample) {
|
|
205
215
|
setCodeSampleCodeText(
|
|
@@ -330,7 +340,10 @@ function CodeSnippets({
|
|
|
330
340
|
},
|
|
331
341
|
includeSample: true,
|
|
332
342
|
currentLanguage: lang,
|
|
333
|
-
defaultValue:
|
|
343
|
+
defaultValue:
|
|
344
|
+
selectedSample && lang.samples.includes(selectedSample)
|
|
345
|
+
? selectedSample
|
|
346
|
+
: lang.samples[0],
|
|
334
347
|
languageSet: mergedLangs,
|
|
335
348
|
lazy: true,
|
|
336
349
|
},
|
|
@@ -342,7 +355,7 @@ function CodeSnippets({
|
|
|
342
355
|
label: lang.samplesLabels
|
|
343
356
|
? lang.samplesLabels[index]
|
|
344
357
|
: sample,
|
|
345
|
-
key: `${lang.language}-${
|
|
358
|
+
key: `${lang.language}-${sample}`,
|
|
346
359
|
attributes: {
|
|
347
360
|
className: `openapi-tabs__code-item--sample`,
|
|
348
361
|
},
|
|
@@ -359,43 +372,44 @@ function CodeSnippets({
|
|
|
359
372
|
);
|
|
360
373
|
})
|
|
361
374
|
),
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
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
|
-
},
|
|
375
|
+
!(hideGeneratedSnippets && lang.samples?.length) &&
|
|
376
|
+
react_1.default.createElement(
|
|
377
|
+
CodeTabs_1.default,
|
|
378
|
+
{
|
|
379
|
+
className: "openapi-tabs__code-container-inner",
|
|
380
|
+
action: {
|
|
381
|
+
setLanguage: setLanguage,
|
|
382
|
+
setSelectedVariant: setSelectedVariant,
|
|
386
383
|
},
|
|
387
|
-
|
|
388
|
-
|
|
384
|
+
includeVariant: true,
|
|
385
|
+
currentLanguage: lang,
|
|
386
|
+
defaultValue: selectedVariant,
|
|
387
|
+
languageSet: mergedLangs,
|
|
388
|
+
lazy: true,
|
|
389
|
+
},
|
|
390
|
+
lang.variants.map((variant, index) => {
|
|
391
|
+
return react_1.default.createElement(
|
|
392
|
+
CodeTab,
|
|
389
393
|
{
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
394
|
+
value: variant.toLowerCase(),
|
|
395
|
+
label: variant.toUpperCase(),
|
|
396
|
+
key: `${lang.language}-${variant}`,
|
|
397
|
+
attributes: {
|
|
398
|
+
className: `openapi-tabs__code-item--variant`,
|
|
399
|
+
},
|
|
393
400
|
},
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
401
|
+
react_1.default.createElement(
|
|
402
|
+
ApiCodeBlock_1.default,
|
|
403
|
+
{
|
|
404
|
+
language: lang.highlight,
|
|
405
|
+
className: "openapi-explorer__code-block",
|
|
406
|
+
showLineNumbers: true,
|
|
407
|
+
},
|
|
408
|
+
codeText
|
|
409
|
+
)
|
|
410
|
+
);
|
|
411
|
+
})
|
|
412
|
+
)
|
|
399
413
|
);
|
|
400
414
|
})
|
|
401
415
|
)
|
|
@@ -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],
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,102 @@
|
|
|
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
|
+
const languages_1 = require("./languages");
|
|
10
|
+
const baseLang = (language, codeSampleLanguage) => ({
|
|
11
|
+
highlight: language,
|
|
12
|
+
language,
|
|
13
|
+
codeSampleLanguage,
|
|
14
|
+
logoClass: language,
|
|
15
|
+
variant: "http",
|
|
16
|
+
variants: ["http"],
|
|
17
|
+
});
|
|
18
|
+
describe("mergeCodeSampleLanguage", () => {
|
|
19
|
+
it("returns the language unchanged when no codeSamples target it", () => {
|
|
20
|
+
const langs = [baseLang("python", "Python")];
|
|
21
|
+
const result = (0, languages_1.mergeCodeSampleLanguage)(langs, []);
|
|
22
|
+
expect(result[0]).toEqual(langs[0]);
|
|
23
|
+
expect(result[0].samples).toBeUndefined();
|
|
24
|
+
});
|
|
25
|
+
it("attaches a single sample with no label using an indexed id", () => {
|
|
26
|
+
const samples = [{ lang: "Python", source: "print('hi')" }];
|
|
27
|
+
const [py] = (0, languages_1.mergeCodeSampleLanguage)(
|
|
28
|
+
[baseLang("python", "Python")],
|
|
29
|
+
samples
|
|
30
|
+
);
|
|
31
|
+
expect(py.samples).toEqual(["Python-0"]);
|
|
32
|
+
expect(py.samplesLabels).toEqual(["Python"]);
|
|
33
|
+
expect(py.samplesSources).toEqual(["print('hi')"]);
|
|
34
|
+
expect(py.sample).toBe("Python-0");
|
|
35
|
+
});
|
|
36
|
+
it("attaches a single sample with a label using lang-label id", () => {
|
|
37
|
+
const samples = [{ lang: "PHP", label: "Custom", source: "<?php" }];
|
|
38
|
+
const [php] = (0, languages_1.mergeCodeSampleLanguage)(
|
|
39
|
+
[baseLang("php", "PHP")],
|
|
40
|
+
samples
|
|
41
|
+
);
|
|
42
|
+
expect(php.samples).toEqual(["PHP-Custom"]);
|
|
43
|
+
expect(php.samplesLabels).toEqual(["Custom"]);
|
|
44
|
+
});
|
|
45
|
+
it("produces unique ids for multiple samples sharing a lang with distinct labels (#1204)", () => {
|
|
46
|
+
const samples = [
|
|
47
|
+
{ lang: "Python", label: "KeyPair Auth", source: "a" },
|
|
48
|
+
{ lang: "Python", label: "Basic Auth", source: "b" },
|
|
49
|
+
{ lang: "Python", label: "OAuth", source: "c" },
|
|
50
|
+
];
|
|
51
|
+
const [py] = (0, languages_1.mergeCodeSampleLanguage)(
|
|
52
|
+
[baseLang("python", "Python")],
|
|
53
|
+
samples
|
|
54
|
+
);
|
|
55
|
+
expect(py.samples).toEqual([
|
|
56
|
+
"Python-KeyPair Auth",
|
|
57
|
+
"Python-Basic Auth",
|
|
58
|
+
"Python-OAuth",
|
|
59
|
+
]);
|
|
60
|
+
expect(new Set(py.samples).size).toBe(3);
|
|
61
|
+
expect(py.samplesLabels).toEqual(["KeyPair Auth", "Basic Auth", "OAuth"]);
|
|
62
|
+
expect(py.samplesSources).toEqual(["a", "b", "c"]);
|
|
63
|
+
});
|
|
64
|
+
it("produces unique indexed ids for multiple samples sharing a lang without labels", () => {
|
|
65
|
+
const samples = [
|
|
66
|
+
{ lang: "PowerShell", source: "x" },
|
|
67
|
+
{ lang: "PowerShell", source: "y" },
|
|
68
|
+
];
|
|
69
|
+
const [ps] = (0, languages_1.mergeCodeSampleLanguage)(
|
|
70
|
+
[baseLang("powershell", "PowerShell")],
|
|
71
|
+
samples
|
|
72
|
+
);
|
|
73
|
+
expect(ps.samples).toEqual(["PowerShell-0", "PowerShell-1"]);
|
|
74
|
+
expect(new Set(ps.samples).size).toBe(2);
|
|
75
|
+
expect(ps.samplesLabels).toEqual(["PowerShell", "PowerShell"]);
|
|
76
|
+
});
|
|
77
|
+
it("defensively suffixes ids when lang+label collides", () => {
|
|
78
|
+
const samples = [
|
|
79
|
+
{ lang: "Java", label: "Auth", source: "a" },
|
|
80
|
+
{ lang: "Java", label: "Auth", source: "b" },
|
|
81
|
+
];
|
|
82
|
+
const [java] = (0, languages_1.mergeCodeSampleLanguage)(
|
|
83
|
+
[baseLang("java", "Java")],
|
|
84
|
+
samples
|
|
85
|
+
);
|
|
86
|
+
expect(java.samples).toEqual(["Java-Auth", "Java-Auth-1"]);
|
|
87
|
+
expect(new Set(java.samples).size).toBe(2);
|
|
88
|
+
expect(java.samplesLabels).toEqual(["Auth", "Auth"]);
|
|
89
|
+
});
|
|
90
|
+
it("filters codeSamples by codeSampleLanguage and leaves other languages alone", () => {
|
|
91
|
+
const samples = [
|
|
92
|
+
{ lang: "Python", label: "A", source: "a" },
|
|
93
|
+
{ lang: "Java", label: "B", source: "b" },
|
|
94
|
+
];
|
|
95
|
+
const result = (0, languages_1.mergeCodeSampleLanguage)(
|
|
96
|
+
[baseLang("python", "Python"), baseLang("php", "PHP")],
|
|
97
|
+
samples
|
|
98
|
+
);
|
|
99
|
+
expect(result[0].samples).toEqual(["Python-A"]);
|
|
100
|
+
expect(result[1].samples).toBeUndefined();
|
|
101
|
+
});
|
|
102
|
+
});
|
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": "0.0.0-
|
|
4
|
+
"version": "0.0.0-1253",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"openapi",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"@types/postman-collection": "^3.5.11",
|
|
39
39
|
"@types/react-modal": "^3.16.3",
|
|
40
40
|
"concurrently": "^9.2.0",
|
|
41
|
-
"docusaurus-plugin-openapi-docs": "0.0.0-
|
|
41
|
+
"docusaurus-plugin-openapi-docs": "0.0.0-1253",
|
|
42
42
|
"docusaurus-plugin-sass": "^0.2.6",
|
|
43
43
|
"eslint-plugin-prettier": "^5.5.1"
|
|
44
44
|
},
|
|
@@ -82,5 +82,5 @@
|
|
|
82
82
|
"engines": {
|
|
83
83
|
"node": ">=14"
|
|
84
84
|
},
|
|
85
|
-
"gitHead": "
|
|
85
|
+
"gitHead": "572b776cbdb70b7e5bcf7d0f976c3bbf894cc627"
|
|
86
86
|
}
|
|
@@ -17,6 +17,8 @@ import cloneDeep from "lodash/cloneDeep";
|
|
|
17
17
|
import codegen from "postman-code-generators";
|
|
18
18
|
import * as sdk from "postman-collection";
|
|
19
19
|
|
|
20
|
+
import type { ThemeConfig } from "docusaurus-theme-openapi-docs/src/types";
|
|
21
|
+
|
|
20
22
|
import { CodeSample, Language } from "./code-snippets-types";
|
|
21
23
|
import {
|
|
22
24
|
getCodeSampleSourceFromLanguage,
|
|
@@ -114,6 +116,10 @@ function CodeSnippets({
|
|
|
114
116
|
encoding,
|
|
115
117
|
});
|
|
116
118
|
|
|
119
|
+
const themeConfig = siteConfig.themeConfig as ThemeConfig;
|
|
120
|
+
const hideGeneratedSnippets =
|
|
121
|
+
themeConfig?.api?.hideGeneratedSnippets ?? false;
|
|
122
|
+
|
|
117
123
|
// User-defined languages array
|
|
118
124
|
// Can override languageSet, change order of langs, override options and variants
|
|
119
125
|
const userDefinedLanguageSet =
|
|
@@ -153,6 +159,14 @@ function CodeSnippets({
|
|
|
153
159
|
getCodeSampleSourceFromLanguage(language)
|
|
154
160
|
);
|
|
155
161
|
|
|
162
|
+
// Reset selectedSample whenever the active language changes so the inner
|
|
163
|
+
// tab strip falls back to its first sample instead of trying to match an
|
|
164
|
+
// id that belongs to a different language's samples.
|
|
165
|
+
useEffect(() => {
|
|
166
|
+
setSelectedSample(language?.samples?.[0]);
|
|
167
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
168
|
+
}, [language?.language]);
|
|
169
|
+
|
|
156
170
|
useEffect(() => {
|
|
157
171
|
if (language && !!language.sample) {
|
|
158
172
|
setCodeSampleCodeText(getCodeSampleSourceFromLanguage(language));
|
|
@@ -282,7 +296,11 @@ function CodeSnippets({
|
|
|
282
296
|
}}
|
|
283
297
|
includeSample={true}
|
|
284
298
|
currentLanguage={lang}
|
|
285
|
-
defaultValue={
|
|
299
|
+
defaultValue={
|
|
300
|
+
selectedSample && lang.samples.includes(selectedSample)
|
|
301
|
+
? selectedSample
|
|
302
|
+
: lang.samples[0]
|
|
303
|
+
}
|
|
286
304
|
languageSet={mergedLangs}
|
|
287
305
|
lazy
|
|
288
306
|
>
|
|
@@ -295,7 +313,7 @@ function CodeSnippets({
|
|
|
295
313
|
? lang.samplesLabels[index]
|
|
296
314
|
: sample
|
|
297
315
|
}
|
|
298
|
-
key={`${lang.language}-${
|
|
316
|
+
key={`${lang.language}-${sample}`}
|
|
299
317
|
attributes={{
|
|
300
318
|
className: `openapi-tabs__code-item--sample`,
|
|
301
319
|
}}
|
|
@@ -315,40 +333,42 @@ function CodeSnippets({
|
|
|
315
333
|
)}
|
|
316
334
|
|
|
317
335
|
{/* Inner generated code snippets */}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
{/* @ts-ignore */}
|
|
341
|
-
<ApiCodeBlock
|
|
342
|
-
language={lang.highlight}
|
|
343
|
-
className="openapi-explorer__code-block"
|
|
344
|
-
showLineNumbers={true}
|
|
336
|
+
{!(hideGeneratedSnippets && lang.samples?.length) && (
|
|
337
|
+
<CodeTabs
|
|
338
|
+
className="openapi-tabs__code-container-inner"
|
|
339
|
+
action={{
|
|
340
|
+
setLanguage: setLanguage,
|
|
341
|
+
setSelectedVariant: setSelectedVariant,
|
|
342
|
+
}}
|
|
343
|
+
includeVariant={true}
|
|
344
|
+
currentLanguage={lang}
|
|
345
|
+
defaultValue={selectedVariant}
|
|
346
|
+
languageSet={mergedLangs}
|
|
347
|
+
lazy
|
|
348
|
+
>
|
|
349
|
+
{lang.variants.map((variant, index) => {
|
|
350
|
+
return (
|
|
351
|
+
<CodeTab
|
|
352
|
+
value={variant.toLowerCase()}
|
|
353
|
+
label={variant.toUpperCase()}
|
|
354
|
+
key={`${lang.language}-${variant}`}
|
|
355
|
+
attributes={{
|
|
356
|
+
className: `openapi-tabs__code-item--variant`,
|
|
357
|
+
}}
|
|
345
358
|
>
|
|
346
|
-
{
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
359
|
+
{/* @ts-ignore */}
|
|
360
|
+
<ApiCodeBlock
|
|
361
|
+
language={lang.highlight}
|
|
362
|
+
className="openapi-explorer__code-block"
|
|
363
|
+
showLineNumbers={true}
|
|
364
|
+
>
|
|
365
|
+
{codeText}
|
|
366
|
+
</ApiCodeBlock>
|
|
367
|
+
</CodeTab>
|
|
368
|
+
);
|
|
369
|
+
})}
|
|
370
|
+
</CodeTabs>
|
|
371
|
+
)}
|
|
352
372
|
</CodeTab>
|
|
353
373
|
);
|
|
354
374
|
})}
|
|
@@ -0,0 +1,109 @@
|
|
|
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
|
+
import { mergeCodeSampleLanguage } from "./languages";
|
|
10
|
+
|
|
11
|
+
const baseLang = (
|
|
12
|
+
language: string,
|
|
13
|
+
codeSampleLanguage: Language["codeSampleLanguage"]
|
|
14
|
+
): Language => ({
|
|
15
|
+
highlight: language,
|
|
16
|
+
language,
|
|
17
|
+
codeSampleLanguage,
|
|
18
|
+
logoClass: language,
|
|
19
|
+
variant: "http",
|
|
20
|
+
variants: ["http"],
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
describe("mergeCodeSampleLanguage", () => {
|
|
24
|
+
it("returns the language unchanged when no codeSamples target it", () => {
|
|
25
|
+
const langs = [baseLang("python", "Python")];
|
|
26
|
+
const result = mergeCodeSampleLanguage(langs, []);
|
|
27
|
+
expect(result[0]).toEqual(langs[0]);
|
|
28
|
+
expect(result[0].samples).toBeUndefined();
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it("attaches a single sample with no label using an indexed id", () => {
|
|
32
|
+
const samples: CodeSample[] = [{ lang: "Python", source: "print('hi')" }];
|
|
33
|
+
const [py] = mergeCodeSampleLanguage(
|
|
34
|
+
[baseLang("python", "Python")],
|
|
35
|
+
samples
|
|
36
|
+
);
|
|
37
|
+
expect(py.samples).toEqual(["Python-0"]);
|
|
38
|
+
expect(py.samplesLabels).toEqual(["Python"]);
|
|
39
|
+
expect(py.samplesSources).toEqual(["print('hi')"]);
|
|
40
|
+
expect(py.sample).toBe("Python-0");
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it("attaches a single sample with a label using lang-label id", () => {
|
|
44
|
+
const samples: CodeSample[] = [
|
|
45
|
+
{ lang: "PHP", label: "Custom", source: "<?php" },
|
|
46
|
+
];
|
|
47
|
+
const [php] = mergeCodeSampleLanguage([baseLang("php", "PHP")], samples);
|
|
48
|
+
expect(php.samples).toEqual(["PHP-Custom"]);
|
|
49
|
+
expect(php.samplesLabels).toEqual(["Custom"]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it("produces unique ids for multiple samples sharing a lang with distinct labels (#1204)", () => {
|
|
53
|
+
const samples: CodeSample[] = [
|
|
54
|
+
{ lang: "Python", label: "KeyPair Auth", source: "a" },
|
|
55
|
+
{ lang: "Python", label: "Basic Auth", source: "b" },
|
|
56
|
+
{ lang: "Python", label: "OAuth", source: "c" },
|
|
57
|
+
];
|
|
58
|
+
const [py] = mergeCodeSampleLanguage(
|
|
59
|
+
[baseLang("python", "Python")],
|
|
60
|
+
samples
|
|
61
|
+
);
|
|
62
|
+
expect(py.samples).toEqual([
|
|
63
|
+
"Python-KeyPair Auth",
|
|
64
|
+
"Python-Basic Auth",
|
|
65
|
+
"Python-OAuth",
|
|
66
|
+
]);
|
|
67
|
+
expect(new Set(py.samples).size).toBe(3);
|
|
68
|
+
expect(py.samplesLabels).toEqual(["KeyPair Auth", "Basic Auth", "OAuth"]);
|
|
69
|
+
expect(py.samplesSources).toEqual(["a", "b", "c"]);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("produces unique indexed ids for multiple samples sharing a lang without labels", () => {
|
|
73
|
+
const samples: CodeSample[] = [
|
|
74
|
+
{ lang: "PowerShell", source: "x" },
|
|
75
|
+
{ lang: "PowerShell", source: "y" },
|
|
76
|
+
];
|
|
77
|
+
const [ps] = mergeCodeSampleLanguage(
|
|
78
|
+
[baseLang("powershell", "PowerShell")],
|
|
79
|
+
samples
|
|
80
|
+
);
|
|
81
|
+
expect(ps.samples).toEqual(["PowerShell-0", "PowerShell-1"]);
|
|
82
|
+
expect(new Set(ps.samples).size).toBe(2);
|
|
83
|
+
expect(ps.samplesLabels).toEqual(["PowerShell", "PowerShell"]);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
it("defensively suffixes ids when lang+label collides", () => {
|
|
87
|
+
const samples: CodeSample[] = [
|
|
88
|
+
{ lang: "Java", label: "Auth", source: "a" },
|
|
89
|
+
{ lang: "Java", label: "Auth", source: "b" },
|
|
90
|
+
];
|
|
91
|
+
const [java] = mergeCodeSampleLanguage([baseLang("java", "Java")], samples);
|
|
92
|
+
expect(java.samples).toEqual(["Java-Auth", "Java-Auth-1"]);
|
|
93
|
+
expect(new Set(java.samples).size).toBe(2);
|
|
94
|
+
expect(java.samplesLabels).toEqual(["Auth", "Auth"]);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it("filters codeSamples by codeSampleLanguage and leaves other languages alone", () => {
|
|
98
|
+
const samples: CodeSample[] = [
|
|
99
|
+
{ lang: "Python", label: "A", source: "a" },
|
|
100
|
+
{ lang: "Java", label: "B", source: "b" },
|
|
101
|
+
];
|
|
102
|
+
const result = mergeCodeSampleLanguage(
|
|
103
|
+
[baseLang("python", "Python"), baseLang("php", "PHP")],
|
|
104
|
+
samples
|
|
105
|
+
);
|
|
106
|
+
expect(result[0].samples).toEqual(["Python-A"]);
|
|
107
|
+
expect(result[1].samples).toBeUndefined();
|
|
108
|
+
});
|
|
109
|
+
});
|
|
@@ -22,12 +22,24 @@ export function mergeCodeSampleLanguage(
|
|
|
22
22
|
);
|
|
23
23
|
|
|
24
24
|
if (languageCodeSamples.length) {
|
|
25
|
-
const samples = languageCodeSamples.map(({ lang }) => lang);
|
|
26
25
|
const samplesLabels = languageCodeSamples.map(
|
|
27
26
|
({ label, lang }) => label || lang
|
|
28
27
|
);
|
|
29
28
|
const samplesSources = languageCodeSamples.map(({ source }) => source);
|
|
30
29
|
|
|
30
|
+
// Build a unique id per sample for use as the inner Tab's `value`.
|
|
31
|
+
// Prefer `${lang}-${label}`; fall back to `${lang}-${index}` when no
|
|
32
|
+
// label is provided. Defensively suffix with `-${index}` on collision
|
|
33
|
+
// so duplicate-label specs render two visually identical tabs instead
|
|
34
|
+
// of crashing Docusaurus's unique-value check.
|
|
35
|
+
const seen = new Set<string>();
|
|
36
|
+
const samples = languageCodeSamples.map((cs, i) => {
|
|
37
|
+
const base = cs.label ? `${cs.lang}-${cs.label}` : `${cs.lang}-${i}`;
|
|
38
|
+
const id = seen.has(base) ? `${base}-${i}` : base;
|
|
39
|
+
seen.add(id);
|
|
40
|
+
return id;
|
|
41
|
+
});
|
|
42
|
+
|
|
31
43
|
return {
|
|
32
44
|
...language,
|
|
33
45
|
sample: samples[0],
|
package/src/types.d.ts
CHANGED
|
@@ -52,6 +52,15 @@ export interface ThemeConfig {
|
|
|
52
52
|
/** Persist the reader's selected depth in `localStorage`. Only meaningful when `enabled` is `true`; defaults to `true` in that case. */
|
|
53
53
|
persist?: boolean;
|
|
54
54
|
};
|
|
55
|
+
/**
|
|
56
|
+
* When `true`, suppresses Postman-generated code snippets (HTTP, cURL,
|
|
57
|
+
* language variants, etc.) on a per-operation, per-language basis whenever
|
|
58
|
+
* `x-codeSamples` are provided for that language on that operation.
|
|
59
|
+
* Languages without custom samples render generated snippets normally.
|
|
60
|
+
* Defaults to `false` (both custom and generated snippets render side by
|
|
61
|
+
* side, preserving existing behavior).
|
|
62
|
+
*/
|
|
63
|
+
hideGeneratedSnippets?: boolean;
|
|
55
64
|
};
|
|
56
65
|
}
|
|
57
66
|
|
package/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/index.ts","./src/plugin-content-docs.d.ts","./src/postman-code-generators.d.ts","./src/react-magic-dropzone.d.ts","./src/theme-classic.d.ts","./src/theme-openapi.d.ts","./src/types.d.ts","./src/markdown/createDescription.ts","./src/markdown/schema.ts","./src/markdown/utils.test.ts","./src/markdown/utils.ts","./src/theme/translationIds.ts","./src/theme/ApiExplorer/buildPostmanRequest.ts","./src/theme/ApiExplorer/index.tsx","./src/theme/ApiExplorer/persistenceMiddleware.ts","./src/theme/ApiExplorer/storage-utils.ts","./src/theme/ApiExplorer/Accept/index.tsx","./src/theme/ApiExplorer/Accept/slice.ts","./src/theme/ApiExplorer/ApiCodeBlock/index.tsx","./src/theme/ApiExplorer/ApiCodeBlock/Container/index.tsx","./src/theme/ApiExplorer/ApiCodeBlock/Content/Element.tsx","./src/theme/ApiExplorer/ApiCodeBlock/Content/String.tsx","./src/theme/ApiExplorer/ApiCodeBlock/CopyButton/index.tsx","./src/theme/ApiExplorer/ApiCodeBlock/ExitButton/index.tsx","./src/theme/ApiExplorer/ApiCodeBlock/ExpandButton/index.tsx","./src/theme/ApiExplorer/ApiCodeBlock/Line/index.tsx","./src/theme/ApiExplorer/ApiCodeBlock/WordWrapButton/index.tsx","./src/theme/ApiExplorer/Authorization/auth-types.ts","./src/theme/ApiExplorer/Authorization/index.tsx","./src/theme/ApiExplorer/Authorization/slice.ts","./src/theme/ApiExplorer/Body/index.tsx","./src/theme/ApiExplorer/Body/json2xml.d.ts","./src/theme/ApiExplorer/Body/resolveSchemaWithSelections.ts","./src/theme/ApiExplorer/Body/slice.ts","./src/theme/ApiExplorer/Body/FileArrayFormBodyItem/index.tsx","./src/theme/ApiExplorer/Body/FormBodyItem/index.tsx","./src/theme/ApiExplorer/CodeSnippets/code-snippets-types.ts","./src/theme/ApiExplorer/CodeSnippets/index.tsx","./src/theme/ApiExplorer/CodeSnippets/languages.ts","./src/theme/ApiExplorer/CodeTabs/index.tsx","./src/theme/ApiExplorer/ContentType/index.tsx","./src/theme/ApiExplorer/ContentType/slice.ts","./src/theme/ApiExplorer/EncodingSelection/slice.ts","./src/theme/ApiExplorer/EncodingSelection/useResolvedEncoding.ts","./src/theme/ApiExplorer/Export/index.tsx","./src/theme/ApiExplorer/FloatingButton/index.tsx","./src/theme/ApiExplorer/FormFileUpload/index.tsx","./src/theme/ApiExplorer/FormItem/index.tsx","./src/theme/ApiExplorer/FormLabel/index.tsx","./src/theme/ApiExplorer/FormMultiSelect/index.tsx","./src/theme/ApiExplorer/FormSelect/index.tsx","./src/theme/ApiExplorer/FormTextInput/index.tsx","./src/theme/ApiExplorer/LiveEditor/index.tsx","./src/theme/ApiExplorer/MethodEndpoint/index.tsx","./src/theme/ApiExplorer/ParamOptions/index.tsx","./src/theme/ApiExplorer/ParamOptions/slice.ts","./src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.tsx","./src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.tsx","./src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.tsx","./src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.tsx","./src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.tsx","./src/theme/ApiExplorer/Request/index.tsx","./src/theme/ApiExplorer/Request/makeRequest.ts","./src/theme/ApiExplorer/Response/index.tsx","./src/theme/ApiExplorer/Response/slice.ts","./src/theme/ApiExplorer/SchemaSelection/index.ts","./src/theme/ApiExplorer/SchemaSelection/slice.ts","./src/theme/ApiExplorer/SecuritySchemes/index.tsx","./src/theme/ApiExplorer/Server/index.tsx","./src/theme/ApiExplorer/Server/slice.ts","./src/theme/ApiItem/hooks.ts","./src/theme/ApiItem/index.tsx","./src/theme/ApiItem/store.ts","./src/theme/ApiItem/Layout/index.tsx","./src/theme/ApiLogo/index.tsx","./src/theme/ApiTabs/index.tsx","./src/theme/ArrayBrackets/index.tsx","./src/theme/CodeSamples/index.tsx","./src/theme/DiscriminatorTabs/index.tsx","./src/theme/Example/index.tsx","./src/theme/Markdown/index.d.ts","./src/theme/MimeTabs/index.tsx","./src/theme/OperationTabs/index.tsx","./src/theme/ParamsDetails/index.tsx","./src/theme/ParamsItem/index.tsx","./src/theme/RequestSchema/index.tsx","./src/theme/ResponseExamples/index.tsx","./src/theme/ResponseHeaders/index.tsx","./src/theme/ResponseSchema/index.tsx","./src/theme/Schema/index.tsx","./src/theme/SchemaExpansion/context.tsx","./src/theme/SchemaExpansion/index.tsx","./src/theme/SchemaItem/index.tsx","./src/theme/SchemaTabs/index.tsx","./src/theme/SkeletonLoader/index.tsx","./src/theme/StatusCodes/index.tsx"],"version":"5.9.3"}
|
|
1
|
+
{"root":["./src/index.ts","./src/plugin-content-docs.d.ts","./src/postman-code-generators.d.ts","./src/react-magic-dropzone.d.ts","./src/theme-classic.d.ts","./src/theme-openapi.d.ts","./src/types.d.ts","./src/markdown/createDescription.ts","./src/markdown/schema.ts","./src/markdown/utils.test.ts","./src/markdown/utils.ts","./src/theme/translationIds.ts","./src/theme/ApiExplorer/buildPostmanRequest.ts","./src/theme/ApiExplorer/index.tsx","./src/theme/ApiExplorer/persistenceMiddleware.ts","./src/theme/ApiExplorer/storage-utils.ts","./src/theme/ApiExplorer/Accept/index.tsx","./src/theme/ApiExplorer/Accept/slice.ts","./src/theme/ApiExplorer/ApiCodeBlock/index.tsx","./src/theme/ApiExplorer/ApiCodeBlock/Container/index.tsx","./src/theme/ApiExplorer/ApiCodeBlock/Content/Element.tsx","./src/theme/ApiExplorer/ApiCodeBlock/Content/String.tsx","./src/theme/ApiExplorer/ApiCodeBlock/CopyButton/index.tsx","./src/theme/ApiExplorer/ApiCodeBlock/ExitButton/index.tsx","./src/theme/ApiExplorer/ApiCodeBlock/ExpandButton/index.tsx","./src/theme/ApiExplorer/ApiCodeBlock/Line/index.tsx","./src/theme/ApiExplorer/ApiCodeBlock/WordWrapButton/index.tsx","./src/theme/ApiExplorer/Authorization/auth-types.ts","./src/theme/ApiExplorer/Authorization/index.tsx","./src/theme/ApiExplorer/Authorization/slice.ts","./src/theme/ApiExplorer/Body/index.tsx","./src/theme/ApiExplorer/Body/json2xml.d.ts","./src/theme/ApiExplorer/Body/resolveSchemaWithSelections.ts","./src/theme/ApiExplorer/Body/slice.ts","./src/theme/ApiExplorer/Body/FileArrayFormBodyItem/index.tsx","./src/theme/ApiExplorer/Body/FormBodyItem/index.tsx","./src/theme/ApiExplorer/CodeSnippets/code-snippets-types.ts","./src/theme/ApiExplorer/CodeSnippets/index.tsx","./src/theme/ApiExplorer/CodeSnippets/languages.test.ts","./src/theme/ApiExplorer/CodeSnippets/languages.ts","./src/theme/ApiExplorer/CodeTabs/index.tsx","./src/theme/ApiExplorer/ContentType/index.tsx","./src/theme/ApiExplorer/ContentType/slice.ts","./src/theme/ApiExplorer/EncodingSelection/slice.ts","./src/theme/ApiExplorer/EncodingSelection/useResolvedEncoding.ts","./src/theme/ApiExplorer/Export/index.tsx","./src/theme/ApiExplorer/FloatingButton/index.tsx","./src/theme/ApiExplorer/FormFileUpload/index.tsx","./src/theme/ApiExplorer/FormItem/index.tsx","./src/theme/ApiExplorer/FormLabel/index.tsx","./src/theme/ApiExplorer/FormMultiSelect/index.tsx","./src/theme/ApiExplorer/FormSelect/index.tsx","./src/theme/ApiExplorer/FormTextInput/index.tsx","./src/theme/ApiExplorer/LiveEditor/index.tsx","./src/theme/ApiExplorer/MethodEndpoint/index.tsx","./src/theme/ApiExplorer/ParamOptions/index.tsx","./src/theme/ApiExplorer/ParamOptions/slice.ts","./src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.tsx","./src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.tsx","./src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.tsx","./src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.tsx","./src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem.tsx","./src/theme/ApiExplorer/Request/index.tsx","./src/theme/ApiExplorer/Request/makeRequest.ts","./src/theme/ApiExplorer/Response/index.tsx","./src/theme/ApiExplorer/Response/slice.ts","./src/theme/ApiExplorer/SchemaSelection/index.ts","./src/theme/ApiExplorer/SchemaSelection/slice.ts","./src/theme/ApiExplorer/SecuritySchemes/index.tsx","./src/theme/ApiExplorer/Server/index.tsx","./src/theme/ApiExplorer/Server/slice.ts","./src/theme/ApiItem/hooks.ts","./src/theme/ApiItem/index.tsx","./src/theme/ApiItem/store.ts","./src/theme/ApiItem/Layout/index.tsx","./src/theme/ApiLogo/index.tsx","./src/theme/ApiTabs/index.tsx","./src/theme/ArrayBrackets/index.tsx","./src/theme/CodeSamples/index.tsx","./src/theme/DiscriminatorTabs/index.tsx","./src/theme/Example/index.tsx","./src/theme/Markdown/index.d.ts","./src/theme/MimeTabs/index.tsx","./src/theme/OperationTabs/index.tsx","./src/theme/ParamsDetails/index.tsx","./src/theme/ParamsItem/index.tsx","./src/theme/RequestSchema/index.tsx","./src/theme/ResponseExamples/index.tsx","./src/theme/ResponseHeaders/index.tsx","./src/theme/ResponseSchema/index.tsx","./src/theme/Schema/index.tsx","./src/theme/SchemaExpansion/context.tsx","./src/theme/SchemaExpansion/index.tsx","./src/theme/SchemaItem/index.tsx","./src/theme/SchemaTabs/index.tsx","./src/theme/SkeletonLoader/index.tsx","./src/theme/StatusCodes/index.tsx"],"version":"5.9.3"}
|