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.
		
		
		
		
		
			
		
			
				
					
					
						
							155 lines
						
					
					
						
							3.6 KiB
						
					
					
				
			
		
		
	
	
							155 lines
						
					
					
						
							3.6 KiB
						
					
					
				'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;
 | 
						|
 |