docusaurus-plugin-openapi-docs 1.0.2 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +106 -17
  2. package/lib/index.d.ts +7 -1
  3. package/lib/index.js +228 -18
  4. package/lib/markdown/createAuthentication.d.ts +2 -0
  5. package/lib/markdown/createAuthentication.js +139 -0
  6. package/lib/markdown/createParamsDetails.js +2 -0
  7. package/lib/markdown/createSchemaDetails.js +2 -0
  8. package/lib/markdown/index.d.ts +3 -2
  9. package/lib/markdown/index.js +10 -2
  10. package/lib/openapi/createExample.js +59 -49
  11. package/lib/openapi/openapi.d.ts +3 -3
  12. package/lib/openapi/openapi.js +71 -41
  13. package/lib/openapi/openapi.test.js +0 -6
  14. package/lib/openapi/utils/loadAndBundleSpec.d.ts +3 -0
  15. package/lib/openapi/utils/loadAndBundleSpec.js +44 -0
  16. package/lib/openapi/utils/types.d.ts +306 -0
  17. package/lib/openapi/utils/types.js +8 -0
  18. package/lib/options.d.ts +0 -2
  19. package/lib/options.js +36 -7
  20. package/lib/sidebars/index.d.ts +1 -1
  21. package/lib/sidebars/index.js +33 -30
  22. package/lib/sidebars/utils.d.ts +2 -0
  23. package/lib/sidebars/utils.js +31 -0
  24. package/lib/types.d.ts +34 -11
  25. package/package.json +10 -8
  26. package/src/index.ts +291 -20
  27. package/src/markdown/createAuthentication.ts +160 -0
  28. package/src/markdown/createParamsDetails.ts +2 -0
  29. package/src/markdown/createSchemaDetails.ts +2 -0
  30. package/src/markdown/index.ts +15 -2
  31. package/src/openapi/createExample.ts +59 -50
  32. package/src/openapi/openapi.test.ts +0 -6
  33. package/src/openapi/openapi.ts +85 -39
  34. package/src/openapi/utils/loadAndBundleSpec.ts +62 -0
  35. package/src/openapi/utils/types.ts +303 -0
  36. package/src/options.ts +41 -8
  37. package/src/sidebars/index.ts +40 -30
  38. package/src/sidebars/utils.ts +29 -0
  39. package/src/types.ts +35 -9
  40. package/src/openapi/__fixtures__/examples/yogurtstore/_category_.json +0 -4
  41. package/src/openapi/__fixtures__/examples/yogurtstore/froyo.yaml +0 -13
  42. package/src/openapi/__fixtures__/examples/yogurtstore/nested/nested.yaml +0 -13
package/src/index.ts CHANGED
@@ -13,26 +13,79 @@ import { Globby } from "@docusaurus/utils";
13
13
  import chalk from "chalk";
14
14
  import { render } from "mustache";
15
15
 
16
- import { createApiPageMD, createInfoPageMD } from "./markdown";
16
+ import { createApiPageMD, createInfoPageMD, createTagPageMD } from "./markdown";
17
17
  import { readOpenapiFiles, processOpenapiFiles } from "./openapi";
18
+ import { OptionsSchema } from "./options";
18
19
  import generateSidebarSlice from "./sidebars";
19
20
  import type { PluginOptions, LoadedContent, APIOptions } from "./types";
20
21
 
