Skip to content

Commit 3fdd88f

Browse files
committed
Support array inputs for match
1 parent c36bdfa commit 3fdd88f

File tree

2 files changed

+63
-23
lines changed

2 files changed

+63
-23
lines changed

src/cases.spec.ts

+31-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export interface ParserTestSet {
1515
}
1616

1717
export interface CompileTestSet {
18-
path: string;
18+
path: Path;
1919
options?: CompileOptions;
2020
tests: Array<{
2121
input: ParamData | undefined;
@@ -24,7 +24,7 @@ export interface CompileTestSet {
2424
}
2525

2626
export interface MatchTestSet {
27-
path: Path;
27+
path: Path | Path[];
2828
options?: MatchOptions;
2929
tests: Array<{
3030
input: string;
@@ -3191,4 +3191,33 @@ export const MATCH_TESTS: MatchTestSet[] = [
31913191
},
31923192
],
31933193
},
3194+
3195+
/**
3196+
* Array input.
3197+
*/
3198+
{
3199+
path: ["/a", "/b"],
3200+
tests: [
3201+
{
3202+
input: "/a",
3203+
matches: ["/a"],
3204+
expected: { path: "/a", index: 0, params: {} },
3205+
},
3206+
{
3207+
input: "/b",
3208+
matches: ["/b"],
3209+
expected: { path: "/b", index: 0, params: {} },
3210+
},
3211+
{
3212+
input: "/c",
3213+
matches: null,
3214+
expected: false,
3215+
},
3216+
{
3217+
input: "/a/b",
3218+
matches: null,
3219+
expected: false,
3220+
},
3221+
],
3222+
},
31943223
];

src/index.ts

+32-21
Original file line numberDiff line numberDiff line change
@@ -475,16 +475,18 @@ export type MatchFunction<P extends ParamData> = (path: string) => Match<P>;
475475
* Create path match function from `path-to-regexp` spec.
476476
*/
477477
export function match<P extends ParamData>(
478-
path: Path,
478+
path: Path | Path[],
479479
options: MatchOptions = {},
480480
): MatchFunction<P> {
481-
const { decode = decodeURIComponent, loose = true } = options;
482-
const data = path instanceof TokenData ? path : parse(path, options);
483-
const stringify = toStringify(loose, data.delimiter);
484-
const keys: Key[] = [];
485-
const re = tokensToRegexp(data, keys, options);
481+
const {
482+
decode = decodeURIComponent,
483+
loose = true,
484+
delimiter = DEFAULT_DELIMITER,
485+
} = options;
486+
const re = pathToRegexp(path, options);
487+
const stringify = toStringify(loose, delimiter);
486488

487-
const decoders = keys.map((key) => {
489+
const decoders = re.keys.map((key) => {
488490
if (decode && (key.modifier === "+" || key.modifier === "*")) {
489491
const { prefix = "", suffix = "", separator = suffix + prefix } = key;
490492
const re = new RegExp(stringify(separator), "g");
@@ -504,7 +506,7 @@ export function match<P extends ParamData>(
504506
for (let i = 1; i < m.length; i++) {
505507
if (m[i] === undefined) continue;
506508

507-
const key = keys[i - 1];
509+
const key = re.keys[i - 1];
508510
const decoder = decoders[i - 1];
509511
params[key.name] = decoder(m[i]);
510512
}
@@ -517,7 +519,7 @@ export function match<P extends ParamData>(
517519
* Escape a regular expression string.
518520
*/
519521
function escape(str: string) {
520-
return str.replace(/([.+*?^${}()[\]|/\\])/g, "\\$1");
522+
return str.replace(/[.+*?^${}()[\]|/\\]/g, "\\$&");
521523
}
522524

523525
/**
@@ -565,27 +567,27 @@ export type Token = string | Key;
565567
/**
566568
* Expose a function for taking tokens and returning a RegExp.
567569
*/
568-
function tokensToRegexp(
569-
data: TokenData,
570+
function pathToSource(
571+
path: Path,
570572
keys: Key[],
573+
flags: string,
571574
options: PathToRegexpOptions,
572-
): RegExp {
575+
): string {
576+
const data = path instanceof TokenData ? path : parse(path, options);
573577
const {
574578
trailing = true,
575579
loose = true,
576580
start = true,
577581
end = true,
578582
strict = false,
579583
} = options;
580-
const flags = toFlags(options);
581584
const stringify = toStringify(loose, data.delimiter);
582585
const sources = toRegExpSource(data, stringify, keys, flags, strict);
583586
let pattern = start ? "^" : "";
584587
pattern += sources.join("");
585-
if (trailing) pattern += `(?:${stringify(data.delimiter)})?`;
588+
if (trailing) pattern += `(?:${stringify(data.delimiter)}$)?`;
586589
pattern += end ? "$" : `(?=${escape(data.delimiter)}|$)`;
587-
588-
return new RegExp(pattern, flags);
590+
return pattern;
589591
}
590592

591593
/**
@@ -602,7 +604,7 @@ function toRegExpSource(
602604
let backtrack = "";
603605
let safe = true;
604606

605-
return data.tokens.map((token, index) => {
607+
return data.tokens.map((token) => {
606608
if (typeof token === "string") {
607609
backtrack = token;
608610
return stringify(token);
@@ -685,9 +687,18 @@ export type Path = string | TokenData;
685687
* placeholder key descriptions. For example, using `/user/:id`, `keys` will
686688
* contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.
687689
*/
688-
export function pathToRegexp(path: Path, options: PathToRegexpOptions = {}) {
689-
const data = path instanceof TokenData ? path : parse(path, options);
690+
export function pathToRegexp(
691+
path: Path | Path[],
692+
options: PathToRegexpOptions = {},
693+
) {
690694
const keys: Key[] = [];
691-
const regexp = tokensToRegexp(data, keys, options);
692-
return Object.assign(regexp, { keys });
695+
const flags = toFlags(options);
696+
697+
if (Array.isArray(path)) {
698+
const regexps = path.map((p) => pathToSource(p, keys, flags, options));
699+
return Object.assign(new RegExp(regexps.join("|")), { keys });
700+
}
701+
702+
const regexp = pathToSource(path, keys, flags, options);
703+
return Object.assign(new RegExp(regexp), { keys });
693704
}

0 commit comments

Comments
 (0)