Skip to content

Commit feddb3d

Browse files
authored
Support named capturing groups for RegExps (#225)
1 parent 8b0ae94 commit feddb3d

File tree

4 files changed

+164
-16
lines changed

4 files changed

+164
-16
lines changed

package-lock.json

Lines changed: 58 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,13 @@
7272
"@size-limit/preset-small-lib": "^2.1.6",
7373
"@types/jest": "^24.0.22",
7474
"@types/node": "^12.12.7",
75+
"@types/semver": "^7.3.1",
7576
"husky": "^3.0.9",
7677
"jest": "^24.9.0",
7778
"lint-staged": "^9.4.2",
7879
"prettier": "^1.19.1",
7980
"rimraf": "^3.0.0",
81+
"semver": "^7.3.2",
8082
"ts-jest": "^24.1.0",
8183
"tslint": "^5.20.1",
8284
"tslint-config-prettier": "^1.18.0",

src/index.spec.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as util from "util";
22
import * as pathToRegexp from "./index";
3+
import { gte } from "semver";
34

45
type Test = [
56
pathToRegexp.Path,
@@ -2594,6 +2595,95 @@ const TESTS: Test[] = [
25942595
]
25952596
];
25962597

2598+
/**
2599+
* Named capturing groups (available from Node version 10)
2600+
*/
2601+
if (gte(process.version, "10.0.0")) {
2602+
TESTS.push(
2603+
[
2604+
/\/(?<groupname>.+)/,
2605+
undefined,
2606+
[
2607+
{
2608+
name: "groupname",
2609+
prefix: "",
2610+
suffix: "",
2611+
modifier: "",
2612+
pattern: ""
2613+
}
2614+
],
2615+
[
2616+
["/", null],
2617+
["/foo", ["/foo", "foo"]]
2618+
],
2619+
[]
2620+
],
2621+
[
2622+
/\/(?<test>.*).(?<format>html|json)/,
2623+
undefined,
2624+
[
2625+
{
2626+
name: "test",
2627+
prefix: "",
2628+
suffix: "",
2629+
modifier: "",
2630+
pattern: ""
2631+
},
2632+
{
2633+
name: "format",
2634+
prefix: "",
2635+
suffix: "",
2636+
modifier: "",
2637+
pattern: ""
2638+
}
2639+
],
2640+
[
2641+
["/route", null],
2642+
["/route.txt", null],
2643+
["/route.html", ["/route.html", "route", "html"]],
2644+
["/route.json", ["/route.json", "route", "json"]]
2645+
],
2646+
[]
2647+
],
2648+
[
2649+
/\/(.+)\/(?<groupname>.+)\/(.+)/,
2650+
undefined,
2651+
[
2652+
{
2653+
name: 0,
2654+
prefix: "",
2655+
suffix: "",
2656+
modifier: "",
2657+
pattern: ""
2658+
},
2659+
{
2660+
name: "groupname",
2661+
prefix: "",
2662+
suffix: "",
2663+
modifier: "",
2664+
pattern: ""
2665+
},
2666+
{
2667+
name: 1,
2668+
prefix: "",
2669+
suffix: "",
2670+
modifier: "",
2671+
pattern: ""
2672+
}
2673+
],
2674+
[
2675+
["/test", null],
2676+
["/test/testData", null],
2677+
[
2678+
"/test/testData/extraStuff",
2679+
["/test/testData/extraStuff", "test", "testData", "extraStuff"]
2680+
]
2681+
],
2682+
[]
2683+
]
2684+
);
2685+
}
2686+
25972687
/**
25982688
* Dynamically generate the entire test suite.
25992689
*/

src/index.ts

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -453,19 +453,20 @@ export type Token = string | Key;
453453
function regexpToRegexp(path: RegExp, keys?: Key[]): RegExp {
454454
if (!keys) return path;
455455

456-
// Use a negative lookahead to match only capturing groups.
457-
const groups = path.source.match(/\((?!\?)/g);
458-
459-
if (groups) {
460-
for (let i = 0; i < groups.length; i++) {
461-
keys.push({
462-
name: i,
463-
prefix: "",
464-
suffix: "",
465-
modifier: "",
466-
pattern: ""
467-
});
468-
}
456+
const groupsRegex = /\((?:\?<(.*?)>)?(?!\?)/g;
457+
458+
let index = 0;
459+
let execResult = groupsRegex.exec(path.source);
460+
while (execResult) {
461+
keys.push({
462+
// Use parenthesized substring match if available, index otherwise
463+
name: execResult[1] || index++,
464+
prefix: "",
465+
suffix: "",
466+
modifier: "",
467+
pattern: ""
468+
});
469+
execResult = groupsRegex.exec(path.source);
469470
}
470471

471472
return path;

0 commit comments

Comments
 (0)