You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					156 lines
				
				3.6 KiB
			
		
		
			
		
	
	
					156 lines
				
				3.6 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var safe = require('safe-regex');
							 | 
						||
| 
								 | 
							
								var define = require('define-property');
							 | 
						||
| 
								 | 
							
								var extend = require('extend-shallow');
							 | 
						||
| 
								 | 
							
								var not = require('regex-not');
							 | 
						||
| 
								 | 
							
								var MAX_LENGTH = 1024 * 64;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Session cache
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var cache = {};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Create a regular expression from the given `pattern` string.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param {String|RegExp} `pattern` Pattern can be a string or regular expression.
							 | 
						||
| 
								 | 
							
								 * @param {Object} `options`
							 | 
						||
| 
								 | 
							
								 * @return {RegExp}
							 | 
						||
| 
								 | 
							
								 * @api public
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = function(patterns, options) {
							 | 
						||
| 
								 | 
							
								  if (!Array.isArray(patterns)) {
							 | 
						||
| 
								 | 
							
								    return makeRe(patterns, options);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return makeRe(patterns.join('|'), options);
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Create a regular expression from the given `pattern` string.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * @param {String|RegExp} `pattern` Pattern can be a string or regular expression.
							 | 
						||
| 
								 | 
							
								 * @param {Object} `options`
							 | 
						||
| 
								 | 
							
								 * @return {RegExp}
							 | 
						||
| 
								 | 
							
								 * @api public
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function makeRe(pattern, options) {
							 | 
						||
| 
								 | 
							
								  if (pattern instanceof RegExp) {
							 | 
						||
| 
								 | 
							
								    return pattern;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (typeof pattern !== 'string') {
							 | 
						||
| 
								 | 
							
								    throw new TypeError('expected a string');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (pattern.length > MAX_LENGTH) {
							 | 
						||
| 
								 | 
							
								    throw new Error('expected pattern to be less than ' + MAX_LENGTH + ' characters');
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var key = pattern;
							 | 
						||
| 
								 | 
							
								  // do this before shallow cloning options, it's a lot faster
							 | 
						||
| 
								 | 
							
								  if (!options || (options && options.cache !== false)) {
							 | 
						||
| 
								 | 
							
								    key = createKey(pattern, options);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (cache.hasOwnProperty(key)) {
							 | 
						||
| 
								 | 
							
								      return cache[key];
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var opts = extend({}, options);
							 | 
						||
| 
								 | 
							
								  if (opts.contains === true) {
							 | 
						||
| 
								 | 
							
								    if (opts.negate === true) {
							 | 
						||
| 
								 | 
							
								      opts.strictNegate = false;
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      opts.strict = false;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (opts.strict === false) {
							 | 
						||
| 
								 | 
							
								    opts.strictOpen = false;
							 | 
						||
| 
								 | 
							
								    opts.strictClose = false;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  var open = opts.strictOpen !== false ? '^' : '';
							 | 
						||
| 
								 | 
							
								  var close = opts.strictClose !== false ? '$' : '';
							 | 
						||
| 
								 | 
							
								  var flags = opts.flags || '';
							 | 
						||
| 
								 | 
							
								  var regex;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (opts.nocase === true && !/i/.test(flags)) {
							 | 
						||
| 
								 | 
							
								    flags += 'i';
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  try {
							 | 
						||
| 
								 | 
							
								    if (opts.negate || typeof opts.strictNegate === 'boolean') {
							 | 
						||
| 
								 | 
							
								      pattern = not.create(pattern, opts);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    var str = open + '(?:' + pattern + ')' + close;
							 | 
						||
| 
								 | 
							
								    regex = new RegExp(str, flags);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (opts.safe === true && safe(regex) === false) {
							 | 
						||
| 
								 | 
							
								      throw new Error('potentially unsafe regular expression: ' + regex.source);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  } catch (err) {
							 | 
						||
| 
								 | 
							
								    if (opts.strictErrors === true || opts.safe === true) {
							 | 
						||
| 
								 | 
							
								      err.key = key;
							 | 
						||
| 
								 | 
							
								      err.pattern = pattern;
							 | 
						||
| 
								 | 
							
								      err.originalOptions = options;
							 | 
						||
| 
								 | 
							
								      err.createdOptions = opts;
							 | 
						||
| 
								 | 
							
								      throw err;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    try {
							 | 
						||
| 
								 | 
							
								      regex = new RegExp('^' + pattern.replace(/(\W)/g, '\\$1') + '$');
							 | 
						||
| 
								 | 
							
								    } catch (err) {
							 | 
						||
| 
								 | 
							
								      regex = /.^/; //<= match nothing
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (opts.cache !== false) {
							 | 
						||
| 
								 | 
							
								    memoize(regex, key, pattern, opts);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return regex;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Memoize generated regex. This can result in dramatic speed improvements
							 | 
						||
| 
								 | 
							
								 * and simplify debugging by adding options and pattern to the regex. It can be
							 | 
						||
| 
								 | 
							
								 * disabled by passing setting `options.cache` to false.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function memoize(regex, key, pattern, options) {
							 | 
						||
| 
								 | 
							
								  define(regex, 'cached', true);
							 | 
						||
| 
								 | 
							
								  define(regex, 'pattern', pattern);
							 | 
						||
| 
								 | 
							
								  define(regex, 'options', options);
							 | 
						||
| 
								 | 
							
								  define(regex, 'key', key);
							 | 
						||
| 
								 | 
							
								  cache[key] = regex;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Create the key to use for memoization. The key is generated
							 | 
						||
| 
								 | 
							
								 * by iterating over the options and concatenating key-value pairs
							 | 
						||
| 
								 | 
							
								 * to the pattern string.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function createKey(pattern, options) {
							 | 
						||
| 
								 | 
							
								  if (!options) return pattern;
							 | 
						||
| 
								 | 
							
								  var key = pattern;
							 | 
						||
| 
								 | 
							
								  for (var prop in options) {
							 | 
						||
| 
								 | 
							
								    if (options.hasOwnProperty(prop)) {
							 | 
						||
| 
								 | 
							
								      key += ';' + prop + '=' + String(options[prop]);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return key;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Expose `makeRe`
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports.makeRe = makeRe;
							 |