From 649baa07bc6959c03fa82f274ae11a377c87d88d Mon Sep 17 00:00:00 2001 From: sebastien Date: Fri, 19 Jun 2026 20:15:35 +0200 Subject: [PATCH] Upgrade React Router POC (AI-assisted) --- package.json | 4 +- .../package.json | 5 +- .../src/index.d.ts | 46 ++- .../package.json | 1 - .../src/plugin-content-docs.d.ts | 20 +- .../docusaurus-theme-classic/package.json | 5 +- packages/docusaurus-theme-common/package.json | 7 +- .../src/utils/historyUtils.ts | 10 +- .../src/utils/routesUtils.ts | 2 +- packages/docusaurus-types/package.json | 2 +- packages/docusaurus/package.json | 12 +- .../src/client/ClientLifecyclesDispatcher.tsx | 4 +- .../src/client/PendingNavigation.tsx | 5 +- .../docusaurus/src/client/clientEntry.tsx | 36 +- packages/docusaurus/src/client/docusaurus.ts | 4 +- .../docusaurus/src/client/exports/Link.tsx | 42 ++- .../src/client/exports/renderRoutes.ts | 2 +- .../docusaurus/src/client/exports/router.ts | 14 +- .../src/client/exports/routerCompat.tsx | 138 +++++++ .../docusaurus/src/client/historyContext.tsx | 29 ++ .../src/client/normalizeLocation.ts | 4 +- packages/docusaurus/src/client/preload.ts | 4 +- .../docusaurus/src/client/serverEntry.tsx | 18 +- packages/docusaurus/src/server/brokenLinks.ts | 16 +- pnpm-lock.yaml | 348 +++++++----------- website/package.json | 4 +- 26 files changed, 491 insertions(+), 291 deletions(-) create mode 100644 packages/docusaurus/src/client/exports/routerCompat.tsx create mode 100644 packages/docusaurus/src/client/historyContext.tsx diff --git a/package.json b/package.json index 161358806731..cadc6da9afa1 100644 --- a/package.json +++ b/package.json @@ -113,8 +113,8 @@ "npm-run-all": "^4.1.5", "oxfmt": "^0.47.0", "pkg-pr-new": "^0.0.68", - "react": "^19.2.5", - "react-dom": "^19.2.5", + "react": "^19.2.7", + "react-dom": "^19.2.7", "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", "rimraf": "^3.0.2", "sharp": "^0.35.1", diff --git a/packages/docusaurus-module-type-aliases/package.json b/packages/docusaurus-module-type-aliases/package.json index 0949776dde5b..139e377494b3 100644 --- a/packages/docusaurus-module-type-aliases/package.json +++ b/packages/docusaurus-module-type-aliases/package.json @@ -13,10 +13,9 @@ }, "dependencies": { "@docusaurus/types": "3.10.1", - "@types/history": "^4.7.11", "@types/react": "19.2.14", - "@types/react-router-config": "*", - "@types/react-router-dom": "*", + "history": "^5.3.0", + "react-router": "^8.0.1", "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", "react-loadable": "npm:@docusaurus/react-loadable@6.0.0" }, diff --git a/packages/docusaurus-module-type-aliases/src/index.d.ts b/packages/docusaurus-module-type-aliases/src/index.d.ts index 4ab1e21a54e4..76d8495d0b51 100644 --- a/packages/docusaurus-module-type-aliases/src/index.d.ts +++ b/packages/docusaurus-module-type-aliases/src/index.d.ts @@ -41,10 +41,10 @@ declare module '@generated/registry' { } declare module '@generated/routes' { - import type {RouteConfig as RRRouteConfig} from 'react-router-config'; + import type {RouteConfig as DocusaurusRouteConfig} from '@docusaurus/types'; import type Loadable from 'react-loadable'; - type RouteConfig = RRRouteConfig & { + type RouteConfig = DocusaurusRouteConfig & { path: string; component: ReturnType; }; @@ -169,7 +169,7 @@ declare module '@docusaurus/Head' { declare module '@docusaurus/Link' { import type {CSSProperties, ComponentProps, ReactNode} from 'react'; - import type {NavLinkProps as RRNavLinkProps} from 'react-router-dom'; + import type {NavLinkProps as RRNavLinkProps} from 'react-router'; type NavLinkProps = Partial; export type Props = NavLinkProps & @@ -260,7 +260,40 @@ declare module '@docusaurus/Translate' { } declare module '@docusaurus/router' { - export {useHistory, useLocation, Redirect, matchPath} from 'react-router-dom'; + import type {ReactNode} from 'react'; + import type {History, Location} from 'history'; + + export { + useLocation, + useNavigate, + useNavigationType, + Link, + NavLink, + BrowserRouter, + HashRouter, + unstable_HistoryRouter as HistoryRouter, + StaticRouter, + } from 'react-router'; + + export function useHistory(): History; + export function Redirect(props: { + push?: boolean; + to: string | Partial; + }): ReactNode; + export function matchPath( + pathname: string, + options: { + path: string; + exact?: boolean; + strict?: boolean; + sensitive?: boolean; + }, + ): { + path: string; + url: string; + isExact: boolean; + params: Record; + } | null; } declare module '@docusaurus/useIsomorphicLayoutEffect' { @@ -351,9 +384,10 @@ declare module '@docusaurus/Noop' { } declare module '@docusaurus/renderRoutes' { - import {renderRoutes} from 'react-router-config'; + import type {ReactNode} from 'react'; + import type {RouteConfig} from '@generated/routes'; - export default renderRoutes; + export default function renderRoutes(routes: RouteConfig[]): ReactNode; } declare module '@docusaurus/useGlobalData' { diff --git a/packages/docusaurus-plugin-content-docs/package.json b/packages/docusaurus-plugin-content-docs/package.json index 45f84b567cbc..7e3e19b08dc6 100644 --- a/packages/docusaurus-plugin-content-docs/package.json +++ b/packages/docusaurus-plugin-content-docs/package.json @@ -44,7 +44,6 @@ "@docusaurus/utils": "3.10.1", "@docusaurus/utils-common": "3.10.1", "@docusaurus/utils-validation": "3.10.1", - "@types/react-router-config": "^5.0.7", "combine-promises": "^1.1.0", "fs-extra": "^11.2.0", "js-yaml": "^4.1.0", diff --git a/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts b/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts index f89b3f63169e..d83a18ed18db 100644 --- a/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts +++ b/packages/docusaurus-plugin-content-docs/src/plugin-content-docs.d.ts @@ -635,10 +635,11 @@ declare module '@theme/DocBreadcrumbs' { declare module '@theme/DocsRoot' { import type {ReactNode} from 'react'; - import type {RouteConfigComponentProps} from 'react-router-config'; - import type {Required} from 'utility-types'; + import type {RouteConfig} from '@docusaurus/types'; - export interface Props extends Required {} + export interface Props { + readonly route: RouteConfig; + } export default function DocsRoot(props: Props): ReactNode; } @@ -646,10 +647,10 @@ declare module '@theme/DocsRoot' { declare module '@theme/DocVersionRoot' { import type {ReactNode} from 'react'; import type {PropVersionMetadata} from '@docusaurus/plugin-content-docs'; - import type {RouteConfigComponentProps} from 'react-router-config'; - import type {Required} from 'utility-types'; + import type {RouteConfig} from '@docusaurus/types'; - export interface Props extends Required { + export interface Props { + readonly route: RouteConfig; readonly version: PropVersionMetadata; } @@ -658,10 +659,11 @@ declare module '@theme/DocVersionRoot' { declare module '@theme/DocRoot' { import type {ReactNode} from 'react'; - import type {RouteConfigComponentProps} from 'react-router-config'; - import type {Required} from 'utility-types'; + import type {RouteConfig} from '@docusaurus/types'; - export interface Props extends Required {} + export interface Props { + readonly route: RouteConfig; + } export default function DocRoot(props: Props): ReactNode; } diff --git a/packages/docusaurus-theme-classic/package.json b/packages/docusaurus-theme-classic/package.json index b55b06573f33..43db018dd233 100644 --- a/packages/docusaurus-theme-classic/package.json +++ b/packages/docusaurus-theme-classic/package.json @@ -42,7 +42,6 @@ "postcss": "^8.5.12", "prism-react-renderer": "^2.4.1", "prismjs": "^1.29.0", - "react-router-dom": "^5.3.4", "rtlcss": "^4.1.0", "tslib": "^2.6.0", "utility-types": "^3.10.0" @@ -54,8 +53,8 @@ "fs-extra": "^11.2.0" }, "peerDependencies": { - "react": "^19.2.5", - "react-dom": "^19.2.5" + "react": "^19.2.7", + "react-dom": "^19.2.7" }, "engines": { "node": ">=24.14" diff --git a/packages/docusaurus-theme-common/package.json b/packages/docusaurus-theme-common/package.json index cde98294dc37..5bd6f48613eb 100644 --- a/packages/docusaurus-theme-common/package.json +++ b/packages/docusaurus-theme-common/package.json @@ -34,9 +34,8 @@ "@docusaurus/module-type-aliases": "3.10.1", "@docusaurus/utils": "3.10.1", "@docusaurus/utils-common": "3.10.1", - "@types/history": "^4.7.11", "@types/react": "19.2.14", - "@types/react-router-config": "*", + "history": "^5.3.0", "clsx": "^2.0.0", "parse-numeric-range": "^1.3.0", "prism-react-renderer": "^2.4.1", @@ -51,8 +50,8 @@ "lodash": "^4.17.21" }, "peerDependencies": { - "react": "^19.2.0", - "react-dom": "^19.2.0" + "react": "^19.2.7", + "react-dom": "^19.2.7" }, "engines": { "node": ">=24.14" diff --git a/packages/docusaurus-theme-common/src/utils/historyUtils.ts b/packages/docusaurus-theme-common/src/utils/historyUtils.ts index 45f9cc22dd01..2c2dc2513f79 100644 --- a/packages/docusaurus-theme-common/src/utils/historyUtils.ts +++ b/packages/docusaurus-theme-common/src/utils/historyUtils.ts @@ -23,7 +23,13 @@ function useHistoryActionHandler(handler: HistoryBlockHandler): void { const stableHandler = useEvent(handler); useEffect( // See https://github.com/remix-run/history/blob/main/docs/blocking-transitions.md - () => history.block((location, action) => stableHandler(location, action)), + () => + history.block((transition) => { + const result = stableHandler(transition.location, transition.action); + if (result !== false) { + transition.retry(); + } + }), [history, stableHandler], ); } @@ -51,7 +57,7 @@ export function useHistoryPopHandler(handler: HistoryBlockHandler): void { * @param selector */ export function useHistorySelector( - selector: (history: History) => Value, + selector: (history: History) => Value, ): Value { const history = useHistory(); return useSyncExternalStore( diff --git a/packages/docusaurus-theme-common/src/utils/routesUtils.ts b/packages/docusaurus-theme-common/src/utils/routesUtils.ts index b662ab4bf23d..61052a5e9162 100644 --- a/packages/docusaurus-theme-common/src/utils/routesUtils.ts +++ b/packages/docusaurus-theme-common/src/utils/routesUtils.ts @@ -8,7 +8,7 @@ import {useMemo} from 'react'; import generatedRoutes from '@generated/routes'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; -import type {RouteConfig} from 'react-router-config'; +import type {RouteConfig} from '@docusaurus/types'; /** * Compare the 2 paths, case insensitive and ignoring trailing slash diff --git a/packages/docusaurus-types/package.json b/packages/docusaurus-types/package.json index cbb4a252ae99..7e6dc29d1ca0 100644 --- a/packages/docusaurus-types/package.json +++ b/packages/docusaurus-types/package.json @@ -14,7 +14,7 @@ "license": "MIT", "dependencies": { "@mdx-js/mdx": "^3.1.1", - "@types/history": "^4.7.11", + "history": "^5.3.0", "@types/mdast": "^4.0.2", "@types/react": "19.2.14", "commander": "^5.1.0", diff --git a/packages/docusaurus/package.json b/packages/docusaurus/package.json index 13ff3da23ad0..c4c3d299d9b1 100644 --- a/packages/docusaurus/package.json +++ b/packages/docusaurus/package.json @@ -63,9 +63,8 @@ "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", "react-loadable-ssr-addon-v5-slorber": "^1.0.3", - "react-router": "^5.3.4", - "react-router-config": "^5.1.1", - "react-router-dom": "^5.3.4", + "history": "^5.3.0", + "react-router": "^8.0.1", "semver": "^7.7.4", "serve-handler": "^6.1.7", "tinypool": "^2.1.0", @@ -81,10 +80,7 @@ "@docusaurus/types": "3.10.1", "@total-typescript/shoehorn": "^0.1.2", "@types/escape-html": "^1.0.4", - "@types/history": "^4.7.11", "@types/react-dom": "^19.2.3", - "@types/react-router-dom": "^5.3.3", - "@types/react-router-config": "^5.0.7", "@types/serve-handler": "^6.1.4", "@types/update-notifier": "^6.0.4", "@types/webpack-bundle-analyzer": "^4.7.0", @@ -94,8 +90,8 @@ "peerDependencies": { "@docusaurus/faster": "*", "@mdx-js/react": "^3.1.1", - "react": "^19.2.5", - "react-dom": "^19.2.5" + "react": "^19.2.7", + "react-dom": "^19.2.7" }, "peerDependenciesMeta": { "@docusaurus/faster": { diff --git a/packages/docusaurus/src/client/ClientLifecyclesDispatcher.tsx b/packages/docusaurus/src/client/ClientLifecyclesDispatcher.tsx index a23445415aaa..62b5df1d1bce 100644 --- a/packages/docusaurus/src/client/ClientLifecyclesDispatcher.tsx +++ b/packages/docusaurus/src/client/ClientLifecyclesDispatcher.tsx @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import type {ReactElement, ReactNode} from 'react'; +import type {ReactNode} from 'react'; import clientModules from '@generated/client-modules'; import useIsomorphicLayoutEffect from './exports/useIsomorphicLayoutEffect'; import type {ClientModule} from '@docusaurus/types'; @@ -63,7 +63,7 @@ function ClientLifecyclesDispatcher({ location, previousLocation, }: { - children: ReactElement; + children: ReactNode; location: Location; previousLocation: Location | null; }): ReactNode { diff --git a/packages/docusaurus/src/client/PendingNavigation.tsx b/packages/docusaurus/src/client/PendingNavigation.tsx index 80855c16fed4..241ab6d4e156 100644 --- a/packages/docusaurus/src/client/PendingNavigation.tsx +++ b/packages/docusaurus/src/client/PendingNavigation.tsx @@ -6,7 +6,6 @@ */ import React, {type ReactNode} from 'react'; -import {Route} from 'react-router-dom'; import ClientLifecyclesDispatcher, { dispatchLifecycleAction, } from './ClientLifecyclesDispatcher'; @@ -82,13 +81,11 @@ class PendingNavigation extends React.Component { override render(): ReactNode { const {children, location} = this.props; - // Use a controlled to trick all descendants into rendering the old - // location. return ( - children} /> + {children} ); } diff --git a/packages/docusaurus/src/client/clientEntry.tsx b/packages/docusaurus/src/client/clientEntry.tsx index db521bb39f50..01bc77d20ee7 100644 --- a/packages/docusaurus/src/client/clientEntry.tsx +++ b/packages/docusaurus/src/client/clientEntry.tsx @@ -8,18 +8,44 @@ import React, {startTransition, type ReactNode} from 'react'; import ReactDOM, {type ErrorInfo} from 'react-dom/client'; import {HelmetProvider} from 'react-helmet-async'; -import {BrowserRouter, HashRouter} from 'react-router-dom'; +import {parsePath} from 'react-router'; +import {unstable_HistoryRouter as HistoryRouter} from 'react-router'; +import {createBrowserHistory, createHashHistory} from 'history'; import siteConfig from '@generated/docusaurus.config'; import ExecutionEnvironment from './exports/ExecutionEnvironment'; import App from './App'; import preload from './preload'; import docusaurus from './docusaurus'; +import {HistoryProvider} from './historyContext'; +import type {History, To} from 'history'; + +type ReactRouterHistory = History & { + createURL: (to: To) => URL; + encodeLocation: (to: To) => Partial; +}; + +function addReactRouterHistoryMethods(history: History): ReactRouterHistory { + return Object.assign(history, { + createURL(to: To) { + return new URL(history.createHref(to), window.location.origin); + }, + encodeLocation(to: To) { + return typeof to === 'string' ? parsePath(to) : to; + }, + }); +} + +const history = addReactRouterHistoryMethods( + siteConfig.future.experimental_router === 'hash' + ? createHashHistory() + : createBrowserHistory(), +); function Router({children}: {children: ReactNode}): ReactNode { - return siteConfig.future.experimental_router === 'hash' ? ( - {children} - ) : ( - {children} + return ( + + {children} + ); } diff --git a/packages/docusaurus/src/client/docusaurus.ts b/packages/docusaurus/src/client/docusaurus.ts index 24dff371728b..e805b2ebba96 100644 --- a/packages/docusaurus/src/client/docusaurus.ts +++ b/packages/docusaurus/src/client/docusaurus.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {matchRoutes} from 'react-router-config'; +import {matchRoutes} from './exports/routerCompat'; import routesChunkNames from '@generated/routesChunkNames'; import routes from '@generated/routes'; import prefetchHelper from './prefetch'; @@ -55,7 +55,7 @@ const prefetch: Docusaurus['prefetch'] = ( fetched.add(routePath); // Find all webpack chunk names needed. - const matches = matchRoutes(routes, routePath); + const matches = matchRoutes(routes as never, routePath); const chunkNamesNeeded = matches.flatMap((match) => getChunkNamesToLoad(match.route.path), diff --git a/packages/docusaurus/src/client/exports/Link.tsx b/packages/docusaurus/src/client/exports/Link.tsx index 1fab775967ee..3335e6182f2d 100644 --- a/packages/docusaurus/src/client/exports/Link.tsx +++ b/packages/docusaurus/src/client/exports/Link.tsx @@ -9,10 +9,9 @@ import React, { useEffect, useImperativeHandle, useRef, - type ComponentType, type ReactNode, } from 'react'; -import {NavLink, Link as RRLink} from 'react-router-dom'; +import {NavLink, Link as RRLink, useLocation} from 'react-router'; import {applyTrailingSlash} from '@docusaurus/utils-common'; import useDocusaurusContext from './useDocusaurusContext'; import isInternalUrl from './isInternalUrl'; @@ -20,6 +19,12 @@ import ExecutionEnvironment from './ExecutionEnvironment'; import useBrokenLinks from './useBrokenLinks'; import {useBaseUrlUtils} from './useBaseUrl'; import type {Props} from '@docusaurus/Link'; +import type {Location} from 'history'; + +type LegacyNavLinkProps = { + activeClassName?: string; + isActive?: (match: unknown, location: Location) => boolean; +}; // TODO all this wouldn't be necessary if we used ReactRouter basename feature // We don't automatically add base urls to all links, @@ -37,13 +42,14 @@ function Link({ 'data-noBrokenLinkCheck': noBrokenLinkCheck, autoAddBaseUrl = true, ...props -}: Props): ReactNode { +}: Props & LegacyNavLinkProps): ReactNode { const {siteConfig} = useDocusaurusContext(); const {trailingSlash, baseUrl} = siteConfig; const router = siteConfig.future.experimental_router; const {withBaseUrl} = useBaseUrlUtils(); const brokenLinks = useBrokenLinks(); const innerRef = useRef(null); + const location = useLocation(); useImperativeHandle(props.ref, () => innerRef.current!); @@ -93,7 +99,6 @@ function Link({ } const preloaded = useRef(false); - const LinkComponent = (isNavLink ? NavLink : RRLink) as ComponentType; const IOSupported = ExecutionEnvironment.canUseIntersectionObserver; @@ -190,17 +195,34 @@ function Link({ {...testOnlyProps} /> ) : ( - + [ + props.className, + (isActive?.(null, location) ?? navLinkProps.isActive) && + activeClassName, + ] + .filter(Boolean) + .join(' ') + } + {...testOnlyProps} + /> + ) : ( + + ) ); } diff --git a/packages/docusaurus/src/client/exports/renderRoutes.ts b/packages/docusaurus/src/client/exports/renderRoutes.ts index 144ae6efd204..a211b2c74e8b 100644 --- a/packages/docusaurus/src/client/exports/renderRoutes.ts +++ b/packages/docusaurus/src/client/exports/renderRoutes.ts @@ -5,4 +5,4 @@ * LICENSE file in the root directory of this source tree. */ -export {renderRoutes as default} from 'react-router-config'; +export {renderRoutes as default} from './routerCompat'; diff --git a/packages/docusaurus/src/client/exports/router.ts b/packages/docusaurus/src/client/exports/router.ts index 453530b353dd..f8b9a0a2c0ca 100644 --- a/packages/docusaurus/src/client/exports/router.ts +++ b/packages/docusaurus/src/client/exports/router.ts @@ -5,4 +5,16 @@ * LICENSE file in the root directory of this source tree. */ -export {useHistory, useLocation, Redirect, matchPath} from 'react-router-dom'; +export { + useLocation, + useNavigate, + useNavigationType, + Link, + NavLink, + BrowserRouter, + HashRouter, + unstable_HistoryRouter as HistoryRouter, + StaticRouter, +} from 'react-router'; +export {useHistory} from '../historyContext'; +export {Redirect, matchPath} from './routerCompat'; diff --git a/packages/docusaurus/src/client/exports/routerCompat.tsx b/packages/docusaurus/src/client/exports/routerCompat.tsx new file mode 100644 index 000000000000..57a7c2715ea0 --- /dev/null +++ b/packages/docusaurus/src/client/exports/routerCompat.tsx @@ -0,0 +1,138 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React, {type ReactNode} from 'react'; +import { + Navigate, + matchPath as reactRouterMatchPath, + useLocation, + useParams, + type PathPattern, +} from 'react-router'; +import type {Location} from 'history'; + +type DocusaurusRouteConfig = { + path: string; + component: React.ComponentType & {preload?: () => void | Promise}; + exact?: boolean; + strict?: boolean; + routes?: DocusaurusRouteConfig[]; + [attributeName: string]: unknown; +}; + +type DocusaurusRouteMatch = { + route: DocusaurusRouteConfig; + match: { + path: string; + url: string; + isExact: boolean; + params: Record; + }; +}; + +function RouteElement({route}: {route: DocusaurusRouteConfig}): ReactNode { + const Component = route.component; + const location = useLocation(); + const params = useParams(); + const match = { + path: route.path, + url: location.pathname, + isExact: location.pathname === route.path, + params, + }; + return ; +} + +function RenderRoutes({routes}: {routes: DocusaurusRouteConfig[]}): ReactNode { + const location = useLocation(); + const route = routes.find((item) => + matchPath(location.pathname, { + path: item.path, + exact: item.exact, + strict: item.strict, + }), + ); + + return route ? : null; +} + +export function matchPath( + pathname: string, + options: { + path: string; + exact?: boolean; + strict?: boolean; + sensitive?: boolean; + }, +): DocusaurusRouteMatch['match'] | null { + const match = reactRouterMatchPath( + { + path: options.path, + end: options.exact ?? false, + caseSensitive: options.sensitive ?? false, + }, + pathname, + ); + + if (!match) { + return null; + } + + return { + path: options.path, + url: match.pathname, + isExact: match.pathname === pathname, + params: match.params, + }; +} + +export function renderRoutes(routes: DocusaurusRouteConfig[]): ReactNode { + return ; +} + +function matchRouteBranch( + route: DocusaurusRouteConfig, + pathname: string, +): DocusaurusRouteMatch[] | null { + const routeMatch = matchPath(pathname, { + path: route.path, + exact: route.exact, + strict: route.strict, + }); + + if (!routeMatch) { + return null; + } + + const currentMatch = {route, match: routeMatch}; + const childMatches = route.routes + ?.map((childRoute) => matchRouteBranch(childRoute, pathname)) + .find(Boolean); + + return childMatches ? [currentMatch, ...childMatches] : [currentMatch]; +} + +export function matchRoutes( + routes: DocusaurusRouteConfig[], + pathname: string, +): DocusaurusRouteMatch[] { + return routes + .map((route) => matchRouteBranch(route, pathname)) + .find(Boolean) ?? []; +} + +export function Redirect({ + push, + to, +}: { + push?: boolean; + to: string | Partial; +}): ReactNode { + return ; +} + +export type {DocusaurusRouteConfig as RouteConfig, PathPattern}; diff --git a/packages/docusaurus/src/client/historyContext.tsx b/packages/docusaurus/src/client/historyContext.tsx new file mode 100644 index 000000000000..f31661993652 --- /dev/null +++ b/packages/docusaurus/src/client/historyContext.tsx @@ -0,0 +1,29 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +import React, {createContext, useContext, type ReactNode} from 'react'; +import type {History} from 'history'; + +const Context = createContext(null); + +export function HistoryProvider({ + children, + history, +}: { + children: ReactNode; + history: History; +}): ReactNode { + return {children}; +} + +export function useHistory(): History { + const history = useContext(Context); + if (!history) { + throw new Error('Unexpected: no Docusaurus history context found'); + } + return history; +} diff --git a/packages/docusaurus/src/client/normalizeLocation.ts b/packages/docusaurus/src/client/normalizeLocation.ts index 74192a451c08..abe3588876d8 100644 --- a/packages/docusaurus/src/client/normalizeLocation.ts +++ b/packages/docusaurus/src/client/normalizeLocation.ts @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -import {matchRoutes} from 'react-router-config'; +import {matchRoutes} from './exports/routerCompat'; import routes from '@generated/routes'; import type {Location} from 'history'; @@ -22,7 +22,7 @@ export default function normalizeLocation(location: T): T { // If the location was registered with an `.html` extension, we don't strip it // away, or it will render to a 404 page. - const matchedRoutes = matchRoutes(routes, location.pathname); + const matchedRoutes = matchRoutes(routes as never, location.pathname); if (matchedRoutes.some(({route}) => route.exact === true)) { pathnames.set(location.pathname, location.pathname); return location; diff --git a/packages/docusaurus/src/client/preload.ts b/packages/docusaurus/src/client/preload.ts index 08f7c81cad9f..232ca423ce53 100644 --- a/packages/docusaurus/src/client/preload.ts +++ b/packages/docusaurus/src/client/preload.ts @@ -6,7 +6,7 @@ */ import routes from '@generated/routes'; -import {matchRoutes} from 'react-router-config'; +import {matchRoutes} from './exports/routerCompat'; /** * Helper function to make sure all async components for that particular route @@ -18,7 +18,7 @@ import {matchRoutes} from 'react-router-config'; */ export default function preload(pathname: string): Promise { const matches = Array.from(new Set([pathname, decodeURI(pathname)])).flatMap( - (p) => matchRoutes(routes, p), + (p) => matchRoutes(routes as never, p), ); return Promise.all(matches.map((match) => match.route.component.preload?.())); diff --git a/packages/docusaurus/src/client/serverEntry.tsx b/packages/docusaurus/src/client/serverEntry.tsx index 1ca10a1d3826..4e712bd6e9c0 100644 --- a/packages/docusaurus/src/client/serverEntry.tsx +++ b/packages/docusaurus/src/client/serverEntry.tsx @@ -6,7 +6,8 @@ */ import React from 'react'; -import {StaticRouter} from 'react-router-dom'; +import {StaticRouter} from 'react-router'; +import {createMemoryHistory} from 'history'; import {HelmetProvider, type FilledContext} from 'react-helmet-async'; import Loadable from 'react-loadable'; import {renderToHtml} from './renderToHtml'; @@ -17,25 +18,28 @@ import { BrokenLinksProvider, } from './BrokenLinksContext'; import {toPageCollectedMetadataInternal} from './serverHelmetUtils'; +import {HistoryProvider} from './historyContext'; import type {AppRenderer, PageCollectedDataInternal} from '../common'; const render: AppRenderer['render'] = async ({pathname}) => { await preload(pathname); const modules = new Set(); - const routerContext = {}; const helmetContext = {}; const statefulBrokenLinks = createStatefulBrokenLinks(); + const history = createMemoryHistory({initialEntries: [pathname]}); const app = ( // @ts-expect-error: we are migrating away from react-loadable anyways modules.add(moduleName)}> - - - - - + + + + + + + ); diff --git a/packages/docusaurus/src/server/brokenLinks.ts b/packages/docusaurus/src/server/brokenLinks.ts index 3ee1971f8128..aa87cb3441e6 100644 --- a/packages/docusaurus/src/server/brokenLinks.ts +++ b/packages/docusaurus/src/server/brokenLinks.ts @@ -7,7 +7,7 @@ import _ from 'lodash'; import logger from '@docusaurus/logger'; -import {matchRoutes as reactRouterMatchRoutes} from 'react-router-config'; +import {matchPath} from 'react-router'; import { parseURLPath, serializeURLPath, @@ -18,10 +18,16 @@ import {addTrailingSlash, removeTrailingSlash} from '@docusaurus/utils-common'; import type {RouteConfig, ReportingSeverity} from '@docusaurus/types'; function matchRoutes(routeConfig: RouteConfig[], pathname: string) { - // @ts-expect-error: React router types RouteConfig with an actual React - // component, but we load route components with string paths. - // We don't actually access component here, so it's fine. - return reactRouterMatchRoutes(routeConfig, pathname); + return routeConfig.filter((route) => + matchPath( + { + path: route.path, + end: route.exact ?? false, + caseSensitive: false, + }, + pathname, + ), + ); } type BrokenLink = { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 73e67963d488..f774ebed39ff 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,7 +15,7 @@ importers: devDependencies: '@ai-sdk/react': specifier: ^3.0.177 - version: 3.0.177(react@19.2.6)(zod@4.4.3) + version: 3.0.177(react@19.2.7)(zod@4.4.3) '@crowdin/cli': specifier: ^4.14.2 version: 4.14.2(encoding@0.1.13) @@ -45,7 +45,7 @@ importers: version: 6.9.1 '@testing-library/react': specifier: ^16.3.2 - version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + version: 16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@types/fs-extra': specifier: ^11.0.4 version: 11.0.4 @@ -120,7 +120,7 @@ importers: version: 5.0.0 jest-serializer-react-helmet-async: specifier: ^1.0.21 - version: 1.0.21(@slorber/react-helmet-async@1.3.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6) + version: 1.0.21(@slorber/react-helmet-async@1.3.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7) jiti: specifier: ^2.7.0 version: 2.7.0 @@ -149,14 +149,14 @@ importers: specifier: ^0.0.68 version: 0.0.68 react: - specifier: ^19.2.5 - version: 19.2.6 + specifier: ^19.2.7 + version: 19.2.7 react-dom: - specifier: ^19.2.5 - version: 19.2.6(react@19.2.6) + specifier: ^19.2.7 + version: 19.2.7(react@19.2.7) react-helmet-async: specifier: npm:@slorber/react-helmet-async@1.3.0 - version: '@slorber/react-helmet-async@1.3.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)' + version: '@slorber/react-helmet-async@1.3.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7)' rimraf: specifier: ^3.0.2 version: 3.0.2 @@ -354,7 +354,7 @@ importers: version: link:../docusaurus-utils-validation '@mdx-js/react': specifier: ^3.1.1 - version: 3.1.1(@types/react@19.2.14)(react@19.2.6) + version: 3.1.1(@types/react@19.2.14)(react@19.2.7) boxen: specifier: ^6.2.1 version: 6.2.1 @@ -394,6 +394,9 @@ importers: fs-extra: specifier: ^11.2.0 version: 11.3.5 + history: + specifier: ^5.3.0 + version: 5.3.0 html-tags: specifier: ^3.3.1 version: 3.3.1 @@ -416,29 +419,23 @@ importers: specifier: ^2.4.2 version: 2.4.2 react: - specifier: ^19.2.5 - version: 19.2.6 + specifier: ^19.2.7 + version: 19.2.7 react-dom: - specifier: ^19.2.5 - version: 19.2.6(react@19.2.6) + specifier: ^19.2.7 + version: 19.2.7(react@19.2.7) react-helmet-async: specifier: npm:@slorber/react-helmet-async@1.3.0 - version: '@slorber/react-helmet-async@1.3.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)' + version: '@slorber/react-helmet-async@1.3.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7)' react-loadable: specifier: npm:@docusaurus/react-loadable@6.0.0 - version: '@docusaurus/react-loadable@6.0.0(react@19.2.6)' + version: '@docusaurus/react-loadable@6.0.0(react@19.2.7)' react-loadable-ssr-addon-v5-slorber: specifier: ^1.0.3 - version: 1.0.3(@docusaurus/react-loadable@6.0.0(react@19.2.6))(webpack@5.107.2(@swc/core@1.15.40)(postcss@8.5.15)) + version: 1.0.3(@docusaurus/react-loadable@6.0.0(react@19.2.7))(webpack@5.107.2(@swc/core@1.15.40)(postcss@8.5.15)) react-router: - specifier: ^5.3.4 - version: 5.3.4(react@19.2.6) - react-router-config: - specifier: ^5.1.1 - version: 5.1.1(react-router@5.3.4(react@19.2.6))(react@19.2.6) - react-router-dom: - specifier: ^5.3.4 - version: 5.3.4(react@19.2.6) + specifier: ^8.0.1 + version: 8.0.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7) semver: specifier: ^7.7.4 version: 7.8.1 @@ -479,18 +476,9 @@ importers: '@types/escape-html': specifier: ^1.0.4 version: 1.0.4 - '@types/history': - specifier: ^4.7.11 - version: 4.7.11 '@types/react-dom': specifier: ^19.2.3 version: 19.2.3(@types/react@19.2.14) - '@types/react-router-config': - specifier: ^5.0.7 - version: 5.0.11 - '@types/react-router-dom': - specifier: ^5.3.3 - version: 5.3.3 '@types/serve-handler': specifier: ^6.1.4 version: 6.1.4 @@ -840,18 +828,12 @@ importers: '@docusaurus/types': specifier: 3.10.1 version: link:../docusaurus-types - '@types/history': - specifier: ^4.7.11 - version: 4.7.11 '@types/react': specifier: 19.2.14 version: 19.2.14 - '@types/react-router-config': - specifier: '*' - version: 5.0.11 - '@types/react-router-dom': - specifier: '*' - version: 5.3.3 + history: + specifier: ^5.3.0 + version: 5.3.0 react: specifier: '*' version: 19.2.6 @@ -864,6 +846,9 @@ importers: react-loadable: specifier: npm:@docusaurus/react-loadable@6.0.0 version: '@docusaurus/react-loadable@6.0.0(react@19.2.6)' + react-router: + specifier: ^8.0.1 + version: 8.0.1(react-dom@19.2.6(react@19.2.6))(react@19.2.6) packages/docusaurus-plugin-client-redirects: dependencies: @@ -1010,9 +995,6 @@ importers: '@docusaurus/utils-validation': specifier: 3.10.1 version: link:../docusaurus-utils-validation - '@types/react-router-config': - specifier: ^5.0.7 - version: 5.0.11 combine-promises: specifier: ^1.1.0 version: 1.2.0 @@ -1560,7 +1542,7 @@ importers: version: link:../docusaurus-utils-validation '@mdx-js/react': specifier: ^3.1.1 - version: 3.1.1(@types/react@19.2.14)(react@19.2.6) + version: 3.1.1(@types/react@19.2.14)(react@19.2.7) clsx: specifier: ^2.0.0 version: 2.1.1 @@ -1581,19 +1563,16 @@ importers: version: 8.5.15 prism-react-renderer: specifier: ^2.4.1 - version: 2.4.1(react@19.2.6) + version: 2.4.1(react@19.2.7) prismjs: specifier: ^1.29.0 version: 1.30.0 react: - specifier: ^19.2.5 - version: 19.2.6 + specifier: ^19.2.7 + version: 19.2.7 react-dom: - specifier: ^19.2.5 - version: 19.2.6(react@19.2.6) - react-router-dom: - specifier: ^5.3.4 - version: 5.3.4(react@19.2.6) + specifier: ^19.2.7 + version: 19.2.7(react@19.2.7) rtlcss: specifier: ^4.1.0 version: 4.3.0 @@ -1631,30 +1610,27 @@ importers: '@docusaurus/utils-common': specifier: 3.10.1 version: link:../docusaurus-utils-common - '@types/history': - specifier: ^4.7.11 - version: 4.7.11 '@types/react': specifier: 19.2.14 version: 19.2.14 - '@types/react-router-config': - specifier: '*' - version: 5.0.11 clsx: specifier: ^2.0.0 version: 2.1.1 + history: + specifier: ^5.3.0 + version: 5.3.0 parse-numeric-range: specifier: ^1.3.0 version: 1.3.0 prism-react-renderer: specifier: ^2.4.1 - version: 2.4.1(react@19.2.6) + version: 2.4.1(react@19.2.7) react: - specifier: ^19.2.0 - version: 19.2.6 + specifier: ^19.2.7 + version: 19.2.7 react-dom: - specifier: ^19.2.0 - version: 19.2.6(react@19.2.6) + specifier: ^19.2.7 + version: 19.2.7(react@19.2.7) tslib: specifier: ^2.6.0 version: 2.8.1 @@ -1869,9 +1845,6 @@ importers: '@mdx-js/mdx': specifier: ^3.1.1 version: 3.1.1 - '@types/history': - specifier: ^4.7.11 - version: 4.7.11 '@types/mdast': specifier: ^4.0.2 version: 4.0.4 @@ -1881,6 +1854,9 @@ importers: commander: specifier: ^5.1.0 version: 5.1.0 + history: + specifier: ^5.3.0 + version: 5.3.0 joi: specifier: ^18.1.2 version: 18.2.1 @@ -2165,17 +2141,17 @@ importers: specifier: ^4.0.2 version: 4.0.2(webpack@5.107.2(@swc/core@1.15.40)(postcss@8.5.15)) react: - specifier: ^19.2.5 - version: 19.2.6 + specifier: ^19.2.7 + version: 19.2.7 react-dom: - specifier: ^19.2.5 - version: 19.2.6(react@19.2.6) + specifier: ^19.2.7 + version: 19.2.7(react@19.2.7) react-lite-youtube-embed: specifier: ^2.3.52 - version: 2.6.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + version: 2.6.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react-medium-image-zoom: specifier: ^5.1.6 - version: 5.4.5(react-dom@19.2.6(react@19.2.6))(react@19.2.6) + version: 5.4.5(react-dom@19.2.7(react@19.2.7))(react@19.2.7) recma-mdx-displayname: specifier: ^0.4.1 version: 0.4.1 @@ -5857,9 +5833,6 @@ packages: '@types/hast@3.0.4': resolution: {integrity: sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==} - '@types/history@4.7.11': - resolution: {integrity: sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==} - '@types/html-minifier-terser@6.1.0': resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==} @@ -5955,15 +5928,6 @@ packages: peerDependencies: '@types/react': ^19.2.0 - '@types/react-router-config@5.0.11': - resolution: {integrity: sha512-WmSAg7WgqW7m4x8Mt4N6ZyKz0BubSj/2tVUMsAHp+Yd2AMwcSbeFq9WympT19p5heCFmF97R9eD5uUR/t4HEqw==} - - '@types/react-router-dom@5.3.3': - resolution: {integrity: sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==} - - '@types/react-router@5.1.20': - resolution: {integrity: sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==} - '@types/react@19.2.14': resolution: {integrity: sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==} @@ -7143,6 +7107,9 @@ packages: resolution: {integrity: sha512-JtXpxqDqJ8P0UwEHwhxLzCIXQy97vlYBZR222Sbzb1q1Erex9ASrztJ29SyhWFQjod1AeFBaPzEEC8YvtZMIYg==} engines: {node: '>=6'} + cookie-es@3.1.1: + resolution: {integrity: sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==} + cookie-signature@1.0.7: resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} @@ -8694,11 +8661,8 @@ packages: highlight.js@10.7.3: resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} - history@4.10.1: - resolution: {integrity: sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==} - - hoist-non-react-statics@3.3.2: - resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + history@5.3.0: + resolution: {integrity: sha512-ZqaKwjjrAYUYfLG+htGaIIZ4nioX2L70ZUMIFysS3xvBsSG4x/n1V6TXV3N8ZYNuFGlDirFg32T7B6WOUPDYcQ==} hookified@1.15.1: resolution: {integrity: sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==} @@ -9237,9 +9201,6 @@ packages: resolution: {integrity: sha512-/kppl+R+LO5VmhYSEWARUFjodS25D68gvj8W7z0I7OWhUla5xWu8KL6CtB2V0R6yqhnRgbcaREMr4EEM6htLPQ==} engines: {node: '>=12'} - isarray@0.0.1: - resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} - isarray@1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} @@ -10644,9 +10605,6 @@ packages: path-to-regexp@0.1.13: resolution: {integrity: sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==} - path-to-regexp@1.9.0: - resolution: {integrity: sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==} - path-to-regexp@3.3.0: resolution: {integrity: sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==} @@ -11325,6 +11283,11 @@ packages: peerDependencies: react: ^19.2.6 + react-dom@19.2.7: + resolution: {integrity: sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==} + peerDependencies: + react: ^19.2.7 + react-fast-compare@3.2.2: resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} @@ -11376,21 +11339,15 @@ packages: resolution: {integrity: sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==} engines: {node: '>=0.10.0'} - react-router-config@5.1.1: - resolution: {integrity: sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg==} - peerDependencies: - react: '>=15' - react-router: '>=5' - - react-router-dom@5.3.4: - resolution: {integrity: sha512-m4EqFMHv/Ih4kpcBCONHbkT68KoAeHN4p3lAGoNryfHi0dMy0kCzEZakiKRsvg5wHZ/JLrLW8o8KomWiz/qbYQ==} + react-router@8.0.1: + resolution: {integrity: sha512-5EL/fANovVUhRK50NLS8RYfX0BxrimoKsHWUPPy8v5UEl8i6vzF7e4POo3u+AhPItDwccUAJjMfIOmydxBJmQw==} + engines: {node: '>=22.22.0'} peerDependencies: - react: '>=15' - - react-router@5.3.4: - resolution: {integrity: sha512-Ys9K+ppnJah3QuaRiLxk+jDWOR1MekYQrlytiXxC1RyfbdsZkS5pvKAzCCr031xHixZwpnsYNT5xysdFHQaYsA==} - peerDependencies: - react: '>=15' + react: '>=19.2.7' + react-dom: '>=19.2.7' + peerDependenciesMeta: + react-dom: + optional: true react@16.14.0: resolution: {integrity: sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==} @@ -11400,6 +11357,10 @@ packages: resolution: {integrity: sha512-sfWGGfavi0xr8Pg0sVsyHMAOziVYKgPLNrS7ig+ivMNb3wbCBw3KxtflsGBAwD3gYQlE/AEZsTLgToRrSCjb0Q==} engines: {node: '>=0.10.0'} + react@19.2.7: + resolution: {integrity: sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==} + engines: {node: '>=0.10.0'} + read-cmd-shim@4.0.0: resolution: {integrity: sha512-yILWifhaSEEytfXI76kB9xEEiG1AiozaCJZ83A87ytjRiN+jVibXjedjCRNjoZviinhG+4UkalO3mWTd8u5O0Q==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -12413,12 +12374,6 @@ packages: thunky@1.1.0: resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} - tiny-invariant@1.3.3: - resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} - - tiny-warning@1.0.3: - resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==} - tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} @@ -12830,9 +12785,6 @@ packages: resolution: {integrity: sha512-IUoow1YUtvoBBC06dXs8bR8B9vuA3aJfmQNKMoaPG/OFsPmoQvw8xh+6Ye25Gx9DQhoEom3Pcu9MKHerm/NpUQ==} engines: {node: ^18.17.0 || >=20.5.0} - value-equal@1.0.1: - resolution: {integrity: sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==} - vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -13372,12 +13324,12 @@ snapshots: dependencies: json-schema: 0.4.0 - '@ai-sdk/react@3.0.177(react@19.2.6)(zod@4.4.3)': + '@ai-sdk/react@3.0.177(react@19.2.7)(zod@4.4.3)': dependencies: '@ai-sdk/provider-utils': 4.0.26(zod@4.4.3) ai: 6.0.175(zod@4.4.3) - react: 19.2.6 - swr: 2.4.1(react@19.2.6) + react: 19.2.7 + swr: 2.4.1(react@19.2.7) throttleit: 2.1.0 transitivePeerDependencies: - zod @@ -14978,6 +14930,11 @@ snapshots: '@types/react': 19.2.14 react: 19.2.6 + '@docusaurus/react-loadable@6.0.0(react@19.2.7)': + dependencies: + '@types/react': 19.2.14 + react: 19.2.7 + '@docusaurus/responsive-loader@1.7.1(jimp@1.6.1)(sharp@0.35.1)': dependencies: loader-utils: 2.0.4 @@ -15809,6 +15766,12 @@ snapshots: '@types/react': 19.2.14 react: 19.2.6 + '@mdx-js/react@3.1.1(@types/react@19.2.14)(react@19.2.7)': + dependencies: + '@types/mdx': 2.0.13 + '@types/react': 19.2.14 + react: 19.2.7 + '@mermaid-js/layout-elk@0.1.9(mermaid@11.15.0)': dependencies: d3: 7.9.0 @@ -16797,6 +16760,16 @@ snapshots: react-fast-compare: 3.2.2 shallowequal: 1.1.0 + '@slorber/react-helmet-async@1.3.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': + dependencies: + '@babel/runtime': 7.29.7 + invariant: 2.2.4 + prop-types: 15.8.1 + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) + react-fast-compare: 3.2.2 + shallowequal: 1.1.0 + '@slorber/remark-comment@1.0.0': dependencies: micromark-factory-space: 1.1.0 @@ -17037,12 +17010,12 @@ snapshots: picocolors: 1.1.1 redent: 3.0.0 - '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)': + '@testing-library/react@16.3.2(@testing-library/dom@10.4.1)(@types/react-dom@19.2.3(@types/react@19.2.14))(@types/react@19.2.14)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)': dependencies: '@babel/runtime': 7.29.7 '@testing-library/dom': 10.4.1 - react: 19.2.6 - react-dom: 19.2.6(react@19.2.6) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) optionalDependencies: '@types/react': 19.2.14 '@types/react-dom': 19.2.3(@types/react@19.2.14) @@ -17321,8 +17294,6 @@ snapshots: dependencies: '@types/unist': 3.0.3 - '@types/history@4.7.11': {} - '@types/html-minifier-terser@6.1.0': {} '@types/html-minifier-terser@7.0.2': {} @@ -17404,23 +17375,6 @@ snapshots: dependencies: '@types/react': 19.2.14 - '@types/react-router-config@5.0.11': - dependencies: - '@types/history': 4.7.11 - '@types/react': 19.2.14 - '@types/react-router': 5.1.20 - - '@types/react-router-dom@5.3.3': - dependencies: - '@types/history': 4.7.11 - '@types/react': 19.2.14 - '@types/react-router': 5.1.20 - - '@types/react-router@5.1.20': - dependencies: - '@types/history': 4.7.11 - '@types/react': 19.2.14 - '@types/react@19.2.14': dependencies: csstype: 3.2.3 @@ -18773,6 +18727,8 @@ snapshots: lodash.clonedeep: 4.5.0 yargs-parser: 20.2.9 + cookie-es@3.1.1: {} + cookie-signature@1.0.7: {} cookie@0.7.2: {} @@ -20657,18 +20613,9 @@ snapshots: highlight.js@10.7.3: {} - history@4.10.1: + history@5.3.0: dependencies: '@babel/runtime': 7.29.7 - loose-envify: 1.4.0 - resolve-pathname: 3.0.0 - tiny-invariant: 1.3.3 - tiny-warning: 1.0.3 - value-equal: 1.0.1 - - hoist-non-react-statics@3.3.2: - dependencies: - react-is: 16.13.1 hookified@1.15.1: {} @@ -21175,8 +21122,6 @@ snapshots: is-yarn-global@0.4.1: {} - isarray@0.0.1: {} - isarray@1.0.0: {} isarray@2.0.5: {} @@ -21223,10 +21168,10 @@ snapshots: dependencies: pretty-ansi: 4.0.0 - jest-serializer-react-helmet-async@1.0.21(@slorber/react-helmet-async@1.3.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6))(react@19.2.6): + jest-serializer-react-helmet-async@1.0.21(@slorber/react-helmet-async@1.3.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7): dependencies: - react: 19.2.6 - react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6)' + react: 19.2.7 + react-helmet-async: '@slorber/react-helmet-async@1.3.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7)' jest-util@30.4.1: dependencies: @@ -23257,10 +23202,6 @@ snapshots: path-to-regexp@0.1.13: {} - path-to-regexp@1.9.0: - dependencies: - isarray: 0.0.1 - path-to-regexp@3.3.0: {} path-type@3.0.0: @@ -23827,6 +23768,12 @@ snapshots: clsx: 2.1.1 react: 19.2.6 + prism-react-renderer@2.4.1(react@19.2.7): + dependencies: + '@types/prismjs': 1.26.6 + clsx: 2.1.1 + react: 19.2.7 + prismjs@1.30.0: {} proc-log@5.0.0: {} @@ -23958,6 +23905,11 @@ snapshots: react: 19.2.6 scheduler: 0.27.0 + react-dom@19.2.7(react@19.2.7): + dependencies: + react: 19.2.7 + scheduler: 0.27.0 + react-fast-compare@3.2.2: {} react-is@16.13.1: {} @@ -23972,10 +23924,10 @@ snapshots: dependencies: react: 19.2.6 - react-lite-youtube-embed@2.6.0(react-dom@19.2.6(react@19.2.6))(react@19.2.6): + react-lite-youtube-embed@2.6.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: - react: 19.2.6 - react-dom: 19.2.6(react@19.2.6) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) react-live@4.1.8(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: @@ -23985,48 +23937,32 @@ snapshots: sucrase: 3.35.1 use-editable: 2.3.3(react@19.2.6) - react-loadable-ssr-addon-v5-slorber@1.0.3(@docusaurus/react-loadable@6.0.0(react@19.2.6))(webpack@5.107.2(@swc/core@1.15.40)(postcss@8.5.15)): + react-loadable-ssr-addon-v5-slorber@1.0.3(@docusaurus/react-loadable@6.0.0(react@19.2.7))(webpack@5.107.2(@swc/core@1.15.40)(postcss@8.5.15)): dependencies: '@babel/runtime': 7.29.7 - react-loadable: '@docusaurus/react-loadable@6.0.0(react@19.2.6)' + react-loadable: '@docusaurus/react-loadable@6.0.0(react@19.2.7)' webpack: 5.107.2(@swc/core@1.15.40)(postcss@8.5.15) - react-medium-image-zoom@5.4.5(react-dom@19.2.6(react@19.2.6))(react@19.2.6): + react-medium-image-zoom@5.4.5(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: - react: 19.2.6 - react-dom: 19.2.6(react@19.2.6) + react: 19.2.7 + react-dom: 19.2.7(react@19.2.7) react-refresh@0.18.0: {} - react-router-config@5.1.1(react-router@5.3.4(react@19.2.6))(react@19.2.6): + react-router@8.0.1(react-dom@19.2.6(react@19.2.6))(react@19.2.6): dependencies: - '@babel/runtime': 7.29.7 + cookie-es: 3.1.1 react: 19.2.6 - react-router: 5.3.4(react@19.2.6) - - react-router-dom@5.3.4(react@19.2.6): - dependencies: - '@babel/runtime': 7.29.7 - history: 4.10.1 - loose-envify: 1.4.0 - prop-types: 15.8.1 - react: 19.2.6 - react-router: 5.3.4(react@19.2.6) - tiny-invariant: 1.3.3 - tiny-warning: 1.0.3 + optionalDependencies: + react-dom: 19.2.6(react@19.2.6) - react-router@5.3.4(react@19.2.6): + react-router@8.0.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: - '@babel/runtime': 7.29.7 - history: 4.10.1 - hoist-non-react-statics: 3.3.2 - loose-envify: 1.4.0 - path-to-regexp: 1.9.0 - prop-types: 15.8.1 - react: 19.2.6 - react-is: 16.13.1 - tiny-invariant: 1.3.3 - tiny-warning: 1.0.3 + cookie-es: 3.1.1 + react: 19.2.7 + optionalDependencies: + react-dom: 19.2.7(react@19.2.7) react@16.14.0: dependencies: @@ -24036,6 +23972,8 @@ snapshots: react@19.2.6: {} + react@19.2.7: {} + read-cmd-shim@4.0.0: {} read-cmd-shim@5.0.0: {} @@ -25212,11 +25150,11 @@ snapshots: '@swc/counter': 0.1.3 webpack: 5.107.2(@swc/core@1.15.40)(@swc/html@1.15.40)(lightningcss@1.32.0)(postcss@8.5.15) - swr@2.4.1(react@19.2.6): + swr@2.4.1(react@19.2.7): dependencies: dequal: 2.0.3 - react: 19.2.6 - use-sync-external-store: 1.6.0(react@19.2.6) + react: 19.2.7 + use-sync-external-store: 1.6.0(react@19.2.7) symbol-tree@3.2.4: {} @@ -25360,10 +25298,6 @@ snapshots: thunky@1.1.0: {} - tiny-invariant@1.3.3: {} - - tiny-warning@1.0.3: {} - tinybench@2.9.0: {} tinycolor2@1.6.0: {} @@ -25733,9 +25667,9 @@ snapshots: dependencies: react: 19.2.6 - use-sync-external-store@1.6.0(react@19.2.6): + use-sync-external-store@1.6.0(react@19.2.7): dependencies: - react: 19.2.6 + react: 19.2.7 utif2@4.1.0: dependencies: @@ -25762,8 +25696,6 @@ snapshots: validate-npm-package-name@6.0.2: {} - value-equal@1.0.1: {} - vary@1.1.2: {} vfile-location@5.0.3: diff --git a/website/package.json b/website/package.json index 2ff2525c1965..431887795054 100644 --- a/website/package.json +++ b/website/package.json @@ -66,8 +66,8 @@ "fs-extra": "^11.2.0", "netlify-plugin-cache": "^1.0.3", "raw-loader": "^4.0.2", - "react": "^19.2.5", - "react-dom": "^19.2.5", + "react": "^19.2.7", + "react-dom": "^19.2.7", "react-lite-youtube-embed": "^2.3.52", "react-medium-image-zoom": "^5.1.6", "recma-mdx-displayname": "^0.4.1",