docusaurus-plugin-openapi-docs 2.1.2 → 2.2.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "docusaurus-plugin-openapi-docs",
3
3
  "description": "OpenAPI plugin for Docusaurus.",
4
- "version": "2.1.2",
4
+ "version": "2.2.0",
5
5
  "license": "MIT",
6
6
  "keywords": [
7
7
  "openapi",
@@ -40,8 +40,6 @@
40
40
  "@docusaurus/plugin-content-docs": ">=2.4.1 <=2.4.3",
41
41
  "@docusaurus/utils": ">=2.4.1 <=2.4.3",
42
42
  "@docusaurus/utils-validation": ">=2.4.1 <=2.4.3",
43
- "@paloaltonetworks/openapi-to-postmanv2": "3.1.0-hotfix.1",
44
- "@paloaltonetworks/postman-collection": "^4.1.0",
45
43
  "@redocly/openapi-core": "^1.10.5",
46
44
  "chalk": "^4.1.2",
47
45
  "clsx": "^1.1.1",
@@ -50,6 +48,8 @@
50
48
  "json-schema-merge-allof": "^0.8.1",
51
49
  "lodash": "^4.17.20",
52
50
  "mustache": "^4.2.0",
51
+ "openapi-to-postmanv2": "^4.21.0",
52
+ "postman-collection": "^4.4.0",
53
53
  "slugify": "^1.6.5",
54
54
  "swagger2openapi": "^7.0.8",
55
55
  "xml-formatter": "^2.6.1"
@@ -60,5 +60,5 @@
60
60
  "engines": {
61
61
  "node": ">=14"
62
62
  },
63
- "gitHead": "4bb7040ce39ebe38b2a2837ab0c6a8c477a9a546"
63
+ "gitHead": "060b5777c783abc23cd3744a6d43deb4df80cebd"
64
64
  }
