Projekt

Obecné

Profil

Stáhnout (3.25 KB) Statistiky
| Větev: | Revize:
1
/**
2
 * Expose `pathtoRegexp`.
3
 */
4

    
5
module.exports = pathtoRegexp;
6

    
7
/**
8
 * Match matching groups in a regular expression.
9
 */
10
var 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 placeholder
18
 * key names. For example "/user/:id" will
19
 * then contain ["id"].
20
 *
21
 * @param  {String|RegExp|Array} path
22
 * @param  {Array} keys
23
 * @param  {Object} options
24
 * @return {RegExp}
25
 * @api private
26
 */
27

    
28
function 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 extraOffset = 0;
35
  var keysOffset = keys.length;
36
  var i = 0;
37
  var name = 0;
38
  var m;
39

    
40
  if (path instanceof RegExp) {
41
    while (m = MATCHING_GROUP_REGEXP.exec(path.source)) {
42
      keys.push({
43
        name: name++,
44
        optional: false,
45
        offset: m.index
46
      });
47
    }
48

    
49
    return path;
50
  }
51

    
52
  if (Array.isArray(path)) {
53
    // Map array parts into regexps and return their source. We also pass
54
    // the same keys and options instance into every generation to get
55
    // consistent matching groups before we join the sources together.
56
    path = path.map(function (value) {
57
      return pathtoRegexp(value, keys, options).source;
58
    });
59

    
60
    return new RegExp('(?:' + path.join('|') + ')', flags);
61
  }
62

    
63
  path = ('^' + path + (strict ? '' : path[path.length - 1] === '/' ? '?' : '/?'))
64
    .replace(/\/\(/g, '/(?:')
65
    .replace(/([\/\.])/g, '\\$1')
66
    .replace(/(\\\/)?(\\\.)?:(\w+)(\(.*?\))?(\*)?(\?)?/g, function (match, slash, format, key, capture, star, optional, offset) {
67
      slash = slash || '';
68
      format = format || '';
69
      capture = capture || '([^\\/' + format + ']+?)';
70
      optional = optional || '';
71

    
72
      keys.push({
73
        name: key,
74
        optional: !!optional,
75
        offset: offset + extraOffset
76
      });
77

    
78
      var result = ''
79
        + (optional ? '' : slash)
80
        + '(?:'
81
        + format + (optional ? slash : '') + capture
82
        + (star ? '((?:[\\/' + format + '].+?)?)' : '')
83
        + ')'
84
        + optional;
85

    
86
      extraOffset += result.length - match.length;
87

    
88
      return result;
89
    })
90
    .replace(/\*/g, function (star, index) {
91
      var len = keys.length
92

    
93
      while (len-- > keysOffset && keys[len].offset > index) {
94
        keys[len].offset += 3; // Replacement length minus asterisk length.
95
      }
96

    
97
      return '(.*)';
98
    });
99

    
100
  // This is a workaround for handling unnamed matching groups.
101
  while (m = MATCHING_GROUP_REGEXP.exec(path)) {
102
    var escapeCount = 0;
103
    var index = m.index;
104

    
105
    while (path.charAt(--index) === '\\') {
106
      escapeCount++;
107
    }
108

    
109
    // It's possible to escape the bracket.
110
    if (escapeCount % 2 === 1) {
111
      continue;
112
    }
113

    
114
    if (keysOffset + i === keys.length || keys[keysOffset + i].offset > m.index) {
115
      keys.splice(keysOffset + i, 0, {
116
        name: name++, // Unnamed matching groups must be consistently linear.
117
        optional: false,
118
        offset: m.index
119
      });
120
    }
121

    
122
    i++;
123
  }
124

    
125
  // If the path is non-ending, match until the end or a slash.
126
  path += (end ? '$' : (path[path.length - 1] === '/' ? '' : '(?=\\/|$)'));
127

    
128
  return new RegExp(path, flags);
129
};
(4-4/5)