1 | ;
|
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') {
|
620 | throw new TypeError('expected a string');
|
621 | }
|
622 |
|
623 | function expand() {
|
624 | if (options && options.nobrace === true) return [pattern];
|
625 | if (!/\{.*\}/.test(pattern)) return [pattern];
|
626 | // if (/[!@*?+]\{/.test(pattern)) {
|
627 | // options = utils.extend({}, options, {expand: true});
|
628 | // }
|
629 | return braces(pattern, options);
|
630 | }
|
631 |
|
632 | return memoize('braces', pattern, options, expand);
|
633 | };
|
634 |
|
635 | /**
|
636 | * Proxy to the [micromatch.braces](#method), for parity with
|
637 | * minimatch.
|
638 | */
|
639 |
|
640 | micromatch.braceExpand = function(pattern, options) {
|
641 | var opts = extend({}, options, {expand: true});
|
642 | return micromatch.braces(pattern, opts);
|
643 | };
|
644 |
|
645 | /**
|
646 | * Parses the given glob `pattern` and returns an array of abstract syntax
|
647 | * trees (ASTs), with the compiled `output` and optional source `map` on
|
648 | * each AST.
|
649 | *
|
650 | * ```js
|
651 | * var mm = require('micromatch');
|
652 | * mm.create(pattern[, options]);
|
653 | *
|
654 | * console.log(mm.create('abc/*.js'));
|
655 | * // [{ options: { source: 'string', sourcemap: true },
|
656 | * // state: {},
|
657 | * // compilers:
|
658 | * // { ... },
|
659 | * // output: '(\\.[\\\\\\/])?abc\\/(?!\\.)(?=.)[^\\/]*?\\.js',
|
660 | * // ast:
|
661 | * // { type: 'root',
|
662 | * // errors: [],
|
663 | * // nodes:
|
664 | * // [ ... ],
|
665 | * // dot: false,
|
666 | * // input: 'abc/*.js' },
|
667 | * // parsingErrors: [],
|
668 | * // map:
|
669 | * // { version: 3,
|
670 | * // sources: [ 'string' ],
|
671 | * // names: [],
|
672 | * // mappings: 'AAAA,GAAG,EAAC,kBAAC,EAAC,EAAE',
|
673 | * // sourcesContent: [ 'abc/*.js' ] },
|
674 | * // position: { line: 1, column: 28 },
|
675 | * // content: {},
|
676 | * // files: {},
|
677 | * // idx: 6 }]
|
678 | * ```
|
679 | * @param {String} `pattern` Glob pattern to parse and compile.
|
680 | * @param {Object} `options` Any [options](#options) to change how parsing and compiling is performed.
|
681 | * @return {Object} Returns an object with the parsed AST, compiled string and optional source map.
|
682 | * @api public
|
683 | */
|
684 |
|
685 | micromatch.create = function(pattern, options) {
|
686 | return memoize('create', pattern, options, function() {
|
687 | function create(str, opts) {
|
688 | return micromatch.compile(micromatch.parse(str, opts), opts);
|
689 | }
|
690 |
|
691 | pattern = micromatch.braces(pattern, options);
|
692 | var len = pattern.length;
|
693 | var idx = -1;
|
694 | var res = [];
|
695 |
|
696 | while (++idx < len) {
|
697 | res.push(create(pattern[idx], options));
|
698 | }
|
699 | return res;
|
700 | });
|
701 | };
|
702 |
|
703 | /**
|
704 | * Parse the given `str` with the given `options`.
|
705 | *
|
706 | * ```js
|
707 | * var mm = require('micromatch');
|
708 | * mm.parse(pattern[, options]);
|
709 | *
|
710 | * var ast = mm.parse('a/{b,c}/d');
|
711 | * console.log(ast);
|
712 | * // { type: 'root',
|
713 | * // errors: [],
|
714 | * // input: 'a/{b,c}/d',
|
715 | * // nodes:
|
716 | * // [ { type: 'bos', val: '' },
|
717 | * // { type: 'text', val: 'a/' },
|
718 | * // { type: 'brace',
|
719 | * // nodes:
|
720 | * // [ { type: 'brace.open', val: '{' },
|
721 | * // { type: 'text', val: 'b,c' },
|
722 | * // { type: 'brace.close', val: '}' } ] },
|
723 | * // { type: 'text', val: '/d' },
|
724 | * // { type: 'eos', val: '' } ] }
|
725 | * ```
|
726 | * @param {String} `str`
|
727 | * @param {Object} `options`
|
728 | * @return {Object} Returns an AST
|
729 | * @api public
|
730 | */
|
731 |
|
732 | micromatch.parse = function(pattern, options) {
|
733 | if (typeof pattern !== 'string') {
|
734 | throw new TypeError('expected a string');
|
735 | }
|
736 |
|
737 | function parse() {
|
738 | var snapdragon = utils.instantiate(null, options);
|
739 | parsers(snapdragon, options);
|
740 |
|
741 | if (pattern.slice(0, 2) === './') {
|
742 | pattern = pattern.slice(2);
|
743 | }
|
744 |
|
745 | pattern = utils.combineDuplicates(pattern, '\\*\\*\\/|\\/\\*\\*');
|
746 | var ast = snapdragon.parse(pattern, options);
|
747 | utils.define(ast, 'snapdragon', snapdragon);
|
748 | ast.input = pattern;
|
749 | return ast;
|
750 | }
|
751 |
|
752 | return memoize('parse', pattern, options, parse);
|
753 | };
|
754 |
|
755 | /**
|
756 | * Compile the given `ast` or string with the given `options`.
|
757 | *
|
758 | * ```js
|
759 | * var mm = require('micromatch');
|
760 | * mm.compile(ast[, options]);
|
761 | *
|
762 | * var ast = mm.parse('a/{b,c}/d');
|
763 | * console.log(mm.compile(ast));
|
764 | * // { options: { source: 'string' },
|
765 | * // state: {},
|
766 | * // compilers:
|
767 | * // { eos: [Function],
|
768 | * // noop: [Function],
|
769 | * // bos: [Function],
|
770 | * // brace: [Function],
|
771 | * // 'brace.open': [Function],
|
772 | * // text: [Function],
|
773 | * // 'brace.close': [Function] },
|
774 | * // output: [ 'a/(b|c)/d' ],
|
775 | * // ast:
|
776 | * // { ... },
|
777 | * // parsingErrors: [] }
|
778 | * ```
|
779 | * @param {Object|String} `ast`
|
780 | * @param {Object} `options`
|
781 | * @return {Object} Returns an object that has an `output` property with the compiled string.
|
782 | * @api public
|
783 | */
|
784 |
|
785 | micromatch.compile = function(ast, options) {
|
786 | if (typeof ast === 'string') {
|
787 | ast = micromatch.parse(ast, options);
|
788 | }
|
789 |
|
790 | return memoize('compile', ast.input, options, function() {
|
791 | var snapdragon = utils.instantiate(ast, options);
|
792 | compilers(snapdragon, options);
|
793 | return snapdragon.compile(ast, options);
|
794 | });
|
795 | };
|
796 |
|
797 | /**
|
798 | * Clear the regex cache.
|
799 | *
|
800 | * ```js
|
801 | * mm.clearCache();
|
802 | * ```
|
803 | * @api public
|
804 | */
|
805 |
|
806 | micromatch.clearCache = function() {
|
807 | micromatch.cache.caches = {};
|
808 | };
|
809 |
|
810 | /**
|
811 | * Returns true if the given value is effectively an empty string
|
812 | */
|
813 |
|
814 | function isEmptyString(val) {
|
815 | return String(val) === '' || String(val) === './';
|
816 | }
|
817 |
|
818 | /**
|
819 | * Compose a matcher function with the given patterns.
|
820 | * This allows matcher functions to be compiled once and
|
821 | * called multiple times.
|
822 | */
|
823 |
|
824 | function compose(patterns, options, matcher) {
|
825 | var matchers;
|
826 |
|
827 | return memoize('compose', String(patterns), options, function() {
|
828 | return function(file) {
|
829 | // delay composition until it's invoked the first time,
|
830 | // after that it won't be called again
|
831 | if (!matchers) {
|
832 | matchers = [];
|
833 | for (var i = 0; i < patterns.length; i++) {
|
834 | matchers.push(matcher(patterns[i], options));
|
835 | }
|
836 | }
|
837 |
|
838 | var len = matchers.length;
|
839 | while (len--) {
|
840 | if (matchers[len](file) === true) {
|
841 | return true;
|
842 | }
|
843 | }
|
844 | return false;
|
845 | };
|
846 | });
|
847 | }
|
848 |
|
849 | /**
|
850 | * Memoize a generated regex or function. A unique key is generated
|
851 | * from the `type` (usually method name), the `pattern`, and
|
852 | * user-defined options.
|
853 | */
|
854 |
|
855 | function memoize(type, pattern, options, fn) {
|
856 | var key = utils.createKey(type + '=' + pattern, options);
|
857 |
|
858 | if (options && options.cache === false) {
|
859 | return fn(pattern, options);
|
860 | }
|
861 |
|
862 | if (cache.has(type, key)) {
|
863 | return cache.get(type, key);
|
864 | }
|
865 |
|
866 | var val = fn(pattern, options);
|
867 | cache.set(type, key, val);
|
868 | return val;
|
869 | }
|
870 |
|
871 | /**
|
872 | * Expose compiler, parser and cache on `micromatch`
|
873 | */
|
874 |
|
875 | micromatch.compilers = compilers;
|
876 | micromatch.parsers = parsers;
|
877 | micromatch.caches = cache.caches;
|
878 |
|
879 | /**
|
880 | * Expose `micromatch`
|
881 | * @type {Function}
|
882 | */
|
883 |
|
884 | module.exports = micromatch;
|