package/src/index.ts CHANGED
@@ -40,6 +40,7 @@ export function isURL(str: string): boolean {
40
40
 
41
41
  export function getDocsPluginConfig(
42
42
  presetsPlugins: any[],
43
+ plugin: string,
43
44
  pluginId: string
44
45
  ): Object | undefined {
45
46
  // eslint-disable-next-line array-callback-return
@@ -51,10 +52,7 @@ export function getDocsPluginConfig(
51
52
  }
52
53
 
53
54
  // Search plugin-content-docs instances
54
- if (
55
- typeof data[0] === "string" &&
56
- data[0] === "@docusaurus/plugin-content-docs"
57
- ) {
55
+ if (typeof data[0] === "string" && data[0] === plugin) {
58
56
  const configPluginId = data[1].id ? data[1].id : "default";
59
57
  if (configPluginId === pluginId) {
60
58
  return data[1];
@@ -70,7 +68,7 @@ export function getDocsPluginConfig(
70
68
  }
71
69
 
72
70
  // Search plugin-content-docs instances
73
- if (filteredConfig[0] === "@docusaurus/plugin-content-docs") {
71
+ if (filteredConfig[0] === plugin) {
74
72
  const configPluginId = filteredConfig[1].id
75
73
  ? filteredConfig[1].id
76
74
  : "default";
@@ -94,14 +92,22 @@ export default function pluginOpenAPIDocs(
94
92
  context: LoadContext,
95
93
  options: PluginOptions
96
94
  ): Plugin<LoadedContent> {
97
- const { config, docsPluginId } = options;
95
+ const {
96
+ config,
97
+ docsPlugin = "@docusaurus/plugin-content-docs",
98
+ docsPluginId,
99
+ } = options;
98
100
  const { siteDir, siteConfig } = context;
99
101
 
100
102
  // Get routeBasePath and path from plugin-content-docs or preset
101
103
  const presets: any = siteConfig.presets;
102
104
  const plugins: any = siteConfig.plugins;
103
105
  const presetsPlugins = presets.concat(plugins);
104
- let docData: any = getDocsPluginConfig(presetsPlugins, docsPluginId);
106
+ let docData: any = getDocsPluginConfig(
107
+ presetsPlugins,
108
+ docsPlugin,
109
+ docsPluginId
110
+ );
105
111
  let docRouteBasePath = docData ? docData.routeBasePath : undefined;
106
112
  let docPath = docData ? (docData.path ? docData.path : "docs") : undefined;
107
113
 
@@ -113,6 +119,7 @@ export default function pluginOpenAPIDocs(
113
119
  markdownGenerators,
114
120
  downloadUrl,
115
121
  sidebarOptions,
122
+ disableCompression,
116
123
  } = options;
117
124
 
118
125
  // Remove trailing slash before proceeding
@@ -120,7 +127,7 @@ export default function pluginOpenAPIDocs(
120
127
 
121
128
  // Override docPath if pluginId provided
122
129
  if (pluginId) {
123
- docData = getDocsPluginConfig(presetsPlugins, pluginId);
130
+ docData = getDocsPluginConfig(presetsPlugins, docsPlugin, pluginId);
124
131
  docRouteBasePath = docData ? docData.routeBasePath : undefined;
125
132
  docPath = docData ? (docData.path ? docData.path : "docs") : undefined;
126
133
  }
@@ -299,7 +306,7 @@ custom_edit_url: null
299
306
 
300
307
  loadedApi.map(async (item) => {
301
308
  if (item.type === "info") {
302
- if (downloadUrl && isURL(downloadUrl)) {
309
+ if (downloadUrl) {
303
310
  item.downloadUrl = downloadUrl;
304
311
  }
305
312
  }
@@ -313,9 +320,11 @@ custom_edit_url: null
313
320
  // const deserialize = (s: any) => {
314
321
  // return zlib.inflateSync(Buffer.from(s, "base64")).toString();
315
322
  // };
316
- item.json = zlib
317
- .deflateSync(JSON.stringify(item.api))
318
- .toString("base64");
323
+ disableCompression === true
324
+ ? (item.json = JSON.stringify(item.api))
325
+ : (item.json = zlib
326
+ .deflateSync(JSON.stringify(item.api))
327
+ .toString("base64"));
319
328
  let infoBasePath = `${outputDir}/${item.infoId}`;
320
329
  if (docRouteBasePath) {
321
330
  infoBasePath = `${docRouteBasePath}/${outputDir
@@ -468,7 +477,7 @@ custom_edit_url: null
468
477
  cwd: path.resolve(apiDir, "schemas"),
469
478
  deep: 1,
470
479
  });
471
- const sidebarFile = await Globby(["sidebar.js"], {
480
+ const sidebarFile = await Globby(["sidebar.{js,ts}"], {
472
481
  cwd: path.resolve(apiDir),
473
482
  deep: 1,
474
483
  });
@@ -523,6 +532,7 @@ custom_edit_url: null
523
532
  version: version,
524
533
  label: metadata.label,
525
534
  baseUrl: metadata.baseUrl,
535
+ downloadUrl: metadata.downloadUrl,
526
536
  });
527
537
  }
528
538
 
@@ -673,6 +683,7 @@ custom_edit_url: null
673
683
  delete parentConfig.version;
674
684
  delete parentConfig.label;
675
685
  delete parentConfig.baseUrl;
686
+ delete parentConfig.downloadUrl;
676
687
 
677
688
  // TODO: handle when no versions are defined by version command is passed
678
689
  if (versionId === "all") {
@@ -108,12 +108,6 @@ export function createRequestSchema({ title, body, ...rest }: Props) {
108
108
  return undefined;
109
109
  }
110
110
 
111
- // we don't show the table if there is no properties to show
112
- if (firstBody.properties !== undefined) {
113
- if (Object.keys(firstBody.properties).length === 0) {
114
- return undefined;
115
- }
116
- }
117
111
  return create("MimeTabs", {
118
112
  className: "openapi-tabs__mime",
119
113
  children: [
@@ -60,12 +60,6 @@ export function createResponseSchema({ title, body, ...rest }: Props) {
60
60
  return undefined;
61
61
  }
62
62
 
63
- if (firstBody?.properties !== undefined) {
64
- if (Object.keys(firstBody?.properties).length === 0) {
65
- return undefined;
66
- }
67
- }
68
-
69
63
  return create("TabItem", {
70
64
  label: `${mimeType}`,
71
65
  value: `${mimeType}`,
@@ -13,6 +13,7 @@ import { SchemaObject } from "../openapi/types";
13
13
  describe("createNodes", () => {
14
14
  it("should create readable MODs for oneOf primitive properties", () => {
15
15
  const schema: SchemaObject = {
16
+ "x-tags": ["clown"],
16
17
  type: "object",
17
18
  properties: {
18
19
  oneOfProperty: {
@@ -44,7 +44,7 @@ export function mergeAllOf(allOf: SchemaObject[]) {
44
44
  ignoreAdditionalProperties: true,
45
45
  });
46
46
 
47
- const required = allOf.reduce((acc, cur) => {
47
+ const mergedRequired = allOf.reduce((acc, cur) => {
48
48
  if (Array.isArray(cur.required)) {
49
49
  const next = [...acc, ...cur.required];
50
50
  return next;
@@ -52,7 +52,7 @@ export function mergeAllOf(allOf: SchemaObject[]) {
52
52
  return acc;
53
53
  }, [] as any);
54
54
 
55
- return { mergedSchemas, required };
55
+ return { mergedSchemas, mergedRequired };
56
56
  }
57
57
 
58
58
  /**
@@ -129,6 +129,16 @@ function createAnyOneOf(schema: SchemaObject): any {
129
129
  */
130
130
  function createProperties(schema: SchemaObject) {
131
131
  const discriminator = schema.discriminator;
132
+ if (Object.keys(schema.properties!).length === 0) {
133
+ return create("SchemaItem", {
134
+ collapsible: false,
135
+ name: "",
136
+ required: false,
137
+ schemaName: "object",
138
+ qualifierMessage: undefined,
139
+ schema: {},
140
+ });
141
+ }
132
142
  return Object.entries(schema.properties!).map(([key, val]) => {
133
143
  return createEdges({
134
144
  name: key,
@@ -260,9 +270,8 @@ function createItems(schema: SchemaObject) {
260
270
  // TODO: figure out if and how we should pass merged required array
261
271
  const {
262
272
  mergedSchemas,
263
- }: { mergedSchemas: SchemaObject; required: string[] } = mergeAllOf(
264
- schema.items?.allOf
265
- );
273
+ }: { mergedSchemas: SchemaObject; mergedRequired: string[] | boolean } =
274
+ mergeAllOf(schema.items?.allOf);
266
275
 
267
276
  // Handles combo anyOf/oneOf + properties
268
277
  if (
@@ -595,8 +604,19 @@ function createEdges({
595
604
  required,
596
605
  discriminator,
597
606
  }: EdgeProps): any {
598
- const schemaName = getSchemaName(schema);
607
+ if (SCHEMA_TYPE === "request") {
608
+ if (schema.readOnly && schema.readOnly === true) {
609
+ return undefined;
610
+ }
611
+ }
612
+
613
+ if (SCHEMA_TYPE === "response") {
614
+ if (schema.writeOnly && schema.writeOnly === true) {
615
+ return undefined;
616
+ }
617
+ }
599
618
 
619
+ const schemaName = getSchemaName(schema);
600
620
  if (discriminator !== undefined && discriminator.propertyName === name) {
601
621
  return createPropertyDiscriminator(
602
622
  name,
@@ -618,11 +638,22 @@ function createEdges({
618
638
  }
619
639
 
620
640
  if (schema.allOf !== undefined) {
621
- const {
622
- mergedSchemas,
623
- required,
624
- }: { mergedSchemas: SchemaObject; required: string[] | boolean } =
625
- mergeAllOf(schema.allOf);
641
+ const { mergedSchemas }: { mergedSchemas: SchemaObject } = mergeAllOf(
642
+ schema.allOf
643
+ );
644
+
645
+ if (SCHEMA_TYPE === "request") {
646
+ if (mergedSchemas.readOnly && mergedSchemas.readOnly === true) {
647
+ return undefined;
648
+ }
649
+ }
650
+
651
+ if (SCHEMA_TYPE === "response") {
652
+ if (mergedSchemas.writeOnly && mergedSchemas.writeOnly === true) {
653
+ return undefined;
654
+ }
655
+ }
656
+
626
657
  const mergedSchemaName = getSchemaName(mergedSchemas);
627
658
  if (
628
659
  mergedSchemas.oneOf !== undefined ||
@@ -668,18 +699,6 @@ function createEdges({
668
699
  );
669
700
  }
670
701
 
671
- if (SCHEMA_TYPE === "request") {
672
- if (mergedSchemas.readOnly && mergedSchemas.readOnly === true) {
673
- return undefined;
674
- }
675
- }
676
-
677
- if (SCHEMA_TYPE === "response") {
678
- if (mergedSchemas.writeOnly && mergedSchemas.writeOnly === true) {
679
- return undefined;
680
- }
681
- }
682
-
683
702
  return create("SchemaItem", {
684
703
  collapsible: false,
685
704
  name,
@@ -731,18 +750,6 @@ function createEdges({
731
750
  );
732
751
  }
733
752
 
734
- if (SCHEMA_TYPE === "request") {
735
- if (schema.readOnly && schema.readOnly === true) {
736
- return undefined;
737
- }
738
- }
739
-
740
- if (SCHEMA_TYPE === "response") {
741
- if (schema.writeOnly && schema.writeOnly === true) {
742
- return undefined;
743
- }
744
- }
745
-
746
753
  // primitives and array of non-objects
747
754
  return create("SchemaItem", {
748
755
  collapsible: false,
@@ -762,6 +769,17 @@ export function createNodes(
762
769
  schemaType: "request" | "response"
763
770
  ): any {
764
771
  SCHEMA_TYPE = schemaType;
772
+ if (SCHEMA_TYPE === "request") {
773
+ if (schema.readOnly && schema.readOnly === true) {
774
+ return undefined;
775
+ }
776
+ }
777
+
778
+ if (SCHEMA_TYPE === "response") {
779
+ if (schema.writeOnly && schema.writeOnly === true) {
780
+ return undefined;
781
+ }
782
+ }
765
783
  const nodes = [];
766
784
  // if (schema.discriminator !== undefined) {
767
785
  // return createDiscriminator(schema);
@@ -285,7 +285,7 @@ export function createStatusCodes({ label, id, responses }: Props) {
285
285
  responseHeaders &&
286
286
  createDetails({
287
287
  className: "openapi-markdown__details",
288
- "data-collaposed": true,
288
+ "data-collapsed": true,
289
289
  open: false,
290
290
  style: { textAlign: "left", marginBottom: "1rem" },
291
291
  children: [
@@ -47,3 +47,25 @@ export const lessThan =
47
47
  export const greaterThan =
48
48
  /(?<!(button|code|details|summary|hr|br|span|strong|small|table|thead|tbody|td|tr|th|h1|h2|h3|h4|h5|h6|title|p|em|b|i|u|strike|bold|a|li|ol|ul|img|svg|div|center|\/|\s|"|'))>/gu;
49
49
  export const codeFence = /`{1,3}[\s\S]*?`{1,3}/g;
50
+ export const curlyBrackets = /([{}])/g;
51
+ export const codeBlock = /(^```.*[\s\S]*?```$|`[^`].+?`)/gm;
52
+
53
+ export function clean(value: string | undefined): string {
54
+ if (!value) {
55
+ return "";
56
+ }
57
+
58
+ let sections = value.split(codeBlock);
59
+ for (let sectionIndex in sections) {
60
+ if (!sections[sectionIndex].startsWith("`")) {
61
+ sections[sectionIndex] = sections[sectionIndex]
62
+ .replace(lessThan, "&lt;")
63
+ .replace(greaterThan, "&gt;")
64
+ .replace(codeFence, function (match) {
65
+ return match.replace(/\\>/g, ">");
66
+ })
67
+ .replace(curlyBrackets, "\\$1");
68
+ }
69
+ }
70
+ return sections.join("");
71
+ }
@@ -40,3 +40,10 @@ x-tagGroups:
40
40
  tags:
41
41
  - tag3
42
42
  - tag4
43
+
44
+ components:
45
+ schemas:
46
+ HelloString:
47
+ x-tags:
48
+ - tag1
49
+ type: string
@@ -31,6 +31,10 @@ describe("openapi", () => {
31
31
 
32
32
  expect(yaml?.data.tags).toBeDefined();
33
33
  expect(yaml?.data["x-tagGroups"]).toBeDefined();
34
+
35
+ expect(
36
+ yaml?.data.components?.schemas?.HelloString["x-tags"]
37
+ ).toBeDefined();
34
38
  });
35
39
  });
36
40
  });
@@ -8,15 +8,15 @@
8
8
  import path from "path";
9
9
 
10
10
  import { Globby, GlobExcludeDefault, posixPath } from "@docusaurus/utils";
11
- import Converter from "@paloaltonetworks/openapi-to-postmanv2";
12
- import sdk from "@paloaltonetworks/postman-collection";
13
- import Collection from "@paloaltonetworks/postman-collection";
14
11
  import chalk from "chalk";
15
12
  import fs from "fs-extra";
16
13
  import cloneDeep from "lodash/cloneDeep";
17
14
  import kebabCase from "lodash/kebabCase";
18
15
  import unionBy from "lodash/unionBy";
19
16
  import uniq from "lodash/uniq";
17
+ import Converter from "openapi-to-postmanv2";
18
+ import Collection from "postman-collection";
19
+ import sdk from "postman-collection";
20
20
 
21
21
  import { sampleRequestFromSchema } from "./createRequestExample";
22
22
  import { OpenApiObject, TagGroupObject, TagObject } from "./types";
@@ -410,43 +410,53 @@ function createItems(
410
410
  }
411
411
  }
412
412
 
413
- if (options?.showSchemas === true) {
413
+ if (
414
+ options?.showSchemas === true ||
415
+ Object.entries(openapiData?.components?.schemas ?? {})
416
+ .flatMap(([_, s]) => s["x-tags"])
417
+ .filter((item) => !!item).length > 0
418
+ ) {
414
419
  // Gather schemas
415
420
  for (let [schema, schemaObject] of Object.entries(
416
421
  openapiData?.components?.schemas ?? {}
417
422
  )) {
418
- const baseIdSpaces =
419
- schemaObject?.title?.replace(" ", "-").toLowerCase() ?? "";
420
- const baseId = kebabCase(baseIdSpaces);
421
-
422
- const schemaDescription = schemaObject.description;
423
- let splitDescription: any;
424
- if (schemaDescription) {
425
- splitDescription = schemaDescription.match(/[^\r\n]+/g);
426
- }
423
+ if (options?.showSchemas === true || schemaObject["x-tags"]) {
424
+ const baseIdSpaces =
425
+ schemaObject?.title?.replace(" ", "-").toLowerCase() ?? "";
426
+ const baseId = kebabCase(baseIdSpaces);
427
+
428
+ const schemaDescription = schemaObject.description;
429
+ let splitDescription: any;
430
+ if (schemaDescription) {
431
+ splitDescription = schemaDescription.match(/[^\r\n]+/g);
432
+ }
427
433
 
428
- const schemaPage: PartialPage<SchemaPageMetadata> = {
429
- type: "schema",
430
- id: baseId,
431
- infoId: infoId ?? "",
432
- unversionedId: baseId,
433
- title: schemaObject.title
434
- ? schemaObject.title.replace(/((?:^|[^\\])(?:\\{2})*)"/g, "$1'")
435
- : schema,
436
- description: schemaObject.description
437
- ? schemaObject.description.replace(/((?:^|[^\\])(?:\\{2})*)"/g, "$1'")
438
- : "",
439
- frontMatter: {
440
- description: splitDescription
441
- ? splitDescription[0]
442
- .replace(/((?:^|[^\\])(?:\\{2})*)"/g, "$1'")
443
- .replace(/\s+$/, "")
434
+ const schemaPage: PartialPage<SchemaPageMetadata> = {
435
+ type: "schema",
436
+ id: baseId,
437
+ infoId: infoId ?? "",
438
+ unversionedId: baseId,
439
+ title: schemaObject.title
440
+ ? schemaObject.title.replace(/((?:^|[^\\])(?:\\{2})*)"/g, "$1'")
441
+ : schema,
442
+ description: schemaObject.description
443
+ ? schemaObject.description.replace(
444
+ /((?:^|[^\\])(?:\\{2})*)"/g,
445
+ "$1'"
446
+ )
444
447
  : "",
445
- },
446
- schema: schemaObject,
447
- };
448
+ frontMatter: {
449
+ description: splitDescription
450
+ ? splitDescription[0]
451
+ .replace(/((?:^|[^\\])(?:\\{2})*)"/g, "$1'")
452
+ .replace(/\s+$/, "")
453
+ : "",
454
+ },
455
+ schema: schemaObject,
456
+ };
448
457
 
449
- items.push(schemaPage);
458
+ items.push(schemaPage);
459
+ }
450
460
  }
451
461
  }
452
462
 
@@ -352,6 +352,7 @@ export type SchemaObject = Omit<
352
352
  externalDocs?: ExternalDocumentationObject;
353
353
  example?: any;
354
354
  deprecated?: boolean;
355
+ "x-tags"?: string[];
355
356
  };
356
357
 
357
358
  export type SchemaObjectWithRef = Omit<
@@ -5,6 +5,6 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- declare module "@paloaltonetworks/openapi-to-postmanv2" {
8
+ declare module "openapi-to-postmanv2" {
9
9
  export default any;
10
10
  }
package/src/options.ts CHANGED
@@ -23,6 +23,7 @@ const markdownGenerators = Joi.object({
23
23
 
24
24
  export const OptionsSchema = Joi.object({
25
25
  id: Joi.string().required(),
26
+ docsPlugin: Joi.string(),
26
27
  docsPluginId: Joi.string().required(),
27
28
  config: Joi.object()
28
29
  .pattern(
@@ -38,6 +39,7 @@ export const OptionsSchema = Joi.object({
38
39
  sidebarOptions: sidebarOptions,
39
40
  markdownGenerators: markdownGenerators,
40
41
  showSchemas: Joi.boolean(),
42
+ disableCompression: Joi.boolean(),
41
43
  version: Joi.string().when("versions", {
42
44
  is: Joi.exist(),
43
45
  then: Joi.required(),
@@ -57,6 +59,7 @@ export const OptionsSchema = Joi.object({
57
59
  outputDir: Joi.string().required(),
58
60
  label: Joi.string().required(),
59
61
  baseUrl: Joi.string().required(),
62
+ downloadUrl: Joi.string(),
60
63
  })
61
64
  ),
62
65
  })
@@ -5,6 +5,6 @@
5
5
  * LICENSE file in the root directory of this source tree.
6
6
  * ========================================================================== */
7
7
 
8
- declare module "@paloaltonetworks/postman-collection" {
8
+ declare module "postman-collection" {
9
9
  export default any;
10
10
  }