1
1
/**
2
- * Expose `pathtoRegexp `.
2
+ * Expose `pathToRegexp `.
3
3
*/
4
4
5
- module . exports = pathtoRegexp ;
5
+ module . exports = pathToRegexp ;
6
6
7
7
/**
8
8
* Match matching groups in a regular expression.
9
9
*/
10
- var MATCHING_GROUP_REGEXP = / \( (?: \? < ( .* ?) > ) ? (? ! \? ) / g;
10
+ var MATCHING_GROUP_REGEXP = / \\ . | \ ((?: \? < ( .* ?) > ) ? (? ! \? ) / g;
11
11
12
12
/**
13
13
* Normalize the given path string,
@@ -25,7 +25,7 @@ var MATCHING_GROUP_REGEXP = /\((?:\?<(.*?)>)?(?!\?)/g;
25
25
* @api private
26
26
*/
27
27
28
- function pathtoRegexp ( path , keys , options ) {
28
+ function pathToRegexp ( path , keys , options ) {
29
29
options = options || { } ;
30
30
keys = keys || [ ] ;
31
31
var strict = options . strict ;
@@ -36,10 +36,14 @@ function pathtoRegexp(path, keys, options) {
36
36
var keysOffset = keys . length ;
37
37
var i = 0 ;
38
38
var name = 0 ;
39
+ var pos = 0 ;
40
+ var backtrack = '' ;
39
41
var m ;
40
42
41
43
if ( path instanceof RegExp ) {
42
44
while ( m = MATCHING_GROUP_REGEXP . exec ( path . source ) ) {
45
+ if ( m [ 0 ] [ 0 ] === '\\' ) continue ;
46
+
43
47
keys . push ( {
44
48
name : m [ 1 ] || name ++ ,
45
49
optional : false ,
@@ -55,62 +59,68 @@ function pathtoRegexp(path, keys, options) {
55
59
// the same keys and options instance into every generation to get
56
60
// consistent matching groups before we join the sources together.
57
61
path = path . map ( function ( value ) {
58
- return pathtoRegexp ( value , keys , options ) . source ;
62
+ return pathToRegexp ( value , keys , options ) . source ;
59
63
} ) ;
60
64
61
- return new RegExp ( '(?:' + path . join ( '|' ) + ')' , flags ) ;
65
+ return new RegExp ( path . join ( '|' ) , flags ) ;
62
66
}
63
67
64
- path = ( '^' + path + ( strict ? '' : path [ path . length - 1 ] === '/' ? '?' : '/?' ) )
65
- . replace ( / \/ \( / g, '/(?:' )
66
- . replace ( / ( [ \/ \. ] ) / g, '\\$1' )
67
- . replace ( / ( \\ \/ ) ? ( \\ \. ) ? : ( \w + ) ( \( .* ?\) ) ? ( \* ) ? ( \? ) ? / g, function ( match , slash , format , key , capture , star , optional , offset ) {
68
+ path = path . replace (
69
+ / \\ .| ( \/ ) ? ( \. ) ? : ( \w + ) ( \( .* ?\) ) ? ( \* ) ? ( \? ) ? | [ . * ] | \/ \( / g,
70
+ function ( match , slash , format , key , capture , star , optional , offset ) {
71
+ pos = offset + match . length ;
72
+
73
+ if ( match [ 0 ] === '\\' ) {
74
+ backtrack += match ;
75
+ return match ;
76
+ }
77
+
78
+ if ( match === '.' ) {
79
+ backtrack += '\\.' ;
80
+ extraOffset += 1 ;
81
+ return '\\.' ;
82
+ }
83
+
84
+ backtrack = slash || format ? '' : path . slice ( pos , offset ) ;
85
+
86
+ if ( match === '*' ) {
87
+ extraOffset += 3 ;
88
+ return '(.*)' ;
89
+ }
90
+
91
+ if ( match === '/(' ) {
92
+ backtrack += '/' ;
93
+ extraOffset += 2 ;
94
+ return '/(?:' ;
95
+ }
96
+
68
97
slash = slash || '' ;
69
- format = format || '' ;
70
- capture = capture || '([^\\/' + format + ']+?)' ;
98
+ format = format ? '\\.' : '' ;
71
99
optional = optional || '' ;
100
+ capture = capture ?
101
+ capture . replace ( / \\ .| \* / , function ( m ) { return m === '*' ? '(.*)' : m ; } ) :
102
+ ( backtrack ? '((?:(?!/|' + backtrack + ').)+?)' : '([^/' + format + ']+?)' ) ;
72
103
73
104
keys . push ( {
74
105
name : key ,
75
106
optional : ! ! optional ,
76
107
offset : offset + extraOffset
77
108
} ) ;
78
109
79
- var result = ''
80
- + ( optional ? '' : slash )
81
- + '(?:'
82
- + format + ( optional ? slash : '' ) + capture
83
- + ( star ? '((?:[\\/' + format + '].+?)?)' : '' )
110
+ var result = '(?:'
111
+ + format + slash + capture
112
+ + ( star ? '((?:[/' + format + '].+?)?)' : '' )
84
113
+ ')'
85
114
+ optional ;
86
115
87
116
extraOffset += result . length - match . length ;
88
117
89
118
return result ;
90
- } )
91
- . replace ( / \* / g, function ( star , index ) {
92
- var len = keys . length
93
-
94
- while ( len -- > keysOffset && keys [ len ] . offset > index ) {
95
- keys [ len ] . offset += 3 ; // Replacement length minus asterisk length.
96
- }
97
-
98
- return '(.*)' ;
99
119
} ) ;
100
120
101
121
// This is a workaround for handling unnamed matching groups.
102
122
while ( m = MATCHING_GROUP_REGEXP . exec ( path ) ) {
103
- var escapeCount = 0 ;
104
- var index = m . index ;
105
-
106
- while ( path . charAt ( -- index ) === '\\' ) {
107
- escapeCount ++ ;
108
- }
109
-
110
- // It's possible to escape the bracket.
111
- if ( escapeCount % 2 === 1 ) {
112
- continue ;
113
- }
123
+ if ( m [ 0 ] [ 0 ] === '\\' ) continue ;
114
124
115
125
if ( keysOffset + i === keys . length || keys [ keysOffset + i ] . offset > m . index ) {
116
126
keys . splice ( keysOffset + i , 0 , {
@@ -123,12 +133,14 @@ function pathtoRegexp(path, keys, options) {
123
133
i ++ ;
124
134
}
125
135
136
+ path += strict ? '' : path [ path . length - 1 ] === '/' ? '?' : '/?' ;
137
+
126
138
// If the path is non-ending, match until the end or a slash.
127
139
if ( end ) {
128
140
path += '$' ;
129
141
} else if ( path [ path . length - 1 ] !== '/' ) {
130
- path += lookahead ? '(?=\\ /|$)' : '(?:\ /|$)' ;
142
+ path += lookahead ? '(?=/|$)' : '(?:/|$)' ;
131
143
}
132
144
133
- return new RegExp ( path , flags ) ;
145
+ return new RegExp ( '^' + path , flags ) ;
134
146
} ;
0 commit comments