|
1 |
| -// Structure defined by `scripts/extract-syntax.js` |
2 |
| -type syntaxData = { |
3 |
| - "file": string, |
4 |
| - "id": string, |
5 |
| - "keywords": array<string>, |
6 |
| - "name": string, |
7 |
| - "summary": string, |
8 |
| - "category": string, |
9 |
| -} |
10 |
| - |
11 |
| -let indexData: array<syntaxData> = %raw("require('index_data/syntax_index.json')") |
12 |
| - |
13 |
| -module MdxComp = { |
14 |
| - type props |
15 |
| - type t = props => React.element |
16 |
| - |
17 |
| - let render: t => React.element = %raw(` |
18 |
| - function(c) { |
19 |
| - return React.createElement(c, {}); |
20 |
| - } |
21 |
| - `) |
22 |
| - |
23 |
| - /* @get */ |
24 |
| - /* external frontmatter: t => Js.Json.t = "frontmatter" */ |
25 |
| -} |
26 |
| - |
27 |
| -let requireSyntaxFile: string => MdxComp.t = %raw(` |
28 |
| - function(name) { |
29 |
| - return require("misc_docs/syntax/" + name + ".mdx").default |
30 |
| - } |
31 |
| -`) |
32 |
| - |
33 | 1 | module Category = {
|
34 | 2 | type t =
|
35 | 3 | | Decorators
|
@@ -82,42 +50,17 @@ type item = {
|
82 | 50 | name: string,
|
83 | 51 | summary: string,
|
84 | 52 | category: Category.t,
|
85 |
| - component: MdxComp.t, |
| 53 | + children: React.element, |
86 | 54 | }
|
87 | 55 |
|
88 |
| -let toItem = (syntaxData: syntaxData): item => { |
89 |
| - let file = syntaxData["file"] |
90 |
| - let id = syntaxData["id"] |
91 |
| - let keywords = syntaxData["keywords"] |
92 |
| - let name = syntaxData["name"] |
93 |
| - let summary = syntaxData["summary"] |
94 |
| - let category = syntaxData["category"] |
95 |
| - let item: item = { |
96 |
| - id, |
97 |
| - keywords, |
98 |
| - name, |
99 |
| - summary, |
100 |
| - category: Category.fromString(category), |
101 |
| - component: requireSyntaxFile(file), |
102 |
| - } |
103 |
| - item |
| 56 | +type itemInfo = { |
| 57 | + id: string, |
| 58 | + keywords: array<string>, |
| 59 | + name: string, |
| 60 | + summary: string, |
| 61 | + category: Category.t, |
104 | 62 | }
|
105 | 63 |
|
106 |
| -let allItems = indexData->Belt.Array.map(toItem) |
107 |
| - |
108 |
| -let fuseOpts = Fuse.Options.t( |
109 |
| - ~shouldSort=false, |
110 |
| - ~includeScore=true, |
111 |
| - ~threshold=0.2, |
112 |
| - ~location=0, |
113 |
| - ~distance=30, |
114 |
| - ~minMatchCharLength=1, |
115 |
| - ~keys=["keywords", "name"], |
116 |
| - (), |
117 |
| -) |
118 |
| - |
119 |
| -let fuse: Fuse.t<item> = Fuse.make(allItems, fuseOpts) |
120 |
| - |
121 | 64 | let getAnchor = path => {
|
122 | 65 | switch Js.String2.split(path, "#") {
|
123 | 66 | | [_, anchor] => Some(anchor)
|
@@ -169,22 +112,85 @@ external scrollTo: (int, int) => unit = "scrollTo"
|
169 | 112 |
|
170 | 113 | let scrollToTop = () => scrollTo(0, 0)
|
171 | 114 |
|
172 |
| -let findItemById = id => allItems->Js.Array2.find(item => item.id === id) |
| 115 | +type props = {mdxSources: array<Mdx.Remote.output>} |
| 116 | +type params = {slug: string} |
| 117 | + |
| 118 | +let decode = (json: Js.Json.t) => { |
| 119 | + open Json.Decode |
| 120 | + let id = json->field("id", string, _) |
| 121 | + let keywords = json->field("keywords", array(string), _) |
| 122 | + let name = json->field("name", string, _) |
| 123 | + let summary = json->field("summary", string, _) |
| 124 | + let category = json->field("category", string, _)->Category.fromString |
| 125 | + |
| 126 | + { |
| 127 | + id, |
| 128 | + keywords, |
| 129 | + name, |
| 130 | + summary, |
| 131 | + category, |
| 132 | + } |
| 133 | +} |
| 134 | + |
| 135 | +type remarkPlugin |
| 136 | +@module("remark-comment") external remarkComment: remarkPlugin = "default" |
| 137 | +@module("remark-gfm") external remarkGfm: remarkPlugin = "default" |
| 138 | +@module("remark-frontmatter") external remarkFrontmatter: remarkPlugin = "default" |
| 139 | + |
| 140 | +let mdxOptions = {"remarkPlugins": [remarkComment, remarkGfm, remarkFrontmatter]} |
173 | 141 |
|
174 |
| -let findItemByExactName = name => allItems->Js.Array2.find(item => item.name === name) |
| 142 | +external asProps: {..} => {"props": Mdx.Remote.output} = "%identity" |
| 143 | + |
| 144 | +let default = (props: props) => { |
| 145 | + let {mdxSources} = props |
| 146 | + |
| 147 | + let allItems = mdxSources->Js.Array2.map(mdxSource => { |
| 148 | + let {id, keywords, category, summary, name} = decode(mdxSource.frontmatter) |
| 149 | + |
| 150 | + let mdxProps = { |
| 151 | + "frontmatter": mdxSource.frontmatter, |
| 152 | + "scope": mdxSource.scope, |
| 153 | + "compiledSource": mdxSource.compiledSource, |
| 154 | + "components": Markdown.default, |
| 155 | + "options": { |
| 156 | + "mdxOptions": mdxOptions, |
| 157 | + }, |
| 158 | + } |
175 | 159 |
|
176 |
| -let searchItems = value => |
177 |
| - fuse |
178 |
| - ->Fuse.search(value) |
179 |
| - ->Belt.Array.map(m => { |
180 |
| - m["item"] |
| 160 | + let children = React.createElement(Mdx.MDXRemote.make, asProps(mdxProps)) |
| 161 | + |
| 162 | + // let children = MdxUtils.createElement(mdxSource) |
| 163 | + |
| 164 | + {id, keywords, category, summary, name, children} |
181 | 165 | })
|
182 | 166 |
|
183 |
| -@react.component |
184 |
| -let make = () => { |
| 167 | + let fuseOpts = Fuse.Options.t( |
| 168 | + ~shouldSort=false, |
| 169 | + ~includeScore=true, |
| 170 | + ~threshold=0.2, |
| 171 | + ~location=0, |
| 172 | + ~distance=30, |
| 173 | + ~minMatchCharLength=1, |
| 174 | + ~keys=["keywords", "name"], |
| 175 | + (), |
| 176 | + ) |
| 177 | + |
| 178 | + let fuse: Fuse.t<item> = Fuse.make(allItems, fuseOpts) |
| 179 | + |
185 | 180 | let router = Next.Router.useRouter()
|
186 | 181 | let (state, setState) = React.useState(_ => ShowAll)
|
187 | 182 |
|
| 183 | + let findItemById = id => allItems->Js.Array2.find(item => item.id === id) |
| 184 | + |
| 185 | + let findItemByExactName = name => allItems->Js.Array2.find(item => item.name === name) |
| 186 | + |
| 187 | + let searchItems = value => |
| 188 | + fuse |
| 189 | + ->Fuse.search(value) |
| 190 | + ->Belt.Array.map(m => { |
| 191 | + m["item"] |
| 192 | + }) |
| 193 | + |
188 | 194 | // This effect is responsible for updating the view state when the router anchor changes.
|
189 | 195 | // This effect is triggered when:
|
190 | 196 | // [A] The page first loads.
|
@@ -234,7 +240,7 @@ let make = () => {
|
234 | 240 | | ShowAll => React.null
|
235 | 241 | | ShowDetails(item) =>
|
236 | 242 | <div className="mb-16">
|
237 |
| - <DetailBox summary={item.summary}> {MdxComp.render(item.component)} </DetailBox> |
| 243 | + <DetailBox summary={item.summary}> item.children </DetailBox> |
238 | 244 | </div>
|
239 | 245 | }
|
240 | 246 |
|
@@ -304,27 +310,67 @@ let make = () => {
|
304 | 310 | onSearchValueChange("")
|
305 | 311 | }
|
306 | 312 |
|
307 |
| - <div> |
308 |
| - <div className="flex flex-col items-center"> |
309 |
| - <div className="text-center" style={ReactDOM.Style.make(~maxWidth="21rem", ())}> |
310 |
| - <Markdown.H1> {React.string("Syntax Lookup")} </Markdown.H1> |
311 |
| - <div className="mb-8 text-gray-60-tr text-14"> |
312 |
| - {React.string("Enter some language construct you want to know more about.")} |
| 313 | + let overlayState = React.useState(() => false) |
| 314 | + let title = "Syntax Lookup | ReScript Documentation" |
| 315 | + |
| 316 | + let content = |
| 317 | + <div> |
| 318 | + <div className="flex flex-col items-center"> |
| 319 | + <div className="text-center" style={ReactDOM.Style.make(~maxWidth="21rem", ())}> |
| 320 | + <Markdown.H1> {React.string("Syntax Lookup")} </Markdown.H1> |
| 321 | + <div className="mb-8 text-gray-60-tr text-14"> |
| 322 | + {React.string("Enter some language construct you want to know more about.")} |
| 323 | + </div> |
| 324 | + </div> |
| 325 | + <div className="w-full" style={ReactDOM.Style.make(~maxWidth="34rem", ())}> |
| 326 | + <SearchBox |
| 327 | + placeholder="Enter keywords or syntax..." |
| 328 | + completionValues={Belt.Array.map(completionItems, item => item.name)} |
| 329 | + value=searchValue |
| 330 | + onClear=onSearchClear |
| 331 | + onValueChange=onSearchValueChange |
| 332 | + /> |
313 | 333 | </div>
|
314 | 334 | </div>
|
315 |
| - <div className="w-full" style={ReactDOM.Style.make(~maxWidth="34rem", ())}> |
316 |
| - <SearchBox |
317 |
| - placeholder="Enter keywords or syntax..." |
318 |
| - completionValues={Belt.Array.map(completionItems, item => item.name)} |
319 |
| - value=searchValue |
320 |
| - onClear=onSearchClear |
321 |
| - onValueChange=onSearchValueChange |
322 |
| - /> |
| 335 | + <div className="mt-10"> |
| 336 | + {details} |
| 337 | + {React.array(categories)} |
323 | 338 | </div>
|
324 | 339 | </div>
|
325 |
| - <div className="mt-10"> |
326 |
| - {details} |
327 |
| - {React.array(categories)} |
| 340 | + |
| 341 | + <> |
| 342 | + <Meta |
| 343 | + siteName="ReScript Blog" title description="News, Announcements, Release Notes and more" |
| 344 | + /> |
| 345 | + <div className="mt-4 xs:mt-16"> |
| 346 | + <div className="text-gray-80"> |
| 347 | + <Navigation overlayState /> |
| 348 | + <div className="flex xs:justify-center overflow-hidden pb-48"> |
| 349 | + <main className="mt-16 min-w-320 lg:align-center w-full px-4 md:px-8 max-w-1280"> |
| 350 | + <Mdx.Provider components=Markdown.default> |
| 351 | + <div className="flex justify-center"> |
| 352 | + <div className="max-w-740 w-full"> content </div> |
| 353 | + </div> |
| 354 | + </Mdx.Provider> |
| 355 | + </main> |
| 356 | + </div> |
| 357 | + <Footer /> |
| 358 | + </div> |
328 | 359 | </div>
|
329 |
| - </div> |
| 360 | + </> |
| 361 | +} |
| 362 | + |
| 363 | +let getStaticProps: Next.GetStaticProps.t<props, params> = async _ctx => { |
| 364 | + let dir = Node.Path.resolve("misc_docs", "syntax") |
| 365 | + |
| 366 | + let allFiles = Node.Fs.readdirSync(dir)->Js.Array2.map(async file => { |
| 367 | + let fullPath = Node.Path.join2(dir, file) |
| 368 | + let source = fullPath->Node.Fs.readFileSync(#utf8) |
| 369 | + // await MdxUtils.serialize(source) |
| 370 | + await Mdx.Remote.serialize(source, {"parseFrontmatter": true, "mdxOptions": mdxOptions}) |
| 371 | + }) |
| 372 | + |
| 373 | + let mdxSources = await Js.Promise2.all(allFiles) |
| 374 | + |
| 375 | + {"props": {mdxSources: mdxSources}} |
330 | 376 | }
|
0 commit comments