-
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.js
85 lines (72 loc) · 2.26 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
var rewrite = function(pattern, visit) {
var captures = [];
pattern = pattern.replace(/\*([^}]|$)/g, '{*}$1');
pattern = pattern.replace(/(\/)?(\.)?\{([^{]+)\}(?:\(([^)]+)\))?(\?)?(?=(.|$))/g, function(_, slash, dot, name, capture, optional, closed) {
if (!/^(\w|\d|[_\-.*])+$/g.test(name)) throw new Error('bad pattern name: '+name);
captures.push(visit({
slash:slash ? '\\/' : '',
dot:dot ? '\\.' : '',
name:name,
capture:capture,
optional:optional,
closed:closed === '' || closed === '/'
}));
return '@';
});
return pattern.replace(/([\\\/."])/g, '\\$1').replace(/@/g, function() {
return captures.shift();
});
};
var replacer = function(pattern, opts) {
if (!pattern) {
return function() {
return '';
};
}
pattern = 'return "'+rewrite(pattern, function(params) {
return params.slash+params.dot+'"+params["'+params.name+'"]+"';
})+'";';
return new Function('params',pattern.replace(/\+"";$/, ';'));
};
var matcher = function(pattern, opts) {
if (!pattern) {
return function() {
return {};
};
}
var names = [];
pattern = rewrite(pattern, function(params) {
names.push(params.name);
params.capture = params.capture || (params.name === '*' ? '.+?' : '[^\\/]+');
params.optional = params.optional || (params.name === '*' ? '?' : '');
return (params.closed ? '(?:'+params.slash+params.dot : params.slash+'(?:'+params.dot)+'('+params.capture+'))'+params.optional;
});
var end = opts.strict ? '' : '[\\/]?';
var src = 'var pattern=/^'+pattern+end+'$/i;\nvar match=str.match(pattern);\nreturn match && {';
for (var i = 0; i < names.length; i++) {
if (names[i] === '*') {
src += '"*":match['+(i+1)+'] || "","glob":match['+(i+1)+'] || ""';
} else {
src += '"'+names[i]+'":match['+(i+1)+']';
}
src += (i+1 < names.length ? ',' : '');
}
src += '};';
return new Function('str', src);
};
module.exports = function(pattern, opts) {
if (!opts) opts = {};
var match = matcher(pattern, opts);
var replace = replacer(pattern, opts);
var vars = {};
var fn = function(url) {
return (typeof url === 'string' ? match : replace)(url);
};
rewrite(pattern || '', function(params) {
vars[params.name] = true;
});
if (vars['*']) vars.glob = true;
fn.variables = Object.keys(vars);
fn.pattern = pattern || '';
return fn;
};