path-to-regexp
Advanced tools
Comparing version 0.1.2 to 0.2.0
{ | ||
"name": "path-to-regexp", | ||
"description": "Express style path to RegExp utility", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"keywords": [ | ||
@@ -6,0 +6,0 @@ "express", |
@@ -0,6 +1,29 @@ | ||
0.2.0 / 2014-06-09 | ||
================== | ||
* Improved support for arrays | ||
* Improved support for regexps | ||
* Better support for non-ending strict mode matches with a trailing slash | ||
* Travis CI support | ||
* Block using regexp special characters in the path | ||
* Removed support for the asterisk to match all | ||
* New support for parameter suffixes - `*`, `+` and `?` | ||
* Updated readme | ||
* Provide delimiter information with keys array | ||
0.1.2 / 2014-03-10 | ||
================== | ||
* Move testing dependencies to `devDependencies` | ||
0.1.1 / 2014-03-10 | ||
================== | ||
* Match entire substring with `options.end` | ||
* Properly handle ending and non-ending matches | ||
0.1.0 / 2014-03-06 | ||
================== | ||
* add options.end | ||
* Add `options.end` | ||
@@ -11,2 +34,2 @@ 0.0.2 / 2013-02-10 | ||
* Update to match current express | ||
* add .license property to component.json | ||
* Add .license property to component.json |
159
index.js
/** | ||
* Expose `pathtoRegexp`. | ||
*/ | ||
module.exports = pathtoRegexp; | ||
var PATH_REGEXP = new RegExp([ | ||
// Match already escaped characters that would otherwise incorrectly appear | ||
// in future matches. This allows the user to escape special characters that | ||
// shouldn't be transformed. | ||
'(\\\\.)', | ||
// Match Express-style parameters and un-named parameters with a prefix | ||
// and optional suffixes. Matches appear as: | ||
// | ||
// "/:test(\\d+)?" => ["/", "test", "\d+", undefined, "?"] | ||
// "/route(\\d+)" => [undefined, undefined, undefined, "\d+", undefined] | ||
'([\\/.])?(?:\\:(\\w+)(?:\\((.+)\\))?|\\((.+)\\))([+*?])?', | ||
// Match regexp special characters that should always be escaped. | ||
'([.+*?=^!:${}()[\\]|\\/])' | ||
].join('|'), 'g'); | ||
/** | ||
* Normalize the given path string, | ||
* returning a regular expression. | ||
* Escape the capturing group by escaping special characters and meaning. | ||
* | ||
* An empty array should be passed, | ||
* which will contain the placeholder | ||
* key names. For example "/user/:id" will | ||
* then contain ["id"]. | ||
* @param {String} group | ||
* @return {String} | ||
*/ | ||
function escapeGroup (group) { | ||
return group.replace(/([=!:$\/()])/g, '\\$1'); | ||
} | ||
/** | ||
* Normalize the given path string, returning a regular expression. | ||
* | ||
* @param {String|RegExp|Array} path | ||
* @param {Array} keys | ||
* @param {Object} options | ||
* An empty array should be passed in, which will contain the placeholder key | ||
* names. For example `/user/:id` will then contain `["id"]`. | ||
* | ||
* @param {(String|RegExp|Array)} path | ||
* @param {Array} keys | ||
* @param {Object} options | ||
* @return {RegExp} | ||
* @api private | ||
*/ | ||
function pathtoRegexp (path, keys, options) { | ||
keys = keys || []; | ||
options = options || {}; | ||
function pathtoRegexp(path, keys, options) { | ||
options = options || {}; | ||
var sensitive = options.sensitive; | ||
var strict = options.strict; | ||
var end = options.end !== false; | ||
keys = keys || []; | ||
var flags = options.sensitive ? '' : 'i'; | ||
var index = 0; | ||
if (path instanceof RegExp) return path; | ||
if (path instanceof Array) path = '(' + path.join('|') + ')'; | ||
if (path instanceof RegExp) { | ||
// Match all capturing groups of a regexp. | ||
var groups = path.source.match(/\((?!\?)/g) || []; | ||
path = path | ||
.concat(strict ? '' : '/?') | ||
.replace(/\/\(/g, '/(?:') | ||
.replace(/([\/\.])/g, '\\$1') | ||
.replace(/(\\\/)?(\\\.)?:(\w+)(\(.*?\))?(\*)?(\?)?/g, function (match, slash, format, key, capture, star, optional) { | ||
slash = slash || ''; | ||
format = format || ''; | ||
capture = capture || '([^/' + format + ']+?)'; | ||
optional = optional || ''; | ||
// Map all the matches to their numeric keys and push into the keys. | ||
keys.push.apply(keys, groups.map(function (match, index) { | ||
return { | ||
name: index, | ||
delimiter: null, | ||
optional: false, | ||
repeat: false | ||
}; | ||
})); | ||
keys.push({ name: key, optional: !!optional }); | ||
// Return the source back to the user. | ||
return path; | ||
} | ||
return '' | ||
+ (optional ? '' : slash) | ||
+ '(?:' | ||
+ format + (optional ? slash : '') + capture | ||
+ (star ? '((?:[\\/' + format + '].+?)?)' : '') | ||
+ ')' | ||
+ optional; | ||
}) | ||
.replace(/\*/g, '(.*)'); | ||
if (Array.isArray(path)) { | ||
// Map array parts into regexps and return their source. We also pass | ||
// the same keys and options instance into every generation to get | ||
// consistent matching groups before we join the sources together. | ||
path = path.map(function (value) { | ||
return pathtoRegexp(value, keys, options).source; | ||
}); | ||
return new RegExp('^' + path + (end ? '$' : '(?=\/|$)'), sensitive ? '' : 'i'); | ||
// Generate a new regexp instance by joining all the parts together. | ||
return new RegExp('(?:' + path.join('|') + ')', flags); | ||
} | ||
// Alter the path string into a usable regexp. | ||
path = path.replace(PATH_REGEXP, function (match, escaped, prefix, key, capture, group, suffix, escape) { | ||
// Avoiding re-escaping escaped characters. | ||
if (escaped) { | ||
return escaped; | ||
} | ||
// Escape regexp special characters. | ||
if (escape) { | ||
return '\\' + escape; | ||
} | ||
keys.push({ | ||
name: key || index++, | ||
delimiter: prefix || '/', | ||
optional: suffix === '?' || suffix === '*', | ||
repeat: suffix === '+' || suffix === '*' | ||
}); | ||
// Escape the prefix character. | ||
prefix = prefix ? '\\' + prefix : ''; | ||
// Match using the custom capturing group, or fallback to capturing | ||
// everything up to the next slash (or next period if the param was | ||
// prefixed with a period). | ||
capture = escapeGroup(capture || group || '[^' + (prefix || '\\/') + ']+?'); | ||
// More complex regexp is required for suffix support. | ||
if (suffix) { | ||
if (suffix === '+') { | ||
return prefix + '(' + capture + '(?:' + prefix + capture + ')*)' | ||
} | ||
if (suffix === '*') { | ||
return '(?:' + prefix + '(' + capture + '(?:' + prefix + capture + ')*|' + capture + '))?'; | ||
} | ||
return '(?:' + prefix + '(' + capture + '))?'; | ||
} | ||
// Basic parameter support. | ||
return prefix + '(' + capture + ')'; | ||
}); | ||
if (path[path.length - 1] !== '/') { | ||
// If we are doing a non-ending match, we need to prompt the matching groups | ||
// to match as much as possible. To do this, we add a positive lookahead for | ||
// the next path fragment or the end. However, if the regexp already ends | ||
// in a path fragment, we'll run into problems. | ||
if (!end) { | ||
path += '(?=\\/|$)'; | ||
} | ||
// Allow trailing slashes to be matched in non-strict, ending mode. | ||
if (end && !strict) { | ||
path += '\\/?'; | ||
} | ||
} | ||
return new RegExp('^' + path + (end ? '$' : ''), flags); | ||
}; |
{ | ||
"name": "path-to-regexp", | ||
"description": "Express style path to RegExp utility", | ||
"version": "0.1.2", | ||
"version": "0.2.0", | ||
"scripts": { | ||
"test": "istanbul cover _mocha -- -R spec" | ||
"test": "istanbul cover node_modules/mocha/bin/_mocha -- -R spec" | ||
}, | ||
"keywords": [ | ||
"express", | ||
"regexp" | ||
"regexp", | ||
"route", | ||
"routing" | ||
], | ||
@@ -22,5 +24,5 @@ "component": { | ||
"devDependencies": { | ||
"mocha": "^1.17.1", | ||
"istanbul": "^0.2.6" | ||
"istanbul": "~0.2.6", | ||
"mocha": "~1.18.2" | ||
} | ||
} |
128
Readme.md
@@ -1,6 +0,8 @@ | ||
# Path-to-RegExp | ||
Turn an Express-style path string such as `/user/:name` into a regular expression. | ||
Turn an Express-style path string such as `/user/:name` into a regular expression. | ||
[![Build Status](https://img.shields.io/travis/component/path-to-regexp/master.svg)](https://travis-ci.org/component/path-to-regexp) | ||
[![NPM version](https://img.shields.io/npm/v/path-to-regexp.svg)](https://www.npmjs.org/package/path-to-regexp) | ||
## Usage | ||
@@ -10,19 +12,119 @@ | ||
var pathToRegexp = require('path-to-regexp'); | ||
// pathToRegexp(path, keys, options); | ||
``` | ||
### pathToRegexp(path, keys, options) | ||
- **path** A string in the express format, an array of such strings, or a regular expression | ||
- **keys** An array to be populated with the keys present in the url. Once the function completes, this will be an array of strings. | ||
- **options** | ||
- **options.sensitive** Defaults to false, set this to true to make routes case sensitive | ||
- **options.strict** Defaults to false, set this to true to make the trailing slash matter. | ||
- **options.end** Defaults to true, set this to false to only match the prefix of the URL. | ||
- **path** A string in the express format, an array of strings, or a regular expression. | ||
- **keys** An array to be populated with the keys present in the url. | ||
- **options** | ||
- **options.sensitive** When set to `true` the route will be case sensitive. | ||
- **options.strict** When set to `true` a slash is allowed to be trailing the path. | ||
- **options.end** When set to `false` the path will match at the beginning. | ||
```javascript | ||
var keys = []; | ||
var exp = pathToRegexp('/foo/:bar', keys); | ||
//keys = ['bar'] | ||
//exp = /^\/foo\/(?:([^\/]+?))\/?$/i | ||
var re = pathToRegexp('/foo/:bar', keys); | ||
// re = /^\/foo\/([^\/]+?)\/?$/i | ||
// keys = [{ name: 'bar', delimiter: '/', repeat: false, optional: false }] | ||
``` | ||
### Parameters | ||
The path has the ability to define parameters and automatically populate the keys array. | ||
#### Named Parameters | ||
Named parameters are defined by prefixing a colon to the parameter name (`:foo`). By default, this parameter will match up to the next path segment. | ||
```js | ||
var re = pathToRegexp('/:foo/:bar', keys); | ||
// keys = [{ name: 'foo', ... }, { name: 'bar', ... }] | ||
re.exec('/test/route'); | ||
//=> ['/test/route', 'test', 'route'] | ||
``` | ||
#### Suffixed Parameters | ||
##### Optional | ||
Parameters can be suffixed with a question mark (`?`) to make the entire parameter optional. This will also make any prefixed path delimiter optional (`/` or `.`). | ||
```js | ||
var re = pathToRegexp('/:foo/:bar?', keys); | ||
// keys = [{ name: 'foo', ... }, { name: 'bar', delimiter: '/', optional: true, repeat: false }] | ||
re.exec('/test'); | ||
//=> ['/test', 'test', undefined] | ||
re.exec('/test/route'); | ||
//=> ['/test', 'test', 'route'] | ||
``` | ||
##### Zero or more | ||
Parameters can be suffixed with an asterisk (`*`) to denote a zero or more parameter match. The prefixed path delimiter is also taken into account for the match. | ||
```js | ||
var re = pathToRegexp('/:foo*', keys); | ||
// keys = [{ name: 'foo', delimiter: '/', optional: true, repeat: true }] | ||
re.exec('/'); | ||
//=> ['/', undefined] | ||
re.exec('/bar/baz'); | ||
//=> ['/bar/baz', 'bar/baz'] | ||
``` | ||
##### One or more | ||
Parameters can be suffixed with a plus sign (`+`) to denote a one or more parameters match. The prefixed path delimiter is included in the match. | ||
```js | ||
var re = pathToRegexp('/:foo+', keys); | ||
// keys = [{ name: 'foo', delimiter: '/', optional: false, repeat: true }] | ||
re.exec('/'); | ||
//=> null | ||
re.exec('/bar/baz'); | ||
//=> ['/bar/baz', 'bar/baz'] | ||
``` | ||
#### Custom Match Parameters | ||
All parameters can be provided a custom matching regexp and override the default. Please note: Backslashes need to be escaped in strings. | ||
```js | ||
var re = pathToRegexp('/:foo(\\d+)', keys); | ||
// keys = [{ name: 'foo', ... }] | ||
re.exec('/123'); | ||
//=> ['/123', '123'] | ||
re.exec('/abc'); | ||
//=> null | ||
``` | ||
#### Unnamed Parameters | ||
It is possible to write an unnamed parameter that is only a matching group. It works the same as a named parameter, except it will be numerically indexed. | ||
```js | ||
var re = pathToRegexp('/:foo/(.*)', keys); | ||
// keys = [{ name: 'foo', ... }, { name: '0', ... }] | ||
re.exec('/test/route'); | ||
//=> ['/test/route', 'test', 'route'] | ||
``` | ||
## Compatibility with Express 3.x | ||
Path-To-RegExp breaks compatibility with Express 3.x in a few ways: | ||
* RegExp special characters can now be used in the regular path. E.g. `/user[(\\d+)]` | ||
* All RegExp special characters can now be used inside the custom match. E.g. `/:user(.*)` | ||
* No more support for asterisk matching - use an explicit parameter instead. E.g. `/(.*)` | ||
* Parameters can have suffixes that augment meaning - `*`, `+` and `?`. E.g. `/:user*` | ||
## Live Demo | ||
@@ -34,2 +136,2 @@ | ||
MIT | ||
MIT |
1244
test.js
@@ -1,510 +0,810 @@ | ||
var pathToRegExp = require('./'); | ||
var util = require('util'); | ||
var assert = require('assert'); | ||
var pathToRegexp = require('./'); | ||
describe('path-to-regexp', function () { | ||
describe('strings', function () { | ||
it('should match simple paths', function () { | ||
var params = []; | ||
var m = pathToRegExp('/test', params).exec('/test'); | ||
/** | ||
* Execute a regular expression and return a flat array for comparison. | ||
* | ||
* @param {RegExp} re | ||
* @param {String} str | ||
* @return {Array} | ||
*/ | ||
var exec = function (re, str) { | ||
var match = re.exec(str); | ||
assert.equal(params.length, 0); | ||
return match && Array.prototype.slice.call(match); | ||
}; | ||
assert.equal(m.length, 1); | ||
assert.equal(m[0], '/test'); | ||
}); | ||
/** | ||
* An array of test cases with expected inputs and outputs. The format of each | ||
* array item is: | ||
* | ||
* ["path", "expected params", "route", "expected output", "options"] | ||
* | ||
* @type {Array} | ||
*/ | ||
var TESTS = [ | ||
/** | ||
* Simple paths. | ||
*/ | ||
['/', [], '/', ['/']], | ||
['/test', [], '/test', ['/test']], | ||
['/test', [], '/route', null], | ||
['/test', [], '/test/route', null], | ||
['/test', [], '/test/', ['/test/']], | ||
['/test/', [], '/test/', ['/test/']], | ||
['/test/', [], '/test//', null], | ||
it('should match express format params', function () { | ||
var params = []; | ||
var m = pathToRegExp('/:test', params).exec('/pathname'); | ||
/** | ||
* Case-sensitive paths. | ||
*/ | ||
['/test', [], '/test', ['/test'], { sensitive: true }], | ||
['/test', [], '/TEST', null, { sensitive: true }], | ||
['/TEST', [], '/test', null, { sensitive: true }], | ||
assert.equal(params.length, 1); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, false); | ||
/** | ||
* Strict mode. | ||
*/ | ||
['/test', [], '/test', ['/test'], { strict: true }], | ||
['/test', [], '/test/', null, { strict: true }], | ||
['/test/', [], '/test', null, { strict: true }], | ||
['/test/', [], '/test/', ['/test/'], { strict: true }], | ||
['/test/', [], '/test//', null, { strict: true }], | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/pathname'); | ||
assert.equal(m[1], 'pathname'); | ||
}); | ||
/** | ||
* Non-ending mode. | ||
*/ | ||
['/test', [], '/test', ['/test'], { end: false }], | ||
['/test', [], '/test/route', ['/test'], { end: false }], | ||
it('should do strict matches', function () { | ||
var params = []; | ||
var re = pathToRegExp('/:test', params, { strict: true }); | ||
var m; | ||
/** | ||
* Combine modes. | ||
*/ | ||
['/test', [], '/test', ['/test'], { end: false, strict: true }], | ||
['/test', [], '/test/', ['/test'], { end: false, strict: true }], | ||
['/test', [], '/test/route', ['/test'], { end: false, strict: true }], | ||
['/test/', [], '/test', null, { end: false, strict: true }], | ||
['/test/', [], '/test/', ['/test/'], { end: false, strict: true }], | ||
['/test/', [], '/test//', ['/test/'], { end: false, strict: true }], | ||
['/test/', [], '/test/route', ['/test/'], { end: false, strict: true }], | ||
['/test.json', [], '/test.json', ['/test.json'], { end: false, strict: true }], | ||
['/test.json', [], '/test.json.hbs', null, { end: false, strict: true }], | ||
assert.equal(params.length, 1); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, false); | ||
/** | ||
* Arrays of simple paths. | ||
*/ | ||
[['/one', '/two'], [], '/one', ['/one']], | ||
[['/one', '/two'], [], '/two', ['/two']], | ||
[['/one', '/two'], [], '/three', null], | ||
[['/one', '/two'], [], '/one/two', null], | ||
m = re.exec('/route'); | ||
/** | ||
* Non-ending simple path. | ||
*/ | ||
['/test', [], '/test/route', ['/test'], { end: false }], | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/route'); | ||
assert.equal(m[1], 'route'); | ||
/** | ||
* Single named parameter. | ||
*/ | ||
[ | ||
'/:test', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/route', | ||
['/route', 'route'] | ||
], | ||
[ | ||
'/:test', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/another', | ||
['/another', 'another'] | ||
], | ||
[ | ||
'/:test', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/something/else', | ||
null | ||
], | ||
[ | ||
'/:test', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/route.json', | ||
['/route.json', 'route.json'] | ||
], | ||
[ | ||
'/:test', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/route', | ||
['/route', 'route'], | ||
{ strict: true }], | ||
[ | ||
'/:test', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/route/', | ||
null, | ||
{ strict: true } | ||
], | ||
[ | ||
'/:test/', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/route/', | ||
['/route/', 'route'], | ||
{ strict: true } | ||
], | ||
[ | ||
'/:test/', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/route//', | ||
null, | ||
{ strict: true } | ||
], | ||
[ | ||
'/:test', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/route.json', | ||
['/route.json', 'route.json'], | ||
{ end: false } | ||
], | ||
m = re.exec('/route/'); | ||
/** | ||
* Optional named parameter. | ||
*/ | ||
[ | ||
'/:test?', | ||
[{ name: 'test', delimiter: '/', optional: true, repeat: false }], | ||
'/route', | ||
['/route', 'route'] | ||
], | ||
[ | ||
'/:test?', | ||
[{ name: 'test', delimiter: '/', optional: true, repeat: false }], | ||
'/route/nested', | ||
null | ||
], | ||
[ | ||
'/:test?', | ||
[{ name: 'test', delimiter: '/', optional: true, repeat: false }], | ||
'/', | ||
['/', undefined] | ||
], | ||
[ | ||
'/:test?', | ||
[{ name: 'test', delimiter: '/', optional: true, repeat: false }], | ||
'/route', | ||
['/route', 'route'], | ||
{ strict: true } | ||
], | ||
[ | ||
'/:test?', | ||
[{ name: 'test', delimiter: '/', optional: true, repeat: false }], | ||
'/', | ||
null, // Questionable behaviour. | ||
{ strict: true } | ||
], | ||
[ | ||
'/:test?/', | ||
[{ name: 'test', delimiter: '/', optional: true, repeat: false }], | ||
'/', | ||
['/', undefined], | ||
{ strict: true } | ||
], | ||
[ | ||
'/:test?/', | ||
[{ name: 'test', delimiter: '/', optional: true, repeat: false }], | ||
'//', | ||
null | ||
], | ||
[ | ||
'/:test?/', | ||
[{ name: 'test', delimiter: '/', optional: true, repeat: false }], | ||
'//', | ||
null, | ||
{ strict: true } | ||
], | ||
assert.ok(!m); | ||
}); | ||
// Repeated once or more times parameters. | ||
[ | ||
'/:test+', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: true }], | ||
'/', | ||
null | ||
], | ||
[ | ||
'/:test+', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: true }], | ||
'/route', | ||
['/route', 'route'] | ||
], | ||
[ | ||
'/:test+', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: true }], | ||
'/some/basic/route', | ||
['/some/basic/route', 'some/basic/route'] | ||
], | ||
[ | ||
'/:test(\\d+)+', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: true }], | ||
'/abc/456/789', | ||
null | ||
], | ||
[ | ||
'/:test(\\d+)+', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: true }], | ||
'/123/456/789', | ||
['/123/456/789', '123/456/789'] | ||
], | ||
[ | ||
'/route.:ext(json|xml)+', | ||
[{ name: 'ext', delimiter: '.', optional: false, repeat: true }], | ||
'/route.json', | ||
['/route.json', 'json'] | ||
], | ||
[ | ||
'/route.:ext(json|xml)+', | ||
[{ name: 'ext', delimiter: '.', optional: false, repeat: true }], | ||
'/route.xml.json', | ||
['/route.xml.json', 'xml.json'] | ||
], | ||
[ | ||
'/route.:ext(json|xml)+', | ||
[{ name: 'ext', delimiter: '.', optional: false, repeat: true }], | ||
'/route.html', | ||
null | ||
], | ||
it('should allow optional express format params', function () { | ||
var params = []; | ||
var re = pathToRegExp('/:test?', params); | ||
var m; | ||
/** | ||
* Repeated zero or more times parameters. | ||
*/ | ||
[ | ||
'/:test*', | ||
[{ name: 'test', delimiter: '/', optional: true, repeat: true }], | ||
'/', | ||
['/', undefined] | ||
], | ||
[ | ||
'/:test*', | ||
[{ name: 'test', delimiter: '/', optional: true, repeat: true }], | ||
'//', | ||
null | ||
], | ||
[ | ||
'/:test*', | ||
[{ name: 'test', delimiter: '/', optional: true, repeat: true }], | ||
'/route', | ||
['/route', 'route'] | ||
], | ||
[ | ||
'/:test*', | ||
[{ name: 'test', delimiter: '/', optional: true, repeat: true }], | ||
'/some/basic/route', | ||
['/some/basic/route', 'some/basic/route'] | ||
], | ||
[ | ||
'/route.:ext([a-z]+)*', | ||
[{ name: 'ext', delimiter: '.', optional: true, repeat: true }], | ||
'/route', | ||
['/route', undefined] | ||
], | ||
[ | ||
'/route.:ext([a-z]+)*', | ||
[{ name: 'ext', delimiter: '.', optional: true, repeat: true }], | ||
'/route.json', | ||
['/route.json', 'json'] | ||
], | ||
[ | ||
'/route.:ext([a-z]+)*', | ||
[{ name: 'ext', delimiter: '.', optional: true, repeat: true }], | ||
'/route.xml.json', | ||
['/route.xml.json', 'xml.json'] | ||
], | ||
[ | ||
'/route.:ext([a-z]+)*', | ||
[{ name: 'ext', delimiter: '.', optional: true, repeat: true }], | ||
'/route.123', | ||
null | ||
], | ||
assert.equal(params.length, 1); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, true); | ||
// Custom named parameters. | ||
[ | ||
'/:test(\\d+)', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/123', | ||
['/123', '123'] | ||
], | ||
[ | ||
'/:test(\\d+)', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/abc', | ||
null | ||
], | ||
[ | ||
'/:test(\\d+)', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/123/abc', | ||
null | ||
], | ||
[ | ||
'/:test(\\d+)', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/123/abc', | ||
['/123', '123'], | ||
{ end: false } | ||
], | ||
[ | ||
'/:test(.*)', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/anything/goes/here', | ||
['/anything/goes/here', 'anything/goes/here'] | ||
], | ||
[ | ||
'/:route([a-z]+)', | ||
[{ name: 'route', delimiter: '/', optional: false, repeat: false }], | ||
'/abcde', | ||
['/abcde', 'abcde'] | ||
], | ||
[ | ||
'/:route([a-z]+)', | ||
[{ name: 'route', delimiter: '/', optional: false, repeat: false }], | ||
'/12345', | ||
null | ||
], | ||
[ | ||
'/:route(this|that)', | ||
[{ name: 'route', delimiter: '/', optional: false, repeat: false }], | ||
'/this', | ||
['/this', 'this'] | ||
], | ||
[ | ||
'/:route(this|that)', | ||
[{ name: 'route', delimiter: '/', optional: false, repeat: false }], | ||
'/that', | ||
['/that', 'that'] | ||
], | ||
m = re.exec('/route'); | ||
/** | ||
* Prefixed slashes could be omitted. | ||
*/ | ||
[ | ||
'test', | ||
[], | ||
'test', | ||
['test'] | ||
], | ||
[ | ||
':test', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'route', | ||
['route', 'route'] | ||
], | ||
[ | ||
':test', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/route', | ||
null | ||
], | ||
[ | ||
':test', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'route/', | ||
['route/', 'route'] | ||
], | ||
[ | ||
':test', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'route/', | ||
null, | ||
{ strict: true } | ||
], | ||
[ | ||
':test', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'route/', | ||
['route', 'route'], | ||
{ end: false } | ||
], | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/route'); | ||
assert.equal(m[1], 'route'); | ||
/** | ||
* Formats. | ||
*/ | ||
[ | ||
'/test.json', | ||
[], | ||
'/test.json', | ||
['/test.json'] | ||
], | ||
[ | ||
'/test.json', | ||
[], | ||
'/route.json', | ||
null | ||
], | ||
[ | ||
'/:test.json', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/route.json', | ||
['/route.json', 'route'] | ||
], | ||
[ | ||
'/:test.json', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/route.json.json', | ||
['/route.json.json', 'route.json'] | ||
], | ||
[ | ||
'/:test.json', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/route.json', | ||
['/route.json', 'route'], | ||
{ end: false } | ||
], | ||
[ | ||
'/:test.json', | ||
[{ name: 'test', delimiter: '/', optional: false, repeat: false }], | ||
'/route.json.json', | ||
['/route.json.json', 'route.json'], | ||
{ end: false } | ||
], | ||
m = re.exec('/'); | ||
/** | ||
* Format params. | ||
*/ | ||
[ | ||
'/test.:format', | ||
[{ name: 'format', delimiter: '.', optional: false, repeat: false }], | ||
'/test.html', | ||
['/test.html', 'html'] | ||
], | ||
[ | ||
'/test.:format', | ||
[{ name: 'format', delimiter: '.', optional: false, repeat: false }], | ||
'/test.hbs.html', | ||
null | ||
], | ||
[ | ||
'/test.:format.:format', | ||
[ | ||
{ name: 'format', delimiter: '.', optional: false, repeat: false }, | ||
{ name: 'format', delimiter: '.', optional: false, repeat: false } | ||
], | ||
'/test.hbs.html', | ||
['/test.hbs.html', 'hbs', 'html'] | ||
], | ||
[ | ||
'/test.:format+', | ||
[ | ||
{ name: 'format', delimiter: '.', optional: false, repeat: true } | ||
], | ||
'/test.hbs.html', | ||
['/test.hbs.html', 'hbs.html'] | ||
], | ||
[ | ||
'/test.:format', | ||
[{ name: 'format', delimiter: '.', optional: false, repeat: false }], | ||
'/test.hbs.html', | ||
null, | ||
{ end: false } | ||
], | ||
[ | ||
'/test.:format.', | ||
[{ name: 'format', delimiter: '.', optional: false, repeat: false }], | ||
'/test.hbs.html', | ||
null, | ||
{ end: false } | ||
], | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/'); | ||
assert.equal(m[1], undefined); | ||
}); | ||
/** | ||
* Format and path params. | ||
*/ | ||
[ | ||
'/:test.:format', | ||
[ | ||
{ name: 'test', delimiter: '/', optional: false, repeat: false }, | ||
{ name: 'format', delimiter: '.', optional: false, repeat: false } | ||
], | ||
'/route.html', | ||
['/route.html', 'route', 'html'] | ||
], | ||
[ | ||
'/:test.:format', | ||
[ | ||
{ name: 'test', delimiter: '/', optional: false, repeat: false }, | ||
{ name: 'format', delimiter: '.', optional: false, repeat: false } | ||
], | ||
'/route', | ||
null | ||
], | ||
[ | ||
'/:test.:format', | ||
[ | ||
{ name: 'test', delimiter: '/', optional: false, repeat: false }, | ||
{ name: 'format', delimiter: '.', optional: false, repeat: false } | ||
], | ||
'/route', | ||
null | ||
], | ||
[ | ||
'/:test.:format?', | ||
[ | ||
{ name: 'test', delimiter: '/', optional: false, repeat: false }, | ||
{ name: 'format', delimiter: '.', optional: true, repeat: false } | ||
], | ||
'/route', | ||
['/route', 'route', undefined] | ||
], | ||
[ | ||
'/:test.:format?', | ||
[ | ||
{ name: 'test', delimiter: '/', optional: false, repeat: false }, | ||
{ name: 'format', delimiter: '.', optional: true, repeat: false } | ||
], | ||
'/route.json', | ||
['/route.json', 'route', 'json'] | ||
], | ||
[ | ||
'/:test.:format?', | ||
[ | ||
{ name: 'test', delimiter: '/', optional: false, repeat: false }, | ||
{ name: 'format', delimiter: '.', optional: true, repeat: false } | ||
], | ||
'/route', | ||
['/route', 'route', undefined], | ||
{ end: false } | ||
], | ||
[ | ||
'/:test.:format?', | ||
[ | ||
{ name: 'test', delimiter: '/', optional: false, repeat: false }, | ||
{ name: 'format', delimiter: '.', optional: true, repeat: false } | ||
], | ||
'/route.json', | ||
['/route.json', 'route', 'json'], | ||
{ end: false } | ||
], | ||
[ | ||
'/:test.:format?', | ||
[ | ||
{ name: 'test', delimiter: '/', optional: false, repeat: false }, | ||
{ name: 'format', delimiter: '.', optional: true, repeat: false } | ||
], | ||
'/route.json.html', | ||
['/route.json.html', 'route.json', 'html'], | ||
{ end: false } | ||
], | ||
[ | ||
'/test.:format(.*)z', | ||
[{ name: 'format', delimiter: '.', optional: false, repeat: false }], | ||
'/test.abc', | ||
null, | ||
{ end: false } | ||
], | ||
[ | ||
'/test.:format(.*)z', | ||
[{ name: 'format', delimiter: '.', optional: false, repeat: false }], | ||
'/test.abcz', | ||
['/test.abcz', 'abc'], | ||
{ end: false } | ||
], | ||
it('should allow express format param regexps', function () { | ||
var params = []; | ||
var m = pathToRegExp('/:page(\\d+)', params).exec('/56'); | ||
/** | ||
* Unnamed params. | ||
*/ | ||
[ | ||
'/(\\d+)', | ||
[{ name: '0', delimiter: '/', optional: false, repeat: false }], | ||
'/123', | ||
['/123', '123'] | ||
], | ||
[ | ||
'/(\\d+)', | ||
[{ name: '0', delimiter: '/', optional: false, repeat: false }], | ||
'/abc', | ||
null | ||
], | ||
[ | ||
'/(\\d+)', | ||
[{ name: '0', delimiter: '/', optional: false, repeat: false }], | ||
'/123/abc', | ||
null | ||
], | ||
[ | ||
'/(\\d+)', | ||
[{ name: '0', delimiter: '/', optional: false, repeat: false }], | ||
'/123/abc', | ||
['/123', '123'], | ||
{ end: false } | ||
], | ||
[ | ||
'/(\\d+)', | ||
[{ name: '0', delimiter: '/', optional: false, repeat: false }], | ||
'/abc', | ||
null, | ||
{ end: false } | ||
], | ||
[ | ||
'/(\\d+)?', | ||
[{ name: '0', delimiter: '/', optional: true, repeat: false }], | ||
'/', | ||
['/', undefined] | ||
], | ||
[ | ||
'/(\\d+)?', | ||
[{ name: '0', delimiter: '/', optional: true, repeat: false }], | ||
'/123', | ||
['/123', '123'] | ||
], | ||
[ | ||
'/(.*)', | ||
[{ name: '0', delimiter: '/', optional: false, repeat: false }], | ||
'/route', | ||
['/route', 'route'] | ||
], | ||
[ | ||
'/(.*)', | ||
[{ name: '0', delimiter: '/', optional: false, repeat: false }], | ||
'/route/nested', | ||
['/route/nested', 'route/nested'] | ||
], | ||
assert.equal(params.length, 1); | ||
assert.equal(params[0].name, 'page'); | ||
assert.equal(params[0].optional, false); | ||
/** | ||
* Regexps. | ||
*/ | ||
[ | ||
/.*/, | ||
[], | ||
'/match/anything', | ||
['/match/anything'] | ||
], | ||
[ | ||
/(.*)/, | ||
[{ name: '0', delimiter: null, optional: false, repeat: false }], | ||
'/match/anything', | ||
['/match/anything', '/match/anything'] | ||
], | ||
[ | ||
/\/(\d+)/, | ||
[{ name: '0', delimiter: null, optional: false, repeat: false }], | ||
'/123', | ||
['/123', '123'] | ||
], | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/56'); | ||
assert.equal(m[1], '56'); | ||
}); | ||
/** | ||
* Mixed arrays. | ||
*/ | ||
[ | ||
['/test', /\/(\d+)/], | ||
[{ name: '0', delimiter: null, optional: false, repeat: false }], | ||
'/test', | ||
['/test', undefined] | ||
], | ||
[ | ||
['/:test(\\d+)', /(.*)/], | ||
[ | ||
{ name: 'test', delimiter: '/', optional: false, repeat: false }, | ||
{ name: '0', delimiter: null, optional: false, repeat: false } | ||
], | ||
'/123', | ||
['/123', '123', undefined] | ||
], | ||
[ | ||
['/:test(\\d+)', /(.*)/], | ||
[ | ||
{ name: 'test', delimiter: '/', optional: false, repeat: false }, | ||
{ name: '0', delimiter: null, optional: false, repeat: false } | ||
], | ||
'/abc', | ||
['/abc', undefined, '/abc'] | ||
], | ||
it('should match without a prefixed slash', function () { | ||
var params = []; | ||
var m = pathToRegExp(':test', params).exec('string'); | ||
/** | ||
* Correct names and indexes. | ||
*/ | ||
[ | ||
['/:test', '/route/:test'], | ||
[ | ||
{ name: 'test', delimiter: '/', optional: false, repeat: false }, | ||
{ name: 'test', delimiter: '/', optional: false, repeat: false } | ||
], | ||
'/test', | ||
['/test', 'test', undefined] | ||
], | ||
[ | ||
['/:test', '/route/:test'], | ||
[ | ||
{ name: 'test', delimiter: '/', optional: false, repeat: false }, | ||
{ name: 'test', delimiter: '/', optional: false, repeat: false } | ||
], | ||
'/route/test', | ||
['/route/test', undefined, 'test'] | ||
], | ||
[ | ||
[/^\/([^\/]+)$/, /^\/route\/([^\/]+)$/], | ||
[ | ||
{ name: '0', delimiter: null, optional: false, repeat: false }, | ||
{ name: '0', delimiter: null, optional: false, repeat: false } | ||
], | ||
'/test', | ||
['/test', 'test', undefined] | ||
], | ||
[ | ||
[/^\/([^\/]+)$/, /^\/route\/([^\/]+)$/], | ||
[ | ||
{ name: '0', delimiter: null, optional: false, repeat: false }, | ||
{ name: '0', delimiter: null, optional: false, repeat: false } | ||
], | ||
'/route/test', | ||
['/route/test', undefined, 'test'] | ||
], | ||
assert.equal(params.length, 1); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, false); | ||
/** | ||
* Ignore non-matching groups in regexps. | ||
*/ | ||
[ | ||
/(?:.*)/, | ||
[], | ||
'/anything/you/want', | ||
['/anything/you/want'] | ||
], | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], 'string'); | ||
assert.equal(m[1], 'string'); | ||
}); | ||
/** | ||
* Respect escaped characters. | ||
*/ | ||
[ | ||
'/\\(testing\\)', | ||
[], | ||
'/testing', | ||
null | ||
], | ||
[ | ||
'/\\(testing\\)', | ||
[], | ||
'/(testing)', | ||
['/(testing)'] | ||
], | ||
[ | ||
'/.+*?=^!:${}[]|', | ||
[], | ||
'/.+*?=^!:${}[]|', | ||
['/.+*?=^!:${}[]|'] | ||
] | ||
]; | ||
it('should not match format parts', function () { | ||
var params = []; | ||
var m = pathToRegExp('/:test.json', params).exec('/route.json'); | ||
/** | ||
* Dynamically generate the entire test suite. | ||
*/ | ||
describe('path-to-regexp', function () { | ||
it('should not break when keys aren\'t provided', function () { | ||
var re = pathToRegexp('/:foo/:bar'); | ||
assert.equal(params.length, 1); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, false); | ||
assert.deepEqual(exec(re, '/test/route'), ['/test/route', 'test', 'route']); | ||
}); | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/route.json'); | ||
assert.equal(m[1], 'route'); | ||
}); | ||
TESTS.forEach(function (test) { | ||
var description = ''; | ||
var options = test[4] || {}; | ||
it('should match format parts', function () { | ||
var params = []; | ||
var re = pathToRegExp('/:test.:format', params); | ||
var m; | ||
// Generate a base description using the test values. | ||
description += 'should ' + (test[3] ? '' : 'not ') + 'match '; | ||
description += util.inspect(test[2]) + ' against ' + util.inspect(test[0]); | ||
assert.equal(params.length, 2); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, false); | ||
assert.equal(params[1].name, 'format'); | ||
assert.equal(params[1].optional, false); | ||
// If additional options have been defined, we should render the options | ||
// in the test descriptions. | ||
if (Object.keys(options).length) { | ||
var optionsDescription = Object.keys(options).map(function (key) { | ||
return (options[key] === false ? 'non-' : '') + key; | ||
}).join(', '); | ||
m = re.exec('/route.json'); | ||
description += ' in ' + optionsDescription + ' mode'; | ||
} | ||
assert.equal(m.length, 3); | ||
assert.equal(m[0], '/route.json'); | ||
assert.equal(m[1], 'route'); | ||
assert.equal(m[2], 'json'); | ||
m = re.exec('/route'); | ||
assert.ok(!m); | ||
}); | ||
it('should match route parts with a trailing format', function () { | ||
// Execute the test and check each parameter is as expected. | ||
it(description, function () { | ||
var params = []; | ||
var m = pathToRegExp('/:test.json', params).exec('/route.json'); | ||
var re = pathToRegexp(test[0], params, test[4]); | ||
assert.equal(params.length, 1); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, false); | ||
// Check the params are as expected. | ||
assert.deepEqual(params, test[1]); | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/route.json'); | ||
assert.equal(m[1], 'route'); | ||
// Run the regexp and check the result is expected. | ||
assert.deepEqual(exec(re, test[2]), test[3]); | ||
}); | ||
it('should match optional trailing routes', function () { | ||
var params = []; | ||
var m = pathToRegExp('/test*', params).exec('/test/route'); | ||
assert.equal(params.length, 0); | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/test/route'); | ||
assert.equal(m[1], '/route'); | ||
}); | ||
it('should match optional trailing routes after a param', function () { | ||
var params = []; | ||
var re = pathToRegExp('/:test*', params); | ||
var m; | ||
assert.equal(params.length, 1); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, false); | ||
m = re.exec('/test/route'); | ||
assert.equal(m.length, 3); | ||
assert.equal(m[0], '/test/route'); | ||
assert.equal(m[1], 'test'); | ||
assert.equal(m[2], '/route'); | ||
m = re.exec('/testing'); | ||
assert.equal(m.length, 3); | ||
assert.equal(m[0], '/testing'); | ||
assert.equal(m[1], 'testing'); | ||
assert.equal(m[2], ''); | ||
}); | ||
it('should match optional trailing routes before a format', function () { | ||
var params = []; | ||
var re = pathToRegExp('/test*.json', params); | ||
var m; | ||
assert.equal(params.length, 0); | ||
m = re.exec('/test.json'); | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/test.json'); | ||
assert.equal(m[1], ''); | ||
m = re.exec('/testing.json'); | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/testing.json'); | ||
assert.equal(m[1], 'ing'); | ||
m = re.exec('/test/route.json'); | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/test/route.json'); | ||
assert.equal(m[1], '/route'); | ||
}); | ||
it('should match optional trailing routes after a param and before a format', function () { | ||
var params = []; | ||
var re = pathToRegExp('/:test*.json', params); | ||
var m; | ||
assert.equal(params.length, 1); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, false); | ||
m = re.exec('/testing.json'); | ||
assert.equal(m.length, 3); | ||
assert.equal(m[0], '/testing.json'); | ||
assert.equal(m[1], 'testing'); | ||
assert.equal(m[2], ''); | ||
m = re.exec('/test/route.json'); | ||
assert.equal(m.length, 3); | ||
assert.equal(m[0], '/test/route.json'); | ||
assert.equal(m[1], 'test'); | ||
assert.equal(m[2], '/route'); | ||
m = re.exec('.json'); | ||
assert.ok(!m); | ||
}); | ||
it('should match optional trailing routes between a normal param and a format param', function () { | ||
var params = []; | ||
var re = pathToRegExp('/:test*.:format', params); | ||
var m; | ||
assert.equal(params.length, 2); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, false); | ||
assert.equal(params[1].name, 'format'); | ||
assert.equal(params[1].optional, false); | ||
m = re.exec('/testing.json'); | ||
assert.equal(m.length, 4); | ||
assert.equal(m[0], '/testing.json'); | ||
assert.equal(m[1], 'testing'); | ||
assert.equal(m[2], ''); | ||
assert.equal(m[3], 'json'); | ||
m = re.exec('/test/route.json'); | ||
assert.equal(m.length, 4); | ||
assert.equal(m[0], '/test/route.json'); | ||
assert.equal(m[1], 'test'); | ||
assert.equal(m[2], '/route'); | ||
assert.equal(m[3], 'json'); | ||
m = re.exec('/test'); | ||
assert.ok(!m); | ||
m = re.exec('.json'); | ||
assert.ok(!m); | ||
}); | ||
it('should match optional trailing routes after a param and before an optional format param', function () { | ||
var params = []; | ||
var re = pathToRegExp('/:test*.:format?', params); | ||
var m; | ||
assert.equal(params.length, 2); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, false); | ||
assert.equal(params[1].name, 'format'); | ||
assert.equal(params[1].optional, true); | ||
m = re.exec('/testing.json'); | ||
assert.equal(m.length, 4); | ||
assert.equal(m[0], '/testing.json'); | ||
assert.equal(m[1], 'testing'); | ||
assert.equal(m[2], ''); | ||
assert.equal(m[3], 'json'); | ||
m = re.exec('/test/route.json'); | ||
assert.equal(m.length, 4); | ||
assert.equal(m[0], '/test/route.json'); | ||
assert.equal(m[1], 'test'); | ||
assert.equal(m[2], '/route'); | ||
assert.equal(m[3], 'json'); | ||
m = re.exec('/test'); | ||
assert.equal(m.length, 4); | ||
assert.equal(m[0], '/test'); | ||
assert.equal(m[1], 'test'); | ||
assert.equal(m[2], ''); | ||
assert.equal(m[3], undefined); | ||
m = re.exec('.json'); | ||
assert.ok(!m); | ||
}); | ||
it('should match optional trailing routes inside optional express param', function () { | ||
var params = []; | ||
var re = pathToRegExp('/:test*?', params); | ||
var m; | ||
assert.equal(params.length, 1); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, true); | ||
m = re.exec('/test/route'); | ||
assert.equal(m.length, 3); | ||
assert.equal(m[0], '/test/route'); | ||
assert.equal(m[1], 'test'); | ||
assert.equal(m[2], '/route'); | ||
m = re.exec('/test'); | ||
assert.equal(m.length, 3); | ||
assert.equal(m[0], '/test'); | ||
assert.equal(m[1], 'test'); | ||
assert.equal(m[2], ''); | ||
m = re.exec('/'); | ||
assert.equal(m.length, 3); | ||
assert.equal(m[0], '/'); | ||
assert.equal(m[1], undefined); | ||
assert.equal(m[2], undefined); | ||
}); | ||
it('should do case insensitive matches', function () { | ||
var m = pathToRegExp('/test').exec('/TEST'); | ||
assert.equal(m[0], '/TEST'); | ||
}); | ||
it('should do case sensitive matches', function () { | ||
var re = pathToRegExp('/test', null, { sensitive: true }); | ||
var m; | ||
m = re.exec('/test'); | ||
assert.equal(m.length, 1); | ||
assert.equal(m[0], '/test'); | ||
m = re.exec('/TEST'); | ||
assert.ok(!m); | ||
}); | ||
it('should do non-ending matches', function () { | ||
var params = []; | ||
var m = pathToRegExp('/:test', params, { end: false }).exec('/test/route'); | ||
assert.equal(params.length, 1); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, false); | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/test'); | ||
assert.equal(m[1], 'test'); | ||
}); | ||
it('should match trailing slashes in non-ending non-strict mode', function () { | ||
var params = []; | ||
var re = pathToRegExp('/:test', params, { end: false }); | ||
var m; | ||
assert.equal(params.length, 1); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, false); | ||
m = re.exec('/test/'); | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/test/'); | ||
assert.equal(m[1], 'test'); | ||
}); | ||
it('should not match trailing slashes in non-ending strict mode', function () { | ||
var params = []; | ||
var re = pathToRegExp('/:test', params, { end: false, strict: true }); | ||
assert.equal(params.length, 1); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, false); | ||
m = re.exec('/test/'); | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/test'); | ||
assert.equal(m[1], 'test'); | ||
}); | ||
it('should match text after an express param', function () { | ||
var params = []; | ||
var re = pathToRegExp('/(:test)route', params); | ||
assert.equal(params.length, 1); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, false); | ||
m = re.exec('/route'); | ||
assert.ok(!m); | ||
m = re.exec('/testroute'); | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/testroute'); | ||
assert.equal(m[1], 'test'); | ||
m = re.exec('testroute'); | ||
assert.ok(!m); | ||
}); | ||
it('should match text after an optional express param', function () { | ||
var params = []; | ||
var re = pathToRegExp('/(:test?)route', params); | ||
var m; | ||
assert.equal(params.length, 1); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, true); | ||
m = re.exec('/route'); | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/route'); | ||
assert.equal(m[1], undefined); | ||
m = re.exec('/testroute'); | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/testroute'); | ||
assert.equal(m[1], 'test'); | ||
m = re.exec('route'); | ||
assert.ok(!m); | ||
}); | ||
it('should match optional formats', function () { | ||
var params = []; | ||
var re = pathToRegExp('/:test.:format?', params); | ||
var m; | ||
assert.equal(params.length, 2); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, false); | ||
assert.equal(params[1].name, 'format'); | ||
assert.equal(params[1].optional, true); | ||
m = re.exec('/route'); | ||
assert.equal(m.length, 3); | ||
assert.equal(m[0], '/route'); | ||
assert.equal(m[1], 'route'); | ||
assert.equal(m[2], undefined); | ||
m = re.exec('/route.json'); | ||
assert.equal(m.length, 3); | ||
assert.equal(m[0], '/route.json'); | ||
assert.equal(m[1], 'route'); | ||
assert.equal(m[2], 'json'); | ||
}); | ||
it('should match full paths with format by default', function () { | ||
var params = []; | ||
var m = pathToRegExp('/:test', params).exec('/test.json'); | ||
assert.equal(params.length, 1); | ||
assert.equal(params[0].name, 'test'); | ||
assert.equal(params[0].optional, false); | ||
assert.equal(m.length, 2); | ||
assert.equal(m[0], '/test.json'); | ||
assert.equal(m[1], 'test.json'); | ||
}); | ||
}); | ||
describe('regexps', function () { | ||
it('should return the regexp', function () { | ||
assert.deepEqual(pathToRegExp(/.*/), /.*/); | ||
}); | ||
}); | ||
describe('arrays', function () { | ||
it('should join arrays parts', function () { | ||
var re = pathToRegExp(['/test', '/route']); | ||
assert.ok(re.exec('/test')); | ||
assert.ok(re.exec('/route')); | ||
assert.ok(!re.exec('/else')); | ||
}); | ||
}); | ||
}); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
28902
8
912
136
1