21
- export default function pluginOpenAPI(
22
+ export function isURL(str: string): boolean {
23
+ return /^(https?:)\/\//m.test(str);
24
+ }
25
+
26
+ export function getDocsData(
27
+ dataArray: any[],
28
+ filter: string
29
+ ): Object | undefined {
30
+ // eslint-disable-next-line array-callback-return
31
+ const filteredData = dataArray.filter((data) => {
32
+ if (data[0] === filter) {
33
+ return data[1];
34
+ }
35
+
36
+ // Search plugin-content-docs instances
37
+ if (data[0] === "@docusaurus/plugin-content-docs") {
38
+ const pluginId = data[1].id ? data[1].id : "default";
39
+ if (pluginId === filter) {
40
+ return data[1];
41
+ }
42
+ }
43
+ })[0];
44
+ if (filteredData) {
45
+ // Search presets, e.g. "classic"
46
+ if (filteredData[0] === filter) {
47
+ return filteredData[1].docs;
48
+ }
49
+
50
+ // Search plugin-content-docs instances
51
+ if (filteredData[0] === "@docusaurus/plugin-content-docs") {
52
+ const pluginId = filteredData[1].id ? filteredData[1].id : "default";
53
+ if (pluginId === filter) {
54
+ return filteredData[1];
55
+ }
56
+ }
57
+ }
58
+ return;
59
+ }
60
+
61
+ export default function pluginOpenAPIDocs(
22
62
  context: LoadContext,
23
63
  options: PluginOptions
24
64
  ): Plugin<LoadedContent> {
25
- let { config } = options;
26
- let { siteDir } = context;
65
+ const { config, docPluginId } = options;
66
+ const { siteDir, siteConfig } = context;
67
+
68
+ // Get routeBasePath and path from plugin-content-docs or preset
69
+ const presets: any = siteConfig.presets;
70
+ const plugins: any = siteConfig.plugins;
71
+ const presetsPlugins = presets.concat(plugins);
72
+ const docData: any = getDocsData(presetsPlugins, docPluginId);
73
+ const docRouteBasePath = docData ? docData.routeBasePath : undefined;
74
+ const docPath = docData ? (docData.path ? docData.path : "docs") : undefined;
27
75
 
28
76
  async function generateApiDocs(options: APIOptions) {
29
77
  let { specPath, outputDir, template, sidebarOptions } = options;
30
78
 
31
- const contentPath = path.resolve(siteDir, specPath);
79
+ const contentPath = isURL(specPath)
80
+ ? specPath
81
+ : path.resolve(siteDir, specPath);
32
82
 
33
83
  try {
34
84
  const openapiFiles = await readOpenapiFiles(contentPath, {});
35
- const [loadedApi, tags] = await processOpenapiFiles(openapiFiles);
85
+ const [loadedApi, tags] = await processOpenapiFiles(
86
+ openapiFiles,
87
+ sidebarOptions!
88
+ );
36
89
  if (!fs.existsSync(outputDir)) {
37
90
  try {
38
91
  fs.mkdirSync(outputDir, { recursive: true });
@@ -48,10 +101,11 @@ export default function pluginOpenAPI(
48
101
  // TODO: figure out better way to set default
49
102
  if (Object.keys(sidebarOptions ?? {}).length > 0) {
50
103
  const sidebarSlice = generateSidebarSlice(
51
- sidebarOptions!, // TODO: find a better way to handle null
104
+ sidebarOptions!,
52
105
  options,
53
106
  loadedApi,
54
- tags
107
+ tags,
108
+ docPath
55
109
  );
56
110
 
57
111
  const sidebarSliceTemplate = template
@@ -100,6 +154,9 @@ api: {{{json}}}
100
154
  {{#api.method}}
101
155
  sidebar_class_name: "{{{api.method}}} api-method"
102
156
  {{/api.method}}
157
+ {{#infoPath}}
158
+ info_path: {{{infoPath}}}
159
+ {{/infoPath}}
103
160
  ---
104
161
 
105
162
  {{{markdown}}}
@@ -119,19 +176,51 @@ hide_title: true
119
176
  import DocCardList from '@theme/DocCardList';
120
177
  import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
121
178
 
179
+ <DocCardList items={useCurrentSidebarCategory().items}/>
180
+ \`\`\`
181
+ `;
182
+
183
+ const tagMdTemplate = template
184
+ ? fs.readFileSync(template).toString()
185
+ : `---
186
+ id: {{{id}}}
187
+ title: {{{description}}}
188
+ description: {{{description}}}
189
+ ---
190
+
191
+ {{{markdown}}}
192
+
193
+ \`\`\`mdx-code-block
194
+ import DocCardList from '@theme/DocCardList';
195
+ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
196
+
122
197
  <DocCardList items={useCurrentSidebarCategory().items}/>
123
198
  \`\`\`
124
199
  `;
125
200
 
126
201
  loadedApi.map(async (item) => {
127
202
  const markdown =
128
- item.type === "api" ? createApiPageMD(item) : createInfoPageMD(item);
203
+ item.type === "api"
204
+ ? createApiPageMD(item)
205
+ : item.type === "info"
206
+ ? createInfoPageMD(item)
207
+ : createTagPageMD(item);
129
208
  item.markdown = markdown;
130
209
  if (item.type === "api") {
131
210
  item.json = JSON.stringify(item.api);
211
+ let infoBasePath = `${outputDir}/${item.infoId}`;
212
+ if (docRouteBasePath) {
213
+ infoBasePath = `${docRouteBasePath}/${outputDir
214
+ .split(docPath!)[1]
215
+ .replace(/^\/+/g, "")}/${item.infoId}`.replace(/^\/+/g, "");
216
+ }
217
+ if (item.infoId) item.infoPath = infoBasePath;
132
218
  }
219
+
133
220
  const view = render(mdTemplate, item);
134
221
  const utils = render(infoMdTemplate, item);
222
+ // eslint-disable-next-line testing-library/render-result-naming-convention
223
+ const tagUtils = render(tagMdTemplate, item);
135
224
 
136
225
  if (item.type === "api") {
137
226
  if (!fs.existsSync(`${outputDir}/${item.id}.api.mdx`)) {
@@ -179,8 +268,31 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
179
268
  }
180
269
  }
181
270
  }
271
+
272
+ if (item.type === "tag") {
273
+ if (!fs.existsSync(`${outputDir}/${item.id}.tag.mdx`)) {
274
+ try {
275
+ fs.writeFileSync(
276
+ `${outputDir}/${item.id}.tag.mdx`,
277
+ tagUtils,
278
+ "utf8"
279
+ );
280
+ console.log(
281
+ chalk.green(
282
+ `Successfully created "${outputDir}/${item.id}.tag.mdx"`
283
+ )
284
+ );
285
+ } catch (err) {
286
+ console.error(
287
+ chalk.red(`Failed to write "${outputDir}/${item.id}.tag.mdx"`),
288
+ chalk.yellow(err)
289
+ );
290
+ }
291
+ }
292
+ }
182
293
  return;
183
294
  });
295
+
184
296
  return;
185
297
  } catch (e) {
186
298
  console.error(chalk.red(`Loading of api failed for "${contentPath}"`));
@@ -191,11 +303,13 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
191
303
  async function cleanApiDocs(options: APIOptions) {
192
304
  const { outputDir } = options;
193
305
  const apiDir = path.join(siteDir, outputDir);
194
- const apiMdxFiles = await Globby(["*.api.mdx", "*.info.mdx"], {
306
+ const apiMdxFiles = await Globby(["*.api.mdx", "*.info.mdx", "*.tag.mdx"], {
195
307
  cwd: path.resolve(apiDir),
308
+ deep: 1,
196
309
  });
197
310
  const sidebarFile = await Globby(["sidebar.js"], {
198
311
  cwd: path.resolve(apiDir),
312
+ deep: 1,
199
313
  });
200
314
  apiMdxFiles.map((mdx) =>
201
315
  fs.unlink(`${apiDir}/${mdx}`, (err) => {
@@ -226,21 +340,66 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
226
340
  );
227
341
  }
228
342
 
343
+ async function generateVersions(versions: object, outputDir: string) {
344
+ let versionsArray = [] as object[];
345
+ for (const [version, metadata] of Object.entries(versions)) {
346
+ versionsArray.push({
347
+ version: version,
348
+ label: metadata.label,
349
+ baseUrl: metadata.baseUrl,
350
+ });
351
+ }
352
+
353
+ const versionsJson = JSON.stringify(versionsArray, null, 2);
354
+ try {
355
+ fs.writeFileSync(`${outputDir}/versions.json`, versionsJson, "utf8");
356
+ console.log(
357
+ chalk.green(`Successfully created "${outputDir}/versions.json"`)
358
+ );
359
+ } catch (err) {
360
+ console.error(
361
+ chalk.red(`Failed to write "${outputDir}/versions.json"`),
362
+ chalk.yellow(err)
363
+ );
364
+ }
365
+ }
366
+
367
+ async function cleanVersions(outputDir: string) {
368
+ if (fs.existsSync(`${outputDir}/versions.json`)) {
369
+ fs.unlink(`${outputDir}/versions.json`, (err) => {
370
+ if (err) {
371
+ console.error(
372
+ chalk.red(`Cleanup failed for "${outputDir}/versions.json"`),
373
+ chalk.yellow(err)
374
+ );
375
+ } else {
376
+ console.log(
377
+ chalk.green(`Cleanup succeeded for "${outputDir}/versions.json"`)
378
+ );
379
+ }
380
+ });
381
+ }
382
+ }
383
+
229
384
  return {
230
- name: `docusaurus-plugin-openapi`,
385
+ name: `docusaurus-plugin-openapi-docs`,
231
386
 
232
387
  extendCli(cli): void {
233
388
  cli
234
389
  .command(`gen-api-docs`)
235
- .description(`Generates API Docs mdx and sidebars.`)
236
- .usage(
237
- "[options] <id key value in plugin config within docusaurus.config.js>"
390
+ .description(
391
+ `Generates OpenAPI docs in MDX file format and sidebar.js (if enabled).`
238
392
  )
393
+ .usage("<id>")
239
394
  .arguments("<id>")
240
395
  .action(async (id) => {
241
396
  if (id === "all") {
242
397
  if (config[id]) {
243
- console.error(chalk.red("Can't use id 'all' for API Doc."));
398
+ console.error(
399
+ chalk.red(
400
+ "Can't use id 'all' for OpenAPI docs configuration key."
401
+ )
402
+ );
244
403
  } else {
245
404
  Object.keys(config).forEach(async function (key) {
246
405
  await generateApiDocs(config[key]);
@@ -248,24 +407,91 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
248
407
  }
249
408
  } else if (!config[id]) {
250
409
  console.error(
251
- chalk.red(`ID ${id} does not exist in openapi-plugin config`)
410
+ chalk.red(`ID '${id}' does not exist in OpenAPI docs config.`)
252
411
  );
253
412
  } else {
254
413
  await generateApiDocs(config[id]);
255
414
  }
256
415
  });
257
416
 
417
+ cli
418
+ .command(`gen-api-docs:version`)
419
+ .description(
420
+ `Generates versioned OpenAPI docs in MDX file format, versions.js and sidebar.js (if enabled).`
421
+ )
422
+ .usage("<id:version>")
423
+ .arguments("<id:version>")
424
+ .action(async (id) => {
425
+ const [parentId, versionId] = id.split(":");
426
+ const parentConfig = Object.assign({}, config[parentId]);
427
+
428
+ const version = parentConfig.version as string;
429
+ const label = parentConfig.label as string;
430
+ const baseUrl = parentConfig.baseUrl as string;
431
+
432
+ let parentVersion = {} as any;
433
+ parentVersion[version] = { label: label, baseUrl: baseUrl };
434
+
435
+ const { versions } = config[parentId] as any;
436
+ const mergedVersions = Object.assign(parentVersion, versions);
437
+
438
+ // Prepare for merge
439
+ delete parentConfig.versions;
440
+ delete parentConfig.version;
441
+ delete parentConfig.label;
442
+ delete parentConfig.baseUrl;
443
+
444
+ // TODO: handle when no versions are defined by version command is passed
445
+ if (versionId === "all") {
446
+ if (versions[id]) {
447
+ console.error(
448
+ chalk.red(
449
+ "Can't use id 'all' for OpenAPI docs versions configuration key."
450
+ )
451
+ );
452
+ } else {
453
+ await generateVersions(mergedVersions, parentConfig.outputDir);
454
+ Object.keys(versions).forEach(async (key) => {
455
+ const versionConfig = versions[key];
456
+ const mergedConfig = {
457
+ ...parentConfig,
458
+ ...versionConfig,
459
+ };
460
+ await generateApiDocs(mergedConfig);
461
+ });
462
+ }
463
+ } else if (!versions[versionId]) {
464
+ console.error(
465
+ chalk.red(
466
+ `Version ID '${versionId}' does not exist in OpenAPI docs versions config.`
467
+ )
468
+ );
469
+ } else {
470
+ const versionConfig = versions[versionId];
471
+ const mergedConfig = {
472
+ ...parentConfig,
473
+ ...versionConfig,
474
+ };
475
+ await generateVersions(mergedVersions, parentConfig.outputDir);
476
+ await generateApiDocs(mergedConfig);
477
+ }
478
+ });
479
+
258
480
  cli
259
481
  .command(`clean-api-docs`)
260
- .description(`Clears the Generated API Docs mdx and sidebars.`)
261
- .usage(
262
- "[options] <id key value in plugin config within docusaurus.config.js>"
482
+ .description(
483
+ `Clears the generated OpenAPI docs MDX files and sidebar.js (if enabled).`
263
484
  )
485
+ .usage("<id>")
264
486
  .arguments("<id>")
265
487
  .action(async (id) => {
266
488
  if (id === "all") {
267
489
  if (config[id]) {
268
- console.error(chalk.red("Can't use id 'all' for API Doc."));
490
+ console.error(
491
+ chalk.red(
492
+ "Can't use id 'all' for OpenAPI docs configuration key."
493
+ )
494
+ );
269
495
  } else {
270
496
  Object.keys(config).forEach(async function (key) {
271
497
  await cleanApiDocs(config[key]);
@@ -275,6 +501,51 @@ import {useCurrentSidebarCategory} from '@docusaurus/theme-common';
275
501
  await cleanApiDocs(config[id]);
276
502
  }
277
503
  });
504
+
505
+ cli
506
+ .command(`clean-api-docs:version`)
507
+ .description(
508
+ `Clears the versioned, generated OpenAPI docs MDX files, versions.json and sidebar.js (if enabled).`
509
+ )
510
+ .usage("<id:version>")
511
+ .arguments("<id:version>")
512
+ .action(async (id) => {
513
+ const [parentId, versionId] = id.split(":");
514
+ const { versions } = config[parentId] as any;
515
+
516
+ const parentConfig = Object.assign({}, config[parentId]);
517
+ delete parentConfig.versions;
518
+
519
+ if (versionId === "all") {
520
+ if (versions[id]) {
521
+ chalk.red(
522
+ "Can't use id 'all' for OpenAPI docs versions configuration key."
523
+ );
524
+ } else {
525
+ await cleanVersions(parentConfig.outputDir);
526
+ Object.keys(versions).forEach(async (key) => {
527
+ const versionConfig = versions[key];
528
+ const mergedConfig = {
529
+ ...parentConfig,
530
+ ...versionConfig,
531
+ };
532
+ await cleanApiDocs(mergedConfig);
533
+ });
534
+ }
535
+ } else {
536
+ const versionConfig = versions[versionId];
537
+ const mergedConfig = {
538
+ ...parentConfig,
539
+ ...versionConfig,
540
+ };
541
+ await cleanApiDocs(mergedConfig);
542
+ }
543
+ });
278
544
  },
279
545
  };
280
546
  }
547
+
548
+ pluginOpenAPIDocs.validateOptions = ({ options, validate }: any) => {
549
+ const validatedOptions = validate(OptionsSchema, options);
550
+ return validatedOptions;
551
+ };
@@ -0,0 +1,160 @@
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 { OAuthFlowObject, SecuritySchemeObject } from "../openapi/types";
9
+ import { createDescription } from "./createDescription";
10
+ import { create, guard } from "./utils";
11
+
12
+ export function createAuthentication(securitySchemes: SecuritySchemeObject) {
13
+ if (!securitySchemes || !Object.keys(securitySchemes).length) return "";
14
+
15
+ const createAuthenticationTable = (securityScheme: any) => {
16
+ const { bearerFormat, flows, name, scheme, type } = securityScheme;
17
+
18
+ const createSecuritySchemeTypeRow = () =>
19
+ create("tr", {
20
+ children: [
21
+ create("th", { children: "Security Scheme Type:" }),
22
+ create("td", { children: type }),
23
+ ],
24
+ });
25
+
26
+ const createOAuthFlowRows = () => {
27
+ const flowRows = Object.entries(flows).map(([flowType, flowObj]) => {
28
+ const { authorizationUrl, tokenUrl, refreshUrl, scopes } =
29
+ flowObj as OAuthFlowObject;
30
+
31
+ return create("tr", {
32
+ children: [
33
+ create("th", { children: `${flowType} OAuth Flow:` }),
34
+ create("td", {
35
+ children: [
36
+ guard(tokenUrl, () =>
37
+ create("p", { children: `Token URL: ${tokenUrl}` })
38
+ ),
39
+ guard(authorizationUrl, () =>
40
+ create("p", {
41
+ children: `Authorization URL: ${authorizationUrl}`,
42
+ })
43
+ ),
44
+ guard(refreshUrl, () =>
45
+ create("p", { children: `Refresh URL: ${refreshUrl}` })
46
+ ),
47
+ create("span", { children: "Scopes:" }),
48
+ create("ul", {
49
+ children: Object.entries(scopes).map(([scope, description]) =>
50
+ create("li", { children: `${scope}: ${description}` })
51
+ ),
52
+ }),
53
+ ],
54
+ }),
55
+ ],
56
+ });
57
+ });
58
+
59
+ return flowRows.join("");
60
+ };
61
+
62
+ switch (type) {
63
+ case "apiKey":
64
+ return create("div", {
65
+ children: [
66
+ create("table", {
67
+ children: create("tbody", {
68
+ children: [
69
+ createSecuritySchemeTypeRow(),
70
+ create("tr", {
71
+ children: [
72
+ create("th", { children: "Header parameter name:" }),
73
+ create("td", { children: name }),
74
+ ],
75
+ }),
76
+ ],
77
+ }),
78
+ }),
79
+ ],
80
+ });
81
+ case "http":
82
+ return create("div", {
83
+ children: [
84
+ create("table", {
85
+ children: create("tbody", {
86
+ children: [
87
+ createSecuritySchemeTypeRow(),
88
+ create("tr", {
89
+ children: [
90
+ create("th", { children: "HTTP Authorization Scheme:" }),
91
+ create("td", { children: scheme }),
92
+ ],
93
+ }),
94
+ create("tr", {
95
+ children: [
96
+ create("th", { children: "Bearer format:" }),
97
+ create("td", { children: bearerFormat }),
98
+ ],
99
+ }),
100
+ ],
101
+ }),
102
+ }),
103
+ ],
104
+ });
105
+ case "oauth2":
106
+ return create("div", {
107
+ children: [
108
+ create("table", {
109
+ children: create("tbody", {
110
+ children: [
111
+ createSecuritySchemeTypeRow(),
112
+ createOAuthFlowRows(),
113
+ ],
114
+ }),
115
+ }),
116
+ ],
117
+ });
118
+ default:
119
+ return "";
120
+ }
121
+ };
122
+
123
+ const formatTabLabel = (str: string) => {
124
+ const formattedLabel = str
125
+ .replace(/(_|-)/g, " ")
126
+ .trim()
127
+ .replace(/\w\S*/g, (str) => str.charAt(0).toUpperCase() + str.substr(1))
128
+ .replace(/([a-z])([A-Z])/g, "$1 $2")
129
+ .replace(/([A-Z])([A-Z][a-z])/g, "$1 $2");
130
+
131
+ const isOAuth = formattedLabel.toLowerCase().includes("oauth2");
132
+ const isApiKey = formattedLabel.toLowerCase().includes("api");
133
+
134
+ return isOAuth ? "OAuth 2.0" : isApiKey ? "API Key" : formattedLabel;
135
+ };
136
+
137
+ return create("div", {
138
+ children: [
139
+ create("h2", {
140
+ children: "Authentication",
141
+ id: "authentication",
142
+ style: { marginBottom: "1rem" },
143
+ }),
144
+ create("Tabs", {
145
+ children: Object.entries(securitySchemes).map(
146
+ ([schemeType, schemeObj]) =>
147
+ create("TabItem", {
148
+ label: formatTabLabel(schemeType),
149
+ value: `${schemeType}`,
150
+ children: [
151
+ createDescription(schemeObj.description),
152
+ createAuthenticationTable(schemeObj),
153
+ ],
154
+ })
155
+ ),
156
+ }),
157
+ ],
158
+ style: { marginBottom: "2rem" },
159
+ });
160
+ }
@@ -25,6 +25,8 @@ export function createParamsDetails({ parameters, type }: Props) {
25
25
  }
26
26
 
27
27
  return createDetails({
28
+ "data-collapsed": false,
29
+ open: true,
28
30
  style: { marginBottom: "1rem" },
29
31
  children: [
30
32
  createDetailsSummary({
@@ -269,6 +269,8 @@ export function createSchemaDetails({ title, body, ...rest }: Props) {
269
269
  }
270
270
 
271
271
  return createDetails({
272
+ "data-collapsed": false,
273
+ open: true,
272
274
  ...rest,
273
275
  children: [
274
276
  createDetailsSummary({
@@ -7,8 +7,13 @@
7
7
 
8
8
  import { escape } from "lodash";
9
9
 
10
- import { ContactObject, LicenseObject } from "../openapi/types";
11
- import { ApiPageMetadata, InfoPageMetadata } from "../types";
10
+ import {
11
+ ContactObject,
12
+ LicenseObject,
13
+ SecuritySchemeObject,
14
+ } from "../openapi/types";
15
+ import { ApiPageMetadata, InfoPageMetadata, TagPageMetadata } from "../types";
16
+ import { createAuthentication } from "./createAuthentication";
12
17
  import { createContactInfo } from "./createContactInfo";
13
18
  import { createDeprecationNotice } from "./createDeprecationNotice";
14
19
  import { createDescription } from "./createDescription";
@@ -50,13 +55,21 @@ export function createApiPageMD({
50
55
 
51
56
  export function createInfoPageMD({
52
57
  info: { title, version, description, contact, license, termsOfService },
58
+ securitySchemes,
53
59
  }: InfoPageMetadata) {
54
60
  return render([
61
+ `import Tabs from "@theme/Tabs";\n`,
62
+ `import TabItem from "@theme/TabItem";\n\n`,
55
63
  createVersionBadge(version),
56
64
  `# ${escape(title)}\n\n`,
57
65
  createDescription(description),
66
+ createAuthentication(securitySchemes as unknown as SecuritySchemeObject),
58
67
  createContactInfo(contact as ContactObject),
59
68
  createTermsOfService(termsOfService),
60
69
  createLicense(license as LicenseObject),
61
70
  ]);
62
71
  }
72
+
73
+ export function createTagPageMD({ tag: { description } }: TagPageMetadata) {
74
+ return render([createDescription(description)]);
75
+ }