You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							309 lines
						
					
					
						
							7.1 KiB
						
					
					
				
			
		
		
	
	
							309 lines
						
					
					
						
							7.1 KiB
						
					
					
				'use strict'; | 
						|
 | 
						|
var utils = module.exports; | 
						|
var path = require('path'); | 
						|
 | 
						|
/** | 
						|
 * Module dependencies | 
						|
 */ | 
						|
 | 
						|
var Snapdragon = require('snapdragon'); | 
						|
utils.define = require('define-property'); | 
						|
utils.diff = require('arr-diff'); | 
						|
utils.extend = require('extend-shallow'); | 
						|
utils.pick = require('object.pick'); | 
						|
utils.typeOf = require('kind-of'); | 
						|
utils.unique = require('array-unique'); | 
						|
 | 
						|
/** | 
						|
 * Returns true if the platform is windows, or `path.sep` is `\\`. | 
						|
 * This is defined as a function to allow `path.sep` to be set in unit tests, | 
						|
 * or by the user, if there is a reason to do so. | 
						|
 * @return {Boolean} | 
						|
 */ | 
						|
 | 
						|
utils.isWindows = function() { | 
						|
  return path.sep === '\\' || process.platform === 'win32'; | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Get the `Snapdragon` instance to use | 
						|
 */ | 
						|
 | 
						|
utils.instantiate = function(ast, options) { | 
						|
  var snapdragon; | 
						|
  // if an instance was created by `.parse`, use that instance | 
						|
  if (utils.typeOf(ast) === 'object' && ast.snapdragon) { | 
						|
    snapdragon = ast.snapdragon; | 
						|
  // if the user supplies an instance on options, use that instance | 
						|
  } else if (utils.typeOf(options) === 'object' && options.snapdragon) { | 
						|
    snapdragon = options.snapdragon; | 
						|
  // create a new instance | 
						|
  } else { | 
						|
    snapdragon = new Snapdragon(options); | 
						|
  } | 
						|
 | 
						|
  utils.define(snapdragon, 'parse', function(str, options) { | 
						|
    var parsed = Snapdragon.prototype.parse.apply(this, arguments); | 
						|
    parsed.input = str; | 
						|
 | 
						|
    // escape unmatched brace/bracket/parens | 
						|
    var last = this.parser.stack.pop(); | 
						|
    if (last && this.options.strictErrors !== true) { | 
						|
      var open = last.nodes[0]; | 
						|
      var inner = last.nodes[1]; | 
						|
      if (last.type === 'bracket') { | 
						|
        if (inner.val.charAt(0) === '[') { | 
						|
          inner.val = '\\' + inner.val; | 
						|
        } | 
						|
 | 
						|
      } else { | 
						|
        open.val = '\\' + open.val; | 
						|
        var sibling = open.parent.nodes[1]; | 
						|
        if (sibling.type === 'star') { | 
						|
          sibling.loose = true; | 
						|
        } | 
						|
      } | 
						|
    } | 
						|
 | 
						|
    // add non-enumerable parser reference | 
						|
    utils.define(parsed, 'parser', this.parser); | 
						|
    return parsed; | 
						|
  }); | 
						|
 | 
						|
  return snapdragon; | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Create the key to use for memoization. The key is generated | 
						|
 * by iterating over the options and concatenating key-value pairs | 
						|
 * to the pattern string. | 
						|
 */ | 
						|
 | 
						|
utils.createKey = function(pattern, options) { | 
						|
  if (utils.typeOf(options) !== 'object') { | 
						|
    return pattern; | 
						|
  } | 
						|
  var val = pattern; | 
						|
  var keys = Object.keys(options); | 
						|
  for (var i = 0; i < keys.length; i++) { | 
						|
    var key = keys[i]; | 
						|
    val += ';' + key + '=' + String(options[key]); | 
						|
  } | 
						|
  return val; | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Cast `val` to an array | 
						|
 * @return {Array} | 
						|
 */ | 
						|
 | 
						|
utils.arrayify = function(val) { | 
						|
  if (typeof val === 'string') return [val]; | 
						|
  return val ? (Array.isArray(val) ? val : [val]) : []; | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Return true if `val` is a non-empty string | 
						|
 */ | 
						|
 | 
						|
utils.isString = function(val) { | 
						|
  return typeof val === 'string'; | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Return true if `val` is a non-empty string | 
						|
 */ | 
						|
 | 
						|
utils.isObject = function(val) { | 
						|
  return utils.typeOf(val) === 'object'; | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Returns true if the given `str` has special characters | 
						|
 */ | 
						|
 | 
						|
utils.hasSpecialChars = function(str) { | 
						|
  return /(?:(?:(^|\/)[!.])|[*?+()|\[\]{}]|[+@]\()/.test(str); | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Escape regex characters in the given string | 
						|
 */ | 
						|
 | 
						|
utils.escapeRegex = function(str) { | 
						|
  return str.replace(/[-[\]{}()^$|*+?.\\\/\s]/g, '\\$&'); | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Normalize slashes in the given filepath. | 
						|
 * | 
						|
 * @param {String} `filepath` | 
						|
 * @return {String} | 
						|
 */ | 
						|
 | 
						|
utils.toPosixPath = function(str) { | 
						|
  return str.replace(/\\+/g, '/'); | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Strip backslashes before special characters in a string. | 
						|
 * | 
						|
 * @param {String} `str` | 
						|
 * @return {String} | 
						|
 */ | 
						|
 | 
						|
utils.unescape = function(str) { | 
						|
  return utils.toPosixPath(str.replace(/\\(?=[*+?!.])/g, '')); | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Strip the prefix from a filepath | 
						|
 * @param {String} `fp` | 
						|
 * @return {String} | 
						|
 */ | 
						|
 | 
						|
utils.stripPrefix = function(str) { | 
						|
  if (str.charAt(0) !== '.') { | 
						|
    return str; | 
						|
  } | 
						|
  var ch = str.charAt(1); | 
						|
  if (utils.isSlash(ch)) { | 
						|
    return str.slice(2); | 
						|
  } | 
						|
  return str; | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Returns true if the given str is an escaped or | 
						|
 * unescaped path character | 
						|
 */ | 
						|
 | 
						|
utils.isSlash = function(str) { | 
						|
  return str === '/' || str === '\\/' || str === '\\' || str === '\\\\'; | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Returns a function that returns true if the given | 
						|
 * pattern matches or contains a `filepath` | 
						|
 * | 
						|
 * @param {String} `pattern` | 
						|
 * @return {Function} | 
						|
 */ | 
						|
 | 
						|
utils.matchPath = function(pattern, options) { | 
						|
  return (options && options.contains) | 
						|
    ? utils.containsPattern(pattern, options) | 
						|
    : utils.equalsPattern(pattern, options); | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Returns true if the given (original) filepath or unixified path are equal | 
						|
 * to the given pattern. | 
						|
 */ | 
						|
 | 
						|
utils._equals = function(filepath, unixPath, pattern) { | 
						|
  return pattern === filepath || pattern === unixPath; | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Returns true if the given (original) filepath or unixified path contain | 
						|
 * the given pattern. | 
						|
 */ | 
						|
 | 
						|
utils._contains = function(filepath, unixPath, pattern) { | 
						|
  return filepath.indexOf(pattern) !== -1 || unixPath.indexOf(pattern) !== -1; | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Returns a function that returns true if the given | 
						|
 * pattern is the same as a given `filepath` | 
						|
 * | 
						|
 * @param {String} `pattern` | 
						|
 * @return {Function} | 
						|
 */ | 
						|
 | 
						|
utils.equalsPattern = function(pattern, options) { | 
						|
  var unixify = utils.unixify(options); | 
						|
  options = options || {}; | 
						|
 | 
						|
  return function fn(filepath) { | 
						|
    var equal = utils._equals(filepath, unixify(filepath), pattern); | 
						|
    if (equal === true || options.nocase !== true) { | 
						|
      return equal; | 
						|
    } | 
						|
    var lower = filepath.toLowerCase(); | 
						|
    return utils._equals(lower, unixify(lower), pattern); | 
						|
  }; | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Returns a function that returns true if the given | 
						|
 * pattern contains a `filepath` | 
						|
 * | 
						|
 * @param {String} `pattern` | 
						|
 * @return {Function} | 
						|
 */ | 
						|
 | 
						|
utils.containsPattern = function(pattern, options) { | 
						|
  var unixify = utils.unixify(options); | 
						|
  options = options || {}; | 
						|
 | 
						|
  return function(filepath) { | 
						|
    var contains = utils._contains(filepath, unixify(filepath), pattern); | 
						|
    if (contains === true || options.nocase !== true) { | 
						|
      return contains; | 
						|
    } | 
						|
    var lower = filepath.toLowerCase(); | 
						|
    return utils._contains(lower, unixify(lower), pattern); | 
						|
  }; | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Returns a function that returns true if the given | 
						|
 * regex matches the `filename` of a file path. | 
						|
 * | 
						|
 * @param {RegExp} `re` Matching regex | 
						|
 * @return {Function} | 
						|
 */ | 
						|
 | 
						|
utils.matchBasename = function(re) { | 
						|
  return function(filepath) { | 
						|
    return re.test(path.basename(filepath)); | 
						|
  }; | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Determines the filepath to return based on the provided options. | 
						|
 * @return {any} | 
						|
 */ | 
						|
 | 
						|
utils.value = function(str, unixify, options) { | 
						|
  if (options && options.unixify === false) { | 
						|
    return str; | 
						|
  } | 
						|
  return unixify(str); | 
						|
}; | 
						|
 | 
						|
/** | 
						|
 * Returns a function that normalizes slashes in a string to forward | 
						|
 * slashes, strips `./` from beginning of paths, and optionally unescapes | 
						|
 * special characters. | 
						|
 * @return {Function} | 
						|
 */ | 
						|
 | 
						|
utils.unixify = function(options) { | 
						|
  options = options || {}; | 
						|
  return function(filepath) { | 
						|
    if (utils.isWindows() || options.unixify === true) { | 
						|
      filepath = utils.toPosixPath(filepath); | 
						|
    } | 
						|
    if (options.stripPrefix !== false) { | 
						|
      filepath = utils.stripPrefix(filepath); | 
						|
    } | 
						|
    if (options.unescape === true) { | 
						|
      filepath = utils.unescape(filepath); | 
						|
    } | 
						|
    return filepath; | 
						|
  }; | 
						|
};
 | 
						|
 |