1 |
3a515b92
|
cagy
|
'use strict';
|
2 |
|
|
|
3 |
|
|
/**
|
4 |
|
|
* Module dependencies
|
5 |
|
|
*/
|
6 |
|
|
|
7 |
|
|
var util = require('util');
|
8 |
|
|
var braces = require('braces');
|
9 |
|
|
var toRegex = require('to-regex');
|
10 |
|
|
var extend = require('extend-shallow');
|
11 |
|
|
|
12 |
|
|
/**
|
13 |
|
|
* Local dependencies
|
14 |
|
|
*/
|
15 |
|
|
|
16 |
|
|
var compilers = require('./lib/compilers');
|
17 |
|
|
var parsers = require('./lib/parsers');
|
18 |
|
|
var cache = require('./lib/cache');
|
19 |
|
|
var utils = require('./lib/utils');
|
20 |
|
|
var MAX_LENGTH = 1024 * 64;
|
21 |
|
|
|
22 |
|
|
/**
|
23 |
|
|
* The main function takes a list of strings and one or more
|
24 |
|
|
* glob patterns to use for matching.
|
25 |
|
|
*
|
26 |
|
|
* ```js
|
27 |
|
|
* var mm = require('micromatch');
|
28 |
|
|
* mm(list, patterns[, options]);
|
29 |
|
|
*
|
30 |
|
|
* console.log(mm(['a.js', 'a.txt'], ['*.js']));
|
31 |
|
|
* //=> [ 'a.js' ]
|
32 |
|
|
* ```
|
33 |
|
|
* @param {Array} `list` A list of strings to match
|
34 |
|
|
* @param {String|Array} `patterns` One or more glob patterns to use for matching.
|
35 |
|
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
36 |
|
|
* @return {Array} Returns an array of matches
|
37 |
|
|
* @summary false
|
38 |
|
|
* @api public
|
39 |
|
|
*/
|
40 |
|
|
|
41 |
|
|
function micromatch(list, patterns, options) {
|
42 |
|
|
patterns = utils.arrayify(patterns);
|
43 |
|
|
list = utils.arrayify(list);
|
44 |
|
|
|
45 |
|
|
var len = patterns.length;
|
46 |
|
|
if (list.length === 0 || len === 0) {
|
47 |
|
|
return [];
|
48 |
|
|
}
|
49 |
|
|
|
50 |
|
|
if (len === 1) {
|
51 |
|
|
return micromatch.match(list, patterns[0], options);
|
52 |
|
|
}
|
53 |
|
|
|
54 |
|
|
var omit = [];
|
55 |
|
|
var keep = [];
|
56 |
|
|
var idx = -1;
|
57 |
|
|
|
58 |
|
|
while (++idx < len) {
|
59 |
|
|
var pattern = patterns[idx];
|
60 |
|
|
|
61 |
|
|
if (typeof pattern === 'string' && pattern.charCodeAt(0) === 33 /* ! */) {
|
62 |
|
|
omit.push.apply(omit, micromatch.match(list, pattern.slice(1), options));
|
63 |
|
|
} else {
|
64 |
|
|
keep.push.apply(keep, micromatch.match(list, pattern, options));
|
65 |
|
|
}
|
66 |
|
|
}
|
67 |
|
|
|
68 |
|
|
var matches = utils.diff(keep, omit);
|
69 |
|
|
if (!options || options.nodupes !== false) {
|
70 |
|
|
return utils.unique(matches);
|
71 |
|
|
}
|
72 |
|
|
|
73 |
|
|
return matches;
|
74 |
|
|
}
|
75 |
|
|
|
76 |
|
|
/**
|
77 |
|
|
* Similar to the main function, but `pattern` must be a string.
|
78 |
|
|
*
|
79 |
|
|
* ```js
|
80 |
|
|
* var mm = require('micromatch');
|
81 |
|
|
* mm.match(list, pattern[, options]);
|
82 |
|
|
*
|
83 |
|
|
* console.log(mm.match(['a.a', 'a.aa', 'a.b', 'a.c'], '*.a'));
|
84 |
|
|
* //=> ['a.a', 'a.aa']
|
85 |
|
|
* ```
|
86 |
|
|
* @param {Array} `list` Array of strings to match
|
87 |
|
|
* @param {String} `pattern` Glob pattern to use for matching.
|
88 |
|
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
89 |
|
|
* @return {Array} Returns an array of matches
|
90 |
|
|
* @api public
|
91 |
|
|
*/
|
92 |
|
|
|
93 |
|
|
micromatch.match = function(list, pattern, options) {
|
94 |
|
|
if (Array.isArray(pattern)) {
|
95 |
|
|
throw new TypeError('expected pattern to be a string');
|
96 |
|
|
}
|
97 |
|
|
|
98 |
|
|
var unixify = utils.unixify(options);
|
99 |
|
|
var isMatch = memoize('match', pattern, options, micromatch.matcher);
|
100 |
|
|
var matches = [];
|
101 |
|
|
|
102 |
|
|
list = utils.arrayify(list);
|
103 |
|
|
var len = list.length;
|
104 |
|
|
var idx = -1;
|
105 |
|
|
|
106 |
|
|
while (++idx < len) {
|
107 |
|
|
var ele = list[idx];
|
108 |
|
|
if (ele === pattern || isMatch(ele)) {
|
109 |
|
|
matches.push(utils.value(ele, unixify, options));
|
110 |
|
|
}
|
111 |
|
|
}
|
112 |
|
|
|
113 |
|
|
// if no options were passed, uniquify results and return
|
114 |
|
|
if (typeof options === 'undefined') {
|
115 |
|
|
return utils.unique(matches);
|
116 |
|
|
}
|
117 |
|
|
|
118 |
|
|
if (matches.length === 0) {
|
119 |
|
|
if (options.failglob === true) {
|
120 |
|
|
throw new Error('no matches found for "' + pattern + '"');
|
121 |
|
|
}
|
122 |
|
|
if (options.nonull === true || options.nullglob === true) {
|
123 |
|
|
return [options.unescape ? utils.unescape(pattern) : pattern];
|
124 |
|
|
}
|
125 |
|
|
}
|
126 |
|
|
|
127 |
|
|
// if `opts.ignore` was defined, diff ignored list
|
128 |
|
|
if (options.ignore) {
|
129 |
|
|
matches = micromatch.not(matches, options.ignore, options);
|
130 |
|
|
}
|
131 |
|
|
|
132 |
|
|
return options.nodupes !== false ? utils.unique(matches) : matches;
|
133 |
|
|
};
|
134 |
|
|
|
135 |
|
|
/**
|
136 |
|
|
* Returns true if the specified `string` matches the given glob `pattern`.
|
137 |
|
|
*
|
138 |
|
|
* ```js
|
139 |
|
|
* var mm = require('micromatch');
|
140 |
|
|
* mm.isMatch(string, pattern[, options]);
|
141 |
|
|
*
|
142 |
|
|
* console.log(mm.isMatch('a.a', '*.a'));
|
143 |
|
|
* //=> true
|
144 |
|
|
* console.log(mm.isMatch('a.b', '*.a'));
|
145 |
|
|
* //=> false
|
146 |
|
|
* ```
|
147 |
|
|
* @param {String} `string` String to match
|
148 |
|
|
* @param {String} `pattern` Glob pattern to use for matching.
|
149 |
|
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
150 |
|
|
* @return {Boolean} Returns true if the string matches the glob pattern.
|
151 |
|
|
* @api public
|
152 |
|
|
*/
|
153 |
|
|
|
154 |
|
|
micromatch.isMatch = function(str, pattern, options) {
|
155 |
|
|
if (typeof str !== 'string') {
|
156 |
|
|
throw new TypeError('expected a string: "' + util.inspect(str) + '"');
|
157 |
|
|
}
|
158 |
|
|
|
159 |
|
|
if (isEmptyString(str) || isEmptyString(pattern)) {
|
160 |
|
|
return false;
|
161 |
|
|
}
|
162 |
|
|
|
163 |
|
|
var equals = utils.equalsPattern(options);
|
164 |
|
|
if (equals(str)) {
|
165 |
|
|
return true;
|
166 |
|
|
}
|
167 |
|
|
|
168 |
|
|
var isMatch = memoize('isMatch', pattern, options, micromatch.matcher);
|
169 |
|
|
return isMatch(str);
|
170 |
|
|
};
|
171 |
|
|
|
172 |
|
|
/**
|
173 |
|
|
* Returns true if some of the strings in the given `list` match any of the
|
174 |
|
|
* given glob `patterns`.
|
175 |
|
|
*
|
176 |
|
|
* ```js
|
177 |
|
|
* var mm = require('micromatch');
|
178 |
|
|
* mm.some(list, patterns[, options]);
|
179 |
|
|
*
|
180 |
|
|
* console.log(mm.some(['foo.js', 'bar.js'], ['*.js', '!foo.js']));
|
181 |
|
|
* // true
|
182 |
|
|
* console.log(mm.some(['foo.js'], ['*.js', '!foo.js']));
|
183 |
|
|
* // false
|
184 |
|
|
* ```
|
185 |
|
|
* @param {String|Array} `list` The string or array of strings to test. Returns as soon as the first match is found.
|
186 |
|
|
* @param {String|Array} `patterns` One or more glob patterns to use for matching.
|
187 |
|
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
188 |
|
|
* @return {Boolean} Returns true if any patterns match `str`
|
189 |
|
|
* @api public
|
190 |
|
|
*/
|
191 |
|
|
|
192 |
|
|
micromatch.some = function(list, patterns, options) {
|
193 |
|
|
if (typeof list === 'string') {
|
194 |
|
|
list = [list];
|
195 |
|
|
}
|
196 |
|
|
for (var i = 0; i < list.length; i++) {
|
197 |
|
|
if (micromatch(list[i], patterns, options).length === 1) {
|
198 |
|
|
return true;
|
199 |
|
|
}
|
200 |
|
|
}
|
201 |
|
|
return false;
|
202 |
|
|
};
|
203 |
|
|
|
204 |
|
|
/**
|
205 |
|
|
* Returns true if every string in the given `list` matches
|
206 |
|
|
* any of the given glob `patterns`.
|
207 |
|
|
*
|
208 |
|
|
* ```js
|
209 |
|
|
* var mm = require('micromatch');
|
210 |
|
|
* mm.every(list, patterns[, options]);
|
211 |
|
|
*
|
212 |
|
|
* console.log(mm.every('foo.js', ['foo.js']));
|
213 |
|
|
* // true
|
214 |
|
|
* console.log(mm.every(['foo.js', 'bar.js'], ['*.js']));
|
215 |
|
|
* // true
|
216 |
|
|
* console.log(mm.every(['foo.js', 'bar.js'], ['*.js', '!foo.js']));
|
217 |
|
|
* // false
|
218 |
|
|
* console.log(mm.every(['foo.js'], ['*.js', '!foo.js']));
|
219 |
|
|
* // false
|
220 |
|
|
* ```
|
221 |
|
|
* @param {String|Array} `list` The string or array of strings to test.
|
222 |
|
|
* @param {String|Array} `patterns` One or more glob patterns to use for matching.
|
223 |
|
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
224 |
|
|
* @return {Boolean} Returns true if any patterns match `str`
|
225 |
|
|
* @api public
|
226 |
|
|
*/
|
227 |
|
|
|
228 |
|
|
micromatch.every = function(list, patterns, options) {
|
229 |
|
|
if (typeof list === 'string') {
|
230 |
|
|
list = [list];
|
231 |
|
|
}
|
232 |
|
|
for (var i = 0; i < list.length; i++) {
|
233 |
|
|
if (micromatch(list[i], patterns, options).length !== 1) {
|
234 |
|
|
return false;
|
235 |
|
|
}
|
236 |
|
|
}
|
237 |
|
|
return true;
|
238 |
|
|
};
|
239 |
|
|
|
240 |
|
|
/**
|
241 |
|
|
* Returns true if **any** of the given glob `patterns`
|
242 |
|
|
* match the specified `string`.
|
243 |
|
|
*
|
244 |
|
|
* ```js
|
245 |
|
|
* var mm = require('micromatch');
|
246 |
|
|
* mm.any(string, patterns[, options]);
|
247 |
|
|
*
|
248 |
|
|
* console.log(mm.any('a.a', ['b.*', '*.a']));
|
249 |
|
|
* //=> true
|
250 |
|
|
* console.log(mm.any('a.a', 'b.*'));
|
251 |
|
|
* //=> false
|
252 |
|
|
* ```
|
253 |
|
|
* @param {String|Array} `str` The string to test.
|
254 |
|
|
* @param {String|Array} `patterns` One or more glob patterns to use for matching.
|
255 |
|
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
256 |
|
|
* @return {Boolean} Returns true if any patterns match `str`
|
257 |
|
|
* @api public
|
258 |
|
|
*/
|
259 |
|
|
|
260 |
|
|
micromatch.any = function(str, patterns, options) {
|
261 |
|
|
if (typeof str !== 'string') {
|
262 |
|
|
throw new TypeError('expected a string: "' + util.inspect(str) + '"');
|
263 |
|
|
}
|
264 |
|
|
|
265 |
|
|
if (isEmptyString(str) || isEmptyString(patterns)) {
|
266 |
|
|
return false;
|
267 |
|
|
}
|
268 |
|
|
|
269 |
|
|
if (typeof patterns === 'string') {
|
270 |
|
|
patterns = [patterns];
|
271 |
|
|
}
|
272 |
|
|
|
273 |
|
|
for (var i = 0; i < patterns.length; i++) {
|
274 |
|
|
if (micromatch.isMatch(str, patterns[i], options)) {
|
275 |
|
|
return true;
|
276 |
|
|
}
|
277 |
|
|
}
|
278 |
|
|
return false;
|
279 |
|
|
};
|
280 |
|
|
|
281 |
|
|
/**
|
282 |
|
|
* Returns true if **all** of the given `patterns` match
|
283 |
|
|
* the specified string.
|
284 |
|
|
*
|
285 |
|
|
* ```js
|
286 |
|
|
* var mm = require('micromatch');
|
287 |
|
|
* mm.all(string, patterns[, options]);
|
288 |
|
|
*
|
289 |
|
|
* console.log(mm.all('foo.js', ['foo.js']));
|
290 |
|
|
* // true
|
291 |
|
|
*
|
292 |
|
|
* console.log(mm.all('foo.js', ['*.js', '!foo.js']));
|
293 |
|
|
* // false
|
294 |
|
|
*
|
295 |
|
|
* console.log(mm.all('foo.js', ['*.js', 'foo.js']));
|
296 |
|
|
* // true
|
297 |
|
|
*
|
298 |
|
|
* console.log(mm.all('foo.js', ['*.js', 'f*', '*o*', '*o.js']));
|
299 |
|
|
* // true
|
300 |
|
|
* ```
|
301 |
|
|
* @param {String|Array} `str` The string to test.
|
302 |
|
|
* @param {String|Array} `patterns` One or more glob patterns to use for matching.
|
303 |
|
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
304 |
|
|
* @return {Boolean} Returns true if any patterns match `str`
|
305 |
|
|
* @api public
|
306 |
|
|
*/
|
307 |
|
|
|
308 |
|
|
micromatch.all = function(str, patterns, options) {
|
309 |
|
|
if (typeof str !== 'string') {
|
310 |
|
|
throw new TypeError('expected a string: "' + util.inspect(str) + '"');
|
311 |
|
|
}
|
312 |
|
|
if (typeof patterns === 'string') {
|
313 |
|
|
patterns = [patterns];
|
314 |
|
|
}
|
315 |
|
|
for (var i = 0; i < patterns.length; i++) {
|
316 |
|
|
if (!micromatch.isMatch(str, patterns[i], options)) {
|
317 |
|
|
return false;
|
318 |
|
|
}
|
319 |
|
|
}
|
320 |
|
|
return true;
|
321 |
|
|
};
|
322 |
|
|
|
323 |
|
|
/**
|
324 |
|
|
* Returns a list of strings that _**do not match any**_ of the given `patterns`.
|
325 |
|
|
*
|
326 |
|
|
* ```js
|
327 |
|
|
* var mm = require('micromatch');
|
328 |
|
|
* mm.not(list, patterns[, options]);
|
329 |
|
|
*
|
330 |
|
|
* console.log(mm.not(['a.a', 'b.b', 'c.c'], '*.a'));
|
331 |
|
|
* //=> ['b.b', 'c.c']
|
332 |
|
|
* ```
|
333 |
|
|
* @param {Array} `list` Array of strings to match.
|
334 |
|
|
* @param {String|Array} `patterns` One or more glob pattern to use for matching.
|
335 |
|
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
336 |
|
|
* @return {Array} Returns an array of strings that **do not match** the given patterns.
|
337 |
|
|
* @api public
|
338 |
|
|
*/
|
339 |
|
|
|
340 |
|
|
micromatch.not = function(list, patterns, options) {
|
341 |
|
|
var opts = extend({}, options);
|
342 |
|
|
var ignore = opts.ignore;
|
343 |
|
|
delete opts.ignore;
|
344 |
|
|
|
345 |
|
|
var unixify = utils.unixify(opts);
|
346 |
|
|
list = utils.arrayify(list).map(unixify);
|
347 |
|
|
|
348 |
|
|
var matches = utils.diff(list, micromatch(list, patterns, opts));
|
349 |
|
|
if (ignore) {
|
350 |
|
|
matches = utils.diff(matches, micromatch(list, ignore));
|
351 |
|
|
}
|
352 |
|
|
|
353 |
|
|
return opts.nodupes !== false ? utils.unique(matches) : matches;
|
354 |
|
|
};
|
355 |
|
|
|
356 |
|
|
/**
|
357 |
|
|
* Returns true if the given `string` contains the given pattern. Similar
|
358 |
|
|
* to [.isMatch](#isMatch) but the pattern can match any part of the string.
|
359 |
|
|
*
|
360 |
|
|
* ```js
|
361 |
|
|
* var mm = require('micromatch');
|
362 |
|
|
* mm.contains(string, pattern[, options]);
|
363 |
|
|
*
|
364 |
|
|
* console.log(mm.contains('aa/bb/cc', '*b'));
|
365 |
|
|
* //=> true
|
366 |
|
|
* console.log(mm.contains('aa/bb/cc', '*d'));
|
367 |
|
|
* //=> false
|
368 |
|
|
* ```
|
369 |
|
|
* @param {String} `str` The string to match.
|
370 |
|
|
* @param {String|Array} `patterns` Glob pattern to use for matching.
|
371 |
|
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
372 |
|
|
* @return {Boolean} Returns true if the patter matches any part of `str`.
|
373 |
|
|
* @api public
|
374 |
|
|
*/
|
375 |
|
|
|
376 |
|
|
micromatch.contains = function(str, patterns, options) {
|
377 |
|
|
if (typeof str !== 'string') {
|
378 |
|
|
throw new TypeError('expected a string: "' + util.inspect(str) + '"');
|
379 |
|
|
}
|
380 |
|
|
|
381 |
|
|
if (typeof patterns === 'string') {
|
382 |
|
|
if (isEmptyString(str) || isEmptyString(patterns)) {
|
383 |
|
|
return false;
|
384 |
|
|
}
|
385 |
|
|
|
386 |
|
|
var equals = utils.equalsPattern(patterns, options);
|
387 |
|
|
if (equals(str)) {
|
388 |
|
|
return true;
|
389 |
|
|
}
|
390 |
|
|
var contains = utils.containsPattern(patterns, options);
|
391 |
|
|
if (contains(str)) {
|
392 |
|
|
return true;
|
393 |
|
|
}
|
394 |
|
|
}
|
395 |
|
|
|
396 |
|
|
var opts = extend({}, options, {contains: true});
|
397 |
|
|
return micromatch.any(str, patterns, opts);
|
398 |
|
|
};
|
399 |
|
|
|
400 |
|
|
/**
|
401 |
|
|
* Returns true if the given pattern and options should enable
|
402 |
|
|
* the `matchBase` option.
|
403 |
|
|
* @return {Boolean}
|
404 |
|
|
* @api private
|
405 |
|
|
*/
|
406 |
|
|
|
407 |
|
|
micromatch.matchBase = function(pattern, options) {
|
408 |
|
|
if (pattern && pattern.indexOf('/') !== -1 || !options) return false;
|
409 |
|
|
return options.basename === true || options.matchBase === true;
|
410 |
|
|
};
|
411 |
|
|
|
412 |
|
|
/**
|
413 |
|
|
* Filter the keys of the given object with the given `glob` pattern
|
414 |
|
|
* and `options`. Does not attempt to match nested keys. If you need this feature,
|
415 |
|
|
* use [glob-object][] instead.
|
416 |
|
|
*
|
417 |
|
|
* ```js
|
418 |
|
|
* var mm = require('micromatch');
|
419 |
|
|
* mm.matchKeys(object, patterns[, options]);
|
420 |
|
|
*
|
421 |
|
|
* var obj = { aa: 'a', ab: 'b', ac: 'c' };
|
422 |
|
|
* console.log(mm.matchKeys(obj, '*b'));
|
423 |
|
|
* //=> { ab: 'b' }
|
424 |
|
|
* ```
|
425 |
|
|
* @param {Object} `object` The object with keys to filter.
|
426 |
|
|
* @param {String|Array} `patterns` One or more glob patterns to use for matching.
|
427 |
|
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
428 |
|
|
* @return {Object} Returns an object with only keys that match the given patterns.
|
429 |
|
|
* @api public
|
430 |
|
|
*/
|
431 |
|
|
|
432 |
|
|
micromatch.matchKeys = function(obj, patterns, options) {
|
433 |
|
|
if (!utils.isObject(obj)) {
|
434 |
|
|
throw new TypeError('expected the first argument to be an object');
|
435 |
|
|
}
|
436 |
|
|
var keys = micromatch(Object.keys(obj), patterns, options);
|
437 |
|
|
return utils.pick(obj, keys);
|
438 |
|
|
};
|
439 |
|
|
|
440 |
|
|
/**
|
441 |
|
|
* Returns a memoized matcher function from the given glob `pattern` and `options`.
|
442 |
|
|
* The returned function takes a string to match as its only argument and returns
|
443 |
|
|
* true if the string is a match.
|
444 |
|
|
*
|
445 |
|
|
* ```js
|
446 |
|
|
* var mm = require('micromatch');
|
447 |
|
|
* mm.matcher(pattern[, options]);
|
448 |
|
|
*
|
449 |
|
|
* var isMatch = mm.matcher('*.!(*a)');
|
450 |
|
|
* console.log(isMatch('a.a'));
|
451 |
|
|
* //=> false
|
452 |
|
|
* console.log(isMatch('a.b'));
|
453 |
|
|
* //=> true
|
454 |
|
|
* ```
|
455 |
|
|
* @param {String} `pattern` Glob pattern
|
456 |
|
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed.
|
457 |
|
|
* @return {Function} Returns a matcher function.
|
458 |
|
|
* @api public
|
459 |
|
|
*/
|
460 |
|
|
|
461 |
|
|
micromatch.matcher = function matcher(pattern, options) {
|
462 |
|
|
if (Array.isArray(pattern)) {
|
463 |
|
|
return compose(pattern, options, matcher);
|
464 |
|
|
}
|
465 |
|
|
|
466 |
|
|
// if pattern is a regex
|
467 |
|
|
if (pattern instanceof RegExp) {
|
468 |
|
|
return test(pattern);
|
469 |
|
|
}
|
470 |
|
|
|
471 |
|
|
// if pattern is invalid
|
472 |
|
|
if (!utils.isString(pattern)) {
|
473 |
|
|
throw new TypeError('expected pattern to be an array, string or regex');
|
474 |
|
|
}
|
475 |
|
|
|
476 |
|
|
// if pattern is a non-glob string
|
477 |
|
|
if (!utils.hasSpecialChars(pattern)) {
|
478 |
|
|
if (options && options.nocase === true) {
|
479 |
|
|
pattern = pattern.toLowerCase();
|
480 |
|
|
}
|
481 |
|
|
return utils.matchPath(pattern, options);
|
482 |
|
|
}
|
483 |
|
|
|
484 |
|
|
// if pattern is a glob string
|
485 |
|
|
var re = micromatch.makeRe(pattern, options);
|
486 |
|
|
|
487 |
|
|
// if `options.matchBase` or `options.basename` is defined
|
488 |
|
|
if (micromatch.matchBase(pattern, options)) {
|
489 |
|
|
return utils.matchBasename(re, options);
|
490 |
|
|
}
|
491 |
|
|
|
492 |
|
|
function test(regex) {
|
493 |
|
|
var equals = utils.equalsPattern(options);
|
494 |
|
|
var unixify = utils.unixify(options);
|
495 |
|
|
|
496 |
|
|
return function(str) {
|
497 |
|
|
if (equals(str)) {
|
498 |
|
|
return true;
|
499 |
|
|
}
|
500 |
|
|
|
501 |
|
|
if (regex.test(unixify(str))) {
|
502 |
|
|
return true;
|
503 |
|
|
}
|
504 |
|
|
return false;
|
505 |
|
|
};
|
506 |
|
|
}
|
507 |
|
|
|
508 |
|
|
var fn = test(re);
|
509 |
|
|
Object.defineProperty(fn, 'result', {
|
510 |
|
|
configurable: true,
|
511 |
|
|
enumerable: false,
|
512 |
|
|
value: re.result
|
513 |
|
|
});
|
514 |
|
|
return fn;
|
515 |
|
|
};
|
516 |
|
|
|
517 |
|
|
/**
|
518 |
|
|
* Returns an array of matches captured by `pattern` in `string, or `null` if the pattern did not match.
|
519 |
|
|
*
|
520 |
|
|
* ```js
|
521 |
|
|
* var mm = require('micromatch');
|
522 |
|
|
* mm.capture(pattern, string[, options]);
|
523 |
|
|
*
|
524 |
|
|
* console.log(mm.capture('test/*.js', 'test/foo.js'));
|
525 |
|
|
* //=> ['foo']
|
526 |
|
|
* console.log(mm.capture('test/*.js', 'foo/bar.css'));
|
527 |
|
|
* //=> null
|
528 |
|
|
* ```
|
529 |
|
|
* @param {String} `pattern` Glob pattern to use for matching.
|
530 |
|
|
* @param {String} `string` String to match
|
531 |
|
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed
|
532 |
|
|
* @return {Boolean} Returns an array of captures if the string matches the glob pattern, otherwise `null`.
|
533 |
|
|
* @api public
|
534 |
|
|
*/
|
535 |
|
|
|
536 |
|
|
micromatch.capture = function(pattern, str, options) {
|
537 |
|
|
var re = micromatch.makeRe(pattern, extend({capture: true}, options));
|
538 |
|
|
var unixify = utils.unixify(options);
|
539 |
|
|
|
540 |
|
|
function match() {
|
541 |
|
|
return function(string) {
|
542 |
|
|
var match = re.exec(unixify(string));
|
543 |
|
|
if (!match) {
|
544 |
|
|
return null;
|
545 |
|
|
}
|
546 |
|
|
|
547 |
|
|
return match.slice(1);
|
548 |
|
|
};
|
549 |
|
|
}
|
550 |
|
|
|
551 |
|
|
var capture = memoize('capture', pattern, options, match);
|
552 |
|
|
return capture(str);
|
553 |
|
|
};
|
554 |
|
|
|
555 |
|
|
/**
|
556 |
|
|
* Create a regular expression from the given glob `pattern`.
|
557 |
|
|
*
|
558 |
|
|
* ```js
|
559 |
|
|
* var mm = require('micromatch');
|
560 |
|
|
* mm.makeRe(pattern[, options]);
|
561 |
|
|
*
|
562 |
|
|
* console.log(mm.makeRe('*.js'));
|
563 |
|
|
* //=> /^(?:(\.[\\\/])?(?!\.)(?=.)[^\/]*?\.js)$/
|
564 |
|
|
* ```
|
565 |
|
|
* @param {String} `pattern` A glob pattern to convert to regex.
|
566 |
|
|
* @param {Object} `options` See available [options](#options) for changing how matches are performed.
|
567 |
|
|
* @return {RegExp} Returns a regex created from the given pattern.
|
568 |
|
|
* @api public
|
569 |
|
|
*/
|
570 |
|
|
|
571 |
|
|
micromatch.makeRe = function(pattern, options) {
|
572 |
|
|
if (typeof pattern !== 'string') {
|
573 |
|
|
throw new TypeError('expected pattern to be a string');
|
574 |
|
|
}
|
575 |
|
|
|
576 |
|
|
if (pattern.length > MAX_LENGTH) {
|
577 |
|
|
throw new Error('expected pattern to be less than ' + MAX_LENGTH + ' characters');
|
578 |
|
|
}
|
579 |
|
|
|
580 |
|
|
function makeRe() {
|
581 |
|
|
var result = micromatch.create(pattern, options);
|
582 |
|
|
var ast_array = [];
|
583 |
|
|
var output = result.map(function(obj) {
|
584 |
|
|
obj.ast.state = obj.state;
|
585 |
|
|
ast_array.push(obj.ast);
|
586 |
|
|
return obj.output;
|
587 |
|
|
});
|
588 |
|
|
|
589 |
|
|
var regex = toRegex(output.join('|'), options);
|
590 |
|
|
Object.defineProperty(regex, 'result', {
|
591 |
|
|
configurable: true,
|
592 |
|
|
enumerable: false,
|
593 |
|
|
value: ast_array
|
594 |
|
|
});
|
595 |
|
|
return regex;
|
596 |
|
|
}
|
597 |
|
|
|
598 |
|
|
return memoize('makeRe', pattern, options, makeRe);
|
599 |
|
|
};
|
600 |
|
|
|
601 |
|
|
/**
|
602 |
|
|
* Expand the given brace `pattern`.
|
603 |
|
|
*
|
604 |
|
|
* ```js
|
605 |
|
|
* var mm = require('micromatch');
|
606 |
|
|
* console.log(mm.braces('foo/{a,b}/bar'));
|
607 |
|
|
* //=> ['foo/(a|b)/bar']
|
608 |
|
|
*
|
609 |
|
|
* console.log(mm.braces('foo/{a,b}/bar', {expand: true}));
|
610 |
|
|
* //=> ['foo/(a|b)/bar']
|
611 |
|
|
* ```
|
612 |
|
|
* @param {String} `pattern` String with brace pattern to expand.
|
613 |
|
|
* @param {Object} `options` Any [options](#options) to change how expansion is performed. See the [braces][] library for all available options.
|
614 |
|
|
* @return {Array}
|
615 |
|
|
* @api public
|
616 |
|
|
*/
|
617 |
|
|
|
618 |
|
|
micromatch.braces = function(pattern, options) {
|
619 |
|
|
if (typeof pattern !== 'string' && !Array.isArray(pattern)) {
|
620 |
|
|
throw new TypeError('expected pattern to be an array or string');
|
621 |
|
|
}
|
622 |
|
|
|
623 |
|
|
function expand() {
|
624 |
|
|
if (options && options.nobrace === true || !/\{.*\}/.test(pattern)) {
|
625 |
|
|
return utils.arrayify(pattern);
|
626 |
|
|
}
|
627 |
|
|
return braces(pattern, options);
|
628 |
|
|
}
|
629 |
|
|
|
630 |
|
|
return memoize('braces', pattern, options, expand);
|
631 |
|
|
};
|
632 |
|
|
|
633 |
|
|
/**
|
634 |
|
|
* Proxy to the [micromatch.braces](#method), for parity with
|
635 |
|
|
* minimatch.
|
636 |
|
|
*/
|
637 |
|
|
|
638 |
|
|
micromatch.braceExpand = function(pattern, options) {
|
639 |
|
|
var opts = extend({}, options, {expand: true});
|
640 |
|
|
return micromatch.braces(pattern, opts);
|
641 |
|
|
};
|
642 |
|
|
|
643 |
|
|
/**
|
644 |
|
|
* Parses the given glob `pattern` and returns an array of abstract syntax
|
645 |
|
|
* trees (ASTs), with the compiled `output` and optional source `map` on
|
646 |
|
|
* each AST.
|
647 |
|
|
*
|
648 |
|
|
* ```js
|
649 |
|
|
* var mm = require('micromatch');
|
650 |
|
|
* mm.create(pattern[, options]);
|
651 |
|
|
*
|
652 |
|
|
* console.log(mm.create('abc/*.js'));
|
653 |
|
|
* // [{ options: { source: 'string', sourcemap: true },
|
654 |
|
|
* // state: {},
|
655 |
|
|
* // compilers:
|
656 |
|
|
* // { ... },
|
657 |
|
|
* // output: '(\\.[\\\\\\/])?abc\\/(?!\\.)(?=.)[^\\/]*?\\.js',
|
658 |
|
|
* // ast:
|
659 |
|
|
* // { type: 'root',
|
660 |
|
|
* // errors: [],
|
661 |
|
|
* // nodes:
|
662 |
|
|
* // [ ... ],
|
663 |
|
|
* // dot: false,
|
664 |
|
|
* // input: 'abc/*.js' },
|
665 |
|
|
* // parsingErrors: [],
|
666 |
|
|
* // map:
|
667 |
|
|
* // { version: 3,
|
668 |
|
|
* // sources: [ 'string' ],
|
669 |
|
|
* // names: [],
|
670 |
|
|
* // mappings: 'AAAA,GAAG,EAAC,kBAAC,EAAC,EAAE',
|
671 |
|
|
* // sourcesContent: [ 'abc/*.js' ] },
|
672 |
|
|
* // position: { line: 1, column: 28 },
|
673 |
|
|
* // content: {},
|
674 |
|
|
* // files: {},
|
675 |
|
|
* // idx: 6 }]
|
676 |
|
|
* ```
|
677 |
|
|
* @param {String} `pattern` Glob pattern to parse and compile.
|
678 |
|
|
* @param {Object} `options` Any [options](#options) to change how parsing and compiling is performed.
|
679 |
|
|
* @return {Object} Returns an object with the parsed AST, compiled string and optional source map.
|
680 |
|
|
* @api public
|
681 |
|
|
*/
|
682 |
|
|
|
683 |
|
|
micromatch.create = function(pattern, options) {
|
684 |
|
|
return memoize('create', pattern, options, function() {
|
685 |
|
|
function create(str, opts) {
|
686 |
|
|
return micromatch.compile(micromatch.parse(str, opts), opts);
|
687 |
|
|
}
|
688 |
|
|
|
689 |
|
|
pattern = micromatch.braces(pattern, options);
|
690 |
|
|
var len = pattern.length;
|
691 |
|
|
var idx = -1;
|
692 |
|
|
var res = [];
|
693 |
|
|
|
694 |
|
|
while (++idx < len) {
|
695 |
|
|
res.push(create(pattern[idx], options));
|
696 |
|
|
}
|
697 |
|
|
return res;
|
698 |
|
|
});
|
699 |
|
|
};
|
700 |
|
|
|
701 |
|
|
/**
|
702 |
|
|
* Parse the given `str` with the given `options`.
|
703 |
|
|
*
|
704 |
|
|
* ```js
|
705 |
|
|
* var mm = require('micromatch');
|
706 |
|
|
* mm.parse(pattern[, options]);
|
707 |
|
|
*
|
708 |
|
|
* var ast = mm.parse('a/{b,c}/d');
|
709 |
|
|
* console.log(ast);
|
710 |
|
|
* // { type: 'root',
|
711 |
|
|
* // errors: [],
|
712 |
|
|
* // input: 'a/{b,c}/d',
|
713 |
|
|
* // nodes:
|
714 |
|
|
* // [ { type: 'bos', val: '' },
|
715 |
|
|
* // { type: 'text', val: 'a/' },
|
716 |
|
|
* // { type: 'brace',
|
717 |
|
|
* // nodes:
|
718 |
|
|
* // [ { type: 'brace.open', val: '{' },
|
719 |
|
|
* // { type: 'text', val: 'b,c' },
|
720 |
|
|
* // { type: 'brace.close', val: '}' } ] },
|
721 |
|
|
* // { type: 'text', val: '/d' },
|
722 |
|
|
* // { type: 'eos', val: '' } ] }
|
723 |
|
|
* ```
|
724 |
|
|
* @param {String} `str`
|
725 |
|
|
* @param {Object} `options`
|
726 |
|
|
* @return {Object} Returns an AST
|
727 |
|
|
* @api public
|
728 |
|
|
*/
|
729 |
|
|
|
730 |
|
|
micromatch.parse = function(pattern, options) {
|
731 |
|
|
if (typeof pattern !== 'string') {
|
732 |
|
|
throw new TypeError('expected a string');
|
733 |
|
|
}
|
734 |
|
|
|
735 |
|
|
function parse() {
|
736 |
|
|
var snapdragon = utils.instantiate(null, options);
|
737 |
|
|
parsers(snapdragon, options);
|
738 |
|
|
|
739 |
|
|
var ast = snapdragon.parse(pattern, options);
|
740 |
|
|
utils.define(ast, 'snapdragon', snapdragon);
|
741 |
|
|
ast.input = pattern;
|
742 |
|
|
return ast;
|
743 |
|
|
}
|
744 |
|
|
|
745 |
|
|
return memoize('parse', pattern, options, parse);
|
746 |
|
|
};
|
747 |
|
|
|
748 |
|
|
/**
|
749 |
|
|
* Compile the given `ast` or string with the given `options`.
|
750 |
|
|
*
|
751 |
|
|
* ```js
|
752 |
|
|
* var mm = require('micromatch');
|
753 |
|
|
* mm.compile(ast[, options]);
|
754 |
|
|
*
|
755 |
|
|
* var ast = mm.parse('a/{b,c}/d');
|
756 |
|
|
* console.log(mm.compile(ast));
|
757 |
|
|
* // { options: { source: 'string' },
|
758 |
|
|
* // state: {},
|
759 |
|
|
* // compilers:
|
760 |
|
|
* // { eos: [Function],
|
761 |
|
|
* // noop: [Function],
|
762 |
|
|
* // bos: [Function],
|
763 |
|
|
* // brace: [Function],
|
764 |
|
|
* // 'brace.open': [Function],
|
765 |
|
|
* // text: [Function],
|
766 |
|
|
* // 'brace.close': [Function] },
|
767 |
|
|
* // output: [ 'a/(b|c)/d' ],
|
768 |
|
|
* // ast:
|
769 |
|
|
* // { ... },
|
770 |
|
|
* // parsingErrors: [] }
|
771 |
|
|
* ```
|
772 |
|
|
* @param {Object|String} `ast`
|
773 |
|
|
* @param {Object} `options`
|
774 |
|
|
* @return {Object} Returns an object that has an `output` property with the compiled string.
|
775 |
|
|
* @api public
|
776 |
|
|
*/
|
777 |
|
|
|
778 |
|
|
micromatch.compile = function(ast, options) {
|
779 |
|
|
if (typeof ast === 'string') {
|
780 |
|
|
ast = micromatch.parse(ast, options);
|
781 |
|
|
}
|
782 |
|
|
|
783 |
|
|
return memoize('compile', ast.input, options, function() {
|
784 |
|
|
var snapdragon = utils.instantiate(ast, options);
|
785 |
|
|
compilers(snapdragon, options);
|
786 |
|
|
return snapdragon.compile(ast, options);
|
787 |
|
|
});
|
788 |
|
|
};
|
789 |
|
|
|
790 |
|
|
/**
|
791 |
|
|
* Clear the regex cache.
|
792 |
|
|
*
|
793 |
|
|
* ```js
|
794 |
|
|
* mm.clearCache();
|
795 |
|
|
* ```
|
796 |
|
|
* @api public
|
797 |
|
|
*/
|
798 |
|
|
|
799 |
|
|
micromatch.clearCache = function() {
|
800 |
|
|
micromatch.cache.caches = {};
|
801 |
|
|
};
|
802 |
|
|
|
803 |
|
|
/**
|
804 |
|
|
* Returns true if the given value is effectively an empty string
|
805 |
|
|
*/
|
806 |
|
|
|
807 |
|
|
function isEmptyString(val) {
|
808 |
|
|
return String(val) === '' || String(val) === './';
|
809 |
|
|
}
|
810 |
|
|
|
811 |
|
|
/**
|
812 |
|
|
* Compose a matcher function with the given patterns.
|
813 |
|
|
* This allows matcher functions to be compiled once and
|
814 |
|
|
* called multiple times.
|
815 |
|
|
*/
|
816 |
|
|
|
817 |
|
|
function compose(patterns, options, matcher) {
|
818 |
|
|
var matchers;
|
819 |
|
|
|
820 |
|
|
return memoize('compose', String(patterns), options, function() {
|
821 |
|
|
return function(file) {
|
822 |
|
|
// delay composition until it's invoked the first time,
|
823 |
|
|
// after that it won't be called again
|
824 |
|
|
if (!matchers) {
|
825 |
|
|
matchers = [];
|
826 |
|
|
for (var i = 0; i < patterns.length; i++) {
|
827 |
|
|
matchers.push(matcher(patterns[i], options));
|
828 |
|
|
}
|
829 |
|
|
}
|
830 |
|
|
|
831 |
|
|
var len = matchers.length;
|
832 |
|
|
while (len--) {
|
833 |
|
|
if (matchers[len](file) === true) {
|
834 |
|
|
return true;
|
835 |
|
|
}
|
836 |
|
|
}
|
837 |
|
|
return false;
|
838 |
|
|
};
|
839 |
|
|
});
|
840 |
|
|
}
|
841 |
|
|
|
842 |
|
|
/**
|
843 |
|
|
* Memoize a generated regex or function. A unique key is generated
|
844 |
|
|
* from the `type` (usually method name), the `pattern`, and
|
845 |
|
|
* user-defined options.
|
846 |
|
|
*/
|
847 |
|
|
|
848 |
|
|
function memoize(type, pattern, options, fn) {
|
849 |
|
|
var key = utils.createKey(type + '=' + pattern, options);
|
850 |
|
|
|
851 |
|
|
if (options && options.cache === false) {
|
852 |
|
|
return fn(pattern, options);
|
853 |
|
|
}
|
854 |
|
|
|
855 |
|
|
if (cache.has(type, key)) {
|
856 |
|
|
return cache.get(type, key);
|
857 |
|
|
}
|
858 |
|
|
|
859 |
|
|
var val = fn(pattern, options);
|
860 |
|
|
cache.set(type, key, val);
|
861 |
|
|
return val;
|
862 |
|
|
}
|
863 |
|
|
|
864 |
|
|
/**
|
865 |
|
|
* Expose compiler, parser and cache on `micromatch`
|
866 |
|
|
*/
|
867 |
|
|
|
868 |
|
|
micromatch.compilers = compilers;
|
869 |
|
|
micromatch.parsers = parsers;
|
870 |
|
|
micromatch.caches = cache.caches;
|
871 |
|
|
|
872 |
|
|
/**
|
873 |
|
|
* Expose `micromatch`
|
874 |
|
|
* @type {Function}
|
875 |
|
|
*/
|
876 |
|
|
|
877 |
|
|
module.exports = micromatch;
|