From d2cba9f593f55e10e590578ec52179fbd93515ae Mon Sep 17 00:00:00 2001 From: Josh Vlk Date: Thu, 9 Apr 2026 09:25:08 -0400 Subject: [PATCH] Add routes for docs/guidelines MDX pages --- app/routes.res | 14 ++++- app/routes/DocsGuidelinesRoute.res | 88 +++++++++++++++++++++++++++++ app/routes/DocsGuidelinesRoute.resi | 11 ++++ 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 app/routes/DocsGuidelinesRoute.res create mode 100644 app/routes/DocsGuidelinesRoute.resi diff --git a/app/routes.res b/app/routes.res index 6f5b9b8fc..8f93f0d2e 100644 --- a/app/routes.res +++ b/app/routes.res @@ -33,10 +33,21 @@ let blogArticleRoutes = route(path, "./routes/BlogArticleRoute.jsx", ~options={id: path}) ) +let docsGuidelinesRoutes = + MdxFile.scanPaths( + ~dir="markdown-pages/docs/guidelines", + ~alias="docs/guidelines", + )->Array.map(path => route(path, "./routes/DocsGuidelinesRoute.jsx", ~options={id: path})) + let mdxRoutes = mdxRoutes("./routes/MdxRoute.jsx")->Array.filter(r => !( r.path - ->Option.map(path => path === "blog" || String.startsWith(path, "blog/")) + ->Option.map(path => + path === "blog" || + String.startsWith(path, "blog/") || + path === "docs/guidelines" || + String.startsWith(path, "docs/guidelines/") + ) ->Option.getOr(false) ) ) @@ -56,6 +67,7 @@ let default = [ ...stdlibRoutes, ...beltRoutes, ...blogArticleRoutes, + ...docsGuidelinesRoutes, ...mdxRoutes, route("*", "./routes/NotFoundRoute.jsx"), ] diff --git a/app/routes/DocsGuidelinesRoute.res b/app/routes/DocsGuidelinesRoute.res new file mode 100644 index 000000000..8cec83187 --- /dev/null +++ b/app/routes/DocsGuidelinesRoute.res @@ -0,0 +1,88 @@ +type loaderData = { + compiledMdx: CompiledMdx.t, + entries: array, + title: string, + description: string, + filePath: string, +} + +let loader: ReactRouter.Loader.t = async ({request}) => { + let {pathname} = WebAPI.URL.make(~url=request.url) + let filePath = MdxFile.resolveFilePath( + (pathname :> string), + ~dir="markdown-pages/docs/guidelines", + ~alias="docs/guidelines", + ) + + let raw = await Node.Fs.readFile(filePath, "utf-8") + let {frontmatter}: MarkdownParser.result = MarkdownParser.parseSync(raw) + + let description = switch frontmatter { + | Object(dict) => + switch dict->Dict.get("description") { + | Some(String(s)) => s + | _ => "" + } + | _ => "" + } + + let title = switch frontmatter { + | Object(dict) => + switch dict->Dict.get("title") { + | Some(String(s)) => s + | _ => "" + } + | _ => "" + } + + let compiledMdx = await MdxFile.compileMdx(raw, ~filePath, ~remarkPlugins=Mdx.plugins) + + // Build table of contents entries from markdown headings + let markdownTree = Mdast.fromMarkdown(raw) + let tocResult = Mdast.toc(markdownTree, {maxDepth: 2}) + + let headers = Dict.make() + Mdast.reduceHeaders(tocResult.map, headers) + + let entries = + headers + ->Dict.toArray + ->Array.map(((header, url)): TableOfContents.entry => { + header, + href: (url :> string), + }) + ->Array.slice(~start=2) // skip document entry and H1 title, keep h2 sections + + { + compiledMdx, + entries, + title: `${title} | ReScript Guidelines`, + description, + filePath, + } +} + +let default = () => { + let {compiledMdx, entries, title, description, filePath} = ReactRouter.useLoaderData() + + let editHref = `https://github.com/rescript-lang/rescript-lang.org/blob/master/${filePath}` + + let categories: array = [] + + <> + + + + + {React.string("Edit")} + + + +
+ +
+
+ +} diff --git a/app/routes/DocsGuidelinesRoute.resi b/app/routes/DocsGuidelinesRoute.resi new file mode 100644 index 000000000..307767dcb --- /dev/null +++ b/app/routes/DocsGuidelinesRoute.resi @@ -0,0 +1,11 @@ +type loaderData = { + compiledMdx: CompiledMdx.t, + entries: array, + title: string, + description: string, + filePath: string, +} + +let loader: ReactRouter.Loader.t + +let default: unit => React.element