-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwalk.js
More file actions
166 lines (139 loc) · 5.17 KB
/
walk.js
File metadata and controls
166 lines (139 loc) · 5.17 KB
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/*jshint node: true */
'use strict';
var walk,
fs = require('fs'),
path = require('path'),
firstDotRegExp = /^\.\//,
jsSuffixRegExp = /\.js$/;
function throwIfMainJson(filePath) {
throw new Error('Package at ' + filePath + ' uses .json, not supported yet');
}
function topPackage(packageName, fullPath, options, baseId) {
var mainId, packageJson,
result = {};
// Do not bother with requirejs, it is a bootstrap package. Also, no need to
// handle the .bin directory.
if (packageName === 'requirejs' || packageName === '.bin') {
return result;
}
if (!options) {
options = {};
}
if (fs.statSync(fullPath).isDirectory()) {
// Read package.json for the main value
var packageJsonPath = path.join(fullPath, 'package.json');
if (fs.existsSync(packageJsonPath)) {
packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
// Some modules use packageJson.browser to indicate a browser alternative
// for a main module. The 'inherits' package is one example.
mainId = typeof packageJson.browser === 'string' ?
packageJson.browser : packageJson.main;
} else if (options.altMainJson) {
var altJsonPath = path.join(fullPath, options.altMainJson);
if (fs.existsSync(altJsonPath)) {
var altJson = JSON.parse(fs.readFileSync(altJsonPath, 'utf8'));
if (altJson.main) {
// This is likely the bower case. If the mainId is not a .js file, or
// just no extension, then disregard.
var ext = path.extname(altJson.main);
if (!ext || ext === '.js') {
mainId = altJson.main;
}
}
}
}
// Check for index.* conventions
if (!mainId) {
if (fs.existsSync(path.join(fullPath, 'index.js'))) {
mainId = 'index';
} else if (fs.existsSync(path.join(fullPath, 'index.json'))) {
throwIfMainJson();
}
}
// Absolute, normalized module ID depends on nesting level.
var normalizedId = (baseId ?
baseId + '/node_modules/' + packageName :
packageName).replace(jsSuffixRegExp, '');
var walkData = {
packageName: packageName,
normalizedId: normalizedId,
fullPath: fullPath
};
var nodeModulesPath = path.join(walkData.fullPath, 'node_modules');
if (mainId) {
// Normalize mainId -- do not need the ./ or the file extension
walkData.main = mainId
.replace(firstDotRegExp, '')
.replace(jsSuffixRegExp, '');
}
// If the package.json has a browser field that is an object of alternatives
// set up map config for them.
var browserAlts = packageJson && packageJson.browser;
if (browserAlts && typeof browserAlts !== 'string') {
walkData.map = {};
Object.keys(browserAlts).forEach(function(targetId) {
var altId = browserAlts[targetId];
if (targetId.indexOf('.') === 0) {
targetId = walkData.normalizedId + '/' + targetId.substring(2);
}
targetId = targetId.replace(jsSuffixRegExp, '');
if (altId === false) {
walkData.map[targetId] = 'notobo-empty';
} else {
altId = altId.replace(jsSuffixRegExp, '');
if (altId.indexOf('.') === 0) {
altId = walkData.normalizedId + '/' + altId.substring(2);
} else {
// Find out if the referenced ID is in nested node_modules, and
// if so, append node_modules to the final ID.
var firstPart = altId.split('/').shift();
if (fs.existsSync(path.join(nodeModulesPath, firstPart))) {
altId = walkData.normalizedId + '/node_modules/' + altId;
} else {
// Try as a sibling
if (fs.existsSync(path.join(nodeModulesPath, '..', '..', firstPart))) {
var parts = walkData.normalizedId.split('/');
parts.pop();
parts.push(altId);
altId = parts.join('/');
}
}
}
walkData.map[targetId] = altId;
}
});
}
// Let callback know of new package dependency found. The callback has the
// capability to modify the walkData.
if (typeof options.onDep === 'function') {
options.onDep(walkData);
}
result = {
normalizedId: walkData.normalizedId
};
if (walkData.main) {
result.main = walkData.main;
}
if (walkData.map) {
result.map = walkData.map;
}
// If the directory has a node_modules, recurse
if (fs.existsSync(nodeModulesPath) &&
fs.statSync(nodeModulesPath).isDirectory()) {
result.deps = walk(nodeModulesPath,
options,
walkData.normalizedId);
}
}
return result;
}
module.exports = walk = function(dirName, options, baseId) {
var result = {};
fs.readdirSync(dirName).forEach(function(packageName) {
var fullPath = path.join(dirName, packageName);
packageName = packageName.replace(jsSuffixRegExp, '');
result[packageName] = topPackage(packageName, fullPath, options, baseId);
});
return result;
};
walk.topPackage = topPackage;