function micromatch(files, patterns, opts) {
if (!files || !patterns) return [];
opts = opts || {};
if (typeof opts.cache === 'undefined') {
opts.cache = true;
}
if (!Array.isArray(patterns)) {
return match(files, patterns, opts);
}
var len = patterns.length, i = 0;
var omit = [], keep = [];
while (len--) {
var glob = patterns[i++];
if (typeof glob === 'string' && glob.charCodeAt(0) === 33 /* ! */) {
omit.push.apply(omit, match(files, glob.slice(1), opts));
} else {
keep.push.apply(keep, match(files, glob, opts));
}
}
return utils.diff(keep, omit);
}n/a
function any(fp, patterns, opts) {
if (!Array.isArray(patterns) && typeof patterns !== 'string') {
throw new TypeError(msg('any', 'patterns', 'a string or array'));
}
patterns = utils.arrayify(patterns);
var len = patterns.length;
fp = utils.unixify(fp, opts);
while (len--) {
var isMatch = matcher(patterns[len], opts);
if (isMatch(fp)) {
return true;
}
}
return false;
}...
### Features
* [Drop-in replacement](#switch-from-minimatch) for [minimatch](https://github.com/isaacs/minimatch) and [multimatch](https://github
.com/sindresorhus/multimatch)
* Built-in support for multiple glob patterns, like `['foo/*.js', '!bar.js']`
* [Brace Expansion](https://github.com/jonschlinkert/braces) (`foo/bar-{1..5}.md`, `one/{two,three}/four.md`)
* Typical glob patterns, like `**/*`, `a/b/*.js`, or `['foo/*.js', '!bar.js']`
* Methods like `.isMatch()`, `.contains()` and `.any()`
**Extended globbing features:**
* Logical `OR` (`foo/bar/(abc|xyz).js`)
* Regex character classes (`foo/bar/baz-[1-5].js`)
* POSIX [bracket expressions](https://github.com/jonschlinkert/expand-brackets) (`**/[[:alpha:][:digit:]]/`)
* [extglobs](https://github.com/jonschlinkert/extglob) (`**/+(x|y)`, `!(a|b)`, etc).
...braceExpand = function (str, options) {
if (typeof str !== 'string') {
throw new Error('braces expects a string');
}
return braces(str, options);
}n/a
braces = function (str, options) {
if (typeof str !== 'string') {
throw new Error('braces expects a string');
}
return braces(str, options);
}...
/**
* Extended globs
*/
// expand braces, e.g `{1..5}`
glob.track('before braces');
if (tok.is.braces) {
glob.braces();
}
glob.track('after braces');
// expand extglobs, e.g `foo/!(a|b)`
glob.track('before extglob');
if (tok.is.extglob) {
glob.extglob();
...function contains(fp, pattern, opts) {
if (typeof fp !== 'string') {
throw new TypeError(msg('contains', 'pattern', 'a string'));
}
opts = opts || {};
opts.contains = (pattern !== '');
fp = utils.unixify(fp, opts);
if (opts.contains && !utils.isGlob(pattern)) {
return fp.indexOf(pattern) !== -1;
}
return matcher(pattern, opts)(fp);
}...
### Features
* [Drop-in replacement](#switch-from-minimatch) for [minimatch](https://github.com/isaacs/minimatch) and [multimatch](https://github
.com/sindresorhus/multimatch)
* Built-in support for multiple glob patterns, like `['foo/*.js', '!bar.js']`
* [Brace Expansion](https://github.com/jonschlinkert/braces) (`foo/bar-{1..5}.md`, `one/{two,three}/four.md`)
* Typical glob patterns, like `**/*`, `a/b/*.js`, or `['foo/*.js', '!bar.js']`
* Methods like `.isMatch()`, `.contains()` and `.any()`
**Extended globbing features:**
* Logical `OR` (`foo/bar/(abc|xyz).js`)
* Regex character classes (`foo/bar/baz-[1-5].js`)
* POSIX [bracket expressions](https://github.com/jonschlinkert/expand-brackets) (`**/[[:alpha:][:digit:]]/`)
* [extglobs](https://github.com/jonschlinkert/extglob) (`**/+(x|y)`, `!(a|b)`, etc).
...function expand(pattern, options) {
if (typeof pattern !== 'string') {
throw new TypeError('micromatch.expand(): argument should be a string.');
}
var glob = new Glob(pattern, options || {});
var opts = glob.options;
if (!utils.isGlob(pattern)) {
glob.pattern = glob.pattern.replace(/([\/.])/g, '\\$1');
return glob;
}
glob.pattern = glob.pattern.replace(/(\+)(?!\()/g, '\\$1');
glob.pattern = glob.pattern.split('$').join('\\$');
if (typeof opts.braces !== 'boolean' && typeof opts.nobraces !== 'boolean') {
opts.braces = true;
}
if (glob.pattern === '.*') {
return {
pattern: '\\.' + star,
tokens: tok,
options: opts
};
}
if (glob.pattern === '*') {
return {
pattern: oneStar(opts.dot),
tokens: tok,
options: opts
};
}
// parse the glob pattern into tokens
glob.parse();
var tok = glob.tokens;
tok.is.negated = opts.negated;
// dotfile handling
if ((opts.dotfiles === true || tok.is.dotfile) && opts.dot !== false) {
opts.dotfiles = true;
opts.dot = true;
}
if ((opts.dotdirs === true || tok.is.dotdir) && opts.dot !== false) {
opts.dotdirs = true;
opts.dot = true;
}
// check for braces with a dotfile pattern
if (/[{,]\./.test(glob.pattern)) {
opts.makeRe = false;
opts.dot = true;
}
if (opts.nonegate !== true) {
opts.negated = glob.negated;
}
// if the leading character is a dot or a slash, escape it
if (glob.pattern.charAt(0) === '.' && glob.pattern.charAt(1) !== '/') {
glob.pattern = '\\' + glob.pattern;
}
/**
* Extended globs
*/
// expand braces, e.g `{1..5}`
glob.track('before braces');
if (tok.is.braces) {
glob.braces();
}
glob.track('after braces');
// expand extglobs, e.g `foo/!(a|b)`
glob.track('before extglob');
if (tok.is.extglob) {
glob.extglob();
}
glob.track('after extglob');
// expand brackets, e.g `[[:alpha:]]`
glob.track('before brackets');
if (tok.is.brackets) {
glob.brackets();
}
glob.track('after brackets');
// special patterns
glob._replace('[!', '[^');
glob._replace('(?', '(%~');
glob._replace(/\[\]/, '\\[\\]');
glob._replace('/[', '/' + (opts.dot ? dotfiles : nodot) + '[', true);
glob._replace('/?', '/' + (opts.dot ? dotfiles : nodot) + '[^/]', true);
glob._replace('/.', '/(?=.)\\.', true);
// windows drives
glob._replace(/^(\w):([\\\/]+?)/gi, '(?=.)$1:$2', true);
// negate slashes in exclusion ranges
if (glob.pattern.indexOf('[^') !== -1) {
glob.pattern = negateSlash(glob.pattern);
}
if (opts.globstar !== false && glob.pattern === '**') {
glob.pattern = globstar(opts.dot);
} else {
glob.pattern = balance(glob.pattern, '[', ']');
glob.escape(glob.pattern);
// if the pattern has `**`
if (tok.is.globstar) {
glob.pattern = collapse(glob.pattern, '/**');
glob.pattern = collapse(glob.pattern, '**/');
glob._replace('/**/', '(?:/' + globstar(opts.dot) + '/|/)', true);
glob._replace(/\*{2,}/g, '**');
// 'foo/*'
glob._replace(/(\w+)\*(?!\/)/g, '$1[^/]*?', true);
glob._replace(/\*\*\/\*(\w)/g, globstar(opts.dot) + '\\/' + (opts.dot ? dotfiles : nodot) + '[^/]*?$1', true);
if (opts.dot !== true) {
glob._replace(/\*\*\/(.)/g, '(?:**\\/|)$1');
}
// 'foo/**' or '{**,*}', but not 'foo**'
if (tok.path.dirname !== '' || /,\*\*|\*\*,/.test(glob.orig)) {
glob._replace('**', globstar(opts.dot), true);
}
}
// ends with /*
glob._replace(/\/\*$/, '\\/' + oneStar(opts.dot), true);
// ends with *, no slashes
glob._replace(/(?!\/)\*$/, star, true);
// has 'n*.' (partial wildcard w/ file extension)
glob._replace(/([^\/]+)\*/, '$1' + oneStar(true), true);
// has '*'
glob._replace('*', oneStar(opts.dot), true);
glob._replace('?.', '?\\.', true);
glob._replace('?:', '?:', true);
glob._replace(/\?+/g, function(match) {
var len = match.length;
if (len === 1) {
return qmark;
}
return qmark + '{' ......
```
### .expand
Returns an object with a regex-compatible string and tokens.
```js
mm.expand('*.js');
// when `track` is enabled (for debugging), the `history` array is used
// to record each mutation to the glob pattern as it's converted to regex
{ options: { track: false, dot: undefined, makeRe: true, negated: false },
pattern: '(.*\\/|^)bar\\/(?:(?!(?:^|\\/)\\.).)*?',
history: [],
tokens:
...function filter(patterns, opts) {
if (!Array.isArray(patterns) && typeof patterns !== 'string') {
throw new TypeError(msg('filter', 'patterns', 'a string or array'));
}
patterns = utils.arrayify(patterns);
var len = patterns.length, i = 0;
var patternMatchers = Array(len);
while (i < len) {
patternMatchers[i] = matcher(patterns[i++], opts);
}
return function(fp) {
if (fp == null) return [];
var len = patternMatchers.length, i = 0;
var res = true;
fp = utils.unixify(fp, opts);
while (i < len) {
var fn = patternMatchers[i++];
if (!fn(fp)) {
res = false;
break;
}
}
return res;
};
}...
* `patterns` **{String|Array}**:
**Examples**
Single glob:
```js
var fn = mm.filter('*.md');
['a.js', 'b.txt', 'c.md'].filter(fn);
//=> ['c.md']
var fn = mm.filter('[a-c]');
['a', 'b', 'c', 'd', 'e'].filter(fn);
//=> ['a', 'b', 'c']
```
...function Glob(pattern, options) {
if (!(this instanceof Glob)) {
return new Glob(pattern, options);
}
this.options = options || {};
this.pattern = pattern;
this.history = [];
this.tokens = {};
this.init(pattern);
}n/a
function isMatch(fp, pattern, opts) {
if (typeof fp !== 'string') {
throw new TypeError(msg('isMatch', 'filepath', 'a string'));
}
fp = utils.unixify(fp, opts);
if (utils.typeOf(pattern) === 'object') {
return matcher(fp, pattern);
}
return matcher(pattern, opts)(fp);
}...
> Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch.
Micromatch supports all of the same matching features as [minimatch](https://github.com/isaacs/minimatch) and [multimatch](https
://github.com/sindresorhus/multimatch).
* [mm()](#usage) is the same as [multimatch()](https://github.com/sindresorhus/multimatch)
* [mm.match()](#match) is the same as [minimatch.match()](https://github.com/isaacs/minimatch)
* use [mm.isMatch()](#ismatch) instead of [minimatch()](https://github.com/isaacs/minimatch
)
## Install
Install with [npm](https://www.npmjs.com/):
```sh
$ npm install --save micromatch
...function makeRe(glob, opts) {
if (utils.typeOf(glob) !== 'string') {
throw new Error(msg('makeRe', 'glob', 'a string'));
}
return utils.cache(toRegex, glob, opts);
}...
```
### .makeRe
Create a regular expression for matching file paths based on the given pattern:
```js
mm.makeRe('*.js');
//=> /^(?:(?!\.)(?=.)[^/]*?\.js)$/
```
## Options
### options.unixify
...function match(files, pattern, opts) {
if (utils.typeOf(files) !== 'string' && !Array.isArray(files)) {
throw new Error(msg('match', 'files', 'a string or array'));
}
files = utils.arrayify(files);
opts = opts || {};
var negate = opts.negate || false;
var orig = pattern;
if (typeof pattern === 'string') {
negate = pattern.charAt(0) === '!';
if (negate) {
pattern = pattern.slice(1);
}
// we need to remove the character regardless,
// so the above logic is still needed
if (opts.nonegate === true) {
negate = false;
}
}
var _isMatch = matcher(pattern, opts);
var len = files.length, i = 0;
var res = [];
while (i < len) {
var file = files[i++];
var fp = utils.unixify(file, opts);
if (!_isMatch(fp)) { continue; }
res.push(fp);
}
if (res.length === 0) {
if (opts.failglob === true) {
throw new Error('micromatch.match() found no matches for: "' + orig + '".');
}
if (opts.nonull || opts.nullglob) {
res.push(utils.unescapeGlob(orig));
}
}
// if `negate` was defined, diff negated files
if (negate) { res = utils.diff(files, res); }
// if `ignore` was defined, diff ignored filed
if (opts.ignore && opts.ignore.length) {
pattern = opts.ignore;
opts = utils.omit(opts, ['ignore']);
res = utils.diff(res, micromatch(res, pattern, opts));
}
if (opts.nodupes) {
return utils.unique(res);
}
return res;
}...
# micromatch [](https://www.npmjs.com/package/micromatch) [](https://npmjs.org/package/micromatch) [](https://travis-ci.org/jonschlinkert/micromatch)
> Glob matching for javascript/node.js. A drop-in replacement and faster alternative to minimatch and multimatch.
Micromatch supports all of the same matching features as [minimatch](https://github.com/isaacs/minimatch) and [multimatch](https
://github.com/sindresorhus/multimatch).
* [mm()](#usage) is the same as [multimatch()](https://github.com/sindresorhus/multimatch)
* [mm.match()](#match) is the same as [minimatch.match()](https://github.com/isaacs/minimatch
)
* use [mm.isMatch()](#ismatch) instead of [minimatch()](https://github.com/isaacs/minimatch)
## Install
Install with [npm](https://www.npmjs.com/):
```sh
...function matchKeys(obj, glob, options) {
if (utils.typeOf(obj) !== 'object') {
throw new TypeError(msg('matchKeys', 'first argument', 'an object'));
}
var fn = matcher(glob, options);
var res = {};
for (var key in obj) {
if (obj.hasOwnProperty(key) && fn(key)) {
res[key] = obj[key];
}
}
return res;
}n/a
function matcher(pattern, opts) {
// pattern is a function
if (typeof pattern === 'function') {
return pattern;
}
// pattern is a regex
if (pattern instanceof RegExp) {
return function(fp) {
return pattern.test(fp);
};
}
if (typeof pattern !== 'string') {
throw new TypeError(msg('matcher', 'pattern', 'a string, regex, or function'));
}
// strings, all the way down...
pattern = utils.unixify(pattern, opts);
// pattern is a non-glob string
if (!utils.isGlob(pattern)) {
return utils.matchPath(pattern, opts);
}
// pattern is a glob string
var re = makeRe(pattern, opts);
// `matchBase` is defined
if (opts && opts.matchBase) {
return utils.hasFilename(re, opts);
}
// `matchBase` is not defined
return function(fp) {
fp = utils.unixify(fp, opts);
return re.test(fp);
};
}...
* `glob/string`
* `regex`
* `function`
**Example**
```js
var isMatch = mm.matcher('*.md');
var files = [];
['a.md', 'b.txt', 'c.md'].forEach(function(fp) {
if (isMatch(fp)) {
files.push(fp);
}
});
...function Glob(pattern, options) {
if (!(this instanceof Glob)) {
return new Glob(pattern, options);
}
this.options = options || {};
this.pattern = pattern;
this.history = [];
this.tokens = {};
this.init(pattern);
}n/a
_replace = function (a, b, escape) {
this.track('before (find): "' + a + '" (replace with): "' + b + '"');
if (escape) b = esc(b);
if (a && b && typeof a === 'string') {
this.pattern = this.pattern.split(a).join(b);
} else {
this.pattern = this.pattern.replace(a, b);
}
this.track('after');
}...
glob.track('before brackets');
if (tok.is.brackets) {
glob.brackets();
}
glob.track('after brackets');
// special patterns
glob._replace('[!', '[^');
glob._replace('(?', '(%~');
glob._replace(/\[\]/, '\\[\\]');
glob._replace('/[', '/' + (opts.dot ? dotfiles : nodot) + '[', true);
glob._replace('/?', '/' + (opts.dot ? dotfiles : nodot) + '[^/]', true);
glob._replace('/.', '/(?=.)\\.', true);
// windows drives
...braces = function () {
if (this.options.nobraces !== true && this.options.nobrace !== true) {
// naive/fast check for imbalanced characters
var a = this.pattern.match(/[\{\(\[]/g);
var b = this.pattern.match(/[\}\)\]]/g);
// if imbalanced, don't optimize the pattern
if (a && b && (a.length !== b.length)) {
this.options.makeRe = false;
}
// expand brace patterns and join the resulting array
var expanded = utils.braces(this.pattern, this.options);
this.pattern = expanded.join('|');
}
}...
/**
* Extended globs
*/
// expand braces, e.g `{1..5}`
glob.track('before braces');
if (tok.is.braces) {
glob.braces();
}
glob.track('after braces');
// expand extglobs, e.g `foo/!(a|b)`
glob.track('before extglob');
if (tok.is.extglob) {
glob.extglob();
...brackets = function () {
if (this.options.nobrackets !== true) {
this.pattern = utils.brackets(this.pattern);
}
}...
glob.extglob();
}
glob.track('after extglob');
// expand brackets, e.g `[[:alpha:]]`
glob.track('before brackets');
if (tok.is.brackets) {
glob.brackets();
}
glob.track('after brackets');
// special patterns
glob._replace('[!', '[^');
glob._replace('(?', '(%~');
glob._replace(/\[\]/, '\\[\\]');
...escape = function (str) {
this.track('before escape: ');
var re = /["\\](['"]?[^"'\\]['"]?)/g;
this.pattern = str.replace(re, function($0, $1) {
var o = chars.ESC;
var ch = o && o[$1];
if (ch) {
return ch;
}
if (/[a-z]/i.test($0)) {
return $0.split('\\').join('');
}
return $0;
});
this.track('after escape: ');
}...
}
if (opts.globstar !== false && glob.pattern === '**') {
glob.pattern = globstar(opts.dot);
} else {
glob.pattern = balance(glob.pattern, '[', ']');
glob.escape(glob.pattern);
// if the pattern has `**`
if (tok.is.globstar) {
glob.pattern = collapse(glob.pattern, '/**');
glob.pattern = collapse(glob.pattern, '**/');
glob._replace('/**/', '(?:/' + globstar(opts.dot) + '/|/)', true);
glob._replace(/\*{2,}/g, '**');
...extglob = function () {
if (this.options.noextglob === true) return;
if (utils.isExtglob(this.pattern)) {
this.pattern = utils.extglob(this.pattern, {escape: true});
}
}...
glob.braces();
}
glob.track('after braces');
// expand extglobs, e.g `foo/!(a|b)`
glob.track('before extglob');
if (tok.is.extglob) {
glob.extglob();
}
glob.track('after extglob');
// expand brackets, e.g `[[:alpha:]]`
glob.track('before brackets');
if (tok.is.brackets) {
glob.brackets();
...init = function (pattern) {
this.orig = pattern;
this.negated = this.isNegated();
this.options.track = this.options.track || false;
this.options.makeRe = true;
}...
if (!(this instanceof Glob)) {
return new Glob(pattern, options);
}
this.options = options || {};
this.pattern = pattern;
this.history = [];
this.tokens = {};
this.init(pattern);
};
/**
* Initialize defaults
*/
Glob.prototype.init = function(pattern) {
...isNegated = function () {
if (this.pattern.charCodeAt(0) === 33 /* '!' */) {
this.pattern = this.pattern.slice(1);
return true;
}
return false;
}...
/**
* Initialize defaults
*/
Glob.prototype.init = function(pattern) {
this.orig = pattern;
this.negated = this.isNegated();
this.options.track = this.options.track || false;
this.options.makeRe = true;
};
/**
* Push a change into `glob.history`. Useful
* for debugging.
...parse = function (pattern) {
this.tokens = utils.parseGlob(pattern || this.pattern, true);
return this.tokens;
}...
pattern: oneStar(opts.dot),
tokens: tok,
options: opts
};
}
// parse the glob pattern into tokens
glob.parse();
var tok = glob.tokens;
tok.is.negated = opts.negated;
// dotfile handling
if ((opts.dotfiles === true || tok.is.dotfile) && opts.dot !== false) {
opts.dotfiles = true;
opts.dot = true;
...track = function (msg) {
if (this.options.track) {
this.history.push({msg: msg, pattern: this.pattern});
}
}...
}
/**
* Extended globs
*/
// expand braces, e.g `{1..5}`
glob.track('before braces');
if (tok.is.braces) {
glob.braces();
}
glob.track('after braces');
// expand extglobs, e.g `foo/!(a|b)`
glob.track('before extglob');
...unescape = function (str) {
var re = /__([A-Z]+)_([A-Z]+)__/g;
this.pattern = str.replace(re, function($0, $1) {
return chars[$1][$0];
});
this.pattern = unesc(this.pattern);
}...
// '///' => '\/'
glob._replace(/\/+/g, '\\/');
// '\\\\\\' => '\\'
glob._replace(/\\{2,}/g, '\\');
}
// unescape previously escaped patterns
glob.unescape(glob.pattern);
glob._replace('__UNESC_STAR__', '*');
// escape dots that follow qmarks
glob._replace('?.', '?\\.');
// remove unnecessary slashes in character classes
glob._replace('[^\\/]', qmark);
...function arrayify(val) {
return !Array.isArray(val)
? [val]
: val;
}...
*/
function match(files, pattern, opts) {
if (utils.typeOf(files) !== 'string' && !Array.isArray(files)) {
throw new Error(msg('match', 'files', 'a string or array'));
}
files = utils.arrayify(files);
opts = opts || {};
var negate = opts.negate || false;
var orig = pattern;
if (typeof pattern === 'string') {
negate = pattern.charAt(0) === '!';
...braces = function (str, options) {
if (typeof str !== 'string') {
throw new Error('braces expects a string');
}
return braces(str, options);
}...
/**
* Extended globs
*/
// expand braces, e.g `{1..5}`
glob.track('before braces');
if (tok.is.braces) {
glob.braces();
}
glob.track('after braces');
// expand extglobs, e.g `foo/!(a|b)`
glob.track('before extglob');
if (tok.is.extglob) {
glob.extglob();
...function brackets(str) {
if (!isPosixBracket(str)) {
return str;
}
var negated = false;
if (str.indexOf('[^') !== -1) {
negated = true;
str = str.split('[^').join('[');
}
if (str.indexOf('[!') !== -1) {
negated = true;
str = str.split('[!').join('[');
}
var a = str.split('[');
var b = str.split(']');
var imbalanced = a.length !== b.length;
var parts = str.split(/(?::\]\[:|\[?\[:|:\]\]?)/);
var len = parts.length, i = 0;
var end = '', beg = '';
var res = [];
// start at the end (innermost) first
while (len--) {
var inner = parts[i++];
if (inner === '^[!' || inner === '[!') {
inner = '';
negated = true;
}
var prefix = negated ? '^' : '';
var ch = POSIX[inner];
if (ch) {
res.push('[' + prefix + ch + ']');
} else if (inner) {
if (/^\[?\w-\w\]?$/.test(inner)) {
if (i === parts.length) {
res.push('[' + prefix + inner);
} else if (i === 1) {
res.push(prefix + inner + ']');
} else {
res.push(prefix + inner);
}
} else {
if (i === 1) {
beg += inner;
} else if (i === parts.length) {
end += inner;
} else {
res.push('[' + prefix + inner + ']');
}
}
}
}
var result = res.join('|');
var rlen = res.length || 1;
if (rlen > 1) {
result = '(?:' + result + ')';
rlen = 1;
}
if (beg) {
rlen++;
if (beg.charAt(0) === '[') {
if (imbalanced) {
beg = '\\[' + beg.slice(1);
} else {
beg += ']';
}
}
result = beg + result;
}
if (end) {
rlen++;
if (end.slice(-1) === ']') {
if (imbalanced) {
end = end.slice(0, end.length - 1) + '\\]';
} else {
end = '[' + end;
}
}
result += end;
}
if (rlen > 1) {
result = result.split('][').join(']|[');
if (result.indexOf('|') !== -1 && !/\(\?/.test(result)) {
result = '(?:' + result + ')';
}
}
result = result.replace(/\[+=|=\]+/g, '\\b');
return result;
}...
glob.extglob();
}
glob.track('after extglob');
// expand brackets, e.g `[[:alpha:]]`
glob.track('before brackets');
if (tok.is.brackets) {
glob.brackets();
}
glob.track('after brackets');
// special patterns
glob._replace('[!', '[^');
glob._replace('(?', '(%~');
glob._replace(/\[\]/, '\\[\\]');
...function regexCache(fn, str, opts) {
var key = '_default_', regex, cached;
if (!str && !opts) {
if (typeof fn !== 'function') {
return fn;
}
return basic[key] || (basic[key] = fn(str));
}
var isString = typeof str === 'string';
if (isString) {
if (!opts) {
return basic[str] || (basic[str] = fn(str));
}
key = str;
} else {
opts = str;
}
cached = cache[key];
if (cached && equal(cached.opts, opts)) {
return cached.regex;
}
memo(key, opts, (regex = fn(str, opts)));
return regex;
}...
* @return {RegExp}
*/
function makeRe(glob, opts) {
if (utils.typeOf(glob) !== 'string') {
throw new Error(msg('makeRe', 'glob', 'a string'));
}
return utils.cache(toRegex, glob, opts);
}
/**
* Make error messages consistent. Follows this format:
*
* ```js
* msg(methodName, argNumber, nativeType);
...function diff(arr, arrays) {
var argsLen = arguments.length;
var len = arr.length, i = -1;
var res = [], arrays;
if (argsLen === 1) {
return arr;
}
if (argsLen > 2) {
arrays = flatten(slice.call(arguments, 1));
}
while (++i < len) {
if (!~arrays.indexOf(arr[i])) {
res.push(arr[i]);
}
}
return res;
}...
var glob = patterns[i++];
if (typeof glob === 'string' && glob.charCodeAt(0) === 33 /* ! */) {
omit.push.apply(omit, match(files, glob.slice(1), opts));
} else {
keep.push.apply(keep, match(files, glob, opts));
}
}
return utils.diff(keep, omit);
}
/**
* Return an array of files that match the given glob pattern.
*
* This function is called by the main `micromatch` function If you only
* need to pass a single pattern you might get very minor speed improvements
...function escapePath(fp) {
return fp.replace(/[\\.]/g, '\\$&');
}n/a
function escapeRe(str) {
return str.replace(/[-[\\$*+?.#^\s{}(|)\]]/g, '\\$&');
}n/a
function extglob(str, opts) {
opts = opts || {};
var o = {}, i = 0;
// fix common character reversals
// '*!(.js)' => '*.!(js)'
str = str.replace(/!\(([^\w*()])/g, '$1!(');
// support file extension negation
str = str.replace(/([*\/])\.!\([*]\)/g, function (m, ch) {
if (ch === '/') {
return escape('\\/[^.]+');
}
return escape('[^.]+');
});
// create a unique key for caching by
// combining the string and options
var key = str
+ String(!!opts.regex)
+ String(!!opts.contains)
+ String(!!opts.escape);
if (cache.hasOwnProperty(key)) {
return cache[key];
}
if (!(re instanceof RegExp)) {
re = regex();
}
opts.negate = false;
var m;
while (m = re.exec(str)) {
var prefix = m[1];
var inner = m[3];
if (prefix === '!') {
opts.negate = true;
}
var id = '__EXTGLOB_' + (i++) + '__';
// use the prefix of the _last_ (outtermost) pattern
o[id] = wrap(inner, prefix, opts.escape);
str = str.split(m[0]).join(id);
}
var keys = Object.keys(o);
var len = keys.length;
// we have to loop again to allow us to convert
// patterns in reverse order (starting with the
// innermost/last pattern first)
while (len--) {
var prop = keys[len];
str = str.split(prop).join(o[prop]);
}
var result = opts.regex
? toRegex(str, opts.contains, opts.negate)
: str;
result = result.split('.').join('\\.');
// cache the result and return it
return (cache[key] = result);
}...
glob.braces();
}
glob.track('after braces');
// expand extglobs, e.g `foo/!(a|b)`
glob.track('before extglob');
if (tok.is.extglob) {
glob.extglob();
}
glob.track('after extglob');
// expand brackets, e.g `[[:alpha:]]`
glob.track('before brackets');
if (tok.is.brackets) {
glob.brackets();
...function filename(fp) {
var seg = fp.match(fileRe());
return seg && seg[0];
}...
*
* @param {RegExp} `re`
* @return {Boolean}
*/
utils.hasFilename = function hasFilename(re) {
return function(fp) {
var name = utils.filename(fp);
return name && re.test(name);
};
};
/**
* Coerce `val` to an array
*
...function hasFilename(re) {
return function(fp) {
var name = utils.filename(fp);
return name && re.test(name);
};
}...
return utils.matchPath(pattern, opts);
}
// pattern is a glob string
var re = makeRe(pattern, opts);
// `matchBase` is defined
if (opts && opts.matchBase) {
return utils.hasFilename(re, opts);
}
// `matchBase` is not defined
return function(fp) {
fp = utils.unixify(fp, opts);
return re.test(fp);
};
}
...function hasPath(pattern, opts) {
return function(fp) {
return utils.unixify(pattern, opts).indexOf(fp) !== -1;
};
}...
*
* @param {String} `pattern`
* @return {Function}
*/
utils.matchPath = function matchPath(pattern, opts) {
var fn = (opts && opts.contains)
? utils.hasPath(pattern, opts)
: utils.isPath(pattern, opts);
return fn;
};
/**
* Returns a function that returns true if the given
* regex matches the `filename` of a file path.
...function isExtglob(str) {
return typeof str === 'string'
&& /[@?!+*]\(/.test(str);
}...
/**
* Expand bracket expressions in `glob.pattern`
*/
Glob.prototype.extglob = function() {
if (this.options.noextglob === true) return;
if (utils.isExtglob(this.pattern)) {
this.pattern = utils.extglob(this.pattern, {escape: true});
}
};
/**
* Parse the given pattern
*/
...function isGlob(str) {
return typeof str === 'string'
&& (/[*!?{}(|)[\]]/.test(str)
|| isExtglob(str));
}...
throw new TypeError(msg('contains', 'pattern', 'a string'));
}
opts = opts || {};
opts.contains = (pattern !== '');
fp = utils.unixify(fp, opts);
if (opts.contains && !utils.isGlob(pattern)) {
return fp.indexOf(pattern) !== -1;
}
return matcher(pattern, opts)(fp);
}
/**
* Returns true if a file path matches any of the
...function isPath(pattern, opts) {
opts = opts || {};
return function(fp) {
var unixified = utils.unixify(fp, opts);
if(opts.nocase){
return pattern.toLowerCase() === unixified.toLowerCase();
}
return pattern === unixified;
};
}...
* @param {String} `pattern`
* @return {Function}
*/
utils.matchPath = function matchPath(pattern, opts) {
var fn = (opts && opts.contains)
? utils.hasPath(pattern, opts)
: utils.isPath(pattern, opts);
return fn;
};
/**
* Returns a function that returns true if the given
* regex matches the `filename` of a file path.
*
...function matchPath(pattern, opts) {
var fn = (opts && opts.contains)
? utils.hasPath(pattern, opts)
: utils.isPath(pattern, opts);
return fn;
}...
}
// strings, all the way down...
pattern = utils.unixify(pattern, opts);
// pattern is a non-glob string
if (!utils.isGlob(pattern)) {
return utils.matchPath(pattern, opts);
}
// pattern is a glob string
var re = makeRe(pattern, opts);
// `matchBase` is defined
if (opts && opts.matchBase) {
return utils.hasFilename(re, opts);
...function normalizePath(str, stripTrailing) {
if (typeof str !== 'string') {
throw new TypeError('expected a string');
}
str = str.replace(/[\\\/]+/g, '/');
if (stripTrailing !== false) {
str = removeTrailingSeparator(str);
}
return str;
}...
* Normalize all slashes in a file path or glob pattern to
* forward slashes.
*/
utils.unixify = function unixify(fp, opts) {
if (opts && opts.unixify === false) return fp;
if (opts && opts.unixify === true || win32 || path.sep === '\\') {
return utils.normalize(fp, false);
}
if (opts && opts.unescape === true) {
return fp ? fp.toString().replace(/\\(\w)/g, '$1') : '';
}
return fp;
};
...function omit(obj, keys) {
if (!isObject(obj)) return {};
keys = [].concat.apply([], [].slice.call(arguments, 1));
var last = keys[keys.length - 1];
var res = {}, fn;
if (typeof last === 'function') {
fn = keys.pop();
}
var isFunction = typeof fn === 'function';
if (!keys.length && !isFunction) {
return obj;
}
forOwn(obj, function(value, key) {
if (keys.indexOf(key) === -1) {
if (!isFunction) {
res[key] = value;
} else if (fn(value, key, obj)) {
res[key] = value;
}
}
});
return res;
}...
// if `negate` was defined, diff negated files
if (negate) { res = utils.diff(files, res); }
// if `ignore` was defined, diff ignored filed
if (opts.ignore && opts.ignore.length) {
pattern = opts.ignore;
opts = utils.omit(opts, ['ignore']);
res = utils.diff(res, micromatch(res, pattern, opts));
}
if (opts.nodupes) {
return utils.unique(res);
}
return res;
...function parseGlob(glob) {
if (cache.hasOwnProperty(glob)) {
return cache[glob];
}
var tok = {};
tok.orig = glob;
tok.is = {};
// unescape dots and slashes in braces/brackets
glob = escape(glob);
var parsed = findBase(glob);
tok.is.glob = parsed.isGlob;
tok.glob = parsed.glob;
tok.base = parsed.base;
var segs = /([^\/]*)$/.exec(glob);
tok.path = {};
tok.path.dirname = '';
tok.path.basename = segs[1] || '';
tok.path.dirname = glob.split(tok.path.basename).join('') || '';
var basename = (tok.path.basename || '').split('.') || '';
tok.path.filename = basename[0] || '';
tok.path.extname = basename.slice(1).join('.') || '';
tok.path.ext = '';
if (isGlob(tok.path.dirname) && !tok.path.basename) {
if (!/\/$/.test(tok.glob)) {
tok.path.basename = tok.glob;
}
tok.path.dirname = tok.base;
}
if (glob.indexOf('/') === -1 && !tok.is.globstar) {
tok.path.dirname = '';
tok.path.basename = tok.orig;
}
var dot = tok.path.basename.indexOf('.');
if (dot !== -1) {
tok.path.filename = tok.path.basename.slice(0, dot);
tok.path.extname = tok.path.basename.slice(dot);
}
if (tok.path.extname.charAt(0) === '.') {
var exts = tok.path.extname.split('.');
tok.path.ext = exts[exts.length - 1];
}
// unescape dots and slashes in braces/brackets
tok.glob = unescape(tok.glob);
tok.path.dirname = unescape(tok.path.dirname);
tok.path.basename = unescape(tok.path.basename);
tok.path.filename = unescape(tok.path.filename);
tok.path.extname = unescape(tok.path.extname);
// Booleans
var is = (glob && tok.is.glob);
tok.is.negated = glob && glob.charAt(0) === '!';
tok.is.extglob = glob && extglob(glob);
tok.is.braces = has(is, glob, '{');
tok.is.brackets = has(is, glob, '[:');
tok.is.globstar = has(is, glob, '**');
tok.is.dotfile = dotfile(tok.path.basename) || dotfile(tok.path.filename);
tok.is.dotdir = dotdir(tok.path.dirname);
return (cache[glob] = tok);
}...
};
/**
* Parse the given pattern
*/
Glob.prototype.parse = function(pattern) {
this.tokens = utils.parseGlob(pattern || this.pattern, true);
return this.tokens;
};
/**
* Replace `a` with `b`. Also tracks the change before and
* after each replacement. This is disabled by default, but
* can be enabled by setting `options.track` to true.
...function kindOf(val) {
// primitivies
if (typeof val === 'undefined') {
return 'undefined';
}
if (val === null) {
return 'null';
}
if (val === true || val === false || val instanceof Boolean) {
return 'boolean';
}
if (typeof val === 'string' || val instanceof String) {
return 'string';
}
if (typeof val === 'number' || val instanceof Number) {
return 'number';
}
// functions
if (typeof val === 'function' || val instanceof Function) {
return 'function';
}
// array
if (typeof Array.isArray !== 'undefined' && Array.isArray(val)) {
return 'array';
}
// check for instances of RegExp and Date before calling `toString`
if (val instanceof RegExp) {
return 'regexp';
}
if (val instanceof Date) {
return 'date';
}
// other objects
var type = toString.call(val);
if (type === '[object RegExp]') {
return 'regexp';
}
if (type === '[object Date]') {
return 'date';
}
if (type === '[object Arguments]') {
return 'arguments';
}
if (type === '[object Error]') {
return 'error';
}
// buffer
if (typeof Buffer !== 'undefined' && isBuffer(val)) {
return 'buffer';
}
// es6: Map, WeakMap, Set, WeakSet
if (type === '[object Set]') {
return 'set';
}
if (type === '[object WeakSet]') {
return 'weakset';
}
if (type === '[object Map]') {
return 'map';
}
if (type === '[object WeakMap]') {
return 'weakmap';
}
if (type === '[object Symbol]') {
return 'symbol';
}
// typed arrays
if (type === '[object Int8Array]') {
return 'int8array';
}
if (type === '[object Uint8Array]') {
return 'uint8array';
}
if (type === '[object Uint8ClampedArray]') {
return 'uint8clampedarray';
}
if (type === '[object Int16Array]') {
return 'int16array';
}
if (type === '[object Uint16Array]') {
return 'uint16array';
}
if (type === '[object Int32Array]') {
return 'int32array';
}
if (type === '[object Uint32Array]') {
return 'uint32array';
}
if (type === '[object Float32Array]') {
return 'float32array';
}
if (type === '[object Float64Array]') {
return 'float64array';
}
// must be a plain object
return 'object';
}...
* @param {Array} `files`
* @param {String} `pattern`
* @param {Object} `options`
* @return {Array}
*/
function match(files, pattern, opts) {
if (utils.typeOf(files) !== 'string' && !Array.isArray(files)) {
throw new Error(msg('match', 'files', 'a string or array'));
}
files = utils.arrayify(files);
opts = opts || {};
var negate = opts.negate || false;
...function unescapeGlob(fp) {
return fp.replace(/[\\"']/g, '');
}...
if (res.length === 0) {
if (opts.failglob === true) {
throw new Error('micromatch.match() found no matches for: "' + orig + '".');
}
if (opts.nonull || opts.nullglob) {
res.push(utils.unescapeGlob(orig));
}
}
// if `negate` was defined, diff negated files
if (negate) { res = utils.diff(files, res); }
// if `ignore` was defined, diff ignored filed
...function unique(arr) {
if (!Array.isArray(arr)) {
throw new TypeError('array-unique expects an array.');
}
var len = arr.length;
var i = -1;
while (i++ < len) {
var j = i + 1;
for (; j < arr.length; ++j) {
if (arr[i] === arr[j]) {
arr.splice(j--, 1);
}
}
}
return arr;
}...
if (opts.ignore && opts.ignore.length) {
pattern = opts.ignore;
opts = utils.omit(opts, ['ignore']);
res = utils.diff(res, micromatch(res, pattern, opts));
}
if (opts.nodupes) {
return utils.unique(res);
}
return res;
}
/**
* Returns a function that takes a glob pattern or array of glob patterns
* to be used with `Array#filter()`. (Internally this function generates
...function unixify(fp, opts) {
if (opts && opts.unixify === false) return fp;
if (opts && opts.unixify === true || win32 || path.sep === '\\') {
return utils.normalize(fp, false);
}
if (opts && opts.unescape === true) {
return fp ? fp.toString().replace(/\\(\w)/g, '$1') : '';
}
return fp;
}...
var _isMatch = matcher(pattern, opts);
var len = files.length, i = 0;
var res = [];
while (i < len) {
var file = files[i++];
var fp = utils.unixify(file, opts);
if (!_isMatch(fp)) { continue; }
res.push(fp);
}
if (res.length === 0) {
if (opts.failglob === true) {
...