opusdev/vector-similarity-api
1
1/**2 * Expose `pathToRegexp`.3 */4 5module.exports = pathToRegexp;6 7/**8 * Match matching groups in a regular expression.9 */10var MATCHING_GROUP_REGEXP = /\\.|\((?:\?<(.*?)>)?(?!\?)/g;11 12/**13 * Normalize the given path string,14 * returning a regular expression.15 *16 * An empty array should be passed,17 * which will contain the placeholder18 * key names. For example "/user/:id" will19 * then contain ["id"].20 *21 * @param {String|RegExp|Array} path22 * @param {Array} keys23 * @param {Object} options24 * @return {RegExp}25 * @api private26 */27 28function pathToRegexp(path, keys, options) {29 options = options || {};30 keys = keys || [];31 var strict = options.strict;32 var end = options.end !== false;33 var flags = options.sensitive ? '' : 'i';34 var lookahead = options.lookahead !== false;35 var extraOffset = 0;36 var keysOffset = keys.length;37 var i = 0;38 var name = 0;39 var pos = 0;40 var backtrack = '';41 var m;42 43 if (path instanceof RegExp) {44 while (m = MATCHING_GROUP_REGEXP.exec(path.source)) {45 if (m[0][0] === '\\') continue;46 47 keys.push({48 name: m[1] || name++,49 optional: false,50 offset: m.index51 });52 }53 54 return path;55 }56 57 if (Array.isArray(path)) {58 // Map array parts into regexps and return their source. We also pass59 // the same keys and options instance into every generation to get60 // consistent matching groups before we join the sources together.61 path = path.map(function (value) {62 return pathToRegexp(value, keys, options).source;63 });64 65 return new RegExp(path.join('|'), flags);66 }67 68 if (typeof path !== 'string') {69 throw new TypeError('path must be a string, array of strings, or regular expression');70 }71 72 path = path.replace(73 /\\.|(\/)?(\.)?:(\w+)(\(.*?\))?(\*)?(\?)?|[.*]|\/\(/g,74 function (match, slash, format, key, capture, star, optional, offset) {75 if (match[0] === '\\') {76 backtrack += match;77 pos += 2;78 return match;79 }80 81 if (match === '.') {82 backtrack += '\\.';83 extraOffset += 1;84 pos += 1;85 return '\\.';86 }87 88 if (slash || format) {89 backtrack = '';90 } else {91 backtrack += path.slice(pos, offset);92 }93 94 pos = offset + match.length;95 96 if (match === '*') {97 extraOffset += 3;98 return '(.*)';99 }100 101 if (match === '/(') {102 backtrack += '/';103 extraOffset += 2;104 return '/(?:';105 }106 107 slash = slash || '';108 format = format ? '\\.' : '';109 optional = optional || '';110 capture = capture ?111 capture.replace(/\\.|\*/, function (m) { return m === '*' ? '(.*)' : m; }) :112 (backtrack ? '((?:(?!/|' + backtrack + ').)+?)' : '([^/' + format + ']+?)');113 114 keys.push({115 name: key,116 optional: !!optional,117 offset: offset + extraOffset118 });119 120 var result = '(?:'121 + format + slash + capture122 + (star ? '((?:[/' + format + '].+?)?)' : '')123 + ')'124 + optional;125 126 extraOffset += result.length - match.length;127 128 return result;129 });130 131 // This is a workaround for handling unnamed matching groups.132 while (m = MATCHING_GROUP_REGEXP.exec(path)) {133 if (m[0][0] === '\\') continue;134 135 if (keysOffset + i === keys.length || keys[keysOffset + i].offset > m.index) {136 keys.splice(keysOffset + i, 0, {137 name: name++, // Unnamed matching groups must be consistently linear.138 optional: false,139 offset: m.index140 });141 }142 143 i++;144 }145 146 path += strict ? '' : path[path.length - 1] === '/' ? '?' : '/?';147 148 // If the path is non-ending, match until the end or a slash.149 if (end) {150 path += '$';151 } else if (path[path.length - 1] !== '/') {152 path += lookahead ? '(?=/|$)' : '(?:/|$)';153 }154 155 return new RegExp('^' + path, flags);156};157 