Skip to content

Commit d1afff6

Browse files
committed
feat: remove MdxRoute and react-router-mdx dependency
- Delete MdxRoute.res/.resi (all pages now handled by split routes) - Remove react-router-mdx from package.json and delete yarn patch - Remove react-router-mdx externals from Mdx.res - Remove mdxRoutes binding from ReactRouter.res - Remove react-router-mdx init from react-router.config.mjs and generate-route-types.mjs - Add DocsManualRoute for /docs/manual pages with sidebar and TOC - Add DocsReactRoute for /docs/react pages with sidebar and TOC - Add SyntaxLookupDetailRoute for /syntax-lookup/* detail pages - Add SidebarHelpers module for shared sidebar nav/category generation - Add MdxFile.loadAllAttributes to replace react-router-mdx loadAllMdx - Migrate BlogRoute to use MdxFile.loadAllAttributes - Migrate SyntaxLookupRoute to use MdxFile.loadAllAttributes - Migrate CommunityRoute to use SidebarHelpers and MdxFile.loadAllAttributes - Fix Mdx.sortSection comparator to handle all cases explicitly - Update routes.res to register all split routes and remove mdxRoutes Combines PRs #1221, #1222, #1225, #1227
1 parent 98addbf commit d1afff6

24 files changed

+534
-692
lines changed

.yarn/patches/react-router-mdx-npm-1.0.8-d4402c3003.patch

Lines changed: 0 additions & 40 deletions
This file was deleted.

AGENTS.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ let default: unit => React.element
201201
- **Lefthook** runs `yarn format` on pre-commit (auto-stages fixed files).
202202
- Generated `.mjs`/`.jsx` output files from ReScript are git-tracked but excluded from Prettier.
203203

204+
## Pull Requests and Commits
205+
206+
- Use conventional commits format for commit messages (e.g. `feat: add new API docs`, `fix: resolve loader data issue`).
207+
- Commit bodies should explain what changed with some concise details
208+
- PR descriptions should provide context for the change, a summary of the changes with descriptions, and reference any related issues.
209+
204210
## Important Warnings
205211

206212
- Do **not** modify generated `.jsx` / `.mjs` files directly — they are ReScript compiler output.

app/routes.res

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -47,26 +47,31 @@ let blogArticleRoutes =
4747
route(path, "./routes/BlogArticleRoute.jsx", ~options={id: path})
4848
)
4949

50+
let docsManualRoutes =
51+
MdxFile.scanPaths(~dir="markdown-pages/docs/manual", ~alias="docs/manual")
52+
->Array.filter(path => !String.includes(path, "docs/manual/api"))
53+
->Array.map(path => route(path, "./routes/DocsManualRoute.jsx", ~options={id: path}))
54+
55+
let docsReactRoutes =
56+
MdxFile.scanPaths(~dir="markdown-pages/docs/react", ~alias="docs/react")->Array.map(path =>
57+
route(path, "./routes/DocsReactRoute.jsx", ~options={id: path})
58+
)
59+
60+
let docsGuidelinesRoutes =
61+
MdxFile.scanPaths(
62+
~dir="markdown-pages/docs/guidelines",
63+
~alias="docs/guidelines",
64+
)->Array.map(path => route(path, "./routes/DocsGuidelinesRoute.jsx", ~options={id: path}))
65+
5066
let communityRoutes =
5167
MdxFile.scanPaths(~dir="markdown-pages/community", ~alias="community")->Array.map(path =>
5268
route(path, "./routes/CommunityRoute.jsx", ~options={id: path})
5369
)
5470

55-
let mdxRoutes = mdxRoutes("./routes/MdxRoute.jsx")->Array.filter(r =>
56-
!(
57-
r.path
58-
->Option.map(path =>
59-
path === "blog" ||
60-
String.startsWith(path, "blog/") ||
61-
path === "community" ||
62-
String.startsWith(path, "community/") ||
63-
path === "docs/manual/api" ||
64-
path === "community" ||
65-
String.startsWith(path, "community/")
66-
)
67-
->Option.getOr(false)
71+
let syntaxLookupDetailRoutes =
72+
MdxFile.scanPaths(~dir="markdown-pages/syntax-lookup", ~alias="syntax-lookup")->Array.map(path =>
73+
route(path, "./routes/SyntaxLookupDetailRoute.jsx", ~options={id: path})
6874
)
69-
)
7075

7176
let default = [
7277
index("./routes/LandingPageRoute.jsx"),
@@ -85,7 +90,10 @@ let default = [
8590
...beltRoutes,
8691
...domRoutes,
8792
...blogArticleRoutes,
93+
...docsManualRoutes,
94+
...docsReactRoutes,
95+
...docsGuidelinesRoutes,
8896
...communityRoutes,
89-
...mdxRoutes,
97+
...syntaxLookupDetailRoutes,
9098
route("*", "./routes/NotFoundRoute.jsx"),
9199
]

app/routes.resi

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
let stdlibPaths: array<string>
2+
let domPaths: array<string>
23
let beltPaths: array<string>
34
let stdlibRoutes: array<ReactRouter.Routes.t>
5+
let domRoutes: array<ReactRouter.Routes.t>
46
let beltRoutes: array<ReactRouter.Routes.t>
5-
let default: Belt.Array.t<ReactRouter.Routes.t>
7+
let blogArticleRoutes: array<ReactRouter.Routes.t>
8+
let docsManualRoutes: array<ReactRouter.Routes.t>
9+
let docsReactRoutes: array<ReactRouter.Routes.t>
10+
let docsGuidelinesRoutes: array<ReactRouter.Routes.t>
11+
let communityRoutes: array<ReactRouter.Routes.t>
12+
let syntaxLookupDetailRoutes: array<ReactRouter.Routes.t>
13+
let default: array<ReactRouter.Routes.t>

app/routes/BlogRoute.res

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ type loaderData = {posts: array<BlogApi.post>, category: Blog.category}
33
let loader: ReactRouter.Loader.t<loaderData> = async ({request}) => {
44
let showArchived = request.url->String.includes("archived")
55
let posts = async () =>
6-
(await Mdx.allMdx(~filterByPaths=["markdown-pages/blog"]))
7-
->Mdx.filterMdxPages("blog")
6+
(await MdxFile.loadAllAttributes(~dir="markdown-pages/blog"))
87
->Array.map(BlogLoader.transform)
98
->Array.toSorted((a, b) => {
109
a.frontmatter.date->DateStr.toDate > b.frontmatter.date->DateStr.toDate ? -1.0 : 1.0

app/routes/CommunityRoute.res

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -7,38 +7,16 @@ type loaderData = {
77
categories: array<SidebarLayout.Sidebar.Category.t>,
88
}
99

10-
let convertToNavItems = (items, rootPath) =>
11-
Array.map(items, (item): SidebarLayout.Sidebar.NavItem.t => {
12-
let href = switch item.Mdx.slug {
13-
| Some(slug) => `${rootPath}/${slug}`
14-
| None => rootPath
15-
}
16-
{
17-
name: item.title,
18-
href,
19-
}
20-
})
21-
22-
let getGroup = (groups, groupName): SidebarLayout.Sidebar.Category.t => {
23-
{
24-
name: groupName,
25-
items: groups
26-
->Dict.get(groupName)
27-
->Option.getOr([]),
28-
}
29-
}
30-
31-
let getAllGroups = (groups, groupNames): array<SidebarLayout.Sidebar.Category.t> =>
32-
groupNames->Array.map(item => getGroup(groups, item))
33-
3410
let communityTableOfContents = async () => {
3511
let groups =
36-
(await Mdx.allMdx(~filterByPaths=["markdown-pages/community"]))
12+
(await MdxFile.loadAllAttributes(~dir="markdown-pages/community"))
3713
->Mdx.filterMdxPages("community")
3814
->Mdx.groupBySection
39-
->Dict.mapValues(values => values->Mdx.sortSection->convertToNavItems("/community"))
15+
->Dict.mapValues(values =>
16+
values->Mdx.sortSection->SidebarHelpers.convertToNavItems("/community")
17+
)
4018

41-
getAllGroups(groups, ["Resources"])
19+
SidebarHelpers.getAllGroups(groups, ["Resources"])
4220
}
4321

4422
let loader: ReactRouter.Loader.t<loaderData> = async ({request}) => {

app/routes/DocsManualRoute.res

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
type loaderData = {
2+
compiledMdx: CompiledMdx.t,
3+
categories: array<SidebarLayout.Sidebar.Category.t>,
4+
entries: array<TableOfContents.entry>,
5+
title: string,
6+
description: string,
7+
filePath: string,
8+
}
9+
10+
// Build sidebar categories from all manual docs, sorted by their "order" field in frontmatter
11+
let manualTableOfContents = async () => {
12+
let groups =
13+
(await MdxFile.loadAllAttributes(~dir="markdown-pages/docs"))
14+
->Mdx.filterMdxPages("docs/manual")
15+
->Mdx.groupBySection
16+
->Dict.mapValues(values =>
17+
values->Mdx.sortSection->SidebarHelpers.convertToNavItems("/docs/manual")
18+
)
19+
20+
SidebarHelpers.getAllGroups(
21+
groups,
22+
[
23+
"Overview",
24+
"Guides",
25+
"Language Features",
26+
"JavaScript Interop",
27+
"Build System",
28+
"Advanced Features",
29+
],
30+
)
31+
}
32+
33+
let loader: ReactRouter.Loader.t<loaderData> = async ({request}) => {
34+
let {pathname} = WebAPI.URL.make(~url=request.url)
35+
let filePath = MdxFile.resolveFilePath(
36+
(pathname :> string),
37+
~dir="markdown-pages/docs/manual",
38+
~alias="docs/manual",
39+
)
40+
41+
let raw = await Node.Fs.readFile(filePath, "utf-8")
42+
let {frontmatter}: MarkdownParser.result = MarkdownParser.parseSync(raw)
43+
44+
let description = switch frontmatter {
45+
| Object(dict) =>
46+
switch dict->Dict.get("description") {
47+
| Some(String(s)) => s
48+
| _ => ""
49+
}
50+
| _ => ""
51+
}
52+
53+
let title = switch frontmatter {
54+
| Object(dict) =>
55+
switch dict->Dict.get("title") {
56+
| Some(String(s)) => s
57+
| _ => ""
58+
}
59+
| _ => ""
60+
}
61+
62+
let categories = await manualTableOfContents()
63+
64+
let compiledMdx = await MdxFile.compileMdx(raw, ~filePath, ~remarkPlugins=Mdx.plugins)
65+
66+
// Build table of contents entries from markdown headings
67+
let markdownTree = Mdast.fromMarkdown(raw)
68+
let tocResult = Mdast.toc(markdownTree, {maxDepth: 2})
69+
70+
let headers = Dict.make()
71+
Mdast.reduceHeaders(tocResult.map, headers)
72+
73+
let entries =
74+
headers
75+
->Dict.toArray
76+
->Array.map(((header, url)): TableOfContents.entry => {
77+
header,
78+
href: (url :> string),
79+
})
80+
->Array.slice(~start=2) // skip document entry and H1 title, keep h2 sections
81+
82+
{
83+
compiledMdx,
84+
categories,
85+
entries,
86+
title: `${title} | ReScript Language Manual`,
87+
description,
88+
filePath,
89+
}
90+
}
91+
92+
let default = () => {
93+
let {pathname} = ReactRouter.useLocation()
94+
let {compiledMdx, categories, entries, title, description, filePath} = ReactRouter.useLoaderData()
95+
96+
let breadcrumbs = list{
97+
{Url.name: "Docs", href: "/docs/manual/introduction"},
98+
{
99+
Url.name: "Language Manual",
100+
href: "/docs/manual/introduction",
101+
},
102+
}
103+
104+
let editHref = `https://github.com/rescript-lang/rescript-lang.org/blob/master/${filePath}`
105+
106+
let sidebarContent =
107+
<aside className="px-4 w-full block">
108+
<div className="flex justify-between items-baseline">
109+
<div className="flex flex-col text-fire font-medium">
110+
<VersionSelect />
111+
</div>
112+
<button
113+
className="flex items-center" onClick={_ => NavbarUtils.closeMobileTertiaryDrawer()}
114+
>
115+
<Icon.Close />
116+
</button>
117+
</div>
118+
<div className="mb-56">
119+
{categories
120+
->Array.map(category => {
121+
let isItemActive = (navItem: SidebarLayout.Sidebar.NavItem.t) =>
122+
navItem.href === (pathname :> string)
123+
let getActiveToc = (navItem: SidebarLayout.Sidebar.NavItem.t) =>
124+
if navItem.href === (pathname :> string) {
125+
Some({TableOfContents.title, entries})
126+
} else {
127+
None
128+
}
129+
<div key=category.name>
130+
<SidebarLayout.Sidebar.Category
131+
isItemActive
132+
getActiveToc
133+
category
134+
onClick={_ => NavbarUtils.closeMobileTertiaryDrawer()}
135+
/>
136+
</div>
137+
})
138+
->React.array}
139+
</div>
140+
</aside>
141+
142+
<>
143+
<Meta title description />
144+
<NavbarSecondary />
145+
<NavbarTertiary sidebar=sidebarContent>
146+
<SidebarLayout.BreadCrumbs crumbs=breadcrumbs />
147+
<a
148+
href=editHref className="inline text-14 hover:underline text-fire" rel="noopener noreferrer"
149+
>
150+
{React.string("Edit")}
151+
</a>
152+
</NavbarTertiary>
153+
<DocsLayout categories activeToc={title, entries}>
154+
<div className="markdown-body">
155+
<MdxContent compiledMdx />
156+
</div>
157+
</DocsLayout>
158+
</>
159+
}
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,10 @@
11
type loaderData = {
2-
...Mdx.t,
2+
compiledMdx: CompiledMdx.t,
33
categories: array<SidebarLayout.Sidebar.Category.t>,
44
entries: array<TableOfContents.entry>,
5-
mdxSources?: array<SyntaxLookup.item>,
6-
activeSyntaxItem?: SyntaxLookup.item,
7-
breadcrumbs?: list<Url.breadcrumb>,
85
title: string,
9-
filePath: option<string>,
6+
description: string,
7+
filePath: string,
108
}
119

1210
let loader: ReactRouter.Loader.t<loaderData>

0 commit comments

Comments
 (0)