This repository has been archived by the owner on Apr 12, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathindex.js
111 lines (93 loc) · 3.74 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
var path = require('path');
var archy = require('archy');
var chalk = require('chalk');
var resolve = require('enhanced-resolve');
// From http://stackoverflow.com/a/6969486/969302
function escapeRegExp(str) {
return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
}
exports.fromStats = function buildTree(stats, opts) {
opts = opts || {};
opts.packageDescriptors = opts.packageDescriptors || ['package.json', 'bower.json', 'component.json'];
// Build a module dependency tree
var tree = {};
stats.toJson({modules: true}).modules.forEach(function(mod) {
// Ignore origin modules
if (mod.name.indexOf('~') === -1) {
return;
}
// Resolve webpack query string and loaders to retrieve the resource path.
// webpack dependencies are prepended with (webpack)
// Module directories are represented by a ~
var modulePath = resolve.parse(mod.name).resource.path.replace('(webpack)', './~/webpack');
var moduleFullPath = resolve.parse(mod.identifier).resource.path;
// The following code maps every `~/module_name` in `modulePath` to its corresponding
// `module_folder/module_name` in `moduleFullPath`
// Split at each `~/module_name` and escape for use in a regexp
var splitParts = modulePath.split(/~\/[^\/]+\//).map(escapeRegExp);
// Find and traverse every `module_folder/module_name` construct in `moduleFullPath`
var parentTree = tree;
for (var i = 1; i < splitParts.length; i++) {
// Remove everything before the module occurrence so that match.index points
// to the beginning of the module_folder/module_name construct
var regexpParts = splitParts.slice(i);
var regexpHead = '([^\/]+\/([^\/]+)\/)'; // match `module_folder/module_name`
var regexpTail = regexpParts.join('[^\/]+\/[^\/]+\/'); // match the rest of the path
var regexp = new RegExp(regexpHead + regexpTail + '$');
var match = moduleFullPath.match(regexp);
if (!match) {
// Shouldn't happen
return;
}
var packagePath = moduleFullPath.slice(0, match.index + match[1].length);
// Retrieve the child module version from its descriptor file (package.json, bower.json, ...)
var packageVersion = 'unknown';
for (var j = 0; j < opts.packageDescriptors.length; j++) {
try {
packageVersion = require(packagePath + opts.packageDescriptors[j]).version;
break;
} catch (e) {
// do nothing
}
}
var packageName = match[2];
var package = parentTree[packageName];
if (!package) {
parentTree[packageName] = package = {
name: packageName,
version: packageVersion,
path: packagePath,
tree: {}
};
}
parentTree = package.tree;
}
});
return tree;
};
exports.treeToString = function treeToString(tree, opts) {
opts = opts || {};
opts.pretty = opts.pretty || false;
opts.fullPaths = opts.fullPaths || false;
// Node that will eventually be passed to archy
var topNode = {
label: '',
nodes: []
};
// Recursively build an archy node tree from our package tree
(function recursiveTreeBuild(tree, node) {
for (var key in tree) {
var package = tree[key];
var packageName = opts.pretty ? chalk.underline(package.name) : package.name;
var packagePath = opts.fullPaths ? package.path : path.relative(path.dirname(module.parent.filename), package.path);
packagePath = opts.pretty ? chalk.grey(packagePath) : packagePath;
var childNode = {
label: packageName + '@' + package.version + '\n' + packagePath,
nodes: []
};
recursiveTreeBuild(package.tree, childNode);
node.nodes.push(childNode);
};
})(tree, topNode);
return archy(topNode);
};