Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/visual-reporter/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,6 @@ yarn-error.log*

# typescript
*.tsbuildinfo

# React Router
/.react-router
2 changes: 1 addition & 1 deletion packages/visual-reporter/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,4 @@ You can find a workflow [here](../../.github/workflows/deploy-visual-reporter.ym
https://github.com/user-attachments/assets/9cdfec36-e1ff-4b48-a842-23f3f7d5768e

> [!NOTE]
> Created with a [Remix](https://remix.run/) project .
> Created with [React Router](https://reactrouter.com/) (framework mode, as a static single-page app).
10 changes: 5 additions & 5 deletions packages/visual-reporter/app/entry.client.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
/**
* By default, Remix will handle hydrating your app on the client for you.
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
* For more information, see https://remix.run/file-conventions/entry.client
* By default, React Router will handle hydrating your app on the client for you.
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx react-router reveal` ✨
* For more information, see https://reactrouter.com/explanation/special-files#entryclienttsx
*/

import { RemixBrowser } from '@remix-run/react'
import { HydratedRouter } from 'react-router/dom'
import { startTransition, StrictMode } from 'react'
import { hydrateRoot } from 'react-dom/client'

startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<RemixBrowser />
<HydratedRouter />
</StrictMode>
)
})
39 changes: 19 additions & 20 deletions packages/visual-reporter/app/entry.server.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
/**
* By default, Remix will handle generating the HTTP Response for you.
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx remix reveal` ✨
* For more information, see https://remix.run/file-conventions/entry.server
* By default, React Router will handle generating the HTTP Response for you.
* You are free to delete this file if you'd like to, but if you ever want it revealed again, you can run `npx react-router reveal` ✨
* For more information, see https://reactrouter.com/explanation/special-files#entryservertsx
*/

import { PassThrough } from 'node:stream'

import type { AppLoadContext, EntryContext } from '@remix-run/node'
import { createReadableStreamFromReadable } from '@remix-run/node'
import { RemixServer } from '@remix-run/react'
import type { AppLoadContext, EntryContext } from 'react-router'
import { createReadableStreamFromReadable } from '@react-router/node'
import { ServerRouter } from 'react-router'
import { isbot } from 'isbot'
import { renderToPipeableStream } from 'react-dom/server'

const ABORT_DELAY = 5_000
// Rejects all pending promises after this time; the render is aborted 1 second later
export const streamTimeout = 5_000

export default function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext,
routerContext: EntryContext,
// This is ignored so we can keep it in the template for visibility. Feel
// free to delete this parameter in your app if you're not using it!
// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand All @@ -29,29 +30,28 @@ export default function handleRequest(
request,
responseStatusCode,
responseHeaders,
remixContext
routerContext
)
: handleBrowserRequest(
request,
responseStatusCode,
responseHeaders,
remixContext
routerContext
)
}

function handleBotRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext
routerContext: EntryContext
) {
return new Promise((resolve, reject) => {
let shellRendered = false
const { pipe, abort } = renderToPipeableStream(
<RemixServer
context={remixContext}
<ServerRouter
context={routerContext}
url={request.url}
abortDelay={ABORT_DELAY}
/>,
{
onAllReady() {
Expand Down Expand Up @@ -85,23 +85,22 @@ function handleBotRequest(
}
)

setTimeout(abort, ABORT_DELAY)
setTimeout(abort, streamTimeout + 1000)
})
}

function handleBrowserRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext
routerContext: EntryContext
) {
return new Promise((resolve, reject) => {
let shellRendered = false
const { pipe, abort } = renderToPipeableStream(
<RemixServer
context={remixContext}
<ServerRouter
context={routerContext}
url={request.url}
abortDelay={ABORT_DELAY}
/>,
{
onShellReady() {
Expand Down Expand Up @@ -135,6 +134,6 @@ function handleBrowserRequest(
}
)

setTimeout(abort, ABORT_DELAY)
setTimeout(abort, streamTimeout + 1000)
})
}
4 changes: 2 additions & 2 deletions packages/visual-reporter/app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import {
Outlet,
Scripts,
ScrollRestoration,
} from '@remix-run/react'
import type { LinksFunction } from '@remix-run/node'
} from 'react-router'
import type { LinksFunction } from 'react-router'
import globalStylesHref from '~/styles/globals.css?url'

export const links: LinksFunction = () => [
Expand Down
3 changes: 3 additions & 0 deletions packages/visual-reporter/app/routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { type RouteConfig, index } from '@react-router/dev/routes'

export default [index('routes/_index.tsx')] satisfies RouteConfig
2 changes: 1 addition & 1 deletion packages/visual-reporter/app/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export interface CanvasTransform {

export interface CanvasDrawingProps {
imageRef: React.RefObject<HTMLImageElement>
canvasRef: React.RefObject<HTMLCanvasElement>
canvasRef: React.RefObject<HTMLCanvasElement | null>
transform: CanvasTransform
diffBoxes: BoundingBox[]
highlightedBox: BoundingBox | null
Expand Down
26 changes: 12 additions & 14 deletions packages/visual-reporter/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
},
"scripts": {
"build": "run-s clean build:*",
"build:report": "remix vite:build",
"build:report": "react-router build",
"build:scripts": "tsc -p tsconfig.scripts.json",
"clean": "rimraf coverage build --glob *.tsbuildinfo",
"dev": "cross-env VISUAL_REPORT_LOCAL_DEV=true run-s build:scripts script:prepare.report && run-p watch:scripts dev:remix",
"dev:remix": "remix vite:dev",
"dev": "cross-env VISUAL_REPORT_LOCAL_DEV=true run-s build:scripts script:prepare.report && run-p watch:scripts dev:app",
"dev:app": "react-router dev",
"script:prepare.report": "node ./dist/prepareReportAssets.js",
"test:lint": "oxlint -c ../../.oxlintrc.json .",
"start": "remix-serve ./build/server/index.js",
"start": "sirv build/client --single",
"typecheck": "tsc",
"watch": "run-s clean watch:*",
"watch:dev": "npm run dev",
Expand All @@ -35,23 +35,21 @@
"sirv-cli": "^3.0.1"
},
"devDependencies": {
"@remix-run/dev": "^2.17.5",
"@remix-run/node": "^2.17.5",
"@remix-run/react": "^2.17.5",
"@remix-run/serve": "^2.17.5",
"@types/react": "^18.3.31",
"@types/react-dom": "^18.3.7",
"@react-router/dev": "^7.18.4",
"@react-router/node": "^7.18.4",
"@types/react": "^19.3.0",
"@types/react-dom": "^19.3.0",
"autoprefixer": "^10.6.1",
"isbot": "^5.2.2",
"postcss": "^8.5.28",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react": "^19.3.0",
"react-dom": "^19.3.0",
"react-icons": "^5.7.0",
"react-router": "^7.18.4",
"react-select": "^5.10.2",
"tailwindcss": "^4.3.3",
"typescript": "^6.0.3",
"vite": "^5.4.21",
"vite-tsconfig-paths": "^5.1.4"
"vite": "^8.3.3"
},
"engines": {
"node": ">=22.19.0"
Expand Down
9 changes: 9 additions & 0 deletions packages/visual-reporter/react-router.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { Config } from '@react-router/dev/config'

const baseName = process.env.GITHUB_PAGES || ''

export default {
// The report is a static single-page app: the CLI copies build/client and serves it
ssr: false,
...(baseName && { basename: baseName }),
} satisfies Config
2 changes: 1 addition & 1 deletion packages/visual-reporter/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
],
"compilerOptions": {
"lib": ["DOM", "DOM.Iterable", "ES2022"],
"types": ["@remix-run/node", "vite/client"],
"types": ["@react-router/node", "vite/client"],
"isolatedModules": true,
"esModuleInterop": true,
"jsx": "react-jsx",
Expand Down
18 changes: 6 additions & 12 deletions packages/visual-reporter/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
import { vitePlugin as remix } from '@remix-run/dev'
import { reactRouter } from '@react-router/dev/vite'
import { defineConfig } from 'vite'
import tsconfigPaths from 'vite-tsconfig-paths'

const baseName = process.env.GITHUB_PAGES || ''

export default defineConfig({
plugins: [
remix({
...(baseName && { basename: baseName }),
future: {
v3_fetcherPersist: true,
v3_relativeSplatPath: true,
v3_throwAbortReason: true,
},
ssr: false,
}),
tsconfigPaths(),
reactRouter(),
],
resolve: {
// The "~/*" paths of tsconfig.json
tsconfigPaths: true,
},
...(baseName && { base: baseName }),
css: {
modules: {
Expand Down
Loading
Loading