Projekt

Obecné

Profil

Stáhnout (3.56 KB) Statistiky
| Větev: | Revize:
1
'use strict';
2

    
3
var safe = require('safe-regex');
4
var define = require('define-property');
5
var extend = require('extend-shallow');
6
var not = require('regex-not');
7
var MAX_LENGTH = 1024 * 64;
8

    
9
/**
10
 * Session cache
11
 */
12

    
13
var cache = {};
14

    
15
/**
16
 * Create a regular expression from the given `pattern` string.
17
 *
18
 * @param {String|RegExp} `pattern` Pattern can be a string or regular expression.
19
 * @param {Object} `options`
20
 * @return {RegExp}
21
 * @api public
22
 */
23

    
24
module.exports = function(patterns, options) {
25
  if (!Array.isArray(patterns)) {
26
    return makeRe(patterns, options);
27
  }
28
  return makeRe(patterns.join('|'), options);
29
};
30

    
31
/**
32
 * Create a regular expression from the given `pattern` string.
33
 *
34
 * @param {String|RegExp} `pattern` Pattern can be a string or regular expression.
35
 * @param {Object} `options`
36
 * @return {RegExp}
37
 * @api public
38
 */
39

    
40
function makeRe(pattern, options) {
41
  if (pattern instanceof RegExp) {
42
    return pattern;
43
  }
44

    
45
  if (typeof pattern !== 'string') {
46
    throw new TypeError('expected a string');
47
  }
48

    
49
  if (pattern.length > MAX_LENGTH) {
50
    throw new Error('expected pattern to be less than ' + MAX_LENGTH + ' characters');
51
  }
52

    
53
  var key = pattern;
54
  // do this before shallow cloning options, it's a lot faster
55
  if (!options || (options && options.cache !== false)) {
56
    key = createKey(pattern, options);
57

    
58
    if (cache.hasOwnProperty(key)) {
59
      return cache[key];
60
    }
61
  }
62

    
63
  var opts = extend({}, options);
64
  if (opts.contains === true) {
65
    if (opts.negate === true) {
66
      opts.strictNegate = false;
67
    } else {
68
      opts.strict = false;
69
    }
70
  }
71

    
72
  if (opts.strict === false) {
73
    opts.strictOpen = false;
74
    opts.strictClose = false;
75
  }
76

    
77
  var open = opts.strictOpen !== false ? '^' : '';
78
  var close = opts.strictClose !== false ? '$' : '';
79
  var flags = opts.flags || '';
80
  var regex;
81

    
82
  if (opts.nocase === true && !/i/.test(flags)) {
83
    flags += 'i';
84
  }
85

    
86
  try {
87
    if (opts.negate || typeof opts.strictNegate === 'boolean') {
88
      pattern = not.create(pattern, opts);
89
    }
90

    
91
    var str = open + '(?:' + pattern + ')' + close;
92
    regex = new RegExp(str, flags);
93

    
94
    if (opts.safe === true && safe(regex) === false) {
95
      throw new Error('potentially unsafe regular expression: ' + regex.source);
96
    }
97

    
98
  } catch (err) {
99
    if (opts.strictErrors === true || opts.safe === true) {
100
      err.key = key;
101
      err.pattern = pattern;
102
      err.originalOptions = options;
103
      err.createdOptions = opts;
104
      throw err;
105
    }
106

    
107
    try {
108
      regex = new RegExp('^' + pattern.replace(/(\W)/g, '\\$1') + '$');
109
    } catch (err) {
110
      regex = /.^/; //<= match nothing
111
    }
112
  }
113

    
114
  if (opts.cache !== false) {
115
    memoize(regex, key, pattern, opts);
116
  }
117
  return regex;
118
}
119

    
120
/**
121
 * Memoize generated regex. This can result in dramatic speed improvements
122
 * and simplify debugging by adding options and pattern to the regex. It can be
123
 * disabled by passing setting `options.cache` to false.
124
 */
125

    
126
function memoize(regex, key, pattern, options) {
127
  define(regex, 'cached', true);
128
  define(regex, 'pattern', pattern);
129
  define(regex, 'options', options);
130
  define(regex, 'key', key);
131
  cache[key] = regex;
132
}
133

    
134
/**
135
 * Create the key to use for memoization. The key is generated
136
 * by iterating over the options and concatenating key-value pairs
137
 * to the pattern string.
138
 */
139

    
140
function createKey(pattern, options) {
141
  if (!options) return pattern;
142
  var key = pattern;
143
  for (var prop in options) {
144
    if (options.hasOwnProperty(prop)) {
145
      key += ';' + prop + '=' + String(options[prop]);
146
    }
147
  }
148
  return key;
149
}
150

    
151
/**
152
 * Expose `makeRe`
153
 */
154

    
155
module.exports.makeRe = makeRe;
(3-3/4)