npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

progeny

v0.12.0

Published

Recursively finds dependencies of style and template source files

Downloads

42,373

Readme

progeny

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.

Usage

progeny ([config]) (path, [sourceContents], callback)

progeny.Sync ([config]) (path, [sourceContents])

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.

Quick and Simple

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);
Configuration

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
};
More Examples

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) {});

Change Log

See release notes page on GitHub

License

MIT