From b0002c0c0dbad0f8259bb46a45acd368d1bbf358 Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Wed, 6 Nov 2024 22:18:40 -0500 Subject: [PATCH 01/22] experimental admonition support --- demo/examples/petstore.yaml | 11 ++++- .../package.json | 1 + .../src/theme/Markdown/index.js | 42 +++++++++++++++++++ .../src/theme/ResponseSchema/index.tsx | 3 +- .../src/theme/StatusCodes/index.tsx | 3 +- yarn.lock | 41 ++++-------------- 6 files changed, 65 insertions(+), 36 deletions(-) diff --git a/demo/examples/petstore.yaml b/demo/examples/petstore.yaml index 1e308500c..3ffe56b88 100644 --- a/demo/examples/petstore.yaml +++ b/demo/examples/petstore.yaml @@ -116,7 +116,16 @@ paths: operationId: addPet responses: "200": - description: All good + description: | + All good, here's some MDX: + + :::info + TEsting !@# + ::: + + ```python + print("hello") + ``` content: application/json: schema: diff --git a/packages/docusaurus-theme-openapi-docs/package.json b/packages/docusaurus-theme-openapi-docs/package.json index a69c2e858..734c484e9 100644 --- a/packages/docusaurus-theme-openapi-docs/package.json +++ b/packages/docusaurus-theme-openapi-docs/package.json @@ -61,6 +61,7 @@ "remark-gfm": "3.0.1", "sass": "^1.80.4", "sass-loader": "^16.0.2", + "unist-util-visit": "^5.0.0", "webpack": "^5.61.0", "xml-formatter": "^2.6.1" }, diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js b/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js index 13ce11a65..0d4a72752 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js +++ b/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js @@ -7,16 +7,54 @@ import React from "react"; +import Admonition from "@theme/Admonition"; import CodeBlock from "@theme/CodeBlock"; import ReactMarkdown from "react-markdown"; import rehypeRaw from "rehype-raw"; +// eslint-disable-next-line import/no-extraneous-dependencies +import { visit } from "unist-util-visit"; +function remarkAdmonition() { + return (tree) => { + visit(tree, "paragraph", (node, index, parent) => { + const { children } = node; + if (children.length > 0 && children[0].type === "text") { + const text = children[0].value; + const match = text.match(/^:::(\w+)\s+(.*?)\s*:::$/); + + if (match) { + const type = match[1]; + const content = match[2]; + + const admonitionNode = { + type: "admonition", + data: { + hName: "div", + hProperties: { + className: `theme-admonition theme-admonition-${type} alert alert--success`, + }, + }, + children: [ + { + type: "div", + value: content, + }, + ], + }; + + parent.children.splice(index, 1, admonitionNode); + } + } + }); + }; +} function Markdown({ children }) { return (
{children} ); }, + admonition: ({ node, ...props }) => { + const className = node.data.hProperties.className; + return ; + }, }} />
diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/ResponseSchema/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/ResponseSchema/index.tsx index 74f18e7e4..863807690 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/ResponseSchema/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/ResponseSchema/index.tsx @@ -9,6 +9,7 @@ import React, { Suspense } from "react"; import BrowserOnly from "@docusaurus/BrowserOnly"; import Details from "@theme/Details"; +import Markdown from "@theme/Markdown"; import MimeTabs from "@theme/MimeTabs"; // Assume these components exist import { ExampleFromSchema, @@ -99,7 +100,7 @@ const ResponseSchemaComponent: React.FC = ({
- {createDescription(body.description)} + {body.description}
)} diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/StatusCodes/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/StatusCodes/index.tsx index 422e396a1..4cc4b96cb 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/StatusCodes/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/StatusCodes/index.tsx @@ -9,6 +9,7 @@ import React from "react"; import ApiTabs from "@theme/ApiTabs"; import Details from "@theme/Details"; +import Markdown from "@theme/Markdown"; import { ResponseHeaders } from "@theme/ResponseExamples"; import ResponseSchema from "@theme/ResponseSchema"; import TabItem from "@theme/TabItem"; @@ -39,7 +40,7 @@ const StatusCodes: React.FC = ({ label, id, responses }: any) => {
{response.description && (
- {createDescription(response.description)} + {response.description}
)}
diff --git a/yarn.lock b/yarn.lock index 0c8a51871..174fedb85 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2293,7 +2293,7 @@ utility-types "^3.10.0" webpack "^5.88.1" -"@docusaurus/plugin-content-docs@3.6.0": +"@docusaurus/plugin-content-docs@3.6.0", "@docusaurus/plugin-content-docs@^3.5.0": version "3.6.0" resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.6.0.tgz#15cae4bf81da0b0ddce09d53b10b7209116ea9c2" integrity sha512-c5gZOxocJKO/Zev2MEZInli+b+VNswDGuKHE6QtFgidhAJonwjh2kwj967RvWFaMMk62HlLJLZ+IGK2XsVy4Aw== @@ -2439,7 +2439,7 @@ tslib "^2.6.0" utility-types "^3.10.0" -"@docusaurus/theme-common@3.6.0": +"@docusaurus/theme-common@3.6.0", "@docusaurus/theme-common@^3.5.0": version "3.6.0" resolved "https://registry.yarnpkg.com/@docusaurus/theme-common/-/theme-common-3.6.0.tgz#9a061d278df76da0f70a9465cd0b7299c14d03d3" integrity sha512-frjlYE5sRs+GuPs4XXlp9aMLI2O4H5FPpznDAXBrCm+8EpWRiIb443ePMxM3IyMCQ5bwFlki0PI9C+r4apstnw== @@ -2487,7 +2487,7 @@ fs-extra "^11.1.1" tslib "^2.6.0" -"@docusaurus/types@3.6.0": +"@docusaurus/types@3.6.0", "@docusaurus/types@^3.5.0": version "3.6.0" resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-3.6.0.tgz#8fa82332a7c7b8093b5c55e1115f5854ce484978" integrity sha512-jADLgoZGWhAzThr+mRiyuFD4OUzt6jHnb7NRArRKorgxckqUBaPyFOau9hhbcSTHtU6ceyeWjN7FDt7uG2Hplw== @@ -2509,7 +2509,7 @@ dependencies: tslib "^2.6.0" -"@docusaurus/utils-validation@3.6.0": +"@docusaurus/utils-validation@3.6.0", "@docusaurus/utils-validation@^3.5.0": version "3.6.0" resolved "https://registry.yarnpkg.com/@docusaurus/utils-validation/-/utils-validation-3.6.0.tgz#5557ca14fa64ac29e6f70e61006be721395ecde5" integrity sha512-CRHiKKJEKA0GFlfOf71JWHl7PtwOyX0+Zg9ep9NFEZv6Lcx3RJ9nhl7p8HRjPL6deyYceavM//BsfW4pCI4BtA== @@ -2523,7 +2523,7 @@ lodash "^4.17.21" tslib "^2.6.0" -"@docusaurus/utils@3.6.0": +"@docusaurus/utils@3.6.0", "@docusaurus/utils@^3.5.0": version "3.6.0" resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-3.6.0.tgz#192785da6fd62dfd83d6f1879c3aa45547f5df23" integrity sha512-VKczAutI4mptiAw/WcYEu5WeVhQ6Q1zdIUl64SGw9K++9lziH+Kt10Ee8l2dMpRkiUk6zzK20kMNlX2WCUwXYQ== @@ -17232,16 +17232,7 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", "string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -17361,7 +17352,7 @@ stringify-object@3.3.0, stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -17375,13 +17366,6 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.1.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" @@ -18923,7 +18907,7 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -18950,15 +18934,6 @@ wrap-ansi@^6.0.1, wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 818403e5dced14d436de0739aa72101ae95bd1f0 Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Wed, 6 Nov 2024 22:24:18 -0500 Subject: [PATCH 02/22] base admonition theme color on type --- .../docusaurus-theme-openapi-docs/src/theme/Markdown/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js b/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js index 0d4a72752..e31bc8023 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js +++ b/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js @@ -31,7 +31,7 @@ function remarkAdmonition() { data: { hName: "div", hProperties: { - className: `theme-admonition theme-admonition-${type} alert alert--success`, + className: `theme-admonition theme-admonition-${type} alert alert--${type}`, }, }, children: [ From 9a5f3c0d30d4802a633a2b97f0a71c9a2488b0c7 Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Wed, 6 Nov 2024 22:51:24 -0500 Subject: [PATCH 03/22] Use @theme/Admonition component --- .../src/theme/Markdown/index.js | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js b/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js index e31bc8023..42029eb6c 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js +++ b/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js @@ -21,7 +21,6 @@ function remarkAdmonition() { if (children.length > 0 && children[0].type === "text") { const text = children[0].value; const match = text.match(/^:::(\w+)\s+(.*?)\s*:::$/); - if (match) { const type = match[1]; const content = match[2]; @@ -29,14 +28,14 @@ function remarkAdmonition() { const admonitionNode = { type: "admonition", data: { - hName: "div", + hName: "Admonition", // Tells ReactMarkdown to replace the node with Admonition component hProperties: { - className: `theme-admonition theme-admonition-${type} alert alert--${type}`, + type, // Passed as a prop to the Admonition component }, }, children: [ { - type: "div", + type: "text", value: content, }, ], @@ -48,6 +47,7 @@ function remarkAdmonition() { }); }; } + function Markdown({ children }) { return (
@@ -66,9 +66,18 @@ function Markdown({ children }) { {children} ); }, + // Render custom admonition nodes admonition: ({ node, ...props }) => { - const className = node.data.hProperties.className; - return ; + const type = node?.data?.hProperties?.type || "note"; // Safely access the type + // Extract the text content from the children nodes + const content = node.children + .map((child) => (child.type === "text" ? child.value : "")) + .join(" "); + return ( + + {content} + + ); }, }} /> From eb3f77113d22687f7a5e97637548dc275ad92183 Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Thu, 7 Nov 2024 15:40:38 -0500 Subject: [PATCH 04/22] concatenate and process all node children and add support for title prop --- .../src/theme/Markdown/index.js | 83 ++++++++++++------- 1 file changed, 53 insertions(+), 30 deletions(-) diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js b/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js index 42029eb6c..5e396c5d3 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js +++ b/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js @@ -16,35 +16,58 @@ import { visit } from "unist-util-visit"; function remarkAdmonition() { return (tree) => { - visit(tree, "paragraph", (node, index, parent) => { - const { children } = node; - if (children.length > 0 && children[0].type === "text") { - const text = children[0].value; - const match = text.match(/^:::(\w+)\s+(.*?)\s*:::$/); - if (match) { - const type = match[1]; - const content = match[2]; + const paragraphs = []; + let collectedText = ""; - const admonitionNode = { - type: "admonition", - data: { - hName: "Admonition", // Tells ReactMarkdown to replace the node with Admonition component - hProperties: { - type, // Passed as a prop to the Admonition component - }, - }, - children: [ - { - type: "text", - value: content, - }, - ], - }; - - parent.children.splice(index, 1, admonitionNode); - } - } + // Collect all 'paragraph' nodes + visit(tree, "paragraph", (node) => { + paragraphs.push(node); + collectedText += + node.children.map((child) => child.value || "").join("\n") + "\n"; }); + + const regex = /^\s*:::(\w+)(?:\[(.*?)\])?\s*([\s\S]*?)\s*:::\s*$/gm; + const matches = collectedText.matchAll(regex); + + // Collect admonition nodes to insert + const admonitionNodes = []; + + for (const match of matches) { + const type = match[1]; + const title = match[2] ? match[2].trim() : undefined; + const content = match[3]; + + const admonitionNode = { + type: "admonition", + data: { + hName: "Admonition", // Tells ReactMarkdown to replace the node with Admonition component + hProperties: { + type, // Passed as a prop to the Admonition component + title, + }, + }, + children: [ + { + type: "text", + value: content.trim(), // Trim leading/trailing whitespace + }, + ], + }; + + admonitionNodes.push(admonitionNode); + } + + // Replace the original paragraph nodes if we found any admonition nodes + if (admonitionNodes.length > 0) { + const firstParagraphIndex = tree.children.findIndex( + (node) => node.type === "paragraph" + ); + tree.children.splice( + firstParagraphIndex, + paragraphs.length, + ...admonitionNodes + ); + } }; } @@ -68,13 +91,13 @@ function Markdown({ children }) { }, // Render custom admonition nodes admonition: ({ node, ...props }) => { - const type = node?.data?.hProperties?.type || "note"; // Safely access the type - // Extract the text content from the children nodes + const type = node?.data?.hProperties?.type || "note"; + const title = node?.data?.hProperties?.title; const content = node.children .map((child) => (child.type === "text" ? child.value : "")) .join(" "); return ( - + {content} ); From 4718e2ae3a9e5fe2e718b974c87b9becea12597b Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Thu, 7 Nov 2024 15:40:53 -0500 Subject: [PATCH 05/22] update example --- demo/examples/petstore.yaml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/demo/examples/petstore.yaml b/demo/examples/petstore.yaml index 3ffe56b88..4efdc6ee3 100644 --- a/demo/examples/petstore.yaml +++ b/demo/examples/petstore.yaml @@ -119,8 +119,18 @@ paths: description: | All good, here's some MDX: - :::info - TEsting !@# + :::note[MR SPOCK] + + testing 123 + + ::: + + :::warning + testing 123 + ::: + + :::danger + testing 123 ::: ```python From f4dcd0656e04aa4d6f20128f71ee9ae3a817857d Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Thu, 7 Nov 2024 15:54:32 -0500 Subject: [PATCH 06/22] use docusaurus examples --- demo/examples/petstore.yaml | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/demo/examples/petstore.yaml b/demo/examples/petstore.yaml index 4efdc6ee3..e07a4d3b2 100644 --- a/demo/examples/petstore.yaml +++ b/demo/examples/petstore.yaml @@ -119,18 +119,34 @@ paths: description: | All good, here's some MDX: - :::note[MR SPOCK] + :::note - testing 123 + Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + + ::: + + :::tip + + Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + + ::: + + :::info + + Some **content** with _Markdown_ `syntax`. Check [this `api`](#). ::: :::warning - testing 123 + + Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + ::: :::danger - testing 123 + + Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + ::: ```python From 99e451a5f5ac7bab7d7c6ee40c2b864ad8fe0e06 Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Thu, 7 Nov 2024 15:54:45 -0500 Subject: [PATCH 07/22] fall back to type if no title found --- .../docusaurus-theme-openapi-docs/src/theme/Markdown/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js b/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js index 5e396c5d3..f51557c8d 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js +++ b/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js @@ -34,7 +34,7 @@ function remarkAdmonition() { for (const match of matches) { const type = match[1]; - const title = match[2] ? match[2].trim() : undefined; + const title = match[2] ? match[2] : type; const content = match[3]; const admonitionNode = { From a9acde90c5ce1df26d90b59d71023cad8c1f89f0 Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Mon, 18 Nov 2024 18:29:04 -0500 Subject: [PATCH 08/22] update demo --- demo/examples/petstore.yaml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/demo/examples/petstore.yaml b/demo/examples/petstore.yaml index e07a4d3b2..c1c348165 100644 --- a/demo/examples/petstore.yaml +++ b/demo/examples/petstore.yaml @@ -121,14 +121,12 @@ paths: :::note - Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + Some content but no markdown is supported :( ::: :::tip - - Some **content** with _Markdown_ `syntax`. Check [this `api`](#). - + A TIP with no leading or trailing spaces between delimiters. ::: :::info @@ -139,16 +137,18 @@ paths: :::warning - Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + Some **content** with _Markdown_ `syntax`. Check [this `api`](#) which is not supported :( yet ::: :::danger - Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + Some plain text ::: + A **code snippet**! + ```python print("hello") ``` From 7ebeb93ec377364fb806345f847dba2fb441857d Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Mon, 18 Nov 2024 18:29:42 -0500 Subject: [PATCH 09/22] allow buffering children and rendering ast to preserve markdown --- .../src/theme/Markdown/index.js | 217 ++++++++++++------ 1 file changed, 141 insertions(+), 76 deletions(-) diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js b/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js index f51557c8d..16da5a381 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js +++ b/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js @@ -11,100 +11,165 @@ import Admonition from "@theme/Admonition"; import CodeBlock from "@theme/CodeBlock"; import ReactMarkdown from "react-markdown"; import rehypeRaw from "rehype-raw"; -// eslint-disable-next-line import/no-extraneous-dependencies -import { visit } from "unist-util-visit"; +import remarkGfm from "remark-gfm"; function remarkAdmonition() { return (tree) => { - const paragraphs = []; - let collectedText = ""; - - // Collect all 'paragraph' nodes - visit(tree, "paragraph", (node) => { - paragraphs.push(node); - collectedText += - node.children.map((child) => child.value || "").join("\n") + "\n"; - }); + const openingTagRegex = /^:::(\w+)(?:\[(.*?)\])?\s*$/; + const closingTagRegex = /^:::\s*$/; + const textOnlyAdmonition = /^:::(\w+)(?:\[(.*?)\])?\s*([\s\S]*?)\s*:::$/; + const newTree = []; + let buffer = []; + let inAdmonition = false; + let currentType = null; + let currentTitle = null; + + tree.children.forEach((node) => { + if ( + node.type === "paragraph" && + node.children.length === 1 && + node.children[0].type === "text" + ) { + const text = node.children[0].value.trim(); + const openingMatch = text.match(openingTagRegex); + const closingMatch = text.match(closingTagRegex); + const textOnlyAdmonitionMatch = text.match(textOnlyAdmonition); - const regex = /^\s*:::(\w+)(?:\[(.*?)\])?\s*([\s\S]*?)\s*:::\s*$/gm; - const matches = collectedText.matchAll(regex); + if (textOnlyAdmonitionMatch) { + const type = textOnlyAdmonitionMatch[1]; + const title = textOnlyAdmonitionMatch[2] + ? textOnlyAdmonitionMatch[2]?.trim() + : undefined; + const content = textOnlyAdmonitionMatch[3]; - // Collect admonition nodes to insert - const admonitionNodes = []; + const admonitionNode = { + type: "admonition", + data: { + hName: "Admonition", // Tells ReactMarkdown to replace the node with Admonition component + hProperties: { + type, // Passed as a prop to the Admonition component + title, + }, + }, + children: [ + { + type: "text", + value: content?.trim(), // Trim leading/trailing whitespace + }, + ], + }; + newTree.push(admonitionNode); + return; + } + if (openingMatch) { + currentType = openingMatch[1]; + currentTitle = openingMatch[2] || currentType; + inAdmonition = true; + return; + } - for (const match of matches) { - const type = match[1]; - const title = match[2] ? match[2] : type; - const content = match[3]; + if (closingMatch && inAdmonition) { + newTree.push({ + type: "admonition", + data: { + hName: "Admonition", + hProperties: { type: currentType, title: currentTitle }, + }, + children: buffer[0].children, + }); + buffer = []; + inAdmonition = false; + currentType = null; + currentTitle = null; + return; + } + } + + if (inAdmonition) { + buffer.push(node); + } else { + newTree.push(node); + } + }); - const admonitionNode = { + if (buffer.length > 0 && currentType) { + newTree.push({ type: "admonition", data: { - hName: "Admonition", // Tells ReactMarkdown to replace the node with Admonition component - hProperties: { - type, // Passed as a prop to the Admonition component - title, - }, + hName: "Admonition", + hProperties: { type: currentType, title: currentTitle }, }, - children: [ - { - type: "text", - value: content.trim(), // Trim leading/trailing whitespace - }, - ], - }; - - admonitionNodes.push(admonitionNode); + children: buffer[0].children, + }); } + tree.children = newTree; + }; +} + +function convertAstToHtmlStr(ast) { + if (!ast || !Array.isArray(ast)) { + return ""; + } - // Replace the original paragraph nodes if we found any admonition nodes - if (admonitionNodes.length > 0) { - const firstParagraphIndex = tree.children.findIndex( - (node) => node.type === "paragraph" - ); - tree.children.splice( - firstParagraphIndex, - paragraphs.length, - ...admonitionNodes - ); + const convertNode = (node) => { + switch (node.type) { + case "text": + return node.value; + case "element": + const { tagName, properties, children } = node; + + // Convert attributes to a string + const attrs = properties + ? Object.entries(properties) + .map(([key, value]) => `${key}="${value}"`) + .join(" ") + : ""; + + // Convert children to HTML + const childrenHtml = children ? children.map(convertNode).join("") : ""; + + return `<${tagName} ${attrs}>${childrenHtml}`; + default: + return ""; } }; + + return ast.map(convertNode).join(""); } function Markdown({ children }) { return ( -
- {children}; - return !inline && match ? ( - {children} - ) : ( - {children} - ); - }, - // Render custom admonition nodes - admonition: ({ node, ...props }) => { - const type = node?.data?.hProperties?.type || "note"; - const title = node?.data?.hProperties?.title; - const content = node.children - .map((child) => (child.type === "text" ? child.value : "")) - .join(" "); - return ( - - {content} - - ); - }, - }} - /> -
+
, + code({ node, inline, className, children, ...props }) { + const match = /language-(\w+)/.exec(className || ""); + return match ? ( + + {children} + + ) : ( + + {children} + + ); + }, + admonition: ({ node, ...props }) => { + const type = node.data?.hProperties?.type || "note"; + const title = node.data?.hProperties?.title || type; + const content = convertAstToHtmlStr(node.children); + return ( + +
+ + ); + }, + }} + > + {children} + ); } From 221f37ffd5f46d2abdd01fccf8042a9d8f5064af Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Mon, 18 Nov 2024 18:39:28 -0500 Subject: [PATCH 10/22] cleanup variables to improve readability --- .../src/theme/Markdown/index.js | 54 ++++++++++--------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js b/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js index 16da5a381..8308f6c2c 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js +++ b/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js @@ -18,11 +18,13 @@ function remarkAdmonition() { const openingTagRegex = /^:::(\w+)(?:\[(.*?)\])?\s*$/; const closingTagRegex = /^:::\s*$/; const textOnlyAdmonition = /^:::(\w+)(?:\[(.*?)\])?\s*([\s\S]*?)\s*:::$/; - const newTree = []; - let buffer = []; - let inAdmonition = false; - let currentType = null; - let currentTitle = null; + + const nodes = []; + let bufferedChildren = []; + + let insideAdmonition = false; + let type = null; + let title = null; tree.children.forEach((node) => { if ( @@ -58,51 +60,53 @@ function remarkAdmonition() { }, ], }; - newTree.push(admonitionNode); + nodes.push(admonitionNode); return; } + if (openingMatch) { - currentType = openingMatch[1]; - currentTitle = openingMatch[2] || currentType; - inAdmonition = true; + type = openingMatch[1]; + title = openingMatch[2] || type; + insideAdmonition = true; return; } - if (closingMatch && inAdmonition) { - newTree.push({ + if (closingMatch && insideAdmonition) { + nodes.push({ type: "admonition", data: { hName: "Admonition", - hProperties: { type: currentType, title: currentTitle }, + hProperties: { type: type, title: title }, }, - children: buffer[0].children, + children: bufferedChildren[0].children, }); - buffer = []; - inAdmonition = false; - currentType = null; - currentTitle = null; + bufferedChildren = []; + insideAdmonition = false; + type = null; + title = null; return; } } - if (inAdmonition) { - buffer.push(node); + if (insideAdmonition) { + bufferedChildren.push(node); } else { - newTree.push(node); + nodes.push(node); } }); - if (buffer.length > 0 && currentType) { - newTree.push({ + if (bufferedChildren.length > 0 && type) { + nodes.push({ type: "admonition", data: { hName: "Admonition", - hProperties: { type: currentType, title: currentTitle }, + hProperties: { type: type, title: title }, }, - children: buffer[0].children, + children: bufferedChildren[0].children, }); } - tree.children = newTree; + + tree.children = nodes; }; } From 9ce4b033bc582a0926adda6a37fa9c4ec0d41388 Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Tue, 19 Nov 2024 07:37:22 -0500 Subject: [PATCH 11/22] add more complex examples --- demo/examples/petstore.yaml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/demo/examples/petstore.yaml b/demo/examples/petstore.yaml index c1c348165..1de97c514 100644 --- a/demo/examples/petstore.yaml +++ b/demo/examples/petstore.yaml @@ -133,6 +133,14 @@ paths: Some **content** with _Markdown_ `syntax`. Check [this `api`](#). + | Month | Savings | + | -------- | ------- | + | January | $250 | + | February | $80 | + | March | $420 | + + Hmm..... + ::: :::warning @@ -145,6 +153,10 @@ paths: Some plain text + Some more plain text + + And more + ::: A **code snippet**! @@ -152,6 +164,14 @@ paths: ```python print("hello") ``` + + _And_ a table! + + | Month | Savings | + | -------- | ------- | + | January | $250 | + | February | $80 | + | March | $420 | content: application/json: schema: From 91d0dabb842c187f6ea02afc328bda9f5709ac19 Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Tue, 19 Nov 2024 07:37:46 -0500 Subject: [PATCH 12/22] ensure all layers of nested children are captured --- .../src/theme/Markdown/index.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js b/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js index 8308f6c2c..8af1f3e7b 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js +++ b/packages/docusaurus-theme-openapi-docs/src/theme/Markdown/index.js @@ -78,7 +78,7 @@ function remarkAdmonition() { hName: "Admonition", hProperties: { type: type, title: title }, }, - children: bufferedChildren[0].children, + children: bufferedChildren, }); bufferedChildren = []; insideAdmonition = false; @@ -102,10 +102,9 @@ function remarkAdmonition() { hName: "Admonition", hProperties: { type: type, title: title }, }, - children: bufferedChildren[0].children, + children: bufferedChildren, }); } - tree.children = nodes; }; } From b1e0a4dbf3472d666150ff3d2a3745e5ede9fc0a Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Tue, 19 Nov 2024 19:14:30 -0500 Subject: [PATCH 13/22] replace react markdown with markdown component --- .../src/theme/ParamsItem/index.tsx | 42 +++---------------- 1 file changed, 6 insertions(+), 36 deletions(-) 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 4a9bf9f08..6d9512576 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/ParamsItem/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/ParamsItem/index.tsx @@ -7,16 +7,12 @@ import React from "react"; -import CodeBlock from "@theme/CodeBlock"; +import Markdown from "@theme/Markdown"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; /* eslint-disable import/no-extraneous-dependencies*/ 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"; import { guard, toString } from "../../markdown/utils"; @@ -97,34 +93,12 @@ function ParamsItem({ param, ...rest }: Props) { deprecated )); - const renderSchema = guard(getQualifierMessage(schema), (message) => ( -
- -
+ const renderQualifier = guard(getQualifierMessage(schema), (qualifier) => ( + {qualifier} )); const renderDescription = guard(description, (description) => ( - <> - {children}; - return !inline && match ? ( - {children} - ) : ( - {children} - ); - }, - }} - rehypePlugins={[rehypeRaw]} - /> - + {description} )); const renderEnumDescriptions = guard( @@ -132,11 +106,7 @@ function ParamsItem({ param, ...rest }: Props) { (value) => { return (
- + {value}
); } @@ -217,7 +187,7 @@ function ParamsItem({ param, ...rest }: Props) { {renderSchemaRequired} {renderDeprecated} - {renderSchema} + {renderQualifier} {renderDescription} {renderEnumDescriptions} {renderDefaultValue()} From 7c25186219438c404fb913c6a526266d3fa71751 Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Tue, 19 Nov 2024 19:18:53 -0500 Subject: [PATCH 14/22] replace createDescription with Markdown --- .../src/theme/RequestSchema/index.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/RequestSchema/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/RequestSchema/index.tsx index 12d13816c..33def2697 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/RequestSchema/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/RequestSchema/index.tsx @@ -9,11 +9,11 @@ import React, { Suspense } from "react"; import BrowserOnly from "@docusaurus/BrowserOnly"; import Details from "@theme/Details"; +import Markdown from "@theme/Markdown"; import MimeTabs from "@theme/MimeTabs"; // Assume these components exist import SchemaNode from "@theme/Schema"; import SkeletonLoader from "@theme/SkeletonLoader"; import TabItem from "@theme/TabItem"; -import { createDescription } from "docusaurus-plugin-openapi-docs/lib/markdown/createDescription"; import { MediaTypeObject } from "docusaurus-plugin-openapi-docs/lib/openapi/types"; interface Props { @@ -78,7 +78,7 @@ const RequestSchemaComponent: React.FC = ({ title, body, style }) => {
{body.description && (
- {createDescription(body.description)} + {body.description}
)}
@@ -131,7 +131,7 @@ const RequestSchemaComponent: React.FC = ({ title, body, style }) => {
{body.description && (
- {createDescription(body.description)} + {body.description}
)}
From e178a5ef5e40d5cf73ffcd8030316cc74c84ad3a Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Thu, 21 Nov 2024 10:19:13 -0500 Subject: [PATCH 15/22] cleanup unused component --- .../src/theme/ResponseExamples/index.tsx | 42 ------------------- 1 file changed, 42 deletions(-) diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/ResponseExamples/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/ResponseExamples/index.tsx index c906d1de0..52287b703 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/ResponseExamples/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/ResponseExamples/index.tsx @@ -7,7 +7,6 @@ import React from "react"; -import ParamsItem from "@theme/ParamsItem"; import ResponseSamples from "@theme/ResponseSamples"; import TabItem from "@theme/TabItem"; import { createDescription } from "docusaurus-plugin-openapi-docs/lib/markdown/createDescription"; @@ -85,47 +84,6 @@ interface Props { mimeType: string; } -// React components -export const ParamsDetails: React.FC = ({ parameters, type }) => { - const params = parameters?.filter((param) => param?.in === type); - - if (!params || params.length === 0) { - return null; - } - - return ( -
- -

- {`${type.charAt(0).toUpperCase() + type.slice(1)} Parameters`} -

-
-
-
    - {params.map((param, index) => ( - - ))} -
-
-
- ); -}; - export const ResponseHeaders: React.FC<{ responseHeaders?: Record; }> = ({ responseHeaders }) => { From 86b12bfc31a85cbf8dfb2e35f3eb0b3d5fa18bf9 Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Thu, 21 Nov 2024 10:33:49 -0500 Subject: [PATCH 16/22] cleanup props --- .../src/theme/ResponseExamples/index.tsx | 50 +++++++------------ 1 file changed, 19 insertions(+), 31 deletions(-) diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/ResponseExamples/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/ResponseExamples/index.tsx index 52287b703..6f02a3bed 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/ResponseExamples/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/ResponseExamples/index.tsx @@ -13,7 +13,6 @@ import { createDescription } from "docusaurus-plugin-openapi-docs/lib/markdown/c import { sampleResponseFromSchema } from "docusaurus-plugin-openapi-docs/lib/openapi/createResponseExample"; import format from "xml-formatter"; -// Utility function export function json2xml(o: Record, tab: string): string { const toXml = (v: any, name: string, ind: string): string => { let xml = ""; @@ -51,16 +50,6 @@ export function json2xml(o: Record, tab: string): string { return tab ? xml.replace(/\t/g, tab) : xml.replace(/\t|\n/g, ""); } -interface ParameterProps { - in: string; - name: string; - schema?: { - type?: string; - items?: Record; - }; - enumDescriptions?: [string, string][]; -} - interface ResponseHeaderProps { description?: string; example?: string; @@ -69,21 +58,6 @@ interface ResponseHeaderProps { }; } -interface ResponseExampleProps { - value: any; - summary?: string; -} - -interface Props { - parameters?: ParameterProps[]; - type: string; - responseHeaders?: Record; - responseExamples?: Record; - responseExample?: any; - schema?: any; - mimeType: string; -} - export const ResponseHeaders: React.FC<{ responseHeaders?: Record; }> = ({ responseHeaders }) => { @@ -120,10 +94,14 @@ export const ResponseHeaders: React.FC<{ ); }; -export const ResponseExamples: React.FC<{ +interface ResponseExamplesProps { responseExamples: any; mimeType: string; -}> = ({ responseExamples, mimeType }): any => { +} +export const ResponseExamples: React.FC = ({ + responseExamples, + mimeType, +}): any => { let language = "shell"; if (mimeType.endsWith("json")) language = "json"; if (mimeType.endsWith("xml")) language = "xml"; @@ -156,10 +134,15 @@ export const ResponseExamples: React.FC<{ return examplesArray; }; -export const ResponseExample: React.FC<{ +interface ResponseExampleProps { responseExample: any; mimeType: string; -}> = ({ responseExample, mimeType }) => { +} + +export const ResponseExample: React.FC = ({ + responseExample, + mimeType, +}) => { let language = "shell"; if (mimeType.endsWith("json")) { language = "json"; @@ -186,7 +169,12 @@ export const ResponseExample: React.FC<{ ); }; -export const ExampleFromSchema: React.FC<{ schema: any; mimeType: string }> = ({ +interface ExampleFromSchemaProps { + schema: any; + mimeType: string; +} + +export const ExampleFromSchema: React.FC = ({ schema, mimeType, }) => { From c341b785192ecbbc7e73cea067309d2b9d5c2294 Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Thu, 21 Nov 2024 10:39:13 -0500 Subject: [PATCH 17/22] cleanup unused import --- .../src/theme/ResponseSchema/index.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/ResponseSchema/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/ResponseSchema/index.tsx index 863807690..cdb552df9 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/ResponseSchema/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/ResponseSchema/index.tsx @@ -20,7 +20,6 @@ import SchemaNode from "@theme/Schema"; import SchemaTabs from "@theme/SchemaTabs"; import SkeletonLoader from "@theme/SkeletonLoader"; import TabItem from "@theme/TabItem"; -import { createDescription } from "docusaurus-plugin-openapi-docs/lib/markdown/createDescription"; import { MediaTypeObject } from "docusaurus-plugin-openapi-docs/lib/openapi/types"; interface Props { From ad741eae4fe77eaa73c5a7743d077598344c4ee1 Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Thu, 21 Nov 2024 10:53:17 -0500 Subject: [PATCH 18/22] move ResponseHeaders to standalone component --- .../src/theme/ResponseHeaders/index.tsx | 49 +++++++++++++++++++ .../src/theme/StatusCodes/index.tsx | 3 +- 2 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 packages/docusaurus-theme-openapi-docs/src/theme/ResponseHeaders/index.tsx diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/ResponseHeaders/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/ResponseHeaders/index.tsx new file mode 100644 index 000000000..d8f2158dd --- /dev/null +++ b/packages/docusaurus-theme-openapi-docs/src/theme/ResponseHeaders/index.tsx @@ -0,0 +1,49 @@ +/* ============================================================================ + * Copyright (c) Palo Alto Networks + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * ========================================================================== */ + +import React from "react"; + +import SchemaItem from "@theme/SchemaItem"; + +import { getQualifierMessage, getSchemaName } from "../../markdown/schema"; + +interface ResponseHeadersProps { + description?: string; + example?: string; + schema?: { + type?: string; + format?: string; + }; +} + +export const ResponseHeaders: React.FC<{ + responseHeaders?: Record; +}> = ({ responseHeaders }) => { + if (!responseHeaders) { + return null; + } + + return ( +
    + {Object.entries(responseHeaders).map(([name, schema]) => { + return ( + + ); + })} +
+ ); +}; + +export default ResponseHeaders; diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/StatusCodes/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/StatusCodes/index.tsx index 4cc4b96cb..e838e9897 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/StatusCodes/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/StatusCodes/index.tsx @@ -10,10 +10,9 @@ import React from "react"; import ApiTabs from "@theme/ApiTabs"; import Details from "@theme/Details"; import Markdown from "@theme/Markdown"; -import { ResponseHeaders } from "@theme/ResponseExamples"; +import ResponseHeaders from "@theme/ResponseHeaders"; import ResponseSchema from "@theme/ResponseSchema"; import TabItem from "@theme/TabItem"; -import { createDescription } from "docusaurus-plugin-openapi-docs/lib/markdown/createDescription"; import { ApiItem } from "docusaurus-plugin-openapi-docs/lib/types"; interface Props { From de31539401bb51da63df3133d9ae5b3ee3f482fe Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Thu, 21 Nov 2024 10:57:32 -0500 Subject: [PATCH 19/22] implement new markdown component as wrapper --- .../src/theme/Schema/index.tsx | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/Schema/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/Schema/index.tsx index 548ab682b..9db3b103c 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/Schema/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/Schema/index.tsx @@ -10,21 +10,19 @@ import React from "react"; import { ClosingArrayBracket, OpeningArrayBracket } from "@theme/ArrayBrackets"; import Details from "@theme/Details"; import DiscriminatorTabs from "@theme/DiscriminatorTabs"; +import Markdown from "@theme/Markdown"; import SchemaItem from "@theme/SchemaItem"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; // eslint-disable-next-line import/no-extraneous-dependencies import { merge } from "allof-merge"; import clsx from "clsx"; -import { createDescription } from "docusaurus-plugin-openapi-docs/lib/markdown/createDescription"; import { getQualifierMessage, getSchemaName, } from "docusaurus-plugin-openapi-docs/lib/markdown/schema"; import { SchemaObject } from "docusaurus-plugin-openapi-docs/lib/openapi/types"; import isEmpty from "lodash/isEmpty"; -import ReactMarkdown from "react-markdown"; -import rehypeRaw from "rehype-raw"; // eslint-disable-next-line import/no-extraneous-dependencies // const jsonSchemaMergeAllOf = require("json-schema-merge-allof"); @@ -44,13 +42,10 @@ interface MarkdownProps { } // Renders string as markdown, useful for descriptions and qualifiers -const Markdown: React.FC = ({ text }) => { +const MarkdownWrapper: React.FC = ({ text }) => { return (
- + {text}
); }; @@ -262,9 +257,11 @@ const PropertyDiscriminator: React.FC = ({ )}
- {schema.description && } + {schema.description && ( + + )} {getQualifierMessage(discriminator) && ( - + )}
@@ -480,9 +477,9 @@ const SchemaNodeDetails: React.FC = ({ } >
- {schema.description && } + {schema.description && } {getQualifierMessage(schema) && ( - + )}
From d0851802a65b081e89d6620c3f993fac26dd7411 Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Thu, 21 Nov 2024 11:03:47 -0500 Subject: [PATCH 20/22] implement markdown support in schema item --- .../src/theme/SchemaItem/index.tsx | 42 ++++--------------- 1 file changed, 8 insertions(+), 34 deletions(-) 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 48ab32d80..65984c318 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/SchemaItem/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/SchemaItem/index.tsx @@ -7,13 +7,9 @@ import React, { ReactNode } from "react"; -import CodeBlock from "@theme/CodeBlock"; +import Markdown from "@theme/Markdown"; 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"; export interface Props { @@ -97,44 +93,22 @@ export default function SchemaItem(props: Props) { (value) => { return (
- + {value}
); } ); const renderSchemaDescription = guard(schemaDescription, (description) => ( -
- {children}; - return !inline && match ? ( - {children} - ) : ( - {children} - ); - }, - }} - rehypePlugins={[rehypeRaw]} - /> -
+ <> + {description} + )); const renderQualifierMessage = guard(qualifierMessage, (message) => ( -
- -
+ <> + {message} + )); function renderDefaultValue() { From 79f56e744b0f045935510a4d83a3810d5abef78d Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Thu, 21 Nov 2024 11:11:32 -0500 Subject: [PATCH 21/22] support markdown in example summaries --- .../src/theme/ResponseExamples/index.tsx | 54 ++----------------- 1 file changed, 5 insertions(+), 49 deletions(-) diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/ResponseExamples/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/ResponseExamples/index.tsx index 6f02a3bed..67eb5361e 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/ResponseExamples/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/ResponseExamples/index.tsx @@ -7,9 +7,9 @@ import React from "react"; +import Markdown from "@theme/Markdown"; import ResponseSamples from "@theme/ResponseSamples"; import TabItem from "@theme/TabItem"; -import { createDescription } from "docusaurus-plugin-openapi-docs/lib/markdown/createDescription"; import { sampleResponseFromSchema } from "docusaurus-plugin-openapi-docs/lib/openapi/createResponseExample"; import format from "xml-formatter"; @@ -50,50 +50,6 @@ export function json2xml(o: Record, tab: string): string { return tab ? xml.replace(/\t/g, tab) : xml.replace(/\t|\n/g, ""); } -interface ResponseHeaderProps { - description?: string; - example?: string; - schema?: { - type?: string; - }; -} - -export const ResponseHeaders: React.FC<{ - responseHeaders?: Record; -}> = ({ responseHeaders }) => { - if (!responseHeaders) { - return null; - } - - return ( -
    - {Object.entries(responseHeaders).map(([headerName, headerObj]) => { - const { description, example, schema } = headerObj; - const type = schema?.type ?? "any"; - - return ( -
  • -
    - - {headerName} - {type && {type}} - -
    - {description && ( -
    - {example && `Example: ${example}`} - {createDescription(description)} -
    - )} -
    -
    -
  • - ); - })} -
- ); -}; - interface ResponseExamplesProps { responseExamples: any; mimeType: string; @@ -118,9 +74,9 @@ export const ResponseExamples: React.FC = ({ // @ts-ignore {exampleValue.summary && ( -
+ {exampleValue.summary} -
+ )} = ({ // @ts-ignore {responseExample.summary && ( -
+ {responseExample.summary} -
+ )}
From 84656871347db6fd2317e9c21a724ef617b3649e Mon Sep 17 00:00:00 2001 From: Steven Serrata Date: Thu, 21 Nov 2024 13:40:25 -0500 Subject: [PATCH 22/22] wrap body summaries in markdown --- .../src/theme/ApiExplorer/Body/index.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/Body/index.tsx b/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/Body/index.tsx index da3951e38..d595fbe24 100644 --- a/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/Body/index.tsx +++ b/packages/docusaurus-theme-openapi-docs/src/theme/ApiExplorer/Body/index.tsx @@ -14,6 +14,7 @@ import FormSelect from "@theme/ApiExplorer/FormSelect"; import FormTextInput from "@theme/ApiExplorer/FormTextInput"; import LiveApp from "@theme/ApiExplorer/LiveEditor"; import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks"; +import Markdown from "@theme/Markdown"; import SchemaTabs from "@theme/SchemaTabs"; import TabItem from "@theme/TabItem"; import { RequestBodyObject } from "docusaurus-plugin-openapi-docs/src/openapi/types"; @@ -303,7 +304,7 @@ function Body({
{/* @ts-ignore */} - {example.summary &&
{example.summary}
} + {example.summary && {example.summary}} {exampleBody && ( - {example.summary &&
{example.summary}
} + {example.summary && {example.summary}} {example.body && ( {example.body}