diff --git a/app/routes/MdxRoute.res b/app/routes/MdxRoute.res index 489734af6..d7671a385 100644 --- a/app/routes/MdxRoute.res +++ b/app/routes/MdxRoute.res @@ -289,6 +289,8 @@ let default = () => { let {entries, categories, title} = loaderData + Hooks.useFixAnchor() + <> {if (pathname :> string) == "/docs/manual/api" { <> diff --git a/package.json b/package.json index 744ef1087..304ec5f46 100644 --- a/package.json +++ b/package.json @@ -69,7 +69,7 @@ "remark-frontmatter": "^5.0.0", "remark-gfm": "^4.0.1", "remark-validate-links": "^13.1.0", - "rescript": "^12.0.0", + "rescript": "^12.1.0", "unified": "^11.0.5", "vfile-matter": "^5.0.0" }, @@ -95,4 +95,4 @@ "vite-plugin-env-compatible": "^2.0.1", "vite-plugin-page-reload": "^0.2.2" } -} \ No newline at end of file +} diff --git a/public/_redirects b/public/_redirects index f12879a3d..be453937e 100644 --- a/public/_redirects +++ b/public/_redirects @@ -13,4 +13,8 @@ /docs/manual/v9.0.0/* https://v11.rescript-lang.org/docs/manual/v9.0.0/:splat 308 /docs/manual/v8.0.0/* https://v11.rescript-lang.org/docs/manual/v8.0.0/:splat 308 /docs/react/v0.11.0/* https://v11.rescript-lang.org/docs/react/v0.11.0/:splat 308 -/docs/react/v0.10.0/* https://v11.rescript-lang.org/docs/react/v0.10.0/:splat 308 \ No newline at end of file +/docs/react/v0.10.0/* https://v11.rescript-lang.org/docs/react/v0.10.0/:splat 308 + + +/docs/manual/api/js https://v11.rescript-lang.org/docs/manual/v10.0.0/api/js/:splat 308 +/docs/manual/api/js/* https://v11.rescript-lang.org/docs/manual/v10.0.0/api/js/:splat 308 \ No newline at end of file diff --git a/src/bindings/ReactRouter.res b/src/bindings/ReactRouter.res index 6df145ca1..51318084d 100644 --- a/src/bindings/ReactRouter.res +++ b/src/bindings/ReactRouter.res @@ -14,7 +14,7 @@ external useSearchParams: unit => (WebAPI.URLAPI.urlSearchParams, {..} => unit) external useLoaderData: unit => 'a = "useLoaderData" /* The types for this are auto-generated from the react-router.config.mjs file */ -type path = {pathname: Path.t, search?: string, hash?: string} +type path = {pathname: Path.t, search?: string, hash?: option} module Loader = { type loaderArgs = {request: WebAPI.FetchAPI.request} diff --git a/src/common/HighlightJs.res b/src/common/HighlightJs.res index ecc9bfd0d..f22311a55 100644 --- a/src/common/HighlightJs.res +++ b/src/common/HighlightJs.res @@ -10,7 +10,7 @@ let renderHLJS = (~highlightedLines=[], ~darkmode=false, ~code: string, ~lang: s // If the language couldn't be parsed, we will fall back to text let options = {language: lang} let (lang, highlighted) = try (lang, highlight(~code, ~options)->valueGet) catch { - | Exn.Error(_) => ("text", code) + | JsExn(_) => ("text", code) } // Add line highlighting as well diff --git a/src/common/Hooks.res b/src/common/Hooks.res index 148ce7790..75dcc6e5b 100644 --- a/src/common/Hooks.res +++ b/src/common/Hooks.res @@ -69,3 +69,19 @@ let useScrollDirection = (~topMargin=80, ~threshold=20) => { scrollDir } + +let useFixAnchor = () => { + let {hash, pathname} = ReactRouter.useLocation() + let navigate = ReactRouter.useNavigate() + let hash = hash->Option.getOr("") + + let target = (pathname :> string)->Util.String.removeTrailingSlash ++ hash + + // let _ = navigate(target) + // React.useEffect(() => { + // let _ = navigate(target) + + // // None + // None + // }, []) +} diff --git a/src/common/Util.res b/src/common/Util.res index b4090d03d..68a4a5cfd 100644 --- a/src/common/Util.res +++ b/src/common/Util.res @@ -24,6 +24,10 @@ module String = { ->Array.join(" ") let leadingSlash = str => str->String.startsWith("/") ? str : "/" ++ str + + let trailingSlash = str => str->String.endsWith("/") ? str : str ++ "/" + + let removeTrailingSlash = str => str->String.replaceRegExp(/\/$/, "") } module Url = { @@ -59,6 +63,18 @@ module Url = { (rootPath ++ href->String.leadingSlash)->Stdlib.String.replaceAll("//", "/") } } + + let removeBaseUrl = str => str->Stdlib.String.replace(Env.root_url, "") + + // Cloudflare links have to include a trailing slash or they will redirect + let normalizeUrl = str => { + // separate the anchor if there is any + let splitUrl = str->Stdlib.String.split("#") + + `${splitUrl[0]->Option.getOr("")}/${splitUrl[1] + ->Option.map(anchor => "#" ++ anchor->String.removeTrailingSlash) + ->Option.getOr("")}`->removeBaseUrl + } } module Date = { diff --git a/src/common/Util.resi b/src/common/Util.resi index ab80d75ef..079ab7226 100644 --- a/src/common/Util.resi +++ b/src/common/Util.resi @@ -2,6 +2,7 @@ module Url: { let isAbsolute: string => bool let getRootPath: string => string let createRelativePath: (string, string) => string + let normalizeUrl: string => string } module Unsafe: { @@ -14,6 +15,8 @@ module String: { let capitalize: string => string let capitalizeSentence: string => string let leadingSlash: string => string + let trailingSlash: string => string + let removeTrailingSlash: string => string } module Date: { diff --git a/src/components/Search.res b/src/components/Search.res index fe3976179..a215e2c72 100644 --- a/src/components/Search.res +++ b/src/components/Search.res @@ -6,7 +6,7 @@ type state = Active | Inactive let hit = ({hit, children}: DocSearch.hitComponent) => { let toTitle = str => str->String.charAt(0)->String.toUpperCase ++ String.slice(str, ~start=1) - + let url = hit.url->Util.Url.normalizeUrl let description = switch hit.url ->String.split("/") ->Array.slice(~start=1) @@ -25,7 +25,9 @@ let hit = ({hit, children}: DocSearch.hitComponent) => { } ) - [doc->toTitle, version->toTitle]->Array.concat(info)->Array.join(" / ") + [doc->toTitle, version->toTitle] + ->Array.concat(info) + ->Array.join(" / ") | _ => "" } @@ -38,7 +40,7 @@ let hit = ({hit, children}: DocSearch.hitComponent) => { : React.null - + {deprecatedBadge} {description->React.string} @@ -50,7 +52,7 @@ let hit = ({hit, children}: DocSearch.hitComponent) => { let transformItems = (items: DocSearch.transformItems) => { items ->Array.filterMap(item => { - let url = try WebAPI.URL.make(~url=item.url)->Some catch { + let url = try WebAPI.URL.make(~url=item.url->Url.normalizePath)->Some catch { | Exn.Error(obj) => Console.error2(`Failed to parse URL ${item.url}`, obj) None @@ -67,7 +69,8 @@ let transformItems = (items: DocSearch.transformItems) => { let lvl1 = hierarchy.lvl1->Nullable.toOption->Option.getOr(lvl0) Some({ ...item, - deprecated: pathname->String.includes("api/js") || pathname->String.includes("api/core") + deprecated: pathname->String.includes("api/js") || + pathname->String.includes("api/core") ? Some("Deprecated") : None, url: pathname->String.replace("/v12.0.0/", "/") ++ hash, @@ -78,6 +81,7 @@ let transformItems = (items: DocSearch.transformItems) => { }, }) } + | None => None } }) @@ -155,7 +159,9 @@ let make = () => { }, [setState]) <> - {switch state { diff --git a/yarn.lock b/yarn.lock index afc8b0715..74a1d5776 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2182,6 +2182,13 @@ __metadata: languageName: node linkType: hard +"@rescript/darwin-arm64@npm:12.1.0": + version: 12.1.0 + resolution: "@rescript/darwin-arm64@npm:12.1.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@rescript/darwin-x64@npm:12.0.0": version: 12.0.0 resolution: "@rescript/darwin-x64@npm:12.0.0" @@ -2189,6 +2196,13 @@ __metadata: languageName: node linkType: hard +"@rescript/darwin-x64@npm:12.1.0": + version: 12.1.0 + resolution: "@rescript/darwin-x64@npm:12.1.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@rescript/linux-arm64@npm:12.0.0": version: 12.0.0 resolution: "@rescript/linux-arm64@npm:12.0.0" @@ -2196,6 +2210,13 @@ __metadata: languageName: node linkType: hard +"@rescript/linux-arm64@npm:12.1.0": + version: 12.1.0 + resolution: "@rescript/linux-arm64@npm:12.1.0" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@rescript/linux-x64@npm:12.0.0": version: 12.0.0 resolution: "@rescript/linux-x64@npm:12.0.0" @@ -2203,6 +2224,13 @@ __metadata: languageName: node linkType: hard +"@rescript/linux-x64@npm:12.1.0": + version: 12.1.0 + resolution: "@rescript/linux-x64@npm:12.1.0" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@rescript/react@npm:^0.14.0": version: 0.14.0 resolution: "@rescript/react@npm:0.14.0" @@ -2220,6 +2248,13 @@ __metadata: languageName: node linkType: hard +"@rescript/runtime@npm:12.1.0": + version: 12.1.0 + resolution: "@rescript/runtime@npm:12.1.0" + checksum: 10c0/7c6c75fce8011873007bbe59fee7b355519fdaf31f64258837e7da420eee57ebb36236e3f55c576258adbb5811841b033188f617351addfdc2034384075e38b8 + languageName: node + linkType: hard + "@rescript/webapi@npm:0.1.0-experimental-29db5f4": version: 0.1.0-experimental-29db5f4 resolution: "@rescript/webapi@npm:0.1.0-experimental-29db5f4" @@ -2236,6 +2271,13 @@ __metadata: languageName: node linkType: hard +"@rescript/win32-x64@npm:12.1.0": + version: 12.1.0 + resolution: "@rescript/win32-x64@npm:12.1.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@rolldown/pluginutils@npm:1.0.0-beta.27": version: 1.0.0-beta.27 resolution: "@rolldown/pluginutils@npm:1.0.0-beta.27" @@ -8475,7 +8517,7 @@ __metadata: remark-frontmatter: "npm:^5.0.0" remark-gfm: "npm:^4.0.1" remark-validate-links: "npm:^13.1.0" - rescript: "npm:^12.0.0" + rescript: "npm:^12.1.0" search-insights: "npm:^2.17.3" tailwindcss: "npm:^4" to-vfile: "npm:^8.0.0" @@ -8489,7 +8531,7 @@ __metadata: languageName: unknown linkType: soft -"rescript@npm:^12.0.0, rescript@npm:^12.0.0-beta.3": +"rescript@npm:^12.0.0-beta.3": version: 12.0.0 resolution: "rescript@npm:12.0.0" dependencies: @@ -8520,6 +8562,37 @@ __metadata: languageName: node linkType: hard +"rescript@npm:^12.1.0": + version: 12.1.0 + resolution: "rescript@npm:12.1.0" + dependencies: + "@rescript/darwin-arm64": "npm:12.1.0" + "@rescript/darwin-x64": "npm:12.1.0" + "@rescript/linux-arm64": "npm:12.1.0" + "@rescript/linux-x64": "npm:12.1.0" + "@rescript/runtime": "npm:12.1.0" + "@rescript/win32-x64": "npm:12.1.0" + dependenciesMeta: + "@rescript/darwin-arm64": + optional: true + "@rescript/darwin-x64": + optional: true + "@rescript/linux-arm64": + optional: true + "@rescript/linux-x64": + optional: true + "@rescript/win32-x64": + optional: true + bin: + bsc: cli/bsc.js + bstracing: cli/bstracing.js + rescript: cli/rescript.js + rescript-legacy: cli/rescript-legacy.js + rescript-tools: cli/rescript-tools.js + checksum: 10c0/526aacd9049427efe31dd450857eec1ab012edd2fbf1eeeeb03f4782ad776097da6c7cf4a21079d0d6dca2125a850201aa3929547f0be4aeccae4df3b8411c69 + languageName: node + linkType: hard + "restore-cursor@npm:^5.0.0": version: 5.1.0 resolution: "restore-cursor@npm:5.1.0"