diff --git a/demo/examples/petstore.yaml b/demo/examples/petstore.yaml index 7b07a34a6..1e308500c 100644 --- a/demo/examples/petstore.yaml +++ b/demo/examples/petstore.yaml @@ -351,6 +351,10 @@ paths: - available - pending - sold + x-enumDescriptions: + available: When the pet is available + pending: When the pet is being sold + sold: When the pet has been sold default: available responses: "200": @@ -1114,6 +1118,15 @@ components: - available - pending - sold + x-enumDescriptions: + available: When the pet is available + pending: When the pet is being sold + sold: | + When the pet has been sold. + + These descriptions can contain line + + breaks and also [links](https://docusaurus.io/) petType: description: Type of a pet type: string diff --git a/packages/docusaurus-plugin-openapi-docs/src/markdown/createParamsDetails.ts b/packages/docusaurus-plugin-openapi-docs/src/markdown/createParamsDetails.ts index f3415e286..ace6dc5ae 100644 --- a/packages/docusaurus-plugin-openapi-docs/src/markdown/createParamsDetails.ts +++ b/packages/docusaurus-plugin-openapi-docs/src/markdown/createParamsDetails.ts @@ -43,12 +43,17 @@ export function createParamsDetails({ parameters, type }: Props) { create("div", { children: [ create("ul", { - children: params.map((param) => - create("ParamsItem", { + children: params.map((param) => { + return create("ParamsItem", { className: "paramsItem", - param: param, - }) - ), + param: { + ...param, + enumDescriptions: Object.entries( + param?.schema?.items?.["x-enumDescriptions"] ?? {} + ), + }, + }); + }), }), ], }), diff --git a/packages/docusaurus-plugin-openapi-docs/src/openapi/types.ts b/packages/docusaurus-plugin-openapi-docs/src/openapi/types.ts index cbb88b97e..cc0092fb1 100644 --- a/packages/docusaurus-plugin-openapi-docs/src/openapi/types.ts +++ b/packages/docusaurus-plugin-openapi-docs/src/openapi/types.ts @@ -197,6 +197,7 @@ export interface ParameterObject { param?: Object; // ignoring stylings: matrix, label, form, simple, spaceDelimited, // pipeDelimited and deepObject + "x-enumDescriptions"?: Record; } export interface ParameterObjectWithRef { @@ -353,6 +354,7 @@ export type SchemaObject = Omit< example?: any; deprecated?: boolean; "x-tags"?: string[]; + "x-enumDescriptions"?: Record; }; export type SchemaObjectWithRef = Omit< diff --git a/packages/docusaurus-plugin-openapi-docs/src/openapi/utils/services/OpenAPIParser.ts b/packages/docusaurus-plugin-openapi-docs/src/openapi/utils/services/OpenAPIParser.ts index 974dff27e..f0ff8029f 100644 --- a/packages/docusaurus-plugin-openapi-docs/src/openapi/utils/services/OpenAPIParser.ts +++ b/packages/docusaurus-plugin-openapi-docs/src/openapi/utils/services/OpenAPIParser.ts @@ -270,6 +270,7 @@ export class OpenAPIParser { const { type, enum: enumProperty, + "x-enumDescription": enumDescription, properties, items, required, diff --git a/packages/docusaurus-theme-openapi-docs/package.json b/packages/docusaurus-theme-openapi-docs/package.json index 78af3f81f..629f845a7 100644 --- a/packages/docusaurus-theme-openapi-docs/package.json +++ b/packages/docusaurus-theme-openapi-docs/package.json @@ -57,6 +57,7 @@ "react-modal": "^3.15.1", "react-redux": "^7.2.0", "rehype-raw": "^6.1.1", + "remark-gfm": "3.0.1", "sass": "^1.58.1", "sass-loader": "^13.3.2", "webpack": "^5.61.0", diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/MethodEndpoint/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/MethodEndpoint/index.tsx index eebbd556c..fb174c619 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/MethodEndpoint/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/MethodEndpoint/index.tsx @@ -39,8 +39,6 @@ export interface Props { } function MethodEndpoint({ method, path, context }: Props) { - const server = useTypedSelector((state: any) => state); - let serverValue = useTypedSelector((state: any) => state.server.value); let serverUrlWithVariables = ""; diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/ParamsItem/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/ParamsItem/index.tsx index ae28a5365..5114f719c 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/ParamsItem/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/ParamsItem/index.tsx @@ -14,6 +14,7 @@ import TabItem from "@theme/TabItem"; import clsx from "clsx"; import ReactMarkdown from "react-markdown"; import rehypeRaw from "rehype-raw"; +import remarkGfm from "remark-gfm"; import { createDescription } from "../../markdown/createDescription"; import { getQualifierMessage, getSchemaName } from "../../markdown/schema"; @@ -39,12 +40,38 @@ export interface Props { required: boolean; deprecated: boolean; schema: any; + enumDescriptions?: [string, string][]; }; } -function ParamsItem({ - param: { description, example, examples, name, required, schema, deprecated }, -}: Props) { +const getEnumDescriptionMarkdown = (enumDescriptions?: [string, string][]) => { + if (enumDescriptions?.length) { + return `| Enum Value | Description | +| ---- | ----- | +${enumDescriptions + .map((desc) => { + return `| ${desc[0]} | ${desc[1]} | `.replaceAll("\n", "
"); + }) + .join("\n")} + `; + } + + return ""; +}; + +function ParamsItem({ param, ...rest }: Props) { + const { + description, + example, + examples, + name, + required, + deprecated, + enumDescriptions, + } = param; + + let schema = param.schema; + if (!schema || !schema?.type) { schema = { type: "any" }; } @@ -91,6 +118,19 @@ function ParamsItem({ )); + const renderEnumDescriptions = guard( + getEnumDescriptionMarkdown(enumDescriptions), + (value) => { + return ( + + ); + } + ); + const renderDefaultValue = guard( schema && schema.items ? schema.items.default @@ -158,6 +198,7 @@ function ParamsItem({ {renderSchema} {renderDefaultValue} {renderDescription} + {renderEnumDescriptions} {renderExample} {renderExamples} diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/SchemaItem/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/SchemaItem/index.tsx index 233c6d3b7..2cda61e26 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/SchemaItem/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/SchemaItem/index.tsx @@ -11,6 +11,7 @@ import CodeBlock from "@theme/CodeBlock"; import clsx from "clsx"; import ReactMarkdown from "react-markdown"; import rehypeRaw from "rehype-raw"; +import remarkGfm from "remark-gfm"; import { createDescription } from "../../markdown/createDescription"; import { guard } from "../../markdown/utils"; @@ -27,22 +28,51 @@ export interface Props { discriminator: boolean; } -export default function SchemaItem({ - children: collapsibleSchemaContent, - collapsible, - name, - qualifierMessage, - required, - schemaName, - schema, -}: Props) { +const transformEnumDescriptions = ( + enumDescriptions?: Record +) => { + if (enumDescriptions) { + return Object.entries(enumDescriptions); + } + + return []; +}; + +const getEnumDescriptionMarkdown = (enumDescriptions?: [string, string][]) => { + if (enumDescriptions?.length) { + return `| Enum Value | Description | +| ---- | ----- | +${enumDescriptions + .map((desc) => { + return `| ${desc[0]} | ${desc[1]} | `.replaceAll("\n", "
"); + }) + .join("\n")} + `; + } + + return ""; +}; + +export default function SchemaItem(props: Props) { + const { + children: collapsibleSchemaContent, + collapsible, + name, + qualifierMessage, + required, + schemaName, + schema, + } = props; let deprecated; let schemaDescription; let defaultValue; let nullable; + let enumDescriptions: [string, string][] = []; + if (schema) { deprecated = schema.deprecated; schemaDescription = schema.description; + enumDescriptions = transformEnumDescriptions(schema["x-enumDescriptions"]); defaultValue = schema.default; nullable = schema.nullable; } @@ -60,6 +90,19 @@ export default function SchemaItem({ nullable )); + const renderEnumDescriptions = guard( + getEnumDescriptionMarkdown(enumDescriptions), + (value) => { + return ( + + ); + } + ); + const renderSchemaDescription = guard(schemaDescription, (description) => (
);