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.
192 lines
6.2 KiB
192 lines
6.2 KiB
/* |
|
* globule |
|
* https://github.com/cowboy/node-globule |
|
* |
|
* Copyright (c) 2018 "Cowboy" Ben Alman |
|
* Licensed under the MIT license. |
|
*/ |
|
|
|
'use strict'; |
|
|
|
var fs = require('fs'); |
|
var path = require('path'); |
|
|
|
var _ = require('lodash'); |
|
var glob = require('glob'); |
|
var minimatch = require('minimatch'); |
|
|
|
// The module. |
|
var globule = exports; |
|
|
|
// Process specified wildcard glob patterns or filenames against a |
|
// callback, excluding and uniquing files in the result set. |
|
function processPatterns(patterns, options, fn) { |
|
var result = []; |
|
_.each(patterns, function(pattern) { |
|
// The first character is not ! (inclusion). Add all matching filepaths |
|
// to the result set. |
|
if (pattern.indexOf('!') !== 0) { |
|
result = _.union(result, fn(pattern)); |
|
return; |
|
} |
|
// The first character is ! (exclusion). Remove any filepaths from the |
|
// result set that match this pattern, sans leading !. |
|
var filterFn = minimatch.filter(pattern.slice(1), options); |
|
result = _.filter(result, function(filepath) { |
|
return !filterFn(filepath); |
|
}); |
|
}); |
|
return result; |
|
} |
|
|
|
// Normalize paths to be unix-style. |
|
var pathSeparatorRe = /[\/\\]/g; |
|
function normalizePath(path) { |
|
return path.replace(pathSeparatorRe, '/'); |
|
} |
|
|
|
// Match a filepath or filepaths against one or more wildcard patterns. Returns |
|
// all matching filepaths. This behaves just like minimatch.match, but supports |
|
// any number of patterns. |
|
globule.match = function(patterns, filepaths, options) { |
|
// Return empty set if either patterns or filepaths was omitted. |
|
if (patterns == null || filepaths == null) { return []; } |
|
// Normalize patterns and filepaths to flattened arrays. |
|
patterns = _.isArray(patterns) ? _.flattenDeep(patterns) : [patterns]; |
|
filepaths = _.isArray(filepaths) ? _.flattenDeep(filepaths) : [filepaths]; |
|
// Return empty set if there are no patterns or filepaths. |
|
if (patterns.length === 0 || filepaths.length === 0) { return []; } |
|
// Return all matching filepaths. |
|
return processPatterns(patterns, options, function(pattern) { |
|
return minimatch.match(filepaths, pattern, options || {}); |
|
}); |
|
}; |
|
|
|
// Match a filepath or filepaths against one or more wildcard patterns. Returns |
|
// true if any of the patterns match. |
|
globule.isMatch = function() { |
|
return globule.match.apply(null, arguments).length > 0; |
|
}; |
|
|
|
// Return an array of all file paths that match the given wildcard patterns. |
|
globule.find = function() { |
|
var args = _.toArray(arguments); |
|
// If the last argument is an options object, remove it from args. |
|
var options = _.isPlainObject(args[args.length - 1]) ? args.pop() : {}; |
|
// If options.src was specified, use it. Otherwise, use all non-options |
|
// arguments. Flatten nested arrays. |
|
var patterns; |
|
if (options.src) { |
|
patterns = _.isArray(options.src) ? _.flattenDeep(options.src) : [options.src]; |
|
} else { |
|
patterns = _.flattenDeep(args); |
|
} |
|
// Return empty set if there are no patterns. |
|
if (patterns.length === 0) { return []; } |
|
var srcBase = options.srcBase || options.cwd; |
|
// Create glob-specific options object. |
|
var globOptions = _.extend({}, options); |
|
if (srcBase) { |
|
globOptions.cwd = srcBase; |
|
} |
|
// Get all matching filepaths. |
|
var matches = processPatterns(patterns, options, function(pattern) { |
|
return glob.sync(pattern, globOptions); |
|
}); |
|
// If srcBase and prefixBase were specified, prefix srcBase to matched paths. |
|
if (srcBase && options.prefixBase) { |
|
matches = matches.map(function(filepath) { |
|
return normalizePath(path.join(srcBase, filepath)); |
|
}); |
|
} |
|
// Filter result set? |
|
if (options.filter) { |
|
matches = matches.filter(function(filepath) { |
|
// If srcBase was specified but prefixBase was NOT, prefix srcBase |
|
// temporarily, for filtering. |
|
if (srcBase && !options.prefixBase) { |
|
filepath = normalizePath(path.join(srcBase, filepath)); |
|
} |
|
try { |
|
if (_.isFunction(options.filter)) { |
|
return options.filter(filepath, options); |
|
} else { |
|
// If the file is of the right type and exists, this should work. |
|
return fs.statSync(filepath)[options.filter](); |
|
} |
|
} catch(err) { |
|
// Otherwise, it's probably not the right type. |
|
return false; |
|
} |
|
}); |
|
} |
|
return matches; |
|
}; |
|
|
|
var extDotRe = { |
|
first: /(\.[^\/]*)?$/, |
|
last: /(\.[^\/\.]*)?$/, |
|
}; |
|
function rename(dest, options) { |
|
// Flatten path? |
|
if (options.flatten) { |
|
dest = path.basename(dest); |
|
} |
|
// Change the extension? |
|
if (options.ext) { |
|
dest = dest.replace(extDotRe[options.extDot], options.ext); |
|
} |
|
// Join dest and destBase? |
|
if (options.destBase) { |
|
dest = path.join(options.destBase, dest); |
|
} |
|
return dest; |
|
} |
|
|
|
// Build a mapping of src-dest filepaths from the given set of filepaths. |
|
globule.mapping = function(filepaths, options) { |
|
// Return empty set if filepaths was omitted. |
|
if (filepaths == null) { return []; } |
|
options = _.defaults({}, options, { |
|
extDot: 'first', |
|
rename: rename, |
|
}); |
|
var files = []; |
|
var fileByDest = {}; |
|
// Find all files matching pattern, using passed-in options. |
|
filepaths.forEach(function(src) { |
|
// Generate destination filename. |
|
var dest = options.rename(src, options); |
|
// Prepend srcBase to all src paths. |
|
if (options.srcBase) { |
|
src = path.join(options.srcBase, src); |
|
} |
|
// Normalize filepaths to be unix-style. |
|
dest = normalizePath(dest); |
|
src = normalizePath(src); |
|
// Map correct src path to dest path. |
|
if (fileByDest[dest]) { |
|
// If dest already exists, push this src onto that dest's src array. |
|
fileByDest[dest].src.push(src); |
|
} else { |
|
// Otherwise create a new src-dest file mapping object. |
|
files.push({ |
|
src: [src], |
|
dest: dest, |
|
}); |
|
// And store a reference for later use. |
|
fileByDest[dest] = files[files.length - 1]; |
|
} |
|
}); |
|
return files; |
|
}; |
|
|
|
// Return a mapping of src-dest filepaths from files matching the given |
|
// wildcard patterns. |
|
globule.findMapping = function() { |
|
var args = _.toArray(arguments); |
|
// If the last argument is an options object, remove it from args. |
|
var options = _.isPlainObject(args[args.length - 1]) ? args.pop() : {}; |
|
// Generate mapping from found filepaths. |
|
return globule.mapping(globule.find(args, options), options); |
|
};
|
|
|