Spaces:
Running
Running
File size: 3,328 Bytes
4bb817b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 |
/**
* Expose `pathtoRegexp`.
*/
module.exports = pathtoRegexp;
/**
* Match matching groups in a regular expression.
*/
var MATCHING_GROUP_REGEXP = /\((?!\?)/g;
/**
* Normalize the given path string,
* returning a regular expression.
*
* An empty array should be passed,
* 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) {
options = options || {};
keys = keys || [];
var strict = options.strict;
var end = options.end !== false;
var flags = options.sensitive ? '' : 'i';
var extraOffset = 0;
var keysOffset = keys.length;
var i = 0;
var name = 0;
var m;
if (path instanceof RegExp) {
while (m = MATCHING_GROUP_REGEXP.exec(path.source)) {
keys.push({
name: name++,
optional: false,
offset: m.index
});
}
return path;
}
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.join('|') + ')', flags);
}
path = ('^' + path + (strict ? '' : path[path.length - 1] === '/' ? '?' : '/?'))
.replace(/\/\(/g, '/(?:')
.replace(/([\/\.])/g, '\\$1')
.replace(/(\\\/)?(\\\.)?:(\w+)(\(.*?\))?(\*)?(\?)?/g, function (match, slash, format, key, capture, star, optional, offset) {
slash = slash || '';
format = format || '';
capture = capture || '([^\\/' + format + ']+?)';
optional = optional || '';
keys.push({
name: key,
optional: !!optional,
offset: offset + extraOffset
});
var result = ''
+ (optional ? '' : slash)
+ '(?:'
+ format + (optional ? slash : '') + capture
+ (star ? '((?:[\\/' + format + '].+?)?)' : '')
+ ')'
+ optional;
extraOffset += result.length - match.length;
return result;
})
.replace(/\*/g, function (star, index) {
var len = keys.length
while (len-- > keysOffset && keys[len].offset > index) {
keys[len].offset += 3; // Replacement length minus asterisk length.
}
return '(.*)';
});
// This is a workaround for handling unnamed matching groups.
while (m = MATCHING_GROUP_REGEXP.exec(path)) {
var escapeCount = 0;
var index = m.index;
while (path.charAt(--index) === '\\') {
escapeCount++;
}
// It's possible to escape the bracket.
if (escapeCount % 2 === 1) {
continue;
}
if (keysOffset + i === keys.length || keys[keysOffset + i].offset > m.index) {
keys.splice(keysOffset + i, 0, {
name: name++, // Unnamed matching groups must be consistently linear.
optional: false,
offset: m.index
});
}
i++;
}
// If the path is non-ending, match until the end or a slash.
path += (end ? '$' : (path[path.length - 1] === '/' ? '' : '(?=\\/|$)'));
return new RegExp(path, flags);
};
|