From 1fec8d2321ba8c5c26aac5bae769e64daa4aa709 Mon Sep 17 00:00:00 2001 From: Maschga Date: Fri, 27 Dec 2024 22:08:08 +0100 Subject: [PATCH 1/9] add and document `nested`-property --- README.md | 1 + packages/docusaurus-plugin-openapi-docs/src/types.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 439097e43..227868722 100644 --- a/README.md +++ b/README.md @@ -179,6 +179,7 @@ The `docusaurus-plugin-openapi-docs` plugin can be configured with the following | Name | Type | Default | Description | | -------------------- | --------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `groupPathsBy` | `string` | `null` | Organize and group sidebar slice by specified option. Note: Currently, `groupPathsBy` only contains support for grouping by `tag` and `tagGroup`. | +| `nested` | `boolean` | `false` | Whether to create a nested filesystem structure. Needs to be `true` for Docusaurus-instances [which create a sidebar automatically from the filesystem structure](https://docusaurus.io/docs/next/sidebar/autogenerated). | | `categoryLinkSource` | `string` | `null` | Defines what source to use for rendering category link pages when grouping paths by tag.

The supported options are as follows:

`tag`: Sets the category link config type to `generated-index` and uses the tag description as the link config description.

`info`: Sets the category link config type to `doc` and renders the `info` section as the category link (recommended only for multi/micro-spec scenarios).

`none`: Does not create pages for categories, only groups that can be expanded/collapsed. | | `sidebarCollapsible` | `boolean` | `true` | Whether sidebar categories are collapsible by default. | | `sidebarCollapsed` | `boolean` | `true` | Whether sidebar categories are collapsed by default. | diff --git a/packages/docusaurus-plugin-openapi-docs/src/types.ts b/packages/docusaurus-plugin-openapi-docs/src/types.ts index 43367bbaa..c4dfd9605 100644 --- a/packages/docusaurus-plugin-openapi-docs/src/types.ts +++ b/packages/docusaurus-plugin-openapi-docs/src/types.ts @@ -74,6 +74,7 @@ export interface SidebarOptions { sidebarCollapsible?: boolean; sidebarCollapsed?: boolean; sidebarGenerators?: SidebarGenerators; + nested?: boolean; } export interface APIVersionOptions { From 23dfc8c8e825b4d83b9b8a0edcfbbbdc0c30420c Mon Sep 17 00:00:00 2001 From: Maschga Date: Fri, 27 Dec 2024 22:09:50 +0100 Subject: [PATCH 2/9] skip generating `sidebar.ts` when directory should be nested --- packages/docusaurus-plugin-openapi-docs/src/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/docusaurus-plugin-openapi-docs/src/index.ts b/packages/docusaurus-plugin-openapi-docs/src/index.ts index 61a84e0ac..b68e5d9b0 100644 --- a/packages/docusaurus-plugin-openapi-docs/src/index.ts +++ b/packages/docusaurus-plugin-openapi-docs/src/index.ts @@ -178,7 +178,10 @@ export default function pluginOpenAPIDocs( ), }); - if (!fs.existsSync(`${outputDir}/sidebar.ts`)) { + if ( + !sidebarOptions?.nested && + !fs.existsSync(`${outputDir}/sidebar.ts`) + ) { try { fs.writeFileSync(`${outputDir}/sidebar.ts`, view, "utf8"); console.log( From fc3dd56809fef283f432c4d07491461ca3bc9fd7 Mon Sep 17 00:00:00 2001 From: Maschga Date: Fri, 27 Dec 2024 22:11:58 +0100 Subject: [PATCH 3/9] calculate path to directory --- .../docusaurus-plugin-openapi-docs/src/index.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/docusaurus-plugin-openapi-docs/src/index.ts b/packages/docusaurus-plugin-openapi-docs/src/index.ts index b68e5d9b0..bd545ff14 100644 --- a/packages/docusaurus-plugin-openapi-docs/src/index.ts +++ b/packages/docusaurus-plugin-openapi-docs/src/index.ts @@ -406,21 +406,26 @@ custom_edit_url: null } if (item.type === "tag") { - if (!fs.existsSync(`${outputDir}/${item.id}.tag.mdx`)) { + let tagOutputDir = sidebarOptions?.nested + ? `${outputDir}/${item.tag.name!}` + : outputDir; + if (!fs.existsSync(`${tagOutputDir}/${item.id}.tag.mdx`)) { try { fs.writeFileSync( - `${outputDir}/${item.id}.tag.mdx`, + `${tagOutputDir}/${item.id}.tag.mdx`, tagUtils, "utf8" ); console.log( chalk.green( - `Successfully created "${outputDir}/${item.id}.tag.mdx"` + `Successfully created "${tagOutputDir}/${item.id}.tag.mdx"` ) ); } catch (err) { console.error( - chalk.red(`Failed to write "${outputDir}/${item.id}.tag.mdx"`), + chalk.red( + `Failed to write "${tagOutputDir}/${item.id}.tag.mdx"` + ), chalk.yellow(err) ); } From 9423319a86379ea47177ca45cb8a7d87bf0a0660 Mon Sep 17 00:00:00 2001 From: Maschga Date: Fri, 27 Dec 2024 23:06:59 +0100 Subject: [PATCH 4/9] update joi --- packages/docusaurus-plugin-openapi-docs/src/options.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/docusaurus-plugin-openapi-docs/src/options.ts b/packages/docusaurus-plugin-openapi-docs/src/options.ts index ff114de7f..07a3af16f 100644 --- a/packages/docusaurus-plugin-openapi-docs/src/options.ts +++ b/packages/docusaurus-plugin-openapi-docs/src/options.ts @@ -18,6 +18,7 @@ const sidebarOptions = Joi.object({ sidebarCollapsible: Joi.boolean(), sidebarCollapsed: Joi.boolean(), sidebarGenerators: sidebarGenerators, + nested: Joi.boolean(), }); const markdownGenerators = Joi.object({ From 61fb69f3e4908edff25d4be6fdc2eef60b673886 Mon Sep 17 00:00:00 2001 From: Maschga Date: Sat, 28 Dec 2024 19:06:03 +0100 Subject: [PATCH 5/9] fix creating and cleaning directories --- .../src/index.ts | 107 ++++++++++++------ 1 file changed, 70 insertions(+), 37 deletions(-) diff --git a/packages/docusaurus-plugin-openapi-docs/src/index.ts b/packages/docusaurus-plugin-openapi-docs/src/index.ts index bd545ff14..17e34cb71 100644 --- a/packages/docusaurus-plugin-openapi-docs/src/index.ts +++ b/packages/docusaurus-plugin-openapi-docs/src/index.ts @@ -156,8 +156,34 @@ export default function pluginOpenAPIDocs( } } + if (sidebarOptions?.nested) { + let dirNames = + sidebarOptions.groupPathsBy === "tag" + ? tags[0].map((tag) => { + return tag.name; + }) + : tagGroups.map((tagGroup) => { + return tagGroup.name; + }); + + dirNames.forEach((directory) => { + if (!fs.existsSync(`${outputDir}/${directory}`)) { + try { + fs.mkdirSync(`${outputDir}/${directory}`, { recursive: true }); + console.log( + chalk.green(`Successfully created "${outputDir}/${directory}"`) + ); + } catch (err) { + console.error( + chalk.red(`Failed to create "${outputDir}/${directory}"`), + chalk.yellow(err) + ); + } + } + }); + } // TODO: figure out better way to set default - if (Object.keys(sidebarOptions ?? {}).length > 0) { + else if (Object.keys(sidebarOptions ?? {}).length > 0) { const sidebarSlice = generateSidebarSlice( sidebarOptions!, options, @@ -178,10 +204,7 @@ export default function pluginOpenAPIDocs( ), }); - if ( - !sidebarOptions?.nested && - !fs.existsSync(`${outputDir}/sidebar.ts`) - ) { + if (!fs.existsSync(`${outputDir}/sidebar.ts`)) { try { fs.writeFileSync(`${outputDir}/sidebar.ts`, view, "utf8"); console.log( @@ -353,7 +376,20 @@ custom_edit_url: null const tagUtils = render(tagMdTemplate, item); if (item.type === "api") { - if (!fs.existsSync(`${outputDir}/${item.id}.api.mdx`)) { + let path = `${outputDir}/${item.id}.tag.mdx`; + if (sidebarOptions?.nested) { + path = `${outputDir}/${item.api.tags![0]}/${item.id}.api.mdx`; + + if (sidebarOptions.groupPathsBy === "tagGroup") { + //get the tagGroup of the tag + tagGroups.forEach((tagGroup) => { + if (tagGroup.tags.includes(item.api.tags![0])) { + path = `${outputDir}/${tagGroup.name}/${item.id}.api.mdx`; + } + }); + } + } + if (!fs.existsSync(path)) { try { // kebabCase(arg) returns 0-length string when arg is undefined if (item.id.length === 0) { @@ -361,15 +397,11 @@ custom_edit_url: null "Operation must have summary or operationId defined" ); } - fs.writeFileSync(`${outputDir}/${item.id}.api.mdx`, view, "utf8"); - console.log( - chalk.green( - `Successfully created "${outputDir}/${item.id}.api.mdx"` - ) - ); + fs.writeFileSync(path, view, "utf8"); + console.log(chalk.green(`Successfully created "${path}"`)); } catch (err) { console.error( - chalk.red(`Failed to write "${outputDir}/${item.id}.api.mdx"`), + chalk.red(`Failed to write "${path}"`), chalk.yellow(err) ); } @@ -404,28 +436,27 @@ custom_edit_url: null } } } - if (item.type === "tag") { - let tagOutputDir = sidebarOptions?.nested - ? `${outputDir}/${item.tag.name!}` - : outputDir; - if (!fs.existsSync(`${tagOutputDir}/${item.id}.tag.mdx`)) { + let path = `${outputDir}/${item.id}.tag.mdx`; + if (sidebarOptions?.nested) { + path = `${outputDir}/${item.tag.name!}/index.mdx`; + + if (sidebarOptions.groupPathsBy === "tagGroup") { + //get the tagGroup of the tag + tagGroups.forEach((tagGroup) => { + if (tagGroup.tags.includes(item.tag.name!)) { + path = `${outputDir}/${tagGroup.name}/index.mdx`; + } + }); + } + } + if (!fs.existsSync(path)) { try { - fs.writeFileSync( - `${tagOutputDir}/${item.id}.tag.mdx`, - tagUtils, - "utf8" - ); - console.log( - chalk.green( - `Successfully created "${tagOutputDir}/${item.id}.tag.mdx"` - ) - ); + fs.writeFileSync(path, tagUtils, "utf8"); + console.log(chalk.green(`Successfully created "${path}"`)); } catch (err) { console.error( - chalk.red( - `Failed to write "${tagOutputDir}/${item.id}.tag.mdx"` - ), + chalk.red(`Failed to write "${path}"`), chalk.yellow(err) ); } @@ -487,15 +518,17 @@ custom_edit_url: null async function cleanApiDocs(options: APIOptions) { const { outputDir } = options; const apiDir = posixPath(path.join(siteDir, outputDir)); - const apiMdxFiles = await Globby(["*.api.mdx", "*.info.mdx", "*.tag.mdx"], { - cwd: path.resolve(apiDir), - deep: 1, - }); + const apiMdxFiles = await Globby( + ["**/*.api.mdx", "**/*.index.mdx", "**/*.info.mdx", "**/*.tag.mdx"], + { + cwd: path.resolve(apiDir), + } + ); const sidebarFile = await Globby(["sidebar.js", "sidebar.ts"], { cwd: path.resolve(apiDir), deep: 1, }); - apiMdxFiles.map((mdx) => + apiMdxFiles.forEach((mdx) => fs.unlink(`${apiDir}/${mdx}`, (err) => { if (err) { console.error( @@ -520,7 +553,7 @@ custom_edit_url: null } } - sidebarFile.map((sidebar) => + sidebarFile.forEach((sidebar) => fs.unlink(`${apiDir}/${sidebar}`, (err) => { if (err) { console.error( From 40078cb0ef5cc880ef0fadabd2ffa980343642ba Mon Sep 17 00:00:00 2001 From: Maschga Date: Sat, 28 Dec 2024 19:06:22 +0100 Subject: [PATCH 6/9] add petstore_nested-demo --- demo/docusaurus.config.ts | 14 ++++++++++++++ demo/sidebars.ts | 1 + 2 files changed, 15 insertions(+) diff --git a/demo/docusaurus.config.ts b/demo/docusaurus.config.ts index d339fba7f..82bb528be 100644 --- a/demo/docusaurus.config.ts +++ b/demo/docusaurus.config.ts @@ -302,6 +302,20 @@ const config: Config = { hideSendButton: false, showSchemas: true, } satisfies OpenApiPlugin.Options, + petstore_nested: { + specPath: "examples/petstore.yaml", + proxy: "https://cors.pan.dev", + outputDir: "docs/petstore_nested", + sidebarOptions: { + groupPathsBy: "tag", + categoryLinkSource: "tag", + nested: true, + }, + template: "api.mustache", // Customize API MDX with mustache template + downloadUrl: "/petstore.yaml", + hideSendButton: false, + showSchemas: true, + } satisfies OpenApiPlugin.Options, petstore31: { specPath: "examples/petstore-3.1.yaml", proxy: "https://cors.pan.dev", diff --git a/demo/sidebars.ts b/demo/sidebars.ts index f7aa38198..779b20f57 100644 --- a/demo/sidebars.ts +++ b/demo/sidebars.ts @@ -136,6 +136,7 @@ const sidebars: SidebarsConfig = { items: require("./docs/restaurant/sidebar.js"), }, ], + petstore_nested: [{ type: "autogenerated", dirName: "." }], "petstore-2.0.0": [ { type: "html", From c7ca7da8f80e7f401adf266b7273f4bc212b0575 Mon Sep 17 00:00:00 2001 From: Maschga Date: Sat, 28 Dec 2024 21:20:01 +0100 Subject: [PATCH 7/9] fix dirName --- demo/sidebars.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/sidebars.ts b/demo/sidebars.ts index 779b20f57..ff51773fe 100644 --- a/demo/sidebars.ts +++ b/demo/sidebars.ts @@ -136,7 +136,7 @@ const sidebars: SidebarsConfig = { items: require("./docs/restaurant/sidebar.js"), }, ], - petstore_nested: [{ type: "autogenerated", dirName: "." }], + petstore_nested: [{ type: "autogenerated", dirName: "petstore_nested" }], "petstore-2.0.0": [ { type: "html", From 61e0dbe6d98aaebb77d7c05b48f03d0163f5ee67 Mon Sep 17 00:00:00 2001 From: Maschga Date: Tue, 31 Dec 2024 14:13:51 +0100 Subject: [PATCH 8/9] Add `demo/**/index.mdx` --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index fd1c0d0b6..8043415e1 100644 --- a/.gitignore +++ b/.gitignore @@ -138,6 +138,7 @@ demo/**/*.api.mdx demo/**/*.info.mdx demo/**/*.tag.mdx demo/**/*.schema.mdx +demo/**/index.mdx demo/**/sidebar.ts demo/**/versions.json From c15ddc629be35b097fd583ec19403661fceea306 Mon Sep 17 00:00:00 2001 From: Maschga Date: Tue, 31 Dec 2024 14:14:02 +0100 Subject: [PATCH 9/9] remove `petstore_nested` from demo --- demo/docusaurus.config.ts | 14 -------------- demo/sidebars.ts | 1 - 2 files changed, 15 deletions(-) diff --git a/demo/docusaurus.config.ts b/demo/docusaurus.config.ts index 82bb528be..d339fba7f 100644 --- a/demo/docusaurus.config.ts +++ b/demo/docusaurus.config.ts @@ -302,20 +302,6 @@ const config: Config = { hideSendButton: false, showSchemas: true, } satisfies OpenApiPlugin.Options, - petstore_nested: { - specPath: "examples/petstore.yaml", - proxy: "https://cors.pan.dev", - outputDir: "docs/petstore_nested", - sidebarOptions: { - groupPathsBy: "tag", - categoryLinkSource: "tag", - nested: true, - }, - template: "api.mustache", // Customize API MDX with mustache template - downloadUrl: "/petstore.yaml", - hideSendButton: false, - showSchemas: true, - } satisfies OpenApiPlugin.Options, petstore31: { specPath: "examples/petstore-3.1.yaml", proxy: "https://cors.pan.dev", diff --git a/demo/sidebars.ts b/demo/sidebars.ts index ff51773fe..f7aa38198 100644 --- a/demo/sidebars.ts +++ b/demo/sidebars.ts @@ -136,7 +136,6 @@ const sidebars: SidebarsConfig = { items: require("./docs/restaurant/sidebar.js"), }, ], - petstore_nested: [{ type: "autogenerated", dirName: "petstore_nested" }], "petstore-2.0.0": [ { type: "html",