| /* |
| * 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); |
| }; |