path-to-regexp 2.4.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/History.md +5 -0
- package/Readme.md +48 -41
- package/index.d.ts +7 -8
- package/index.js +21 -25
- package/package.json +2 -2
package/History.md
CHANGED
package/Readme.md
CHANGED
@@ -18,7 +18,7 @@ npm install path-to-regexp --save
|
|
18
18
|
## Usage
|
19
19
|
|
20
20
|
```javascript
|
21
|
-
|
21
|
+
const pathToRegexp = require('path-to-regexp')
|
22
22
|
|
23
23
|
// pathToRegexp(path, keys?, options?)
|
24
24
|
// pathToRegexp.parse(path)
|
@@ -26,25 +26,24 @@ var pathToRegexp = require('path-to-regexp')
|
|
26
26
|
```
|
27
27
|
|
28
28
|
- **path** A string, array of strings, or a regular expression.
|
29
|
-
- **keys** An array to
|
29
|
+
- **keys** An array to populate with keys found in the path.
|
30
30
|
- **options**
|
31
31
|
- **sensitive** When `true` the regexp will be case sensitive. (default: `false`)
|
32
32
|
- **strict** When `true` the regexp allows an optional trailing delimiter to match. (default: `false`)
|
33
33
|
- **end** When `true` the regexp will match to the end of the string. (default: `true`)
|
34
34
|
- **start** When `true` the regexp will match from the beginning of the string. (default: `true`)
|
35
|
-
-
|
36
|
-
|
37
|
-
|
38
|
-
- **delimiters** List of characters to consider delimiters when parsing. (default: `'./'`)
|
35
|
+
- **delimiter** The default delimiter for segments. (default: `'/'`)
|
36
|
+
- **endsWith** Optional character, or list of characters, to treat as "end" characters.
|
37
|
+
- **whitelist** List of characters to consider delimiters when parsing. (default: `undefined`, any character)
|
39
38
|
|
40
39
|
```javascript
|
41
|
-
|
42
|
-
|
43
|
-
//
|
40
|
+
const keys = []
|
41
|
+
const regexp = pathToRegexp('/foo/:bar', keys)
|
42
|
+
// regexp = /^\/foo\/([^\/]+?)\/?$/i
|
44
43
|
// keys = [{ name: 'bar', prefix: '/', delimiter: '/', optional: false, repeat: false, pattern: '[^\\/]+?' }]
|
45
44
|
```
|
46
45
|
|
47
|
-
**Please note:** The `RegExp` returned by `path-to-regexp` is intended for ordered data (e.g. pathnames, hostnames). It
|
46
|
+
**Please note:** The `RegExp` returned by `path-to-regexp` is intended for ordered data (e.g. pathnames, hostnames). It can not handle arbitrarily ordered data (e.g. query strings, URL fragments, JSON, etc).
|
48
47
|
|
49
48
|
### Parameters
|
50
49
|
|
@@ -52,17 +51,17 @@ The path argument is used to define parameters and populate the list of keys.
|
|
52
51
|
|
53
52
|
#### Named Parameters
|
54
53
|
|
55
|
-
Named parameters are defined by prefixing a colon to the parameter name (`:foo`). By default, the parameter will match until the
|
54
|
+
Named parameters are defined by prefixing a colon to the parameter name (`:foo`). By default, the parameter will match until the next prefix (e.g. `[^/]+`).
|
56
55
|
|
57
56
|
```js
|
58
|
-
|
57
|
+
const regexp = pathToRegexp('/:foo/:bar')
|
59
58
|
// keys = [{ name: 'foo', prefix: '/', ... }, { name: 'bar', prefix: '/', ... }]
|
60
59
|
|
61
60
|
re.exec('/test/route')
|
62
61
|
//=> ['/test/route', 'test', 'route']
|
63
62
|
```
|
64
63
|
|
65
|
-
**Please note:** Parameter names must
|
64
|
+
**Please note:** Parameter names must use "word characters" (`[A-Za-z0-9_]`).
|
66
65
|
|
67
66
|
#### Parameter Modifiers
|
68
67
|
|
@@ -71,7 +70,7 @@ re.exec('/test/route')
|
|
71
70
|
Parameters can be suffixed with a question mark (`?`) to make the parameter optional.
|
72
71
|
|
73
72
|
```js
|
74
|
-
|
73
|
+
const regexp = pathToRegexp('/:foo/:bar?')
|
75
74
|
// keys = [{ name: 'foo', ... }, { name: 'bar', delimiter: '/', optional: true, repeat: false }]
|
76
75
|
|
77
76
|
re.exec('/test')
|
@@ -81,14 +80,14 @@ re.exec('/test/route')
|
|
81
80
|
//=> ['/test', 'test', 'route']
|
82
81
|
```
|
83
82
|
|
84
|
-
**Tip:**
|
83
|
+
**Tip:** The prefix is also optional, escape the prefix `\/` to make it required.
|
85
84
|
|
86
85
|
##### Zero or more
|
87
86
|
|
88
|
-
Parameters can be suffixed with an asterisk (`*`) to denote a zero or more parameter matches. The prefix is
|
87
|
+
Parameters can be suffixed with an asterisk (`*`) to denote a zero or more parameter matches. The prefix is used for each match.
|
89
88
|
|
90
89
|
```js
|
91
|
-
|
90
|
+
const regexp = pathToRegexp('/:foo*')
|
92
91
|
// keys = [{ name: 'foo', delimiter: '/', optional: true, repeat: true }]
|
93
92
|
|
94
93
|
re.exec('/')
|
@@ -100,10 +99,10 @@ re.exec('/bar/baz')
|
|
100
99
|
|
101
100
|
##### One or more
|
102
101
|
|
103
|
-
Parameters can be suffixed with a plus sign (`+`) to denote a one or more parameter matches. The prefix is
|
102
|
+
Parameters can be suffixed with a plus sign (`+`) to denote a one or more parameter matches. The prefix is used for each match.
|
104
103
|
|
105
104
|
```js
|
106
|
-
|
105
|
+
const regexp = pathToRegexp('/:foo+')
|
107
106
|
// keys = [{ name: 'foo', delimiter: '/', optional: false, repeat: true }]
|
108
107
|
|
109
108
|
re.exec('/')
|
@@ -113,41 +112,50 @@ re.exec('/bar/baz')
|
|
113
112
|
//=> ['/bar/baz', 'bar/baz']
|
114
113
|
```
|
115
114
|
|
115
|
+
#### Unnamed Parameters
|
116
|
+
|
117
|
+
It is possible to write an unnamed parameter that only consists of a matching group. It works the same as a named parameter, except it will be numerically indexed.
|
118
|
+
|
119
|
+
```js
|
120
|
+
const regexp = pathToRegexp('/:foo/(.*)')
|
121
|
+
// keys = [{ name: 'foo', ... }, { name: 0, ... }]
|
122
|
+
|
123
|
+
regexp.exec('/test/route')
|
124
|
+
//=> ['/test/route', 'test', 'route']
|
125
|
+
```
|
126
|
+
|
116
127
|
#### Custom Matching Parameters
|
117
128
|
|
118
|
-
All parameters can
|
129
|
+
All parameters can have a custom regexp, which overrides the default match (`[^/]+`). For example, you can match digits or names in a path:
|
119
130
|
|
120
131
|
```js
|
121
|
-
|
132
|
+
const regexpNumbers = pathToRegexp('/icon-:foo(\\d+).png')
|
122
133
|
// keys = [{ name: 'foo', ... }]
|
123
134
|
|
124
|
-
|
135
|
+
regexpNumbers.exec('/icon-123.png')
|
125
136
|
//=> ['/icon-123.png', '123']
|
126
137
|
|
127
|
-
|
138
|
+
regexpNumbers.exec('/icon-abc.png')
|
128
139
|
//=> null
|
129
|
-
```
|
130
140
|
|
131
|
-
|
141
|
+
const regexpWord = pathToRegexp('/(user|u)')
|
142
|
+
// keys = [{ name: 0, ... }]
|
132
143
|
|
133
|
-
|
134
|
-
|
135
|
-
It is possible to write an unnamed parameter that only consists of a matching group. It works the same as a named parameter, except it will be numerically indexed.
|
136
|
-
|
137
|
-
```js
|
138
|
-
var re = pathToRegexp('/:foo/(.*)')
|
139
|
-
// keys = [{ name: 'foo', ... }, { name: 0, ... }]
|
144
|
+
regexpWord.exec('/u')
|
145
|
+
//=> ['/u', 'u']
|
140
146
|
|
141
|
-
|
142
|
-
//=>
|
147
|
+
regexpWord.exec('/users')
|
148
|
+
//=> null
|
143
149
|
```
|
144
150
|
|
151
|
+
**Tip:** Backslashes need to be escaped with another backslash in JavaScript strings.
|
152
|
+
|
145
153
|
### Parse
|
146
154
|
|
147
155
|
The parse function is exposed via `pathToRegexp.parse`. This will return an array of strings and keys.
|
148
156
|
|
149
157
|
```js
|
150
|
-
|
158
|
+
const tokens = pathToRegexp.parse('/route/:foo/(.*)')
|
151
159
|
|
152
160
|
console.log(tokens[0])
|
153
161
|
//=> "/route"
|
@@ -166,7 +174,7 @@ console.log(tokens[2])
|
|
166
174
|
Path-To-RegExp exposes a compile function for transforming a string into a valid path.
|
167
175
|
|
168
176
|
```js
|
169
|
-
|
177
|
+
const toPath = pathToRegexp.compile('/user/:id')
|
170
178
|
|
171
179
|
toPath({ id: 123 }) //=> "/user/123"
|
172
180
|
toPath({ id: 'café' }) //=> "/user/caf%C3%A9"
|
@@ -175,12 +183,12 @@ toPath({ id: '/' }) //=> "/user/%2F"
|
|
175
183
|
toPath({ id: ':/' }) //=> "/user/%3A%2F"
|
176
184
|
toPath({ id: ':/' }, { encode: (value, token) => value }) //=> "/user/:/"
|
177
185
|
|
178
|
-
|
186
|
+
const toPathRepeated = pathToRegexp.compile('/:segment+')
|
179
187
|
|
180
188
|
toPathRepeated({ segment: 'foo' }) //=> "/foo"
|
181
189
|
toPathRepeated({ segment: ['a', 'b', 'c'] }) //=> "/a/b/c"
|
182
190
|
|
183
|
-
|
191
|
+
const toPathRegexp = pathToRegexp.compile('/user/:id(\\d+)')
|
184
192
|
|
185
193
|
toPathRegexp({ id: 123 }) //=> "/user/123"
|
186
194
|
toPathRegexp({ id: '123' }) //=> "/user/123"
|
@@ -199,11 +207,10 @@ Path-To-RegExp exposes the two functions used internally that accept an array of
|
|
199
207
|
#### Token Information
|
200
208
|
|
201
209
|
* `name` The name of the token (`string` for named or `number` for index)
|
202
|
-
* `prefix` The prefix character for the segment (`/`
|
203
|
-
* `delimiter` The delimiter for the segment (same as prefix or
|
210
|
+
* `prefix` The prefix character for the segment (e.g. `/`)
|
211
|
+
* `delimiter` The delimiter for the segment (same as prefix or default delimiter)
|
204
212
|
* `optional` Indicates the token is optional (`boolean`)
|
205
213
|
* `repeat` Indicates the token is repeated (`boolean`)
|
206
|
-
* `partial` Indicates this token is a partial path segment (`boolean`)
|
207
214
|
* `pattern` The RegExp used to match this token (`string`)
|
208
215
|
|
209
216
|
## Compatibility with Express <= 4.x
|
package/index.d.ts
CHANGED
@@ -26,6 +26,10 @@ declare namespace pathToRegexp {
|
|
26
26
|
* List of characters that can also be "end" characters.
|
27
27
|
*/
|
28
28
|
endsWith?: string | string[];
|
29
|
+
/**
|
30
|
+
* List of characters to consider delimiters when parsing. (default: `undefined`, any character)
|
31
|
+
*/
|
32
|
+
whitelist?: string | string[];
|
29
33
|
}
|
30
34
|
|
31
35
|
export interface ParseOptions {
|
@@ -33,10 +37,6 @@ declare namespace pathToRegexp {
|
|
33
37
|
* Set the default delimiter for repeat parameters. (default: `'/'`)
|
34
38
|
*/
|
35
39
|
delimiter?: string;
|
36
|
-
/**
|
37
|
-
* List of valid delimiter characters. (default: `'./'`)
|
38
|
-
*/
|
39
|
-
delimiters?: string | string[];
|
40
40
|
}
|
41
41
|
|
42
42
|
/**
|
@@ -47,12 +47,12 @@ declare namespace pathToRegexp {
|
|
47
47
|
/**
|
48
48
|
* Transforming an Express-style path into a valid path.
|
49
49
|
*/
|
50
|
-
export function compile (path: string, options?: ParseOptions): PathFunction
|
50
|
+
export function compile <P extends object = object> (path: string, options?: ParseOptions): PathFunction<P>;
|
51
51
|
|
52
52
|
/**
|
53
53
|
* Transform an array of tokens into a path generator function.
|
54
54
|
*/
|
55
|
-
export function tokensToFunction (tokens: Token[]): PathFunction
|
55
|
+
export function tokensToFunction <P extends object = object> (tokens: Token[]): PathFunction<P>;
|
56
56
|
|
57
57
|
/**
|
58
58
|
* Transform an array of tokens into a matching regular expression.
|
@@ -66,7 +66,6 @@ declare namespace pathToRegexp {
|
|
66
66
|
optional: boolean;
|
67
67
|
repeat: boolean;
|
68
68
|
pattern: string;
|
69
|
-
partial: boolean;
|
70
69
|
}
|
71
70
|
|
72
71
|
interface PathFunctionOptions {
|
@@ -78,7 +77,7 @@ declare namespace pathToRegexp {
|
|
78
77
|
|
79
78
|
export type Token = string | Key;
|
80
79
|
export type Path = string | RegExp | Array<string | RegExp>;
|
81
|
-
export type PathFunction = (data?:
|
80
|
+
export type PathFunction <P extends object = object> = (data?: P, options?: PathFunctionOptions) => string;
|
82
81
|
}
|
83
82
|
|
84
83
|
export = pathToRegexp;
|
package/index.js
CHANGED
@@ -11,7 +11,6 @@ module.exports.tokensToRegExp = tokensToRegExp
|
|
11
11
|
* Default configs.
|
12
12
|
*/
|
13
13
|
var DEFAULT_DELIMITER = '/'
|
14
|
-
var DEFAULT_DELIMITERS = './'
|
15
14
|
|
16
15
|
/**
|
17
16
|
* The main path matching regexp utility.
|
@@ -43,7 +42,7 @@ function parse (str, options) {
|
|
43
42
|
var index = 0
|
44
43
|
var path = ''
|
45
44
|
var defaultDelimiter = (options && options.delimiter) || DEFAULT_DELIMITER
|
46
|
-
var
|
45
|
+
var whitelist = (options && options.whitelist) || undefined
|
47
46
|
var pathEscaped = false
|
48
47
|
var res
|
49
48
|
|
@@ -62,7 +61,6 @@ function parse (str, options) {
|
|
62
61
|
}
|
63
62
|
|
64
63
|
var prev = ''
|
65
|
-
var next = str[index]
|
66
64
|
var name = res[2]
|
67
65
|
var capture = res[3]
|
68
66
|
var group = res[4]
|
@@ -70,9 +68,11 @@ function parse (str, options) {
|
|
70
68
|
|
71
69
|
if (!pathEscaped && path.length) {
|
72
70
|
var k = path.length - 1
|
71
|
+
var c = path[k]
|
72
|
+
var matches = whitelist ? whitelist.indexOf(c) > -1 : true
|
73
73
|
|
74
|
-
if (
|
75
|
-
prev =
|
74
|
+
if (matches) {
|
75
|
+
prev = c
|
76
76
|
path = path.slice(0, k)
|
77
77
|
}
|
78
78
|
}
|
@@ -84,11 +84,10 @@ function parse (str, options) {
|
|
84
84
|
pathEscaped = false
|
85
85
|
}
|
86
86
|
|
87
|
-
var partial = prev !== '' && next !== undefined && next !== prev
|
88
87
|
var repeat = modifier === '+' || modifier === '*'
|
89
88
|
var optional = modifier === '?' || modifier === '*'
|
90
|
-
var delimiter = prev || defaultDelimiter
|
91
89
|
var pattern = capture || group
|
90
|
+
var delimiter = prev || defaultDelimiter
|
92
91
|
|
93
92
|
tokens.push({
|
94
93
|
name: name || key++,
|
@@ -96,8 +95,9 @@ function parse (str, options) {
|
|
96
95
|
delimiter: delimiter,
|
97
96
|
optional: optional,
|
98
97
|
repeat: repeat,
|
99
|
-
|
100
|
-
|
98
|
+
pattern: pattern
|
99
|
+
? escapeGroup(pattern)
|
100
|
+
: '[^' + escapeString(delimiter === defaultDelimiter ? delimiter : (delimiter + defaultDelimiter)) + ']+?'
|
101
101
|
})
|
102
102
|
}
|
103
103
|
|
@@ -184,12 +184,7 @@ function tokensToFunction (tokens) {
|
|
184
184
|
continue
|
185
185
|
}
|
186
186
|
|
187
|
-
if (token.optional)
|
188
|
-
// Prepend partial segment prefixes.
|
189
|
-
if (token.partial) path += token.prefix
|
190
|
-
|
191
|
-
continue
|
192
|
-
}
|
187
|
+
if (token.optional) continue
|
193
188
|
|
194
189
|
throw new TypeError('Expected "' + token.name + '" to be ' + (token.repeat ? 'an array' : 'a string'))
|
195
190
|
}
|
@@ -249,7 +244,6 @@ function regexpToRegexp (path, keys) {
|
|
249
244
|
delimiter: null,
|
250
245
|
optional: false,
|
251
246
|
repeat: false,
|
252
|
-
partial: false,
|
253
247
|
pattern: null
|
254
248
|
})
|
255
249
|
}
|
@@ -302,11 +296,9 @@ function tokensToRegExp (tokens, keys, options) {
|
|
302
296
|
var strict = options.strict
|
303
297
|
var start = options.start !== false
|
304
298
|
var end = options.end !== false
|
305
|
-
var delimiter =
|
306
|
-
var delimiters = options.delimiters || DEFAULT_DELIMITERS
|
299
|
+
var delimiter = options.delimiter || DEFAULT_DELIMITER
|
307
300
|
var endsWith = [].concat(options.endsWith || []).map(escapeString).concat('$').join('|')
|
308
301
|
var route = start ? '^' : ''
|
309
|
-
var isEndDelimited = tokens.length === 0
|
310
302
|
|
311
303
|
// Iterate over the tokens and create our regexp string.
|
312
304
|
for (var i = 0; i < tokens.length; i++) {
|
@@ -314,7 +306,6 @@ function tokensToRegExp (tokens, keys, options) {
|
|
314
306
|
|
315
307
|
if (typeof token === 'string') {
|
316
308
|
route += escapeString(token)
|
317
|
-
isEndDelimited = i === tokens.length - 1 && delimiters.indexOf(token[token.length - 1]) > -1
|
318
309
|
} else {
|
319
310
|
var capture = token.repeat
|
320
311
|
? '(?:' + token.pattern + ')(?:' + escapeString(token.delimiter) + '(?:' + token.pattern + '))*'
|
@@ -323,8 +314,8 @@ function tokensToRegExp (tokens, keys, options) {
|
|
323
314
|
if (keys) keys.push(token)
|
324
315
|
|
325
316
|
if (token.optional) {
|
326
|
-
if (token.
|
327
|
-
route +=
|
317
|
+
if (!token.prefix) {
|
318
|
+
route += '(' + capture + ')?'
|
328
319
|
} else {
|
329
320
|
route += '(?:' + escapeString(token.prefix) + '(' + capture + '))?'
|
330
321
|
}
|
@@ -335,12 +326,17 @@ function tokensToRegExp (tokens, keys, options) {
|
|
335
326
|
}
|
336
327
|
|
337
328
|
if (end) {
|
338
|
-
if (!strict) route += '(?:' + delimiter + ')?'
|
329
|
+
if (!strict) route += '(?:' + escapeString(delimiter) + ')?'
|
339
330
|
|
340
331
|
route += endsWith === '$' ? '$' : '(?=' + endsWith + ')'
|
341
332
|
} else {
|
342
|
-
|
343
|
-
|
333
|
+
var endToken = tokens[tokens.length - 1]
|
334
|
+
var isEndDelimited = typeof endToken === 'string'
|
335
|
+
? endToken[endToken.length - 1] === delimiter
|
336
|
+
: endToken === undefined
|
337
|
+
|
338
|
+
if (!strict) route += '(?:' + escapeString(delimiter) + '(?=' + endsWith + '))?'
|
339
|
+
if (!isEndDelimited) route += '(?=' + escapeString(delimiter) + '|' + endsWith + ')'
|
344
340
|
}
|
345
341
|
|
346
342
|
return new RegExp(route, flags(options))
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "path-to-regexp",
|
3
3
|
"description": "Express style path to RegExp utility",
|
4
|
-
"version": "
|
4
|
+
"version": "3.0.0",
|
5
5
|
"main": "index.js",
|
6
6
|
"typings": "index.d.ts",
|
7
7
|
"files": [
|
@@ -38,7 +38,7 @@
|
|
38
38
|
"chai": "^4.1.1",
|
39
39
|
"istanbul": "^0.4.5",
|
40
40
|
"mocha": "^5.2.0",
|
41
|
-
"standard": "^
|
41
|
+
"standard": "^12.0.1",
|
42
42
|
"ts-node": "^7.0.1",
|
43
43
|
"typescript": "^3.0.1"
|
44
44
|
}
|