2022-04-27 11:50:29 +02:00
|
|
|
import type { Key } from 'next/dist/compiled/path-to-regexp'
|
|
|
|
import { pathToRegexp } from 'next/dist/compiled/path-to-regexp'
|
|
|
|
import { regexpToFunction } from 'next/dist/compiled/path-to-regexp'
|
2019-12-23 22:20:17 +01:00
|
|
|
|
2022-04-27 11:50:29 +02:00
|
|
|
interface Options {
|
|
|
|
/**
|
|
|
|
* A transformer function that will be applied to the regexp generated
|
|
|
|
* from the provided path and path-to-regexp.
|
|
|
|
*/
|
|
|
|
regexModifier?: (regex: string) => string
|
|
|
|
/**
|
|
|
|
* When true the function will remove all unnamed parameters
|
|
|
|
* from the matched parameters.
|
|
|
|
*/
|
|
|
|
removeUnnamedParams?: boolean
|
|
|
|
/**
|
|
|
|
* When true the regexp won't allow an optional trailing delimiter
|
|
|
|
* to match.
|
|
|
|
*/
|
|
|
|
strict?: boolean
|
2020-08-13 14:39:36 +02:00
|
|
|
}
|
|
|
|
|
2022-04-27 11:50:29 +02:00
|
|
|
/**
|
|
|
|
* Generates a path matcher function for a given path and options based on
|
2022-10-24 03:24:32 +02:00
|
|
|
* path-to-regexp. By default the match will be case insensitive, non strict
|
2022-04-27 11:50:29 +02:00
|
|
|
* and delimited by `/`.
|
|
|
|
*/
|
|
|
|
export function getPathMatch(path: string, options?: Options) {
|
|
|
|
const keys: Key[] = []
|
|
|
|
const regexp = pathToRegexp(path, keys, {
|
|
|
|
delimiter: '/',
|
|
|
|
sensitive: false,
|
|
|
|
strict: options?.strict,
|
|
|
|
})
|
2020-08-13 14:39:36 +02:00
|
|
|
|
2022-04-27 11:50:29 +02:00
|
|
|
const matcher = regexpToFunction(
|
|
|
|
options?.regexModifier
|
|
|
|
? new RegExp(options.regexModifier(regexp.source), regexp.flags)
|
|
|
|
: regexp,
|
|
|
|
keys
|
|
|
|
)
|
2021-07-13 21:38:14 +02:00
|
|
|
|
2022-04-27 11:50:29 +02:00
|
|
|
/**
|
|
|
|
* A matcher function that will check if a given pathname matches the path
|
|
|
|
* given in the builder function. When the path does not match it will return
|
|
|
|
* `false` but if it does it will return an object with the matched params
|
|
|
|
* merged with the params provided in the second argument.
|
|
|
|
*/
|
|
|
|
return <T extends { [key: string]: any }>(
|
|
|
|
pathname?: string | null,
|
|
|
|
params?: any
|
|
|
|
): false | T => {
|
|
|
|
const res = pathname == null ? false : matcher(pathname)
|
|
|
|
if (!res) {
|
|
|
|
return false
|
2021-07-13 21:38:14 +02:00
|
|
|
}
|
|
|
|
|
2022-04-27 11:50:29 +02:00
|
|
|
/**
|
|
|
|
* If unnamed params are not allowed they must be removed from
|
|
|
|
* the matched parameters. path-to-regexp uses "string" for named and
|
|
|
|
* "number" for unnamed parameters.
|
|
|
|
*/
|
|
|
|
if (options?.removeUnnamedParams) {
|
|
|
|
for (const key of keys) {
|
|
|
|
if (typeof key.name === 'number') {
|
|
|
|
delete (res.params as any)[key.name]
|
2020-01-16 23:38:38 +01:00
|
|
|
}
|
|
|
|
}
|
2018-02-01 19:54:09 +01:00
|
|
|
}
|
2022-04-27 11:50:29 +02:00
|
|
|
|
|
|
|
return { ...params, ...res.params }
|
2018-02-01 19:54:09 +01:00
|
|
|
}
|
|
|
|
}
|