documentation/lib/smart_glob.js
Tom MacWright 631c6925d4 feat(core): Switch to Promises everywhere. Adopt Node v4 ES6 (#648)
* feat(core): Switch to Promises everywhere. Adopt Node v4 ES6

Big changes:

* Uses template strings where appropriate
* Config and argument parsing is unified and there is no such thing
  as formatterOptions anymore. All user-passed options go through
  mergeConfig.
* The node API surface changed (again): `buildSync` is removed,
  building operations return Promises.
* Now using Flow for internal type annotations.

More changes:

* Remove buildSync command
* feat(inference): Partially implement object shorthand support
* Refs #649
* Use Flow annotations to  enforce types
* Keep flow but switch to comment syntax
* Clarify types
* More flow improvements
* Turn server into class
* LinkerStack becomes class too
* Fix comment description type
* Run flow on lint
* Many more flow fixes
* More intense flow refactoring
* Simplify inference steps
* Update inference tests, flow errors down to 1
* Continue refining types
* Fix more flow issues
* Use 'use strict' everywhere
* Make 'ast' property configurable
* Fix many tests
* Fix more tests
* Fix more tests
* Fix augments
* Test Markdown meta support
* Improve test coverage
* Switch back from for of to for for speed
2017-01-27 16:14:19 -05:00

137 lines
3.9 KiB
JavaScript

/* @flow */
'use strict';
var fs = require('fs');
var path = require('path');
var glob = require('glob');
var shell = require('shelljs');
/**
* Replace Windows with posix style paths
*
* @param {string} filepath Path to convert
* @returns {string} Converted filepath
*/
function convertPathToPosix(filepath) {
var normalizedFilepath = path.normalize(filepath);
var posixFilepath = normalizedFilepath.replace(/\\/g, '/');
return posixFilepath;
}
/**
* Checks if a provided path is a directory and returns a glob string matching
* all files under that directory if so, the path itself otherwise.
*
* Reason for this is that `glob` needs `/**` to collect all the files under a
* directory where as our previous implementation without `glob` simply walked
* a directory that is passed. So this is to maintain backwards compatibility.
*
* Also makes sure all path separators are POSIX style for `glob` compatibility.
*
* @param {string[]} [extensions=['.js']] An array of accepted extensions
* @returns {Function} A function that takes a pathname and returns a glob that
* matches all files with the provided extensions if
* pathname is a directory.
*/
function processPath(extensions) {
var cwd = process.cwd();
extensions = extensions || ['.js'];
extensions = extensions.map(function (ext) {
return ext.replace(/^\./, '');
});
var suffix = '/**';
if (extensions.length === 1) {
suffix += '/*.' + extensions[0];
} else {
suffix += '/*.{' + extensions.join(',') + '}';
}
/**
* A function that converts a directory name to a glob pattern
*
* @param {string} pathname The directory path to be modified
* @returns {string} The glob path or the file path itself
* @private
*/
return function (pathname) {
var newPath = pathname;
var resolvedPath = path.resolve(cwd, pathname);
if (shell.test('-d', resolvedPath)) {
newPath = pathname.replace(/[/\\]$/, '') + suffix;
}
return convertPathToPosix(newPath);
};
}
/**
* Resolves any directory patterns into glob-based patterns for easier handling.
* @param {string[]} patterns File patterns (such as passed on the command line).
* @param {Array<string>} extensions A list of file extensions
* @returns {string[]} The equivalent glob patterns and filepath strings.
*/
function resolveFileGlobPatterns(patterns, extensions) {
var processPathExtensions = processPath(extensions);
return patterns.map(processPathExtensions);
}
/**
* Build a list of absolute filesnames on which ESLint will act.
* Ignored files are excluded from the results, as are duplicates.
*
* @param globPatterns Glob patterns.
* @returns Resolved absolute filenames.
*/
function listFilesToProcess(globPatterns/*: Array<string>*/)/*: Array<string> */ {
var files = [],
added = new Set();
var cwd = process.cwd();
/**
* Executes the linter on a file defined by the `filename`. Skips
* unsupported file extensions and any files that are already linted.
* @param {string} filename The file to be processed
* @returns {void}
*/
function addFile(filename) {
if (added.has(filename)) {
return;
}
files.push(filename);
added.add(filename);
}
globPatterns.forEach(function (pattern) {
var file = path.resolve(cwd, pattern);
if (shell.test('-f', file)) {
addFile(fs.realpathSync(file), !shell.test('-d', file));
} else {
var globOptions = {
nodir: true,
dot: true,
cwd,
};
glob.sync(pattern, globOptions).forEach(function (globMatch) {
addFile(path.resolve(cwd, globMatch), false);
});
}
});
return files;
}
function smartGlob(indexes/*: Array<string>*/,
extensions/*: Array<string>*/) {
return listFilesToProcess(
resolveFileGlobPatterns(indexes, extensions)
);
}
module.exports = smartGlob;