From 14425a15d19ecea2c2b2812be04b72fea8c9a2b2 Mon Sep 17 00:00:00 2001 From: Pedro Castro Date: Sat, 31 Oct 2026 21:27:10 -0300 Subject: [PATCH] chore: migrate website workspaces to ReScript v13 Support the alpha compiler with compatible React and WebAPI bindings across the docs, guide, playground, and shared workspaces. Replace removed APIs and implicit globals so compilation and browser workflows keep working with the new type definitions. Refresh temporary React bindings in the example checker after dependency upgrades to prevent stale cached packages from masking content errors. --- .../__tests__/BlogArticleBehavior_.test.res | 14 +- .../__tests__/BreadcrumbsBehavior_.test.res | 8 +- .../CommunityLayoutBehavior_.test.res | 2 +- apps/docs/__tests__/CopyButtons_.test.res | 2 +- .../__tests__/DocsLayoutBehavior_.test.res | 16 +- .../__tests__/DocsOverviewBehavior_.test.res | 22 +- .../__tests__/LandingPageBehavior_.test.res | 71 ++--- .../LandingPageInstallInstructions_.test.res | 6 +- .../LandingPagePlaygroundLoader_.test.res | 2 +- .../docs/__tests__/LandingPageVideo_.test.res | 3 +- .../MarkdownComponentsBehavior_.test.res | 61 +++-- apps/docs/__tests__/Meta_.test.res | 25 +- apps/docs/__tests__/NotFound_.test.res | 2 +- apps/docs/__tests__/ResponsiveImage_.test.res | 27 +- apps/docs/__tests__/Search_.test.res | 6 +- .../__tests__/SyntaxLookupBehavior_.test.res | 14 +- .../__tests__/visual/LandingPage_.test.res | 8 +- .../visual/MarkdownComponents_.test.res | 6 +- .../__tests__/visual/SyntaxLookup_.test.res | 15 +- apps/docs/app/layouts/DocsLayoutRoute.res | 2 +- apps/docs/app/routes/ApiDocs.res | 19 +- apps/docs/app/routes/ApiOverviewRoute.res | 2 +- apps/docs/app/routes/BlogArticle.res | 7 +- apps/docs/app/routes/BlogArticle.resi | 2 +- apps/docs/app/routes/BlogArticleRoute.res | 2 +- apps/docs/app/routes/CommunityRoute.res | 2 +- apps/docs/app/routes/DocsGuidesRoute.res | 2 +- apps/docs/app/routes/DocsManualRoute.res | 2 +- apps/docs/app/routes/DocsOverview.res | 4 +- apps/docs/app/routes/DocsOverview.resi | 2 +- apps/docs/app/routes/DocsReactRoute.res | 2 +- apps/docs/app/routes/LandingPage.res | 3 +- apps/docs/app/routes/Packages.res | 55 ++-- apps/docs/app/routes/Packages.resi | 2 +- apps/docs/app/routes/SyntaxLookup.res | 57 ++-- .../app/routes/SyntaxLookupDetailRoute.res | 2 +- apps/docs/app/routes/TryRoute.res | 12 +- apps/docs/e2e/Playground.cy.res | 10 +- apps/docs/e2e/bindings/Cypress.res | 36 ++- .../functions/ogimage/[[path]]/index.png.res | 39 +-- apps/docs/package.json | 6 +- apps/docs/rescript.json | 6 - .../scripts/__tests__/Clipboard_.test.res | 23 +- .../__tests__/HomepagePerformance_.test.res | 9 +- .../scripts/__tests__/test-examples.test.mjs | 18 ++ apps/docs/scripts/test-examples.mjs | 11 +- apps/docs/src/bindings/Cloudflare.res | 2 +- apps/docs/src/bindings/Fuse.res | 25 +- apps/docs/src/common/Hooks.res | 6 +- apps/docs/src/components/CodeCopyButton.res | 25 +- apps/docs/src/components/CodeExample.res | 37 +-- .../src/components/CommunityMobileSidebar.res | 4 +- apps/docs/src/components/Docson.res | 2 +- .../src/components/LandingPageCopyButton.res | 13 +- .../LandingPageInstallInstructions.res | 3 +- apps/docs/src/components/LandingPageIntro.res | 3 +- .../src/components/LandingPageTrustedBy.res | 3 +- apps/docs/src/components/Markdown.res | 67 ++--- .../src/components/MarkdownComponents.res | 57 ++-- apps/docs/src/components/NavbarPrimary.res | 9 +- apps/docs/src/components/NavbarUtils.res | 48 ++-- apps/docs/src/components/Search.res | 35 ++- apps/docs/src/components/SearchModal.res | 2 +- apps/docs/src/components/SidebarNav.res | 10 +- apps/docs/src/layouts/CommunityLayout.res | 2 +- apps/docs/src/layouts/DocsLayout.res | 3 +- apps/docs/src/layouts/MainLayout.res | 4 +- apps/docs/src/layouts/MainLayout.resi | 2 +- apps/docs/src/layouts/SidebarPageLayout.res | 12 +- apps/docs/src/layouts/SidebarPageLayout.resi | 2 - apps/docs/src/markdown/Mdx.res | 2 +- apps/docs/src/markdown/MdxLegacy.res | 9 +- apps/docs/test-utils/TestUtils.res | 10 +- apps/guide/app/GuideCompilerBridgeHook.res | 23 +- apps/guide/app/GuideCompilerData.res | 3 +- apps/guide/app/GuideDom.res | 2 +- apps/guide/app/GuideHome.res | 5 +- apps/guide/app/GuideLayout.res | 6 +- apps/guide/app/GuideLayoutHook.res | 20 +- apps/guide/package.json | 6 +- apps/guide/rescript.json | 1 - apps/guide/vite.config.mjs | 21 +- package.json | 2 +- packages/playground/package.json | 4 +- packages/playground/rescript.json | 1 - .../playground/src/CompilerManagerHook.res | 9 +- packages/playground/src/ConsolePanel.res | 7 +- packages/playground/src/EvalIFrame.res | 9 +- packages/playground/src/Playground.res | 243 +++++++++--------- .../playground/src/PlaygroundShareButton.res | 2 +- packages/shared/package.json | 4 +- packages/shared/rescript.json | 1 - packages/shared/src/Clipboard.res | 30 ++- packages/shared/src/CodeMirror.res | 115 ++++++++- packages/shared/src/CodeMirror.resi | 2 +- packages/shared/src/HtmlRef.res | 2 +- packages/shared/src/ReactRouter.res | 4 +- packages/shared/src/WebDocument.res | 2 + yarn.lock | 107 ++++---- 99 files changed, 964 insertions(+), 711 deletions(-) create mode 100644 packages/shared/src/WebDocument.res diff --git a/apps/docs/__tests__/BlogArticleBehavior_.test.res b/apps/docs/__tests__/BlogArticleBehavior_.test.res index 05857a4dd..572887e06 100644 --- a/apps/docs/__tests__/BlogArticleBehavior_.test.res +++ b/apps/docs/__tests__/BlogArticleBehavior_.test.res @@ -1,7 +1,7 @@ open ReactRouter open Vitest -@get external textContent: WebAPI.DOMAPI.element => string = "textContent" +@get external textContent: WebAPI.Element.t => string = "textContent" let mockAuthor: BlogFrontmatter.author = { username: "test-author", @@ -33,14 +33,18 @@ test("blog article marks body content for DocSearch crawling", async () => { , ) - switch document->WebAPI.Document.querySelector("article.DocSearch-content") { + switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("article.DocSearch-content") { | Value(_) => () - | Null => failwith("expected blog article body to be marked as DocSearch content") + | Null => panic("expected blog article body to be marked as DocSearch content") } - let lvl0 = switch document->WebAPI.Document.querySelector("article .DocSearch-lvl0") { + let lvl0 = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("article .DocSearch-lvl0") { | Value(element) => element - | Null => failwith("expected blog article to render a DocSearch lvl0 marker") + | Null => panic("expected blog article to render a DocSearch lvl0 marker") } expect(lvl0->textContent)->toBe("Blog") diff --git a/apps/docs/__tests__/BreadcrumbsBehavior_.test.res b/apps/docs/__tests__/BreadcrumbsBehavior_.test.res index 4b5739be5..b318581cc 100644 --- a/apps/docs/__tests__/BreadcrumbsBehavior_.test.res +++ b/apps/docs/__tests__/BreadcrumbsBehavior_.test.res @@ -1,7 +1,7 @@ open ReactRouter open Vitest -@get external textContent: WebAPI.DOMAPI.element => string = "textContent" +@get external textContent: WebAPI.Element.t => string = "textContent" test("breadcrumbs do not repeat the current page crumb when it is already included", async () => { await viewport(1440, 900) @@ -21,9 +21,11 @@ test("breadcrumbs do not repeat the current page crumb when it is already includ ) let _breadcrumbs = await screen->getByTestId("breadcrumbs") - let breadcrumbs = switch document->WebAPI.Document.querySelector("[data-testid='breadcrumbs']") { + let breadcrumbs = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("[data-testid='breadcrumbs']") { | Value(breadcrumbs) => breadcrumbs - | Null => failwith("expected breadcrumbs") + | Null => panic("expected breadcrumbs") } expect(breadcrumbs->textContent)->toBe("Docs / API / Stdlib") diff --git a/apps/docs/__tests__/CommunityLayoutBehavior_.test.res b/apps/docs/__tests__/CommunityLayoutBehavior_.test.res index 22abfb1c8..8c057c918 100644 --- a/apps/docs/__tests__/CommunityLayoutBehavior_.test.res +++ b/apps/docs/__tests__/CommunityLayoutBehavior_.test.res @@ -23,7 +23,7 @@ module CurrentPage = { @react.component let make = () => { let {pathname} = ReactRouter.useLocation() -
{React.string((pathname :> string))}
+
{React.string(pathname :> string)}
} } diff --git a/apps/docs/__tests__/CopyButtons_.test.res b/apps/docs/__tests__/CopyButtons_.test.res index 82a2886e2..ed39383fc 100644 --- a/apps/docs/__tests__/CopyButtons_.test.res +++ b/apps/docs/__tests__/CopyButtons_.test.res @@ -40,7 +40,7 @@ test( let button = await screen->getByText("Copy Share Link") await button->click await element(button)->toBeDisabled - expect(copied.contents)->toEqual(Some(window.location.href)) + expect(copied.contents)->toEqual(Some((WebAPI.DOM.window->WebAPI.Window.location).href)) complete.contents(Error(Clipboard.WriteFailed)) let retry = await screen->getByText("Copy failed, try again") await element(retry)->notToBeDisabled diff --git a/apps/docs/__tests__/DocsLayoutBehavior_.test.res b/apps/docs/__tests__/DocsLayoutBehavior_.test.res index c53becae3..08ac2b362 100644 --- a/apps/docs/__tests__/DocsLayoutBehavior_.test.res +++ b/apps/docs/__tests__/DocsLayoutBehavior_.test.res @@ -1,7 +1,7 @@ open ReactRouter open Vitest -@get external textContent: WebAPI.DOMAPI.element => string = "textContent" +@get external textContent: WebAPI.Element.t => string = "textContent" let mockCategories: array = [ { @@ -43,11 +43,11 @@ test("docs layout marks the textual content for DocSearch crawling", async () => let _mainContent = await screen->getByTestId("side-layout-children") - let mainContent = switch document->WebAPI.Document.querySelector( - "[data-testid='side-layout-children']", - ) { + let mainContent = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("[data-testid='side-layout-children']") { | Value(element) => element - | Null => failwith("expected docs layout main content") + | Null => panic("expected docs layout main content") } let className = switch mainContent->WebAPI.Element.getAttribute("class") { @@ -57,9 +57,11 @@ test("docs layout marks the textual content for DocSearch crawling", async () => expect(className->String.includes("DocSearch-content"))->toBe(true) - let lvl0 = switch document->WebAPI.Document.querySelector(".DocSearch-lvl0") { + let lvl0 = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector(".DocSearch-lvl0") { | Value(element) => element - | Null => failwith("expected docs layout to render a DocSearch lvl0 marker") + | Null => panic("expected docs layout to render a DocSearch lvl0 marker") } expect(lvl0->textContent)->toBe("Manual") diff --git a/apps/docs/__tests__/DocsOverviewBehavior_.test.res b/apps/docs/__tests__/DocsOverviewBehavior_.test.res index 19fbe58fe..9ab4a153c 100644 --- a/apps/docs/__tests__/DocsOverviewBehavior_.test.res +++ b/apps/docs/__tests__/DocsOverviewBehavior_.test.res @@ -12,24 +12,26 @@ test("docs overview uses unversioned docs links", async () => { , ) - let overviewLink = switch document->WebAPI.Document.querySelector( - "a[href='/docs/manual/introduction']", - ) { + let overviewLink = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("a[href='/docs/manual/introduction']") { | Value(link) => link - | Null => failwith("expected docs overview to link to the unversioned manual introduction") + | Null => panic("expected docs overview to link to the unversioned manual introduction") } await element(overviewLink)->toBeVisible - let genTypeLink = switch document->WebAPI.Document.querySelector( - "a[href='/docs/manual/typescript-integration']", - ) { + let genTypeLink = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("a[href='/docs/manual/typescript-integration']") { | Value(link) => link - | Null => failwith("expected docs overview to link to the unversioned GenType docs page") + | Null => panic("expected docs overview to link to the unversioned GenType docs page") } await element(genTypeLink)->toBeVisible - switch document->WebAPI.Document.querySelector("a[href*='/docs/manual/v']") { - | Value(_) => failwith("expected docs overview to avoid versioned manual links") + switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("a[href*='/docs/manual/v']") { + | Value(_) => panic("expected docs overview to avoid versioned manual links") | Null => () } }) diff --git a/apps/docs/__tests__/LandingPageBehavior_.test.res b/apps/docs/__tests__/LandingPageBehavior_.test.res index 1d7b5bb20..5b724165b 100644 --- a/apps/docs/__tests__/LandingPageBehavior_.test.res +++ b/apps/docs/__tests__/LandingPageBehavior_.test.res @@ -2,13 +2,15 @@ open ReactRouter open Vitest let getOpenGraphImageUrl = () => { - switch document->WebAPI.Document.querySelector("meta[property='og:image']") { + switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("meta[property='og:image']") { | Value(meta) => switch meta->WebAPI.Element.getAttribute("content") { | Value(content) => WebAPI.URL.make(~url=content) - | Null => failwith("expected Open Graph image metadata to have content") + | Null => panic("expected Open Graph image metadata to have content") } - | Null => failwith("expected Open Graph image metadata") + | Null => panic("expected Open Graph image metadata") } } @@ -22,10 +24,9 @@ test("landing page Open Graph image targets its absolute page URL", async () => let imageUrl = getOpenGraphImageUrl() let targetUrl = switch imageUrl.searchParams ->WebAPI.URLSearchParams.get("url") - ->Nullable.make - ->Nullable.toOption { + ->Null.toOption { | Some(targetUrl) => WebAPI.URL.make(~url=targetUrl) - | None => failwith("expected Open Graph image URL to include a page URL") + | None => panic("expected Open Graph image URL to include a page URL") } expect(imageUrl.origin)->toBe(pageUrl.origin) @@ -44,21 +45,22 @@ test( let _ = await screen->getByText("Edit this example in Playground") - let href = switch document->WebAPI.Document.querySelector("a[href*='/try?code=']") { + let href = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("a[href*='/try?code=']") { | Value(link) => switch link->WebAPI.Element.getAttribute("href") { | Value(href) => href - | Null => failwith("expected landing page playground link to have an href") + | Null => panic("expected landing page playground link to have an href") } - | Null => failwith("expected to find the landing page playground link") + | Null => panic("expected to find the landing page playground link") } let {pathname, searchParams} = WebAPI.URL.make(~url=href, ~base="https://rescript-lang.org") expect(pathname)->toBe("/try") - let compressedCode = - searchParams->WebAPI.URLSearchParams.get("code")->Nullable.make->Nullable.toOption + let compressedCode = searchParams->WebAPI.URLSearchParams.get("code")->Null.toOption let decodedCode = compressedCode @@ -81,18 +83,18 @@ test("landing page playground hero renders highlighted code tokens", async () => let _ = await screen->getByText("Write in ReScript") - let rescriptCodeBlock = switch document->WebAPI.Document.querySelector( - "[data-testid='landing-playground-hero'] code.lang-res", - ) { + let rescriptCodeBlock = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("[data-testid='landing-playground-hero'] code.lang-res") { | Value(codeBlock) => codeBlock - | Null => failwith("expected landing playground hero to render the ReScript code block") + | Null => panic("expected landing playground hero to render the ReScript code block") } - let javascriptCodeBlock = switch document->WebAPI.Document.querySelector( - "[data-testid='landing-playground-hero'] code.lang-js", - ) { + let javascriptCodeBlock = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("[data-testid='landing-playground-hero'] code.lang-js") { | Value(codeBlock) => codeBlock - | Null => failwith("expected landing playground hero to render the JavaScript code block") + | Null => panic("expected landing playground hero to render the JavaScript code block") } expect(rescriptCodeBlock.innerHTML->String.includes("toBe(true) @@ -159,11 +161,11 @@ test( , ) - let sourceSection = switch document->WebAPI.Document.querySelector( - "[data-testid='landing-playground-hero']", - ) { + let sourceSection = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("[data-testid='landing-playground-hero']") { | Value(section) => section - | Null => failwith("expected to find the landing playground hero section") + | Null => panic("expected to find the landing playground hero section") } let sandboxTestId = "landing-playground-hero-sandbox" @@ -180,29 +182,32 @@ test( let _ = await snapshotScreen->getByTestId(sandboxTestId) - let sandbox = switch document->WebAPI.Document.querySelector( - "[data-testid='landing-playground-hero-sandbox']", - ) { + let sandbox = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("[data-testid='landing-playground-hero-sandbox']") { | Value(sandbox) => sandbox - | Null => failwith("expected to find the sandboxed landing playground hero") + | Null => panic("expected to find the sandboxed landing playground hero") } - let sandboxRect: WebAPI.DOMAPI.domRect = sandbox->WebAPI.Element.getBoundingClientRect + let sandboxRect: WebAPI.DOM.domRect = sandbox->WebAPI.Element.getBoundingClientRect - let rescriptCodeBlock = switch document->WebAPI.Document.querySelector( + let rescriptCodeBlock = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector( "[data-testid='landing-playground-hero-sandbox'] code.lang-res", ) { | Value(codeBlock) => codeBlock - | Null => - failwith("expected sandboxed landing playground hero to render the ReScript code block") + | Null => panic("expected sandboxed landing playground hero to render the ReScript code block") } - let javascriptCodeBlock = switch document->WebAPI.Document.querySelector( + let javascriptCodeBlock = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector( "[data-testid='landing-playground-hero-sandbox'] code.lang-js", ) { | Value(codeBlock) => codeBlock | Null => - failwith("expected sandboxed landing playground hero to render the JavaScript code block") + panic("expected sandboxed landing playground hero to render the JavaScript code block") } expect(sandboxRect.width > 1000.0)->toBe(true) diff --git a/apps/docs/__tests__/LandingPageInstallInstructions_.test.res b/apps/docs/__tests__/LandingPageInstallInstructions_.test.res index 586db9134..30bfe4e49 100644 --- a/apps/docs/__tests__/LandingPageInstallInstructions_.test.res +++ b/apps/docs/__tests__/LandingPageInstallInstructions_.test.res @@ -2,9 +2,11 @@ open Vitest test("install instructions update their class prop and keep copying available", async () => { let screen = await render() - let root = switch document->WebAPI.Document.querySelector(".initial-layout") { + let root = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector(".initial-layout") { | Value(root) => root - | Null => failwith("expected the install instructions root") + | Null => panic("expected the install instructions root") } await element(root)->toHaveAttribute("class", "w-full max-w-400 initial-layout") diff --git a/apps/docs/__tests__/LandingPagePlaygroundLoader_.test.res b/apps/docs/__tests__/LandingPagePlaygroundLoader_.test.res index b9c1389f8..5b6cfc2e1 100644 --- a/apps/docs/__tests__/LandingPagePlaygroundLoader_.test.res +++ b/apps/docs/__tests__/LandingPagePlaygroundLoader_.test.res @@ -21,7 +21,7 @@ test( ~url=data.playgroundHref, ~base="https://rescript-lang.org", ) - let code = searchParams->WebAPI.URLSearchParams.get("code") + let code = searchParams->WebAPI.URLSearchParams.get("code")->Null.getOrThrow expect(pathname)->toBe("/try") expect(LzString.lzString.decompressFromEncodedURIComponent(code))->toBe( diff --git a/apps/docs/__tests__/LandingPageVideo_.test.res b/apps/docs/__tests__/LandingPageVideo_.test.res index a71fa3fd6..851920755 100644 --- a/apps/docs/__tests__/LandingPageVideo_.test.res +++ b/apps/docs/__tests__/LandingPageVideo_.test.res @@ -1,7 +1,8 @@ open Vitest let attribute = (selector, name) => - document + WebAPI.DOM.window + ->WebAPI.Window.document ->WebAPI.Document.querySelector(selector) ->Null.toOption ->Option.flatMap(element => element->WebAPI.Element.getAttribute(name)->Null.toOption) diff --git a/apps/docs/__tests__/MarkdownComponentsBehavior_.test.res b/apps/docs/__tests__/MarkdownComponentsBehavior_.test.res index 9b7e1cc3c..f04615e78 100644 --- a/apps/docs/__tests__/MarkdownComponentsBehavior_.test.res +++ b/apps/docs/__tests__/MarkdownComponentsBehavior_.test.res @@ -9,9 +9,11 @@ test("h1 keeps the generated markdown id for DocSearch", async () => { , ) - switch document->WebAPI.Document.querySelector("h1#heading-level-1") { + switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("h1#heading-level-1") { | Value(_) => () - | Null => failwith("expected markdown h1 to keep the generated id") + | Null => panic("expected markdown h1 to keep the generated id") } }) @@ -28,25 +30,35 @@ test("markdown headings expose explicit DocSearch hierarchy markers", async () = , ) - switch document->WebAPI.Document.querySelector("h1.DocSearch-lvl1#heading-level-1") { + switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("h1.DocSearch-lvl1#heading-level-1") { | Value(_) => () - | Null => failwith("expected h1 to expose DocSearch lvl1") + | Null => panic("expected h1 to expose DocSearch lvl1") } - switch document->WebAPI.Document.querySelector("h2.DocSearch-lvl2#heading-level-2") { + switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("h2.DocSearch-lvl2#heading-level-2") { | Value(_) => () - | Null => failwith("expected h2 to expose DocSearch lvl2") + | Null => panic("expected h2 to expose DocSearch lvl2") } - switch document->WebAPI.Document.querySelector("h3.DocSearch-lvl3#heading-level-3") { + switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("h3.DocSearch-lvl3#heading-level-3") { | Value(_) => () - | Null => failwith("expected h3 to expose DocSearch lvl3") + | Null => panic("expected h3 to expose DocSearch lvl3") } - switch document->WebAPI.Document.querySelector("h4.DocSearch-lvl4#heading-level-4") { + switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("h4.DocSearch-lvl4#heading-level-4") { | Value(_) => () - | Null => failwith("expected h4 to expose DocSearch lvl4") + | Null => panic("expected h4 to expose DocSearch lvl4") } - switch document->WebAPI.Document.querySelector("h5.DocSearch-lvl5#heading-level-5") { + switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("h5.DocSearch-lvl5#heading-level-5") { | Value(_) => () - | Null => failwith("expected h5 to expose DocSearch lvl5") + | Null => panic("expected h5 to expose DocSearch lvl5") } }) @@ -59,7 +71,10 @@ test("heading anchor links do not duplicate heading ids", async () => { , ) - let matches = document->WebAPI.Document.querySelectorAll("[id='duplicate-check']") + let matches = + WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelectorAll("[id='duplicate-check']") expect(matches.length)->toBe(1) }) @@ -77,22 +92,24 @@ test("heading anchor scroll offset clears the sticky docs nav", async () => { , ) - let target = switch document->WebAPI.Document.querySelector("#anchor-offset-target") { + let target = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("#anchor-offset-target") { | Value(target) => target - | Null => failwith("expected heading anchor target") + | Null => panic("expected heading anchor target") } - let tertiaryNav = switch document->WebAPI.Document.querySelector( - "[data-testid='anchor-tertiary']", - ) { + let tertiaryNav = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("[data-testid='anchor-tertiary']") { | Value(nav) => nav - | Null => failwith("expected tertiary nav") + | Null => panic("expected tertiary nav") } - target->WebAPI.Element.scrollIntoView_alignToTop + target->WebAPI.Element.scrollIntoViewAlignToTop - let targetRect: WebAPI.DOMAPI.domRect = target->WebAPI.Element.getBoundingClientRect - let tertiaryNavRect: WebAPI.DOMAPI.domRect = tertiaryNav->WebAPI.Element.getBoundingClientRect + let targetRect: WebAPI.DOM.domRect = target->WebAPI.Element.getBoundingClientRect + let tertiaryNavRect: WebAPI.DOM.domRect = tertiaryNav->WebAPI.Element.getBoundingClientRect expect(targetRect.top >= tertiaryNavRect.bottom)->toBe(true) await screen->unmount diff --git a/apps/docs/__tests__/Meta_.test.res b/apps/docs/__tests__/Meta_.test.res index d439517ab..a77eaad43 100644 --- a/apps/docs/__tests__/Meta_.test.res +++ b/apps/docs/__tests__/Meta_.test.res @@ -7,31 +7,37 @@ test("advertises the blog RSS feed in page metadata", async () => { , ) let feed = - document->WebAPI.Document.querySelector("link[rel='alternate'][type='application/rss+xml']") + WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("link[rel='alternate'][type='application/rss+xml']") expect(feed->Null.toOption->Option.map(WebAPI.Element.getAttribute(_, "href")))->toBe( Some(Null.make("/blog/feed.xml")), ) }) let getMetaContent = name => { - switch document->WebAPI.Document.querySelector(`meta[name='${name}']`) { + switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector(`meta[name='${name}']`) { | Value(element) => switch element->WebAPI.Element.getAttribute("content") { | Value(content) => content - | Null => failwith(`expected ${name} meta tag to have content`) + | Null => panic(`expected ${name} meta tag to have content`) } - | Null => failwith(`expected ${name} meta tag`) + | Null => panic(`expected ${name} meta tag`) } } let getMetaPropertyContent = property => { - switch document->WebAPI.Document.querySelector(`meta[property='${property}']`) { + switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector(`meta[property='${property}']`) { | Value(element) => switch element->WebAPI.Element.getAttribute("content") { | Value(content) => content - | Null => failwith(`expected ${property} meta tag to have content`) + | Null => panic(`expected ${property} meta tag to have content`) } - | Null => failwith(`expected ${property} meta tag`) + | Null => panic(`expected ${property} meta tag`) } } @@ -64,6 +70,9 @@ test("generates Open Graph image URLs from the current page URL", async () => { `${rootUrl}ogimage/index.png?url=${encodeURIComponent(pageUrl)}`, ) expect(getMetaContent("twitter:image"))->toBe(getMetaPropertyContent("og:image")) - let images = document->WebAPI.Document.querySelectorAll("meta[property='og:image']") + let images = + WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelectorAll("meta[property='og:image']") expect(images.length)->toBe(1) }) diff --git a/apps/docs/__tests__/NotFound_.test.res b/apps/docs/__tests__/NotFound_.test.res index aa454fdbb..8881c4a5e 100644 --- a/apps/docs/__tests__/NotFound_.test.res +++ b/apps/docs/__tests__/NotFound_.test.res @@ -4,7 +4,7 @@ module Location = { @react.component let make = () => { let {pathname} = ReactRouter.useLocation() - {React.string((pathname :> string))} + {React.string(pathname :> string)} } } diff --git a/apps/docs/__tests__/ResponsiveImage_.test.res b/apps/docs/__tests__/ResponsiveImage_.test.res index 94f46c6d6..476a8ef0c 100644 --- a/apps/docs/__tests__/ResponsiveImage_.test.res +++ b/apps/docs/__tests__/ResponsiveImage_.test.res @@ -20,13 +20,15 @@ let original: ImageAsset.t = { // Source elements have no accessible role; inspect their native media-selection attributes. let sourceAttribute = name => - document + WebAPI.DOM.window + ->WebAPI.Window.document ->WebAPI.Document.querySelector("picture source") ->Null.toOption ->Option.flatMap(source => source->WebAPI.Element.getAttribute(name)->Null.toOption) let imageAttribute = name => - document + WebAPI.DOM.window + ->WebAPI.Window.document ->WebAPI.Document.querySelector("img") ->Null.toOption ->Option.flatMap(image => image->WebAPI.Element.getAttribute(name)->Null.toOption) @@ -41,7 +43,12 @@ test("original images retain a plain image with dimensions and loading attribute await element(image)->toHaveAttribute("height", "667") await element(image)->toHaveAttribute("loading", "lazy") await element(image)->toHaveAttribute("decoding", "async") - expect(document->WebAPI.Document.querySelector("picture")->Null.toOption)->toEqual(None) + expect( + WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("picture") + ->Null.toOption, + )->toEqual(None) expect(imageAttribute("srcset"))->toEqual(None) }) @@ -73,7 +80,12 @@ test("responsive images render one AVIF source and a sized WebP image fallback", "/lp/community-3.avif?width=360&format=avif 360w, /lp/community-3.avif?width=640&format=avif 640w, /lp/community-3.avif?width=1000&format=avif 1000w", ), ) - expect(document->WebAPI.Document.querySelector("source ~ source")->Null.toOption)->toEqual(None) + expect( + WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("source ~ source") + ->Null.toOption, + )->toEqual(None) }) test( @@ -89,7 +101,12 @@ test( await element(image)->toHaveAttribute("src", "/lp/community-3.avif") expect(imageAttribute("srcset"))->toEqual(None) expect(sourceAttribute("srcset"))->toEqual(None) - expect(document->WebAPI.Document.querySelector("picture")->Null.toOption)->toEqual(None) + expect( + WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("picture") + ->Null.toOption, + )->toEqual(None) }, ) diff --git a/apps/docs/__tests__/Search_.test.res b/apps/docs/__tests__/Search_.test.res index 503e4de4c..658be0792 100644 --- a/apps/docs/__tests__/Search_.test.res +++ b/apps/docs/__tests__/Search_.test.res @@ -57,14 +57,14 @@ let withHierarchy = ( module ThrowsOnRender = { @react.component - let make = (): React.element => failwith("search render exploded") + let make = (): React.element => panic("search render exploded") } module CurrentPath = { @react.component let make = () => { let location = ReactRouter.useLocation() - {React.string((location.pathname :> string))} + {React.string(location.pathname :> string)} } } @@ -550,7 +550,7 @@ test("active DocSearch enables Algolia Insights", async () => { ) let hasInsightsScript = switch WebAPI.Document.querySelector( - document, + WebAPI.DOM.window->WebAPI.Window.document, "script[src*='search-insights']", ) { | Value(_) => true diff --git a/apps/docs/__tests__/SyntaxLookupBehavior_.test.res b/apps/docs/__tests__/SyntaxLookupBehavior_.test.res index 06b8473ad..4b77b6319 100644 --- a/apps/docs/__tests__/SyntaxLookupBehavior_.test.res +++ b/apps/docs/__tests__/SyntaxLookupBehavior_.test.res @@ -1,7 +1,7 @@ open ReactRouter open Vitest -@get external textContent: WebAPI.DOMAPI.element => string = "textContent" +@get external textContent: WebAPI.Element.t => string = "textContent" let mockItems: array = [ { @@ -53,14 +53,18 @@ test("syntax lookup detail marks active content for DocSearch crawling", async ( , ) - switch document->WebAPI.Document.querySelector(".DocSearch-content h1") { + switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector(".DocSearch-content h1") { | Value(heading) => expect(heading->textContent)->toBe("@as") - | Null => failwith("expected active syntax detail to provide a DocSearch heading") + | Null => panic("expected active syntax detail to provide a DocSearch heading") } - let lvl0 = switch document->WebAPI.Document.querySelector(".DocSearch-content .DocSearch-lvl0") { + let lvl0 = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector(".DocSearch-content .DocSearch-lvl0") { | Value(element) => element - | Null => failwith("expected syntax detail to render a DocSearch lvl0 marker") + | Null => panic("expected syntax detail to render a DocSearch lvl0 marker") } expect(lvl0->textContent)->toBe("Syntax Lookup") diff --git a/apps/docs/__tests__/visual/LandingPage_.test.res b/apps/docs/__tests__/visual/LandingPage_.test.res index cbab54d93..317e0def2 100644 --- a/apps/docs/__tests__/visual/LandingPage_.test.res +++ b/apps/docs/__tests__/visual/LandingPage_.test.res @@ -10,11 +10,11 @@ let snapshotSection = async (~width, ~height, ~sectionTestId, ~screenshotName) = , ) - let sourceSection = switch document->WebAPI.Document.querySelector( - `[data-testid="${sectionTestId}"]`, - ) { + let sourceSection = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector(`[data-testid="${sectionTestId}"]`) { | Value(section) => section - | Null => failwith(`expected to find section ${sectionTestId}`) + | Null => panic(`expected to find section ${sectionTestId}`) } if sectionTestId == "landing-other-selling-points" { diff --git a/apps/docs/__tests__/visual/MarkdownComponents_.test.res b/apps/docs/__tests__/visual/MarkdownComponents_.test.res index 63140ba67..81ba17c11 100644 --- a/apps/docs/__tests__/visual/MarkdownComponents_.test.res +++ b/apps/docs/__tests__/visual/MarkdownComponents_.test.res @@ -257,9 +257,11 @@ test("renders inline code", async () => { await element(code)->toHaveClass("md-inline-code") await element(code)->toHaveClass("font-mono") - switch document->WebAPI.Document.querySelector("[data-testid='inline-code-wrapper'] p > code") { + switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("[data-testid='inline-code-wrapper'] p > code") { | Value(_) => () - | Null => failwith("expected Markdown.Code to render inline code inside the paragraph") + | Null => panic("expected Markdown.Code to render inline code inside the paragraph") } let wrapper = await screen->getByTestId("inline-code-wrapper") diff --git a/apps/docs/__tests__/visual/SyntaxLookup_.test.res b/apps/docs/__tests__/visual/SyntaxLookup_.test.res index 734382feb..bc6b24645 100644 --- a/apps/docs/__tests__/visual/SyntaxLookup_.test.res +++ b/apps/docs/__tests__/visual/SyntaxLookup_.test.res @@ -67,16 +67,17 @@ test("desktop syntax lookup renders categories and styles deprecated tags", asyn await element(deprecatedTag)->toBeVisible await element(deprecatedTag)->toHaveClass("line-through") - let deprecatedLink = switch document->WebAPI.Document.querySelector( - "a[href='/syntax-lookup/operators_deprecated_pipe']", - ) { + let deprecatedLink = switch WebAPI.DOM.window + ->WebAPI.Window.document + ->WebAPI.Document.querySelector("a[href='/syntax-lookup/operators_deprecated_pipe']") { | Value(link) => link - | Null => failwith("expected a link for the deprecated pipe operator") + | Null => panic("expected a link for the deprecated pipe operator") } expect( - getComputedStyle(~elt=deprecatedLink)->WebAPI.CSSStyleDeclaration.getPropertyValue( - "text-decoration-line", - ), + WebAPI.Window.getComputedStyle( + WebAPI.DOM.window, + ~elt=deprecatedLink, + )->WebAPI.CSSStyleDeclaration.getPropertyValue("text-decoration-line"), )->toBe("line-through") let wrapper = await screen->getByTestId("syntax-lookup-wrapper") diff --git a/apps/docs/app/layouts/DocsLayoutRoute.res b/apps/docs/app/layouts/DocsLayoutRoute.res index fb19c2034..9d02839de 100644 --- a/apps/docs/app/layouts/DocsLayoutRoute.res +++ b/apps/docs/app/layouts/DocsLayoutRoute.res @@ -6,7 +6,7 @@ let default = () => { // This layout persists across docs route changes. Key the secondary nav by // pathname so its scroll-direction state cannot keep the mobile nav hidden // after client-side navigation. - string)} /> + string} /> } diff --git a/apps/docs/app/routes/ApiDocs.res b/apps/docs/app/routes/ApiDocs.res index 0b4ea59f3..7fae415b0 100644 --- a/apps/docs/app/routes/ApiDocs.res +++ b/apps/docs/app/routes/ApiDocs.res @@ -154,7 +154,7 @@ module SidebarTree = { {node.name->React.string} - tocModule + {tocModule} {if hasChildren {