From 023816fb3c5c823d0bb3ab692af6efd4ca0bcd5c Mon Sep 17 00:00:00 2001 From: Roberto Kok Date: Fri, 18 Aug 2023 12:19:32 +0800 Subject: [PATCH 1/2] Support custom regex to match route path parts --- src/router.tsx | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/src/router.tsx b/src/router.tsx index bd67e46..18d2952 100644 --- a/src/router.tsx +++ b/src/router.tsx @@ -11,10 +11,14 @@ export interface PathParamOptions { basePath?: string matchTrailingSlash?: boolean } +export interface RouteMatcherOptions { + partRegex?: string +} export interface RouteOptionParams extends PathParamOptions { // eslint-disable-next-line @typescript-eslint/no-explicit-any routeProps?: { [k: string]: any } overridePathParams?: boolean + matcherOpts?: RouteMatcherOptions } interface RouteMatcher { path: string @@ -44,6 +48,7 @@ export function useRoutes( routeProps = {}, overridePathParams = true, matchTrailingSlash = true, + matcherOpts = {} }: RouteOptionParams = {} ): JSX.Element | null { /* @@ -64,6 +69,7 @@ export function useRoutes( routeProps, overridePathParams, matchTrailingSlash, + matcherOpts }) // No match should not return an empty Provider, just null @@ -83,10 +89,11 @@ function useMatchRoute( routeProps, overridePathParams, matchTrailingSlash, - }: Omit & { matchTrailingSlash: boolean } + matcherOpts + }: Omit & { matchTrailingSlash: boolean, matcherOpts: RouteMatcherOptions } ) { path = trailingMatch(path, matchTrailingSlash) - const matchers = useMatchers(Object.keys(routes)) + const matchers = useMatchers(Object.keys(routes), matcherOpts) if (path === null) return null const [routeMatch, props] = getMatchParams(path, matchers) @@ -158,17 +165,19 @@ export function useMatch(routes: string | string[], options: PathParamOptions = function usePathOptions( routeOrRoutes: string | string[], - { basePath, matchTrailingSlash = true }: PathParamOptions + { basePath, matchTrailingSlash = true, matcherOpts }: PathParamOptions & { matcherOpts?: RouteMatcherOptions} ): [string | null, RouteMatcher[]] { const routes = (!Array.isArray(routeOrRoutes) ? [routeOrRoutes] : routeOrRoutes) as string[] - const matchers = useMatchers(routes) + const matchers = useMatchers(routes, matcherOpts) return [trailingMatch(usePath(basePath), matchTrailingSlash), matchers] } -function useMatchers(routes: string[]): RouteMatcher[] { - // eslint-disable-next-line react-hooks/exhaustive-deps - return useMemo(() => routes.map(createRouteMatcher), [hashParams(routes)]) +function useMatchers(routes: string[], opts?: RouteMatcherOptions): RouteMatcher[] { + return useMemo(() => { + return routes.map(route => createRouteMatcher(route, opts)) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [hashParams(routes)]) } function getMatchParams( @@ -195,16 +204,19 @@ function getMatchParams( return [routeMatch, props] } -function createRouteMatcher(path: string): RouteMatcher { +function createRouteMatcher(path: string, { + partRegex = ':[a-zA-Z]+' +}: RouteMatcherOptions = {}): RouteMatcher { + const partMatcher = new RegExp(partRegex, 'g') return { path, regex: new RegExp( `${path.substr(0, 1) === '*' ? '' : '^'}${escapeRegExp(path) - .replace(/:[a-zA-Z]+/g, '([^/]+)') + .replace(partRegex, '([^/]+)') .replace(/\*/g, '')}${path.substr(-1) === '*' ? '' : '$'}`, 'i' ), - props: (path.match(/:[a-zA-Z]+/g) ?? []).map((paramName) => paramName.substr(1)), + props: (partMatcher.exec(path) ?? []).map((paramName) => paramName.substr(1)) } } From c81972332e5c169938259d06a57f2854a9b1d182 Mon Sep 17 00:00:00 2001 From: Roberto Kok Date: Fri, 18 Aug 2023 16:34:22 +0800 Subject: [PATCH 2/2] Fix matcher regex --- src/router.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/router.tsx b/src/router.tsx index 18d2952..636f184 100644 --- a/src/router.tsx +++ b/src/router.tsx @@ -212,7 +212,7 @@ function createRouteMatcher(path: string, { path, regex: new RegExp( `${path.substr(0, 1) === '*' ? '' : '^'}${escapeRegExp(path) - .replace(partRegex, '([^/]+)') + .replace(partMatcher, '([^/]+)') .replace(/\*/g, '')}${path.substr(-1) === '*' ? '' : '$'}`, 'i' ),