Spaces:
Configuration error
Configuration error
module.exports = function (glob, opts) { | |
if (typeof glob !== 'string') { | |
throw new TypeError('Expected a string'); | |
} | |
var str = String(glob); | |
// The regexp we are building, as a string. | |
var reStr = ""; | |
// Whether we are matching so called "extended" globs (like bash) and should | |
// support single character matching, matching ranges of characters, group | |
// matching, etc. | |
var extended = opts ? !!opts.extended : false; | |
// When globstar is _false_ (default), '/foo/*' is translated a regexp like | |
// '^\/foo\/.*$' which will match any string beginning with '/foo/' | |
// When globstar is _true_, '/foo/*' is translated to regexp like | |
// '^\/foo\/[^/]*$' which will match any string beginning with '/foo/' BUT | |
// which does not have a '/' to the right of it. | |
// E.g. with '/foo/*' these will match: '/foo/bar', '/foo/bar.txt' but | |
// these will not '/foo/bar/baz', '/foo/bar/baz.txt' | |
// Lastely, when globstar is _true_, '/foo/**' is equivelant to '/foo/*' when | |
// globstar is _false_ | |
var globstar = opts ? !!opts.globstar : false; | |
// If we are doing extended matching, this boolean is true when we are inside | |
// a group (eg {*.html,*.js}), and false otherwise. | |
var inGroup = false; | |
// RegExp flags (eg "i" ) to pass in to RegExp constructor. | |
var flags = opts && typeof( opts.flags ) === "string" ? opts.flags : ""; | |
var c; | |
for (var i = 0, len = str.length; i < len; i++) { | |
c = str[i]; | |
switch (c) { | |
case "/": | |
case "$": | |
case "^": | |
case "+": | |
case ".": | |
case "(": | |
case ")": | |
case "=": | |
case "!": | |
case "|": | |
reStr += "\\" + c; | |
break; | |
case "?": | |
if (extended) { | |
reStr += "."; | |
break; | |
} | |
case "[": | |
case "]": | |
if (extended) { | |
reStr += c; | |
break; | |
} | |
case "{": | |
if (extended) { | |
inGroup = true; | |
reStr += "("; | |
break; | |
} | |
case "}": | |
if (extended) { | |
inGroup = false; | |
reStr += ")"; | |
break; | |
} | |
case ",": | |
if (inGroup) { | |
reStr += "|"; | |
break; | |
} | |
reStr += "\\" + c; | |
break; | |
case "*": | |
// Move over all consecutive "*"'s. | |
// Also store the previous and next characters | |
var prevChar = str[i - 1]; | |
var starCount = 1; | |
while(str[i + 1] === "*") { | |
starCount++; | |
i++; | |
} | |
var nextChar = str[i + 1]; | |
if (!globstar) { | |
// globstar is disabled, so treat any number of "*" as one | |
reStr += ".*"; | |
} else { | |
// globstar is enabled, so determine if this is a globstar segment | |
var isGlobstar = starCount > 1 // multiple "*"'s | |
&& (prevChar === "/" || prevChar === undefined) // from the start of the segment | |
&& (nextChar === "/" || nextChar === undefined) // to the end of the segment | |
if (isGlobstar) { | |
// it's a globstar, so match zero or more path segments | |
reStr += "((?:[^/]*(?:\/|$))*)"; | |
i++; // move over the "/" | |
} else { | |
// it's not a globstar, so only match one path segment | |
reStr += "([^/]*)"; | |
} | |
} | |
break; | |
default: | |
reStr += c; | |
} | |
} | |
// When regexp 'g' flag is specified don't | |
// constrain the regular expression with ^ & $ | |
if (!flags || !~flags.indexOf('g')) { | |
reStr = "^" + reStr + "$"; | |
} | |
return new RegExp(reStr, flags); | |
}; | |