Skip to content

Commit 47fa859

Browse files
committed
feat: split syntax-lookup detail pages out of MdxRoute into SyntaxLookupDetailRoute
- Create SyntaxLookupDetailRoute.res with dedicated loader for /syntax-lookup/* pages - Register syntaxLookupDetailRoutes in routes.res, filter syntax-lookup from mdxRoutes - Remove syntax-lookup branch, mdxSources/activeSyntaxItem fields, and components dict from MdxRoute - Flatten loader body after if/else removal
1 parent 4801dfe commit 47fa859

3 files changed

Lines changed: 160 additions & 164 deletions

File tree

app/routes.res

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,11 @@ let communityRoutes =
5454
route(path, "./routes/CommunityRoute.jsx", ~options={id: path})
5555
)
5656

57+
let syntaxLookupDetailRoutes =
58+
MdxFile.scanPaths(~dir="markdown-pages/syntax-lookup", ~alias="syntax-lookup")->Array.map(path =>
59+
route(path, "./routes/SyntaxLookupDetailRoute.jsx", ~options={id: path})
60+
)
61+
5762
let mdxRoutes = mdxRoutes("./routes/MdxRoute.jsx")->Array.filter(r =>
5863
!(
5964
r.path
@@ -67,7 +72,9 @@ let mdxRoutes = mdxRoutes("./routes/MdxRoute.jsx")->Array.filter(r =>
6772
path === "docs/guidelines" ||
6873
String.startsWith(path, "docs/guidelines/") ||
6974
path === "community" ||
70-
String.startsWith(path, "community/")
75+
String.startsWith(path, "community/") ||
76+
path === "syntax-lookup" ||
77+
String.startsWith(path, "syntax-lookup/")
7178
)
7279
->Option.getOr(false)
7380
)
@@ -92,6 +99,7 @@ let default = [
9299
...docsReactRoutes,
93100
...docsGuidelinesRoutes,
94101
...communityRoutes,
102+
...syntaxLookupDetailRoutes,
95103
...mdxRoutes,
96104
route("*", "./routes/NotFoundRoute.jsx"),
97105
]

app/routes/MdxRoute.res

Lines changed: 80 additions & 163 deletions
Original file line numberDiff line numberDiff line change
@@ -4,53 +4,11 @@ type loaderData = {
44
...Mdx.t,
55
categories: array<SidebarLayout.Sidebar.Category.t>,
66
entries: array<TableOfContents.entry>,
7-
mdxSources?: array<SyntaxLookup.item>,
8-
activeSyntaxItem?: SyntaxLookup.item,
97
breadcrumbs?: list<Url.breadcrumb>,
108
title: string,
119
filePath: option<string>,
1210
}
1311

14-
/**
15-
This configures the MDX component to use our custom markdown components
16-
*/
17-
let components = {
18-
// Replacing HTML defaults
19-
"a": Markdown.A.make,
20-
"blockquote": Markdown.Blockquote.make,
21-
"code": Markdown.Code.make,
22-
"h1": Markdown.H1.make,
23-
"h2": Markdown.H2.make,
24-
"h3": Markdown.H3.make,
25-
"h4": Markdown.H4.make,
26-
"h5": Markdown.H5.make,
27-
"hr": Markdown.Hr.make,
28-
"intro": Markdown.Intro.make,
29-
"li": Markdown.Li.make,
30-
"ol": Markdown.Ol.make,
31-
"p": Markdown.P.make,
32-
"pre": Markdown.Pre.make,
33-
"strong": Markdown.Strong.make,
34-
"table": Markdown.Table.make,
35-
"th": Markdown.Th.make,
36-
"thead": Markdown.Thead.make,
37-
"td": Markdown.Td.make,
38-
"ul": Markdown.Ul.make,
39-
// These are custom components we provide
40-
"Cite": Markdown.Cite.make,
41-
"CodeTab": Markdown.CodeTab.make,
42-
"Image": Markdown.Image.make,
43-
"Info": Markdown.Info.make,
44-
"Intro": Markdown.Intro.make,
45-
"UrlBox": Markdown.UrlBox.make,
46-
"Video": Markdown.Video.make,
47-
"Warn": Markdown.Warn.make,
48-
"CommunityContent": CommunityContent.make,
49-
"WarningTable": WarningTable.make,
50-
"Docson": DocsonLazy.make,
51-
"Suspense": React.Suspense.make,
52-
}
53-
5412
let convertToNavItems = (items, rootPath) =>
5513
Array.map(items, (item): SidebarLayout.Sidebar.NavItem.t => {
5614
let href = switch item.slug {
@@ -104,128 +62,102 @@ let loader: ReactRouter.Loader.t<loaderData> = async ({request}) => {
10462

10563
let mdx = await loadMdx(request, ~options={remarkPlugins: Mdx.plugins})
10664

107-
if pathname->String.includes("syntax-lookup") {
108-
let mdxSources =
109-
(await allMdx(~filterByPaths=["markdown-pages/syntax-lookup"]))
110-
->Array.filter(page =>
111-
page.path
112-
->Option.map(String.includes(_, "syntax-lookup"))
113-
->Option.getOr(false)
114-
)
115-
->Array.map(SyntaxLookupRoute.convert)
116-
117-
let activeSyntaxItem =
118-
mdxSources->Array.find(item => item.id == mdx.attributes.id->Option.getOrThrow)
119-
120-
let res: loaderData = {
121-
__raw: mdx.__raw,
122-
attributes: mdx.attributes,
123-
entries: [],
124-
categories: [],
125-
mdxSources,
126-
?activeSyntaxItem,
127-
title: mdx.attributes.title, // TODO RR7: check if this is correct
128-
filePath: None,
129-
}
130-
res
131-
} else {
132-
let categories = {
133-
if pathname == "/docs/manual/api" {
134-
[]
135-
} else if pathname->String.includes("docs/manual") {
136-
await manualTableOfContents()
137-
} else {
138-
[]
139-
}
65+
let categories = {
66+
if pathname == "/docs/manual/api" {
67+
[]
68+
} else if pathname->String.includes("docs/manual") {
69+
await manualTableOfContents()
70+
} else {
71+
[]
14072
}
73+
}
14174

142-
let filePath = ref(None)
143-
144-
let fileContents = await (await allMdx())
145-
->Array.filter(mdx => {
146-
switch (mdx.slug, mdx.canonical) {
147-
// Having a canonical path is the best way to ensure we get the right file
148-
| (_, Nullable.Value(canonical)) => pathname == (canonical :> string)
149-
// if we don't have a canonical path, see if we can find the slug in the pathname
150-
| (Some(slug), _) => pathname->String.includes(slug)
151-
// otherwise we can't match it and the build should fail
152-
| _ => false
153-
}
154-
})
155-
->Array.get(0)
156-
->Option.flatMap(mdx => {
157-
filePath :=
158-
mdx.path->Option.map(mdxPath =>
159-
String.slice(mdxPath, ~start=mdxPath->String.indexOf("rescript-lang.org/") + 17)
160-
)
161-
// remove the filesystem path to get the relative path to the files in the repo
162-
mdx.path
163-
})
164-
->Option.map(path => Node.Fs.readFile(path, "utf-8"))
165-
->Option.getOrThrow(~message="Could not find MDX file for path " ++ (pathname :> string))
166-
167-
let markdownTree = Mdast.fromMarkdown(fileContents)
168-
let tocResult = Mdast.toc(markdownTree, {maxDepth: 2})
75+
let filePath = ref(None)
16976

170-
let headers = Dict.make()
77+
let fileContents = await (await allMdx())
78+
->Array.filter(mdx => {
79+
switch (mdx.slug, mdx.canonical) {
80+
// Having a canonical path is the best way to ensure we get the right file
81+
| (_, Nullable.Value(canonical)) => pathname == (canonical :> string)
82+
// if we don't have a canonical path, see if we can find the slug in the pathname
83+
| (Some(slug), _) => pathname->String.includes(slug)
84+
// otherwise we can't match it and the build should fail
85+
| _ => false
86+
}
87+
})
88+
->Array.get(0)
89+
->Option.flatMap(mdx => {
90+
filePath :=
91+
mdx.path->Option.map(mdxPath =>
92+
String.slice(mdxPath, ~start=mdxPath->String.indexOf("rescript-lang.org/") + 17)
93+
)
94+
// remove the filesystem path to get the relative path to the files in the repo
95+
mdx.path
96+
})
97+
->Option.map(path => Node.Fs.readFile(path, "utf-8"))
98+
->Option.getOrThrow(~message="Could not find MDX file for path " ++ (pathname :> string))
17199

172-
Mdast.reduceHeaders(tocResult.map, headers)
100+
let markdownTree = Mdast.fromMarkdown(fileContents)
101+
let tocResult = Mdast.toc(markdownTree, {maxDepth: 2})
173102

174-
let entries =
175-
headers
176-
->Dict.toArray
177-
->Array.map(((header, url)): TableOfContents.entry => {
178-
header,
179-
href: (url :> string),
180-
})
181-
->Array.slice(~start=2) // skip first two entries which are the document entry and the H1 title for the page, we just want the h2 sections
103+
let headers = Dict.make()
182104

183-
let breadcrumbs =
184-
pathname->String.includes("docs/manual")
185-
? Some(list{
186-
{Url.name: "Docs", href: "/docs/"},
187-
{
188-
Url.name: "Language Manual",
189-
href: "/docs/manual/" ++ "introduction",
190-
},
191-
})
192-
: None
105+
Mdast.reduceHeaders(tocResult.map, headers)
193106

194-
let metaTitleCategory = {
195-
let path = (pathname :> string)
196-
let title = if path->String.includes("docs/manual/api") {
197-
"ReScript API"
198-
} else if path->String.includes("docs/manual") {
199-
"ReScript Language Manual"
200-
} else {
201-
"ReScript"
202-
}
107+
let entries =
108+
headers
109+
->Dict.toArray
110+
->Array.map(((header, url)): TableOfContents.entry => {
111+
header,
112+
href: (url :> string),
113+
})
114+
->Array.slice(~start=2) // skip first two entries which are the document entry and the H1 title for the page, we just want the h2 sections
203115

204-
title
205-
}
116+
let breadcrumbs =
117+
pathname->String.includes("docs/manual")
118+
? Some(list{
119+
{Url.name: "Docs", href: "/docs/"},
120+
{
121+
Url.name: "Language Manual",
122+
href: "/docs/manual/" ++ "introduction",
123+
},
124+
})
125+
: None
206126

207-
let title = if pathname == "/docs/manual/api" {
208-
"API"
127+
let metaTitleCategory = {
128+
let path = (pathname :> string)
129+
let title = if path->String.includes("docs/manual/api") {
130+
"ReScript API"
131+
} else if path->String.includes("docs/manual") {
132+
"ReScript Language Manual"
209133
} else {
210-
mdx.attributes.title
134+
"ReScript"
211135
}
212136

213-
let res: loaderData = {
214-
__raw: mdx.__raw,
215-
attributes: mdx.attributes,
216-
entries,
217-
categories,
218-
?breadcrumbs,
219-
title: `${title} | ${metaTitleCategory}`,
220-
filePath: filePath.contents,
221-
}
222-
res
137+
title
138+
}
139+
140+
let title = if pathname == "/docs/manual/api" {
141+
"API"
142+
} else {
143+
mdx.attributes.title
223144
}
145+
146+
let res: loaderData = {
147+
__raw: mdx.__raw,
148+
attributes: mdx.attributes,
149+
entries,
150+
categories,
151+
?breadcrumbs,
152+
title: `${title} | ${metaTitleCategory}`,
153+
filePath: filePath.contents,
154+
}
155+
res
224156
}
225157

226158
let default = () => {
227159
let {pathname} = ReactRouter.useLocation()
228-
let component = useMdxComponent(~components)
160+
let component = useMdxComponent()
229161
let attributes = useMdxAttributes()
230162

231163
let loaderData: loaderData = ReactRouter.useLoaderData()
@@ -355,22 +287,7 @@ let default = () => {
355287
}
356288
</>
357289
} else {
358-
switch loaderData.mdxSources {
359-
| Some(mdxSources) =>
360-
<>
361-
<Meta
362-
title={loaderData.activeSyntaxItem
363-
->Option.map(item => item.name)
364-
->Option.getOr("Syntax Lookup | ReScript API")}
365-
description={attributes.description->Nullable.getOr("")}
366-
/>
367-
<NavbarSecondary />
368-
<SyntaxLookup mdxSources activeItem=?loaderData.activeSyntaxItem>
369-
{component()}
370-
</SyntaxLookup>
371-
</>
372-
| None => React.null
373-
}
290+
React.null
374291
}}
375292
</>
376293
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
type loaderData = {
2+
compiledMdx: CompiledMdx.t,
3+
mdxSources: array<SyntaxLookup.item>,
4+
activeSyntaxItem: option<SyntaxLookup.item>,
5+
title: string,
6+
description: string,
7+
}
8+
9+
let loader: ReactRouter.Loader.t<loaderData> = async ({request}) => {
10+
let {pathname} = WebAPI.URL.make(~url=request.url)
11+
let filePath = MdxFile.resolveFilePath(
12+
(pathname :> string),
13+
~dir="markdown-pages/syntax-lookup",
14+
~alias="syntax-lookup",
15+
)
16+
17+
let raw = await Node.Fs.readFile(filePath, "utf-8")
18+
let {frontmatter}: MarkdownParser.result = MarkdownParser.parseSync(raw)
19+
20+
let id = switch frontmatter {
21+
| Object(dict) =>
22+
switch dict->Dict.get("id") {
23+
| Some(String(s)) => s
24+
| _ => ""
25+
}
26+
| _ => ""
27+
}
28+
29+
let name = switch frontmatter {
30+
| Object(dict) =>
31+
switch dict->Dict.get("name") {
32+
| Some(String(s)) => s
33+
| _ => ""
34+
}
35+
| _ => ""
36+
}
37+
38+
let compiledMdx = await MdxFile.compileMdx(raw, ~filePath, ~remarkPlugins=Mdx.plugins)
39+
40+
let mdxSources =
41+
(await MdxFile.loadAllAttributes(~dir="markdown-pages/syntax-lookup"))->Array.map(
42+
SyntaxLookupRoute.convert,
43+
)
44+
45+
let activeSyntaxItem = mdxSources->Array.find(item => item.id == id)
46+
47+
{
48+
compiledMdx,
49+
mdxSources,
50+
activeSyntaxItem,
51+
title: name,
52+
description: "",
53+
}
54+
}
55+
56+
let default = () => {
57+
let {compiledMdx, mdxSources, activeSyntaxItem} = ReactRouter.useLoaderData()
58+
59+
<>
60+
<Meta
61+
title={activeSyntaxItem
62+
->Option.map(item => item.name)
63+
->Option.getOr("Syntax Lookup | ReScript API")}
64+
description=""
65+
/>
66+
<NavbarSecondary />
67+
<SyntaxLookup mdxSources activeItem=?activeSyntaxItem>
68+
<MdxContent compiledMdx />
69+
</SyntaxLookup>
70+
</>
71+
}

0 commit comments

Comments
 (0)