Recursively finds dependencies of style and template source files.
Or configure it to do the same kind of thing with any other type of code file
that has an import
-type syntax.
Call progeny with an optional configuration object, it returns a reusable
function. Call that function with a path to a source file (and its
source code if you already have it handy), and it will figure out all of that
file's dependencies and sub-dependencies, passing an array of them to your
callback. Or use the Sync
API to get the results as a return value.
Result array has non-enumerable patterns
property with an array of
glob patterns found in source files' import
statements.
Examples using path
assume you already have var path = require('path');
.
You could just use strings like '/path/to/project'
, but you may run into
cross-compatibility issues.
You can skip the config object and the source code, letting Progeny read the source from the file itself and apply a built-in configuration based on the file extension.
var progeny = require('progeny');
var filePath = path.join('path', 'to', 'project', 'style-or-template.pug');
// Async
progeny()(filePath, function (err, dependencies) {
// use the dependencies array in here
});
// Sync
var dependencies = progeny()(filePath);
There are
built-in configurations
already for css
, sass
/scss
, less
, stylus
, pug
/jade
, slm
, and proto
.
Configuration must be specified for any other formats. Feel free to submit Pull
Requests to add default types, or improve the settings for the existing ones.
var progenyConfig = {
// The file extension for the source code you want parsed
// Will be derived from the source file path if not specified
extension: 'styl',
// Array of multiple file extensions to try when looking for dependencies
extensionsList: ['scss', 'sass'],
// Regexp to run on each line of source code to match dependency references
// Make sure you wrap the file name part in (parentheses)
regexp: /^\s*@import\s+['"]?([^'"]+)['"]?/,
// File prefix to try (in addition to the raw value matched in the regexp)
prefix: '_',
// Matched stuff to exclude: string, regex, or array of either/both
exclusion: /^compass/,
// In case a match starts with a slash, the absolute path to apply
rootPath: path.join('path', 'to', 'project'),
// Other paths to check for possible dependency resolution
altPaths: [
path.join('path', 'to', 'shared'),
path.join('path', 'to', 'common')
],
// An array of regexps to run in series for more complex dependency parsing
// Useful for matching multiple dependencies from one, possibly mult-line,
// statement. All regexps except the last one must use the global flag.
multipass: [
/@import[^;]+;/g,
/\s*['"][^'"]+['"]\s*,?/g,
/(?:['"])([^'"]+)/
],
// By default the list of paths progeny provides will be limited to files
// actually found in the file system. Use this option to get every possible
// path progeny thinks a depencency could be located at.
potentialDeps: true,
// By default progeny will strip all line comments like "// ..." and
// multiline comments like "/* ... */". You could disable this behavior.
skipComments: true;
// Custom resolver allows to preprocess dependency name. For example, webpack
// has well known way to reference node_modules-related path with ~ in the
// beginning of import name.
// Return true, undefined or null to accept dependency without changes.
// Return false to reject dependency.
// Return new filename to override dependency.
resolver: function (depFilename, parentDir, parentFilename) {
if (depFilename.startsWith('~')) {
var absPath = path.resolve(path.join('.', 'node_modules', depFilename.substr(1)));
return path.relative(parentDir, absPath);
}
},
// Print dependency resolution information to console.log
debug: true
};
Process a list of files:
var progeny = require('progeny');
var getDependencies = progeny(progenyConfig);
myFiles.forEach(function (file) {
getDependencies(file.path, file.source, function (err, deps) {
if (err) throw new Error(err);
file.dependencies = deps;
});
});
Multiple configs:
var getDefaultDependencies = progeny();
var getCustomDependencies = progeny({
extension: 'foo',
regexp: /([^\s,]+)/
});
Process source code from a string without its file path:
var mySourceString; // assume this contains valid source code
progeny({
// extension and rootPath must be specified for this to work
// also need regexp if extension not one of the predefined ones
extension: 'less',
rootPath: path.join('path', 'to', 'project')
})(null, mySourceString, function (err, deps) {});