Skip to content

Commit cbe55a4

Browse files
committed
Merge pull request #56 from pillarjs/array-wildcard-index-patch
Fix index property in favour of numbered params
2 parents fa40b5f + 241650f commit cbe55a4

File tree

2 files changed

+110
-55
lines changed

2 files changed

+110
-55
lines changed

index.js

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
module.exports = pathtoRegexp;
66

7+
/**
8+
* Match matching groups in a regular expression.
9+
*/
10+
var MATCHING_GROUP_REGEXP = /\((?!\?)/g;
11+
712
/**
813
* Normalize the given path string,
914
* returning a regular expression.
@@ -22,14 +27,25 @@ module.exports = pathtoRegexp;
2227

2328
function pathtoRegexp(path, keys, options) {
2429
options = options || {};
30+
keys = keys || [];
2531
var strict = options.strict;
2632
var end = options.end !== false;
2733
var flags = options.sensitive ? '' : 'i';
2834
var extraOffset = 0;
29-
30-
keys = keys || [];
35+
var keysOffset = keys.length;
36+
var i = 0;
37+
var name = 0;
38+
var m;
3139

3240
if (path instanceof RegExp) {
41+
while (m = MATCHING_GROUP_REGEXP.exec(path.source)) {
42+
keys.push({
43+
name: name++,
44+
optional: false,
45+
offset: m.index
46+
});
47+
}
48+
3349
return path;
3450
}
3551

@@ -56,8 +72,7 @@ function pathtoRegexp(path, keys, options) {
5672
keys.push({
5773
name: key,
5874
optional: !!optional,
59-
index: 0,
60-
_offset: offset + extraOffset
75+
offset: offset + extraOffset
6176
});
6277

6378
var result = ''
@@ -75,23 +90,24 @@ function pathtoRegexp(path, keys, options) {
7590
.replace(/\*/g, function (star, index) {
7691
var len = keys.length
7792

78-
while (len-- && keys[len]._offset > index) {
79-
keys[len]._offset += 3;
93+
while (len-- > keysOffset && keys[len].offset > index) {
94+
keys[len].offset += 3;
8095
}
8196

8297
return '(.*)';
8398
});
8499

85-
// This is a workaround for handling *all* matching group positioning.
86-
var re = /\((?!\?)/g;
87-
var m;
88-
89-
while (m = re.exec(path)) {
90-
var len = keys.length;
91-
92-
while (len-- && keys[len]._offset > m.index) {
93-
keys[len].index++;
100+
// This is a workaround for handling unnamed matching groups.
101+
while (m = MATCHING_GROUP_REGEXP.exec(path)) {
102+
if (keysOffset + i === keys.length || keys[keysOffset + i].offset > m.index) {
103+
keys.splice(keysOffset + i, 0, {
104+
name: name++, // Unnamed matching groups must be consistently linear.
105+
optional: false,
106+
offset: m.index
107+
});
94108
}
109+
110+
i++;
95111
}
96112

97113
// If the path is non-ending, match until the end or a slash.

test.js

Lines changed: 79 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,9 @@ describe('path-to-regexp', function () {
5050
var params = [];
5151
var m = pathToRegExp('/*', params).exec('/pathname');
5252

53-
assert.equal(params.length, 0);
53+
assert.equal(params.length, 1);
54+
assert.equal(params[0].name, 0);
55+
assert.equal(params[0].optional, false);
5456

5557
assert.equal(m.length, 2);
5658
assert.equal(m[0], '/pathname');
@@ -61,7 +63,9 @@ describe('path-to-regexp', function () {
6163
var params = [];
6264
var m = pathToRegExp('*', params).exec('/pathname');
6365

64-
assert.equal(params.length, 0);
66+
assert.equal(params.length, 1);
67+
assert.equal(params[0].name, 0);
68+
assert.equal(params[0].optional, false);
6569

6670
assert.equal(m.length, 2);
6771
assert.equal(m[0], '/pathname');
@@ -72,10 +76,11 @@ describe('path-to-regexp', function () {
7276
var params = [];
7377
var m = pathToRegExp('/:test/*', params).exec('/pathone/pathtwo');
7478

75-
assert.equal(params.length, 1);
79+
assert.equal(params.length, 2);
7680
assert.equal(params[0].name, 'test');
7781
assert.equal(params[0].optional, false);
78-
assert.equal(params[0].index, 0);
82+
assert.equal(params[1].name, 0);
83+
assert.equal(params[1].optional, false);
7984

8085
assert.equal(m.length, 3);
8186
assert.equal(m[0], '/pathone/pathtwo');
@@ -87,10 +92,11 @@ describe('path-to-regexp', function () {
8792
var params = [];
8893
var m = pathToRegExp('/*/:test', params).exec('/pathone/pathtwo');
8994

90-
assert.equal(params.length, 1);
91-
assert.equal(params[0].name, 'test');
95+
assert.equal(params.length, 2);
96+
assert.equal(params[0].name, 0);
9297
assert.equal(params[0].optional, false);
93-
assert.equal(params[0].index, 1);
98+
assert.equal(params[1].name, 'test');
99+
assert.equal(params[1].optional, false);
94100

95101
assert.equal(m.length, 3);
96102
assert.equal(m[0], '/pathone/pathtwo');
@@ -102,10 +108,11 @@ describe('path-to-regexp', function () {
102108
var params = [];
103109
var m = pathToRegExp('*/:test', params).exec('/pathone/pathtwo');
104110

105-
assert.equal(params.length, 1);
106-
assert.equal(params[0].name, 'test');
111+
assert.equal(params.length, 2);
112+
assert.equal(params[0].name, 0);
107113
assert.equal(params[0].optional, false);
108-
assert.equal(params[0].index, 1);
114+
assert.equal(params[1].name, 'test');
115+
assert.equal(params[1].optional, false);
109116

110117
assert.equal(m.length, 3);
111118
assert.equal(m[0], '/pathone/pathtwo');
@@ -117,16 +124,14 @@ describe('path-to-regexp', function () {
117124
var params = [];
118125
var m = pathToRegExp('*/:test/*/:foo/*/:bar/*', params).exec('/a/b/c/d/e/f/g');
119126

120-
assert.equal(params.length, 3);
121-
assert.equal(params[0].name, 'test');
122-
assert.equal(params[0].optional, false);
123-
assert.equal(params[0].index, 1);
124-
125-
assert.equal(params[1].name, 'foo');
126-
assert.equal(params[1].index, 3);
127-
128-
assert.equal(params[2].name, 'bar');
129-
assert.equal(params[2].index, 5);
127+
assert.equal(params.length, 7);
128+
assert.equal(params[0].name, 0);
129+
assert.equal(params[1].name, 'test');
130+
assert.equal(params[2].name, 1);
131+
assert.equal(params[3].name, 'foo');
132+
assert.equal(params[4].name, 2);
133+
assert.equal(params[5].name, 'bar');
134+
assert.equal(params[6].name, 3);
130135

131136
assert.equal(m.length, 8);
132137
assert.equal(m[0], '/a/b/c/d/e/f/g');
@@ -143,13 +148,13 @@ describe('path-to-regexp', function () {
143148
var params = [];
144149
var m = pathToRegExp('/:foo((\\d)+)/:bar', params).exec('/123/abc');
145150

146-
assert.equal(params.length, 2);
151+
assert.equal(params.length, 3);
147152
assert.equal(params[0].name, 'foo');
148153
assert.equal(params[0].optional, false);
149-
assert.equal(params[0].index, 0);
150-
assert.equal(params[1].name, 'bar');
154+
assert.equal(params[1].name, 0);
151155
assert.equal(params[1].optional, false);
152-
assert.equal(params[1].index, 2);
156+
assert.equal(params[2].name, 'bar');
157+
assert.equal(params[2].optional, false);
153158

154159
assert.equal(m.length, 4);
155160
assert.equal(m[0], '/123/abc');
@@ -283,7 +288,9 @@ describe('path-to-regexp', function () {
283288
var params = [];
284289
var m = pathToRegExp('/test*', params).exec('/test/route');
285290

286-
assert.equal(params.length, 0);
291+
assert.equal(params.length, 1);
292+
assert.equal(params[0].name, 0);
293+
assert.equal(params[0].optional, false);
287294

288295
assert.equal(m.length, 2);
289296
assert.equal(m[0], '/test/route');
@@ -295,9 +302,11 @@ describe('path-to-regexp', function () {
295302
var re = pathToRegExp('/:test*', params);
296303
var m;
297304

298-
assert.equal(params.length, 1);
305+
assert.equal(params.length, 2);
299306
assert.equal(params[0].name, 'test');
300307
assert.equal(params[0].optional, false);
308+
assert.equal(params[1].name, 0);
309+
assert.equal(params[1].optional, false);
301310

302311
m = re.exec('/test/route');
303312

@@ -319,7 +328,9 @@ describe('path-to-regexp', function () {
319328
var re = pathToRegExp('/test*.json', params);
320329
var m;
321330

322-
assert.equal(params.length, 0);
331+
assert.equal(params.length, 1);
332+
assert.equal(params[0].name, 0);
333+
assert.equal(params[0].optional, false);
323334

324335
m = re.exec('/test.json');
325336

@@ -345,9 +356,11 @@ describe('path-to-regexp', function () {
345356
var re = pathToRegExp('/:test*.json', params);
346357
var m;
347358

348-
assert.equal(params.length, 1);
359+
assert.equal(params.length, 2);
349360
assert.equal(params[0].name, 'test');
350361
assert.equal(params[0].optional, false);
362+
assert.equal(params[1].name, 0);
363+
assert.equal(params[1].optional, false);
351364

352365
m = re.exec('/testing.json');
353366

@@ -373,11 +386,13 @@ describe('path-to-regexp', function () {
373386
var re = pathToRegExp('/:test*.:format', params);
374387
var m;
375388

376-
assert.equal(params.length, 2);
389+
assert.equal(params.length, 3);
377390
assert.equal(params[0].name, 'test');
378391
assert.equal(params[0].optional, false);
379-
assert.equal(params[1].name, 'format');
392+
assert.equal(params[1].name, 0);
380393
assert.equal(params[1].optional, false);
394+
assert.equal(params[2].name, 'format');
395+
assert.equal(params[2].optional, false);
381396

382397
m = re.exec('/testing.json');
383398

@@ -409,11 +424,13 @@ describe('path-to-regexp', function () {
409424
var re = pathToRegExp('/:test*.:format?', params);
410425
var m;
411426

412-
assert.equal(params.length, 2);
427+
assert.equal(params.length, 3);
413428
assert.equal(params[0].name, 'test');
414429
assert.equal(params[0].optional, false);
415-
assert.equal(params[1].name, 'format');
416-
assert.equal(params[1].optional, true);
430+
assert.equal(params[1].name, 0);
431+
assert.equal(params[1].optional, false);
432+
assert.equal(params[2].name, 'format');
433+
assert.equal(params[2].optional, true);
417434

418435
m = re.exec('/testing.json');
419436

@@ -449,9 +466,11 @@ describe('path-to-regexp', function () {
449466
var re = pathToRegExp('/:test*?', params);
450467
var m;
451468

452-
assert.equal(params.length, 1);
469+
assert.equal(params.length, 2);
453470
assert.equal(params[0].name, 'test');
454471
assert.equal(params[0].optional, true);
472+
assert.equal(params[1].name, 0);
473+
assert.equal(params[1].optional, false);
455474

456475
m = re.exec('/test/route');
457476

@@ -688,6 +707,22 @@ describe('path-to-regexp', function () {
688707
it('should return the regexp', function () {
689708
assert.deepEqual(pathToRegExp(/.*/), /.*/);
690709
});
710+
711+
it('should pull out matching groups', function () {
712+
var params = [];
713+
var re = pathToRegExp(/(.*)/, params);
714+
var m;
715+
716+
assert.equal(params.length, 1);
717+
assert.equal(params[0].name, 0);
718+
assert.equal(params[0].optional, false);
719+
720+
m = re.exec('/route');
721+
722+
assert.equal(m.length, 2);
723+
assert.equal(m[0], '/route');
724+
assert.equal(m[1], '/route');
725+
});
691726
});
692727

693728
describe('arrays', function () {
@@ -701,28 +736,32 @@ describe('path-to-regexp', function () {
701736

702737
it('should match parts properly', function () {
703738
var params = [];
704-
var re = pathToRegExp(['/:test', '/test/:route'], params);
739+
var re = pathToRegExp(['/:test', '/*/route', '/test/:route'], params);
705740
var m;
706741

707-
assert.equal(params.length, 2);
742+
assert.equal(params.length, 3);
708743
assert.equal(params[0].name, 'test');
709744
assert.equal(params[0].optional, false);
710-
assert.equal(params[1].name, 'route');
745+
assert.equal(params[1].name, 0);
711746
assert.equal(params[1].optional, false);
747+
assert.equal(params[2].name, 'route');
748+
assert.equal(params[2].optional, false);
712749

713750
m = re.exec('/route');
714751

715-
assert.equal(m.length, 3);
752+
assert.equal(m.length, 4);
716753
assert.equal(m[0], '/route');
717754
assert.equal(m[1], 'route');
718755
assert.equal(m[2], undefined);
756+
assert.equal(m[3], undefined);
719757

720758
m = re.exec('/test/path');
721759

722-
assert.equal(m.length, 3);
760+
assert.equal(m.length, 4);
723761
assert.equal(m[0], '/test/path');
724762
assert.equal(m[1], undefined);
725-
assert.equal(m[2], 'path');
763+
assert.equal(m[2], undefined);
764+
assert.equal(m[3], 'path');
726765
});
727766
});
728767
});

0 commit comments

Comments
 (0)