diff --git a/docusaurus.config.ts b/docusaurus.config.ts index c39eb3651..7c52735fd 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -22,7 +22,7 @@ if (process.env.CI_MERGE_REQUEST_IID) { const config = { future: { experimental_faster: (process.env.DOCUSAURUS_FASTER ?? "true") === "true", - v4: true + v4: true, }, title: "Develop with Palo Alto Networks", tagline: @@ -1171,6 +1171,7 @@ const config = { }, ], tailwindPlugin, + require.resolve("./plugins/markdown-route/index.cjs"), ], stylesheets: [ { diff --git a/plugins/markdown-route/index.cjs b/plugins/markdown-route/index.cjs new file mode 100644 index 000000000..d5d1483bd --- /dev/null +++ b/plugins/markdown-route/index.cjs @@ -0,0 +1,13 @@ +function markdownRoutePlugin() { + return { + name: "markdown-route-plugin", + async contentLoaded({ actions }) { + actions.addRoute({ + path: "/__md", + matchPath: "/:route+.md", + component: "@site/src/components/MarkdownPage", + }); + }, + }; +} +module.exports = markdownRoutePlugin; diff --git a/src/components/MarkdownPage.tsx b/src/components/MarkdownPage.tsx new file mode 100644 index 000000000..52bb825fd --- /dev/null +++ b/src/components/MarkdownPage.tsx @@ -0,0 +1,74 @@ +import React, { useEffect, useState } from "react"; +import { useLocation } from "@docusaurus/router"; +import TurndownService from "turndown"; + +export default function MarkdownPage() { + const location = useLocation(); + const [markdown, setMarkdown] = useState(null); + const [error, setError] = useState(null); + + useEffect(() => { + async function fetchAndConvert() { + const htmlPath = location.pathname.replace(/\.md$/, "/index.html"); + try { + const res = await fetch(htmlPath); + if (!res.ok) { + throw new Error(`Failed to fetch source page: ${res.status}`); + } + const html = await res.text(); + const parser = new DOMParser(); + const doc = parser.parseFromString(html, "text/html"); + const content = + doc.querySelector(".openapi-left-panel__container") || + doc.querySelector(".theme-doc-markdown"); + if (!content) { + throw new Error("Unable to locate markdown source"); + } + const turndownService = new TurndownService(); + turndownService.addRule("details-rule", { + filter: "details", + replacement: function (content, node) { + const summary = node.querySelector("summary"); + const summaryText = summary ? summary.textContent?.trim() : ""; + const detailsContent = content.substring( + content.indexOf("") + 1 + ); + let md = `\n${summaryText}\n`; + const indented = detailsContent + .split("\n") + .map((line) => { + if (line.trim() === "") return line; + return ` ${line}`; + }) + .join("\n"); + md += indented; + return md + "\n"; + }, + }); + setMarkdown(turndownService.turndown(content)); + } catch (e) { + setError((e as Error).message); + } + } + fetchAndConvert(); + }, [location.pathname]); + + const preStyle: React.CSSProperties = { + all: "unset", + whiteSpace: "pre-wrap", + fontFamily: "monospace", + display: "block", + padding: 0, + margin: 0, + background: "transparent", + color: "inherit", + }; + + if (error) { + return
{error}
; + } + if (markdown === null) { + return

Loading...

; + } + return
{markdown}
; +}