-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathindex.js
More file actions
148 lines (126 loc) · 4.34 KB
/
index.js
File metadata and controls
148 lines (126 loc) · 4.34 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
'use strict';
var fs = require('fs'),
path = require('path'),
exists = fs.existsSync || path.existsSync,
relativeSegmentRegExp = /^\.\//,
jsExtRegExp = /\.js$/,
idRegExp = /\{id\}/g,
badExtensions = {
'css': true,
'html': true,
'htm': true
};
var optDefaults = {
configFileNames: ['package.json', 'bower.json'],
adapterText: 'define([\'./{id}\'], function(m) { return m; });'
};
function mix(target, source, override) {
Object.keys(source).forEach(function(key) {
if (!target.hasOwnProperty(key) || override) {
target[key] = source[key];
}
});
return target;
}
function getConfigPath(dir, configFileNames) {
var finalPath = null;
configFileNames.some(function(configFileName) {
var testPath = path.join(dir, configFileName);
if (exists(testPath) && fs.statSync(testPath).isFile()) {
finalPath = testPath;
return true;
}
});
return finalPath;
}
// Given an array of file paths, only return a value if there is only
// one that ends in a .js extension.
function findOneJsInArray(ary) {
var found,
count = 0;
ary.forEach(function(entry) {
if (jsExtRegExp.test(entry)) {
count += 1;
found = entry;
}
});
return count === 1 ? found : null;
}
module.exports = function(dir, opts) {
if (typeof dir !== 'string' || !dir) {
throw new Error('Missing first argument as a string for the directory');
}
opts = mix(mix({}, opts || {}), optDefaults);
if (typeof opts.adapterText !== 'string' || ! opts.adapterText) {
throw new Error('adapterText needs to be a non-empty string');
}
if (!Array.isArray(opts.configFileNames) || !opts.configFileNames.length) {
throw new Error('configFileNames needs to be a non-zero array');
}
if ('include' in opts && !Array.isArray(opts.include)) {
throw new Error('include needs to be an array');
}
fs.readdirSync(dir)
.filter(function(pkgName) {
return (!('include' in opts)) || opts.include.indexOf(pkgName) !== -1;
})
.forEach(function(pkgName) {
var pkgPath = path.join(dir, pkgName);
if (!fs.statSync(pkgPath).isFile()) {
var main,
configFile = getConfigPath(pkgPath, opts.configFileNames);
if (configFile) {
var contents = fs.readFileSync(configFile, 'utf8');
if (contents) {
var config = JSON.parse(contents);
main = config.main;
if (Array.isArray(main)) {
// A bower thing. Need to find main value.
if (main.length === 0) {
main = null;
} else if (main.length === 1) {
main = main[0];
} else {
main = findOneJsInArray(main);
}
}
}
} else {
// No config files.
// May not have a main, but the the directory just has one JS
// file in it, then use that as the main.
main = findOneJsInArray(fs.readdirSync(pkgPath));
}
if (!main) {
return;
}
// Ignore main values that may not be JS files. Cannot just blindly
// rely on the value of whatever is past the last dot and discard if
// not JS, since some front end library ecosystems, like jQuery
// plugins, use dots to segment parts of their names. So going with
// an exclusion list instead.
var ext = path.extname(main);
if (ext.indexOf('.') === 0) {
ext = ext.substring(1);
}
if (badExtensions.hasOwnProperty(ext)) {
return;
}
// Confirm the main file actually exists.
var mainPath = path.join(pkgPath, main);
if (!exists(mainPath) && !exists(mainPath + '.js')) {
console.error('WARNING: ' +
mainPath +
' does not exist, skipping.');
return;
}
// Remove any trailing relative path segment, just to make it prettier.
main = main.replace(relativeSegmentRegExp, '');
// Remove any trailing .js extension, since it is not needed for
// module IDs, and mixes up the separation of IDs from paths.
main = main.replace(jsExtRegExp, '');
var text = opts.adapterText.replace(idRegExp, pkgName + '/' + main);
fs.writeFileSync(path.join(dir, pkgName + '.js'), text, 'utf8');
}
});
};