131 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
		
			3.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
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);
 | 
						|
};
 |