Socket
Socket
Sign inDemoInstall

madge

Package Overview
Dependencies
Maintainers
1
Versions
77
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

madge - npm Package Compare versions

Comparing version 0.5.5 to 0.6.0

TODO

22

lib/cyclic.js

@@ -10,5 +10,5 @@ 'use strict';

function getPath(parent, unresolved) {
var parentVisited = false;
let parentVisited = false;
return Object.keys(unresolved).filter(function (module) {
return Object.keys(unresolved).filter((module) => {
if (module === parent) {

@@ -34,3 +34,3 @@ parentVisited = true;

if (modules[id]) {
modules[id].forEach(function (dependency) {
modules[id].forEach((dependency) => {
if (!resolved[dependency]) {

@@ -56,7 +56,7 @@ if (unresolved[dependency]) {

module.exports = function (modules) {
var circular = [];
var resolved = {};
var unresolved = {};
const circular = [];
const resolved = {};
const unresolved = {};
Object.keys(modules).forEach(function (id) {
Object.keys(modules).forEach((id) => {
resolver(id, modules, circular, resolved, unresolved);

@@ -70,3 +70,3 @@ });

*/
getArray: function () {
getArray() {
return circular;

@@ -80,5 +80,5 @@ },

*/
isCyclic: function (id) {
var cyclic = false;
circular.forEach(function (path) {
isCyclic(id) {
let cyclic = false;
circular.forEach((path) => {
if (path.indexOf(id) >= 0) {

@@ -85,0 +85,0 @@ cyclic = true;

'use strict';
/**
* Module dependencies.
*/
var exec = require('child_process').exec;
var cyclic = require('./cyclic');
var graphviz = require('graphviz');
const exec = require('child_process').exec;
const cyclic = require('./cyclic');
const graphviz = require('graphviz');

@@ -34,3 +31,3 @@ /**

function checkGraphvizInstalled() {
exec('gvpr -V', function (error, stdout, stderr) {
exec('gvpr -V', (error, stdout, stderr) => {
if (error !== null) {

@@ -49,3 +46,3 @@ throw new Error('Graphviz could not be found. Ensure that "gvpr" is in your $PATH.\n' + error);

// Valid attributes: http://www.graphviz.org/doc/info/attrs.html
var G = {
const G = {
layout: opts.layout || 'dot',

@@ -56,3 +53,3 @@ overlap: false,

var N = {
const N = {
fontname: opts.fontFace || 'Times-Roman',

@@ -62,3 +59,3 @@ fontsize: opts.fontSize || 14

var E = {};
const E = {};

@@ -87,3 +84,4 @@ if (opts.colors) {

module.exports.image = function (modules, opts, callback) {
var g = graphviz.digraph('G');
const g = graphviz.digraph('G');
const nodes = {};

@@ -94,6 +92,5 @@ checkGraphvizInstalled();

var nodes = {};
var cyclicResults = cyclic(modules);
const cyclicResults = cyclic(modules);
Object.keys(modules).forEach(function (id) {
Object.keys(modules).forEach((id) => {

@@ -109,3 +106,3 @@ nodes[id] = nodes[id] || g.addNode(id);

modules[id].forEach(function (depId) {
modules[id].forEach((depId) => {
nodes[depId] = nodes[depId] || g.addNode(depId);

@@ -128,11 +125,11 @@ if (opts.colors && !modules[depId]) {

module.exports.dot = function (modules) {
var nodes = {};
var g = graphviz.digraph('G');
const nodes = {};
const g = graphviz.digraph('G');
checkGraphvizInstalled();
Object.keys(modules).forEach(function (id) {
Object.keys(modules).forEach((id) => {
nodes[id] = nodes[id] || g.addNode(id);
modules[id].forEach(function (depId) {
modules[id].forEach((depId) => {
nodes[depId] = nodes[depId] || g.addNode(depId);

@@ -139,0 +136,0 @@ g.addEdge(nodes[id], nodes[depId]);

'use strict';
/**
* Module dependencies.
*/
var cyclic = require('./cyclic');
var CJS = require('./parse/cjs');
var AMD = require('./parse/amd');
var ES6 = require('./parse/es6');
var graph = require('./graph');
const cyclic = require('./cyclic');
const CJS = require('./parse/cjs');
const AMD = require('./parse/amd');
const ES6 = require('./parse/es6');
const graph = require('./graph');
/**
* Expose factory function.
* @api public
* @param {String|Array|Object} src
* @param {Object} opts
* @return {Madge}
*/
module.exports = function (src, opts) {
return new Madge(src, opts);
};
class Madge {
/**
* Class constructor.
* @constructor
* @api public
* @param {String|Array|Object} src
* @param {Object} opts
*/
constructor(src, opts) {
let tree = [];
/**
* Class constructor.
* @constructor
* @api public
* @param {String|Array|Object} src
* @param {Object} opts
*/
function Madge(src, opts) {
var tree = [];
this.opts = opts || {};
this.opts.format = String(this.opts.format || 'cjs').toLowerCase();
this.opts = opts || {};
this.opts.format = String(this.opts.format || 'cjs').toLowerCase();
if (typeof src === 'object' && !Array.isArray(src)) {
this.tree = src;
return;
}
if (typeof src === 'object' && !Array.isArray(src)) {
this.tree = src;
return;
if (typeof src === 'string') {
src = [src];
}
if (src && src.length) {
tree = this.parse(src);
}
this.tree = tree;
}
if (typeof src === 'string') {
src = [src];
/**
* Parse the given source folder(s).
* @param {Array|Object} src
* @return {Object}
*/
parse(src) {
if (this.opts.format === 'cjs') {
return new CJS(src, this.opts, this).tree;
} else if (this.opts.format === 'amd') {
return new AMD(src, this.opts, this).tree;
} else if (this.opts.format === 'es6') {
return new ES6(src, this.opts, this).tree;
} else {
throw new Error('invalid module format "' + this.opts.format + '"');
}
}
if (src && src.length) {
tree = this.parse(src);
/**
* Return the module dependency graph as an object.
* @api public
* @return {Object}
*/
obj() {
return this.tree;
}
this.tree = tree;
}
/**
* Return the modules that has circular dependencies.
* @api public
* @return {Object}
*/
circular() {
return cyclic(this.tree);
}
/**
* Parse the given source folder(s).
* @param {Array|Object} src
* @return {Object}
*/
Madge.prototype.parse = function (src) {
if (this.opts.format === 'cjs') {
return new CJS(src, this.opts, this).tree;
} else if (this.opts.format === 'amd') {
return new AMD(src, this.opts, this).tree;
} else if (this.opts.format === 'es6') {
return new ES6(src, this.opts, this).tree;
} else {
throw new Error('invalid module format "' + this.opts.format + '"');
/**
* Return a list of modules that depends on the given module.
* @api public
* @param {String} id
* @return {Array|Object}
*/
depends(id) {
return Object.keys(this.tree).filter((module) => {
if (this.tree[module]) {
return this.tree[module].reduce((acc, dependency) => {
if (dependency === id) {
acc = module;
}
return acc;
}, false);
}
});
}
};
/**
* Return the module dependency graph as an object.
* @api public
* @return {Object}
*/
Madge.prototype.obj = function () {
return this.tree;
};
/**
* Return the module dependency graph as DOT output.
* @api public
* @return {String}
*/
dot() {
return graph.dot(this.tree);
}
/**
* Return the modules that has circular dependencies.
* @api public
* @return {Object}
*/
Madge.prototype.circular = function () {
return cyclic(this.tree);
};
/**
* Return the module dependency graph as a PNG image.
* @api public
* @param {Object} opts
* @param {Function} callback
*/
image(opts, callback) {
graph.image(this.tree, opts, callback);
}
}
/**
* Return a list of modules that depends on the given module.
* @api public
* @param {String} id
* @return {Array|Object}
*/
Madge.prototype.depends = function (id) {
return Object.keys(this.tree).filter(function (module) {
if (this.tree[module]) {
return this.tree[module].reduce(function (acc, dependency) {
if (dependency === id) {
acc = module;
}
return acc;
}, false);
}
}, this);
};
/**
* Return the module dependency graph as DOT output.
* @api public
* @return {String}
*/
Madge.prototype.dot = function () {
return graph.dot(this.tree);
};
/**
* Return the module dependency graph as a PNG image.
* @api public
* @param {Object} opts
* @param {Function} callback
*/
Madge.prototype.image = function (opts, callback) {
graph.image(this.tree, opts, callback);
};
module.exports = (src, opts) => new Madge(src, opts);
'use strict';
/**
* Module dependencies.
*/
var fs = require('fs');
var path = require('path');
var util = require('util');
var amdetective = require('amdetective');
var parse = require('./parse');
var Base = require('./base');
const fs = require('fs');
const path = require('path');
const amdetective = require('amdetective');
const parse = require('./parse');
const Base = require('./base');

@@ -19,3 +15,3 @@ /**

function mergeTrees(a, b) {
Object.keys(b).forEach(function (id) {
Object.keys(b).forEach((id) => {
if (!a[id]) {

@@ -25,3 +21,3 @@ a[id] = [];

b[id].forEach(function (dep) {
b[id].forEach((dep) => {
if (a[id].indexOf(dep) < 0) {

@@ -41,3 +37,3 @@ a[id].push(dep);

function convertPathsToIds(deps, pathDefs, baseDir) {
var path, pathDeps, i1, len1, i2, len2;
let path, pathDeps, i1, len1, i2, len2;

@@ -50,3 +46,3 @@ if (baseDir) {

Object.keys(pathDefs).forEach(function (id) {
Object.keys(pathDefs).forEach((id) => {
path = pathDefs[id];

@@ -83,3 +79,3 @@

// normalize entries within deps-arrays (i.e. replace path-refs with id-refs)
Object.keys(pathDefs).forEach(function (id) {
Object.keys(pathDefs).forEach((id) => {
path = baseDir + pathDefs[id];

@@ -105,6 +101,6 @@ if (deps[id]) {

function getShimDepsFromConfig(filename, exclude) {
var deps = {};
var config = parse.findConfig(filename, fs.readFileSync(filename, 'utf8')); // eslint-disable-line no-sync
var excludeRegex = exclude ? new RegExp(exclude) : false;
var isIncluded = function (key) {
const deps = {};
const config = parse.findConfig(filename, fs.readFileSync(filename, 'utf8')); // eslint-disable-line no-sync
const excludeRegex = exclude ? new RegExp(exclude) : false;
const isIncluded = function (key) {
return !(excludeRegex && key.match(excludeRegex));

@@ -114,3 +110,3 @@ };

if (config.shim) {
Object.keys(config.shim).filter(isIncluded).forEach(function (key) {
Object.keys(config.shim).filter(isIncluded).forEach((key) => {
if (config.shim[key].deps) {

@@ -134,6 +130,6 @@ deps[key] = config.shim[key].deps.filter(isIncluded);

function getPathsFromConfig(filename, exclude) {
var paths = {};
var config = parse.findConfig(filename, fs.readFileSync(filename, 'utf8')); // eslint-disable-line no-sync
var excludeRegex = exclude ? new RegExp(exclude) : false;
var isIncluded = function (key) {
const paths = {};
const config = parse.findConfig(filename, fs.readFileSync(filename, 'utf8')); // eslint-disable-line no-sync
const excludeRegex = exclude ? new RegExp(exclude) : false;
const isIncluded = function (key) {
return !(excludeRegex && key.match(excludeRegex));

@@ -143,3 +139,3 @@ };

if (config.paths) {
Object.keys(config.paths).filter(isIncluded).forEach(function (key) {
Object.keys(config.paths).filter(isIncluded).forEach((key) => {
paths[key] = config.paths[key];

@@ -159,60 +155,55 @@ });

function getBaseUrlFromConfig(filename, srcBaseDir) {
var config = parse.findConfig(filename, fs.readFileSync(filename, 'utf8')); // eslint-disable-line no-sync
const config = parse.findConfig(filename, fs.readFileSync(filename, 'utf8')); // eslint-disable-line no-sync
return config.baseUrl ? path.relative(srcBaseDir, config.baseUrl) : '';
}
/**
* This class will parse the AMD module format.
* @see https://github.com/amdjs/amdjs-api/wiki/AMD
* @constructor
* @param {Array} src
* @param {Object} opts
* @param {Object} parent
*/
var AMD = module.exports = function (src, opts, parent) {
Base.apply(this, arguments);
class AMD extends Base {
/**
* @constructor
* @param {Array} src
* @param {Object} opts
* @param {Object} parent
*/
constructor(src, opts, parent) {
super(src, opts, parent);
if (opts.requireConfig) {
var baseDir = src.length ? src[0].replace(/\\/g, '/') : '';
baseDir = getBaseUrlFromConfig(opts.requireConfig, baseDir);
convertPathsToIds(this.tree, getPathsFromConfig(opts.requireConfig, opts.exclude), baseDir);
mergeTrees(this.tree, getShimDepsFromConfig(opts.requireConfig, opts.exclude));
if (opts.requireConfig) {
let baseDir = src.length ? src[0].replace(/\\/g, '/') : '';
baseDir = getBaseUrlFromConfig(opts.requireConfig, baseDir);
convertPathsToIds(this.tree, getPathsFromConfig(opts.requireConfig, opts.exclude), baseDir);
mergeTrees(this.tree, getShimDepsFromConfig(opts.requireConfig, opts.exclude));
}
}
};
/**
* Inherit from `Base`
*/
util.inherits(AMD, Base);
/**
* Normalize a module file path and return a proper identificator.
* @param {String} filename
* @return {String}
*/
normalize(filename) {
return this.replaceBackslashInPath(path.relative(this.baseDir, filename).replace(this.extRegEx, ''));
}
/**
* Normalize a module file path and return a proper identificator.
* @param {String} filename
* @return {String}
*/
AMD.prototype.normalize = function (filename) {
return this.replaceBackslashInPath(path.relative(this.baseDir, filename).replace(this.extRegEx, ''));
};
/**
* Parse the given file and return all found dependencies.
* @param {String} filename
* @return {Array}
*/
parseFile(filename) {
const dependencies = [];
const src = this.getFileSource(filename);
/**
* Parse the given file and return all found dependencies.
* @param {String} filename
* @return {Array}
*/
AMD.prototype.parseFile = function (filename) {
try {
var dependencies = [];
var src = this.getFileSource(filename);
var fileData = {filename: filename, src: src};
this.emit('parseFile', {
filename: filename,
src: src
});
this.emit('parseFile', fileData);
if (/define|require\s*\(/m.test(fileData.src)) {
amdetective(fileData.src, {findNestedDependencies: this.opts.findNestedDependencies}).map(function (obj) {
if (/define|require\s*\(/m.test(src)) {
amdetective(src, {findNestedDependencies: this.opts.findNestedDependencies}).map((obj) => {
return typeof obj === 'string' ? [obj] : obj.deps;
}).filter(function (deps) {
deps.filter(function (id) {
}).filter((deps) => {
deps.filter((id) => {
// Ignore RequireJS IDs and plugins
return id !== 'require' && id !== 'exports' && id !== 'module' && !id.match(/\.?\w\!/);
}).map(function (id) {
}).map((id) => {
// Only resolve relative module identifiers (if the first term is "." or "..")

@@ -223,3 +214,3 @@ if (id.charAt(0) !== '.') {

var depFilename = path.resolve(path.dirname(fileData.filename), id);
const depFilename = path.resolve(path.dirname(filename), id);

@@ -229,62 +220,56 @@ if (depFilename) {

}
}, this).forEach(function (id) {
}).forEach((id) => {
if (!this.isExcluded(id) && dependencies.indexOf(id) < 0) {
dependencies.push(id);
}
}, this);
}, this);
});
});
}
return dependencies;
}
} catch (e) {
if (this.opts.breakOnError) {
console.log(String('\nError while parsing file: ' + filename).red);
throw e;
}
return dependencies;
}
return [];
};
/**
* Get module dependencies from optimize file (r.js).
* @param {String} filename
*/
addOptimizedModules(filename) {
const anonymousRequire = [];
/**
* Get module dependencies from optimize file (r.js).
* @param {String} filename
*/
AMD.prototype.addOptimizedModules = function (filename) {
var self = this;
var anonymousRequire = [];
amdetective(this.getFileSource(filename))
.filter((obj) => {
const id = obj.name || obj;
return id !== 'require' && id !== 'exports' && id !== 'module' && !id.match(/\.?\w\!/) && !this.isExcluded(id);
})
.forEach((obj) => {
if (typeof obj === 'string') {
anonymousRequire.push(obj);
return;
}
amdetective(this.getFileSource(filename))
.filter(function (obj) {
var id = obj.name || obj;
return id !== 'require' && id !== 'exports' && id !== 'module' && !id.match(/\.?\w\!/) && !self.isExcluded(id);
})
.forEach(function (obj) {
if (typeof obj === 'string') {
anonymousRequire.push(obj);
return;
}
if (!this.isExcluded(obj.name)) {
this.tree[obj.name] = obj.deps.filter((id) => {
return id !== 'require' && id !== 'exports' && id !== 'module' && !id.match(/\.?\w\!/) && !this.isExcluded(id);
});
}
});
if (!self.isExcluded(obj.name)) {
self.tree[obj.name] = obj.deps.filter(function (id) {
return id !== 'require' && id !== 'exports' && id !== 'module' && !id.match(/\.?\w\!/) && !self.isExcluded(id);
});
}
});
if (anonymousRequire.length > 0) {
this.tree[this.opts.mainRequireModule || ''] = anonymousRequire;
}
}
if (anonymousRequire.length > 0) {
this.tree[this.opts.mainRequireModule || ''] = anonymousRequire;
/**
* Parse the given `filename` and add it to the module tree.
* @param {String} filename
*/
addModule(filename) {
if (this.opts.optimized) {
this.addOptimizedModules(filename);
} else {
Base.prototype.addModule.call(this, filename);
}
}
};
}
/**
* Parse the given `filename` and add it to the module tree.
* @param {String} filename
*/
AMD.prototype.addModule = function (filename) {
if (this.opts.optimized) {
this.addOptimizedModules(filename);
} else {
Base.prototype.addModule.call(this, filename);
}
};
module.exports = AMD;
'use strict';
/**
* Module dependencies
*/
var fs = require('fs');
var path = require('path');
var util = require('util');
var resolve = require('resolve');
var EventEmitter = require('events').EventEmitter;
var commondir = require('commondir');
var finder = require('walkdir');
var coffee = require('coffee-script');
const fs = require('fs');
const path = require('path');
const resolve = require('resolve');
const EventEmitter = require('events').EventEmitter;
const commondir = require('commondir');
const finder = require('walkdir');
const coffee = require('coffee-script');
/**
* Traversing `src` and fetches all dependencies.
* @constructor
* @param {Array} src
* @param {Object} opts
* @param {Object} parent
*/
var Base = module.exports = function (src, opts, parent) {
if (opts.onParseFile) {
this.on('parseFile', opts.onParseFile.bind(parent));
}
class Base extends EventEmitter {
/**
* Traversing `src` and fetches all dependencies.
* @constructor
* @param {Array} src
* @param {Object} opts
* @param {Object} parent
*/
constructor(src, opts, parent) {
super();
if (opts.onAddModule) {
this.on('addModule', opts.onAddModule.bind(parent));
}
if (opts.onParseFile) {
this.on('parseFile', opts.onParseFile.bind(parent));
}
this.opts = opts;
if (opts.onAddModule) {
this.on('addModule', opts.onAddModule.bind(parent));
}
if (typeof this.opts.extensions === 'undefined') {
this.opts.extensions = ['.js'];
}
this.opts = opts;
this.tree = {};
this.extRegEx = new RegExp('\\.(coffee|jsx|' + this.opts.extensions.map(function (str) {
return str.substring(1);
}).join('|') + ')$', 'g');
this.coffeeExtRegEx = /\.coffee$/;
src = this.resolveTargets(src);
this.excludeRegex = opts.exclude ? new RegExp(opts.exclude) : false;
this.baseDir = this.getBaseDir(src);
this.readFiles(src);
this.sortDependencies();
};
if (typeof this.opts.extensions === 'undefined') {
this.opts.extensions = ['.js'];
}
util.inherits(Base, EventEmitter);
this.tree = {};
this.extRegEx = new RegExp('\\.(coffee|jsx|' + this.opts.extensions.map((str) => {
return str.substring(1);
}).join('|') + ')$', 'g');
this.coffeeExtRegEx = /\.coffee$/;
src = this.resolveTargets(src);
this.excludeRegex = opts.exclude ? new RegExp(opts.exclude) : false;
this.baseDir = this.getBaseDir(src);
this.readFiles(src);
this.sortDependencies();
}
/**
* Resolve the given `id` to a filename.
* @param {String} dir
* @param {String} id
* @return {String}
*/
Base.prototype.resolve = function (dir, id) {
try {
return resolve.sync(id, {
basedir: dir,
paths: this.opts.paths,
extensions: this.opts.extensions
});
} catch (e) {
if (this.opts.breakOnError) {
console.log(String('\nError while resolving module from: ' + id).red);
throw e;
/**
* Resolve the given `id` to a filename.
* @param {String} dir
* @param {String} id
* @return {String}
*/
resolve(dir, id) {
try {
return resolve.sync(id, {
basedir: dir,
paths: this.opts.paths,
extensions: this.opts.extensions
});
} catch (e) {
if (this.opts.breakOnError) {
console.log(String('\nError while resolving module from: ' + id).red);
throw e;
}
return id;
}
return id;
}
};
/**
* Get the most common dir from the `src`.
* @param {Array} src
* @return {String}
*/
Base.prototype.getBaseDir = function (src) {
var dir = commondir(src);
/**
* Get the most common dir from the `src`.
* @param {Array} src
* @return {String}
*/
getBaseDir(src) {
const dir = commondir(src);
if (!fs.statSync(dir).isDirectory()) { // eslint-disable-line no-sync
dir = path.dirname(dir);
if (!fs.statSync(dir).isDirectory()) { // eslint-disable-line no-sync
return path.dirname(dir);
}
return dir;
}
return dir;
};
/**
* Resolves all paths in `sources` and ensure we have a absolute path.
* @param {Array} sources
* @return {Array}
*/
Base.prototype.resolveTargets = function (sources) {
return sources.map(function (src) {
return path.resolve(src);
});
};
/**
* Resolves all paths in `sources` and ensure we have a absolute path.
* @param {Array} sources
* @return {Array}
*/
resolveTargets(sources) {
return sources.map((src) => path.resolve(src));
}
/**
* Normalize a module file path and return a proper identificator.
* @param {String} filename
* @return {String}
*/
Base.prototype.normalize = function (filename) {
return this.replaceBackslashInPath(path.relative(this.baseDir, filename).replace(this.extRegEx, ''));
};
/**
* Normalize a module file path and return a proper identificator.
* @param {String} filename
* @return {String}
*/
normalize(filename) {
return this.replaceBackslashInPath(path.relative(this.baseDir, filename).replace(this.extRegEx, ''));
}
/**
* Check if module should be excluded.
* @param {String} id
* @return {Boolean}
*/
Base.prototype.isExcluded = function (id) {
return this.excludeRegex && id.match(this.excludeRegex);
};
/**
* Check if module should be excluded.
* @param {String} id
* @return {Boolean}
*/
isExcluded(id) {
return this.excludeRegex && id.match(this.excludeRegex);
}
/**
* Parse the given `filename` and add it to the module tree.
* @param {String} filename
*/
Base.prototype.addModule = function (filename) {
var id = this.normalize(filename);
/**
* Parse the given `filename` and add it to the module tree.
* @param {String} filename
*/
addModule(filename) {
const id = this.normalize(filename);
if (!this.isExcluded(id) && fs.existsSync(filename)) { // eslint-disable-line no-sync
this.tree[id] = this.parseFile(filename);
this.emit('addModule', {id: id, dependencies: this.tree[id]});
if (!this.isExcluded(id) && fs.existsSync(filename)) { // eslint-disable-line no-sync
try {
this.tree[id] = this.parseFile(filename);
this.emit('addModule', {id: id, dependencies: this.tree[id]});
} catch (e) {
if (this.opts.breakOnError) {
console.log(String('\nError while parsing file: ' + filename).red);
throw e;
}
}
}
}
};
/**
* Traverse `sources` and parse files found.
* @param {Array} sources
*/
Base.prototype.readFiles = function (sources) {
sources.forEach(function (src) {
if (fs.statSync(src).isDirectory()) { // eslint-disable-line no-sync
finder.sync(src).filter(function (filename) {
return filename.match(this.extRegEx);
}, this).forEach(function (filename) {
this.addModule(filename);
}, this);
} else {
this.addModule(src);
/**
* Traverse `sources` and parse files found.
* @param {Array} sources
*/
readFiles(sources) {
sources.forEach((src) => {
if (fs.statSync(src).isDirectory()) { // eslint-disable-line no-sync
finder.sync(src).filter((filename) => {
return filename.match(this.extRegEx);
}).forEach((filename) => {
this.addModule(filename);
});
} else {
this.addModule(src);
}
});
}
/**
* Read the given filename and compile it if necessary and return the content.
* @param {String} filename
* @return {String}
*/
getFileSource(filename) {
const src = fs.readFileSync(filename, 'utf8'); // eslint-disable-line no-sync
if (filename.match(this.coffeeExtRegEx)) {
return coffee.compile(src, {
header: false,
bare: true
});
}
}, this);
};
/**
* Read the given filename and compile it if necessary and return the content.
* @param {String} filename
* @return {String}
*/
Base.prototype.getFileSource = function (filename) {
var src = fs.readFileSync(filename, 'utf8'); // eslint-disable-line no-sync
return src;
}
if (filename.match(this.coffeeExtRegEx)) {
return coffee.compile(src, {
header: false,
bare: true
});
/**
* Sort dependencies by name.
*/
sortDependencies() {
this.tree = Object.keys(this.tree).sort().reduce((acc, id) => {
(acc[id] = this.tree[id]).sort();
return acc;
}, {});
}
return src;
};
/**
* Replace back slashes in path (Windows) with forward slashes (*nix).
* @param {String} path
* @return {String}
*/
replaceBackslashInPath(path) {
return path.replace(/\\/g, '/');
}
}
/**
* Sort dependencies by name.
*/
Base.prototype.sortDependencies = function () {
var self = this;
this.tree = Object.keys(this.tree).sort().reduce(function (acc, id) {
(acc[id] = self.tree[id]).sort();
return acc;
}, {});
};
/**
* Replace back slashes in path (Windows) with forward slashes (*nix).
* @param {String} path
* @return {String}
*/
Base.prototype.replaceBackslashInPath = function (path) {
return path.replace(/\\/g, '/');
};
module.exports = Base;
'use strict';
/**
* Module dependencies.
*/
var fs = require('fs');
var path = require('path');
var util = require('util');
var detective = require('detective');
var Base = require('./base');
const path = require('path');
const detective = require('detective');
const Base = require('./base');
/**
* This class will parse the CommonJS module format.
* @see http://nodejs.org/api/modules.html
* @constructor
*/
var CJS = module.exports = function () {
Base.apply(this, arguments);
};
/**
* Inherit from `Base`.
*/
util.inherits(CJS, Base);
/**
* Normalize a module file path and return a proper identificator.
* @param {String} filename
* @return {String}
*/
CJS.prototype.normalize = function (filename) {
filename = this.replaceBackslashInPath(filename);
if (filename.charAt(0) !== '/' && !filename.match(/^[A-Za-z:]+\//i)) {
// a core module (not mapped to a file)
return filename;
class CJS extends Base {
/**
* Normalize a module file path and return a proper identificator.
* @param {String} filename
* @return {String}
*/
normalize(filename) {
filename = this.replaceBackslashInPath(filename);
if (filename.charAt(0) !== '/' && !filename.match(/^[A-Za-z:]+\//i)) {
// a core module (not mapped to a file)
return filename;
}
return super.normalize(filename);
}
return Base.prototype.normalize.apply(this, arguments);
};
/**
* Parse the given file and return all found dependencies.
* @param {String} filename
* @return {Array}
*/
CJS.prototype.parseFile = function (filename) {
try {
if (fs.existsSync(filename)) { // eslint-disable-line no-sync
var dependencies = [];
var src = this.getFileSource(filename);
var fileData = {filename: filename, src: src};
/**
* Parse the given file and return all found dependencies.
* @param {String} filename
* @return {Array}
*/
parseFile(filename) {
const dependencies = [];
const src = this.getFileSource(filename);
this.emit('parseFile', fileData);
this.emit('parseFile', {
filename: filename,
src: src
});
if (/require\s*\(/m.test(fileData.src)) {
detective(fileData.src).map(function (id) {
var depFilename = this.resolve(path.dirname(fileData.filename), id);
if (depFilename) {
return this.normalize(depFilename);
}
}, this).filter(function (id) {
if (!this.isExcluded(id) && dependencies.indexOf(id) < 0) {
dependencies.push(id);
}
}, this);
if (/require\s*\(/m.test(src)) {
detective(src).map((id) => {
const depFilename = this.resolve(path.dirname(filename), id);
if (depFilename) {
return this.normalize(depFilename);
}
}).filter((id) => {
if (!this.isExcluded(id) && dependencies.indexOf(id) < 0) {
dependencies.push(id);
}
});
}
return dependencies;
}
}
} catch (e) {
if (this.opts.breakOnError) {
console.log(String('\nError while parsing file: ' + filename).red);
throw e;
}
return dependencies;
}
}
return [];
};
module.exports = CJS;
'use strict';
/**
* Module dependencies.
*/
var fs = require('fs');
var path = require('path');
var util = require('util');
var detective = require('detective-es6');
var Base = require('./base');
const path = require('path');
const detective = require('detective-es6');
const Base = require('./base');
/**
* This class will parse the ES6 module format.
* @see http://nodejs.org/api/modules.html
* @constructor
*/
var ES6 = module.exports = function () {
Base.apply(this, arguments);
};
class ES6 extends Base {
/**
* Parse the given file and return all found dependencies.
* @param {String} filename
* @return {Array}
*/
parseFile(filename) {
const dependencies = [];
const src = this.getFileSource(filename);
/**
* Inherit from `Base`.
*/
util.inherits(ES6, Base);
this.emit('parseFile', {
filename: filename,
src: src
});
/**
* Parse the given file and return all found dependencies.
* @param {String} filename
* @return {Array}
*/
ES6.prototype.parseFile = function (filename) {
try {
if (fs.existsSync(filename)) { // eslint-disable-line no-sync
var dependencies = [];
var src = this.getFileSource(filename);
var fileData = {filename: filename, src: src};
if (/import.*from/m.test(src) || /export.*from/m.test(src)) {
detective(src).map((id) => {
const depFilename = this.resolve(path.dirname(filename), id);
this.emit('parseFile', fileData);
if (depFilename) {
return this.normalize(depFilename);
}
}).filter((id) => {
if (!this.isExcluded(id) && dependencies.indexOf(id) < 0) {
dependencies.push(id);
}
});
}
if (/import.*from/m.test(fileData.src) || /export.*from/m.test(fileData.src)) {
detective(fileData.src).map(function (id) {
var depFilename = this.resolve(path.dirname(fileData.filename), id);
if (depFilename) {
return this.normalize(depFilename);
}
}, this).filter(function (id) {
if (!this.isExcluded(id) && dependencies.indexOf(id) < 0) {
dependencies.push(id);
}
}, this);
return dependencies;
}
}
} catch (e) {
if (this.opts.breakOnError) {
console.log(String('\nError while parsing file: ' + filename).red);
throw e;
}
return dependencies;
}
}
return [];
};
module.exports = ES6;
'use strict';
require('colors');
/**
* Module dependencies.
* Return colored string (or not).
* @param {String} str
* @param {String} name
* @param {Boolean} use
* @return {String}
*/
var c = require('./color');
function c(str, name, use) {
return use ? String(str)[name] : str;
}

@@ -30,8 +38,8 @@ /**

Object.keys(modules).forEach(function (id) {
Object.keys(modules).forEach((id) => {
console.log(c(id, 'cyan', opts.colors));
modules[id].forEach(function (depId) {
modules[id].forEach((depId) => {
console.log(c(' ' + depId, 'grey', opts.colors));
}, this);
}, this);
});
});
};

@@ -46,9 +54,9 @@

module.exports.summary = function (modules, opts) {
var o = {};
const o = {};
opts = opts || {};
Object.keys(modules).sort(function (a, b) {
Object.keys(modules).sort((a, b) => {
return modules[b].length - modules[a].length;
}).forEach(function (id) {
}).forEach((id) => {
if (opts.output === 'json') {

@@ -73,3 +81,4 @@ o[id] = modules[id].length;

module.exports.circular = function (circular, opts) {
var arr = circular.getArray();
const arr = circular.getArray();
if (opts.output === 'json') {

@@ -82,4 +91,4 @@ return process.stdout.write(toJSON(arr));

} else {
arr.forEach(function (path, idx) {
path.forEach(function (module, idx) {
arr.forEach((path, idx) => {
path.forEach((module, idx) => {
if (idx) {

@@ -107,5 +116,5 @@ process.stdout.write(c(' -> ', 'cyan', opts.colors));

modules.forEach(function (id) {
modules.forEach((id) => {
console.log(c(id, 'grey', opts.colors));
});
};
{
"name": "madge",
"version": "0.5.5",
"version": "0.6.0",
"author": "Patrik Henningsson <patrik.henningsson@gmail.com>",

@@ -22,10 +22,10 @@ "repository": "git://github.com/pahen/madge",

],
"engines": [
"node >= 0.8.0"
],
"engines": {
"node": ">=4.x.x"
},
"scripts": {
"test": "npm run lint && npm run mocha && npm run madge",
"mocha": "mocha test/*.js",
"lint": "eslint bin lib",
"madge": "bin/madge -c -f cjs ./lib",
"lint": "eslint bin/madge lib test/*.js",
"madge": "bin/madge -c -L ./lib",
"release": "npm test && release-it -n -i patch",

@@ -32,0 +32,0 @@ "release:minor": "npm run test && release-it -n -i minor",

@@ -142,2 +142,3 @@ # MaDGe - Module Dependency Graph

-s, --summary show summary of all dependencies
-L, --list show list of all dependencies
-c, --circular show circular dependencies

@@ -256,8 +257,11 @@ -d, --depends <id> show modules that depends on the given id

## v0.6.0 (July 06, 2016)
* Refactored Madge to use ES6 and now requires Node.js 4 to run.
## v0.5.5 (July 03, 2016)
* Add note about Graphviz and Windows in README
* Fix matching absolute path in Windows (Thanks to nadejdashed)
* Support for ES6 re-export syntax (Thanks to Oli Lalonde)
* Support files with ES6 (Thanks to Joel Kemp)
* Improve readme circular return object (Thanks to Way Of The Future)
* Add note about Graphviz and Windows in README.
* Fix matching absolute path in Windows (Thanks to nadejdashed).
* Support for ES6 re-export syntax (Thanks to Oli Lalonde).
* Support files with ES6 (Thanks to Joel Kemp).
* Improve readme circular return object (Thanks to Way Of The Future).

@@ -264,0 +268,0 @@ ## v0.5.4 (June 13, 2016)

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc