customizr 2.0.0 → 2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/crawler.js CHANGED
@@ -1,298 +1,298 @@
1
- module.exports = function (modernizrPath) {
2
- "use strict";
3
-
4
- var _ = require("lodash");
5
-
6
- // Dependencies
7
- var fs = require("fs"),
8
- cwd = process.cwd(),
9
- path = require("path");
10
-
11
- // Deferreds
12
- var promise = require("promised-io/promise");
13
-
14
- // Cache utils
15
- var utils, settings;
16
-
17
- return {
18
- matchedTestsInFile : {},
19
- stringMatches : {},
20
-
21
- filterTests : function (tests) {
22
- var i, j, obj = {},
23
- filteredTests = [];
24
-
25
- for (i = 0, j = tests.length; i < j; i++) {
26
- obj[tests[i]] = 0;
27
- }
28
-
29
- for (var key in obj) {
30
- filteredTests.push(key);
31
- }
32
-
33
- return filteredTests;
34
- },
35
-
36
- findStringMatches : function (type, file, data, testpath) {
37
- var match, regExp, prefix,
38
- basename = path.basename(file);
39
-
40
- // JavaScript/CoffeeScript/TypeScript files
41
- if ((/\.(js|coffee|ts)$/).test(basename)) {
42
- // Don't bother if we don't find a reference to Modernizr in the file...
43
- if (!(/Modernizr/im).test(data)) {
44
- return;
45
- }
46
- // Match usage such as: Modernizr.classname --or-- Modernizr['classname']
47
- regExp = new RegExp("(?:\\.|\\[(?:\"|'))(" + type + ")(?![\\w-])(?:(?:\"|')\\])?", "gm");
48
- }
49
- // If it's not script, assume it's CSS (or similar, e.g.: LESS, SCSS) files
50
- else {
51
- prefix = settings.classPrefix || '';
52
- // When no prefix, match usage such as: .classname --or-- .no-classname
53
- // When prefix set, match usage such as: .<prefix>classname --or-- .<prefix>no-classname
54
- regExp = new RegExp("(?:\\." + prefix + ")(?:no-)?(" + type + ")(?![\\w-])", "gm");
55
- }
56
- match = (regExp).exec(data);
57
-
58
- this.matchedTestsInFile[file] = this.matchedTestsInFile[file] || [];
59
-
60
- while (match) {
61
- var test = match[1];
62
-
63
- if (test) {
64
- this.stringMatches[testpath] = this.stringMatches[testpath] || [];
65
-
66
- if (this.stringMatches[testpath].indexOf(file) === -1) {
67
- this.stringMatches[testpath].push(file);
68
- }
69
-
70
- if (this.matchedTestsInFile[file].indexOf(test) === -1) {
71
- this.matchedTestsInFile[file].push(test);
72
- }
73
- }
74
-
75
- match = (regExp).exec(data);
76
- }
77
- },
78
-
79
- parseData : function (file, data, metadata) {
80
- data = data.toString();
81
- var testpath, test, type, value, i, j;
82
-
83
- for (test in metadata) {
84
- for (type in metadata[test]) {
85
- if (type === "name" || type === "path") {
86
- continue;
87
- }
88
-
89
- value = metadata[test][type];
90
- testpath = metadata[test].path;
91
-
92
- if (Array.isArray(value)) {
93
- for (i = 0, j = value.length; i < j; i++) {
94
- this.findStringMatches(value[i], file, data, testpath);
95
- }
96
- } else {
97
- this.findStringMatches(value, file, data, testpath);
98
- }
99
- }
100
- }
101
-
102
- var matchedTests = this.matchedTestsInFile[file];
103
-
104
- if (!settings.quiet && matchedTests && matchedTests.length) {
105
- utils.log.writeln();
106
-
107
- var testCount = matchedTests.length;
108
- var testText = " match" + (testCount > 1 ? "es" : "") + " in ";
109
-
110
- utils.log.ok(testCount.toString().green + testText + file);
111
- utils.log.ok(matchedTests.sort().join(", ").grey);
112
- }
113
- },
114
-
115
- readFile : function (file, metadata, deferred) {
116
- var stream = fs.createReadStream(file);
117
-
118
- stream.on("data", function (data) {
119
- this.parseData(file, data, metadata);
120
- }.bind(this));
121
-
122
- stream.on("end", function () {
123
- if ((++this.currentFile) === this.totalFiles) {
124
- return deferred.resolve();
125
- }
126
- }.bind(this));
127
- },
128
-
129
- readFilesAsync : function (files, metadata) {
130
- var deferred = new promise.Deferred(),
131
- i, j, last;
132
-
133
- this.currentFile = 0;
134
- this.totalFiles = files.length;
135
-
136
- for (i = 0, j = files.length; i < j; i++) {
137
- this.readFile(files[i], metadata, deferred);
138
- }
139
-
140
- return deferred.promise;
141
- },
142
-
143
- parseCodeFromBuffers : function (buffers, metadata) {
144
- var i, j, file;
145
-
146
- for (i = 0, j = buffers.length; i < j; i++) {
147
- file = buffers[i];
148
- this.parseData(file.path, String(file.contents), metadata);
149
- }
150
- },
151
-
152
- init : function (metadata) {
153
- // Cache utils
154
- utils = this.utils;
155
- settings = utils.getSettings();
156
-
157
- var _private = utils.getDefaults().private;
158
-
159
- var deferred = new promise.Deferred(),
160
- buildPath = path.join(modernizrPath, "build"),
161
- files;
162
-
163
- var tests = settings.tests.map(function (test) {
164
- var data = metadata.filter(function (data) {
165
- if (Array.isArray(test)) {
166
- return test.indexOf(data) !== -1 || _.isEqual(test, data.property);
167
- }
168
- return data.property === test;
169
- });
170
-
171
- return data[0] || {};
172
- }).filter(function (test) {
173
- return test.path;
174
- });
175
-
176
- if (!settings.quiet && tests && tests.length) {
177
- utils.log.writeln();
178
- utils.log.ok("Explicitly including these tests:");
179
- utils.log.ok(tests.map(function (test) {
180
- return test.property;
181
- }).sort().join(", ").grey);
182
- }
183
-
184
- var excludedTests = settings.excludeTests.map(function (test) {
185
- var data = metadata.filter(function (data) {
186
- if (Array.isArray(data.property)) {
187
- return data.property.indexOf(test) !== -1;
188
- } else {
189
- return data.property === test;
190
- }
191
- });
192
-
193
- return data[0] || {};
194
- }).filter(function (test) {
195
- return test.path;
196
- });
197
-
198
- if (!settings.quiet && excludedTests && excludedTests.length) {
199
- utils.log.writeln();
200
- utils.log.ok("Explicitly excluding these tests:");
201
- utils.log.ok(excludedTests.map(function (test) {
202
- return test.property;
203
- }).sort().join(", ").grey);
204
- }
205
-
206
- tests = tests.map(function (test) {
207
- return test.path;
208
- }).filter(function (test) {
209
- return excludedTests.map(function (test) {
210
- return test.path;
211
- }).indexOf(test) === -1;
212
- }).concat(settings.customTests.map(function (test) {
213
- return path.relative(buildPath, fs.realpathSync(test));
214
- }));
215
-
216
- metadata = metadata.filter(function (data) {
217
- return excludedTests.map(function (test) {
218
- return test.path;
219
- }).indexOf(data.path) === -1;
220
- });
221
-
222
- if (settings.crawl !== true && settings.useBuffers !== true) {
223
- tests = this.crawler.filterTests(tests);
224
-
225
- if (!settings.quiet) {
226
- utils.log.subhead("Skipping file traversal");
227
- }
228
-
229
- setTimeout(function () {
230
- return deferred.resolve(tests);
231
- }, 0);
232
-
233
- return deferred.promise;
234
- }
235
-
236
- if (!settings.quiet) {
237
- utils.log.subhead("Looking for Modernizr references");
238
- }
239
-
240
- // Support including code via string rather than reading a file.
241
- if (settings.useBuffers === true) {
242
- this.crawler.parseCodeFromBuffers(settings.files.src, metadata);
243
-
244
- for (var key in this.crawler.stringMatches) {
245
- tests.push(key);
246
- }
247
-
248
- tests = this.crawler.filterTests(tests);
249
-
250
- setTimeout(function () {
251
- return deferred.resolve(tests);
252
- });
253
-
254
- return deferred.promise;
255
- }
256
-
257
- // Exclude developer build
258
- if (settings.devFile !== "remote" && settings.devFile !== false) {
259
- if (!fs.existsSync(settings.devFile)) {
260
- utils.log.warn([
261
- "Can't find your Modernizr development build at " + settings.devFile,
262
- "this tool needs this path to avoid false positives",
263
- "",
264
- "Update your settings via the modernizr.devFile config option",
265
- "See %s#devfile-string for more details".replace("%s", _private.url.github),
266
- "",
267
- ""
268
- ].join("\n ").replace(/\s$/, ""));
269
- } else {
270
- settings.files.src.push("!" + settings.devFile);
271
- }
272
- }
273
-
274
- // Exclude generated file
275
- if (settings.dest) {
276
- settings.files.src.push("!" + settings.dest);
277
- }
278
-
279
- // And exclude all files in this current directory
280
- settings.files.src.push("!" + path.join(__dirname.replace(cwd + path.sep, ""), "**", "*"));
281
-
282
- files = utils.file.expand({
283
- filter: "isFile"
284
- }, settings.files.src);
285
-
286
- this.crawler.readFilesAsync(files, metadata).then(function () {
287
- for (var key in this.crawler.stringMatches) {
288
- tests.push(key);
289
- }
290
-
291
- tests = this.crawler.filterTests(tests);
292
- return deferred.resolve(tests);
293
- }.bind(this));
294
-
295
- return deferred.promise;
296
- }
297
- };
298
- };
1
+ module.exports = function (modernizrPath) {
2
+ "use strict";
3
+
4
+ var _ = require("lodash");
5
+
6
+ // Dependencies
7
+ var fs = require("fs"),
8
+ cwd = process.cwd(),
9
+ path = require("path");
10
+
11
+ // Deferreds
12
+ var promise = require("promised-io/promise");
13
+
14
+ // Cache utils
15
+ var utils, settings;
16
+
17
+ return {
18
+ matchedTestsInFile : {},
19
+ stringMatches : {},
20
+
21
+ filterTests : function (tests) {
22
+ var i, j, obj = {},
23
+ filteredTests = [];
24
+
25
+ for (i = 0, j = tests.length; i < j; i++) {
26
+ obj[tests[i]] = 0;
27
+ }
28
+
29
+ for (var key in obj) {
30
+ filteredTests.push(key);
31
+ }
32
+
33
+ return filteredTests;
34
+ },
35
+
36
+ findStringMatches : function (type, file, data, testpath) {
37
+ var match, regExp, prefix,
38
+ basename = path.basename(file);
39
+
40
+ // JavaScript/CoffeeScript/TypeScript files
41
+ if ((/\.(js|coffee|ts)$/).test(basename)) {
42
+ // Don't bother if we don't find a reference to Modernizr in the file...
43
+ if (!(/Modernizr/im).test(data)) {
44
+ return;
45
+ }
46
+ // Match usage such as: Modernizr.classname --or-- Modernizr['classname']
47
+ regExp = new RegExp("(?:\\.|\\[(?:\"|'))(" + type + ")(?![\\w-])(?:(?:\"|')\\])?", "gm");
48
+ }
49
+ // If it's not script, assume it's CSS (or similar, e.g.: LESS, SCSS) files
50
+ else {
51
+ prefix = settings.classPrefix || '';
52
+ // When no prefix, match usage such as: .classname --or-- .no-classname
53
+ // When prefix set, match usage such as: .<prefix>classname --or-- .<prefix>no-classname
54
+ regExp = new RegExp("(?:\\." + prefix + ")(?:no-)?(" + type + ")(?![\\w-])", "gm");
55
+ }
56
+ match = (regExp).exec(data);
57
+
58
+ this.matchedTestsInFile[file] = this.matchedTestsInFile[file] || [];
59
+
60
+ while (match) {
61
+ var test = match[1];
62
+
63
+ if (test) {
64
+ this.stringMatches[testpath] = this.stringMatches[testpath] || [];
65
+
66
+ if (this.stringMatches[testpath].indexOf(file) === -1) {
67
+ this.stringMatches[testpath].push(file);
68
+ }
69
+
70
+ if (this.matchedTestsInFile[file].indexOf(test) === -1) {
71
+ this.matchedTestsInFile[file].push(test);
72
+ }
73
+ }
74
+
75
+ match = (regExp).exec(data);
76
+ }
77
+ },
78
+
79
+ parseData : function (file, data, metadata) {
80
+ data = data.toString();
81
+ var testpath, test, type, value, i, j;
82
+
83
+ for (test in metadata) {
84
+ for (type in metadata[test]) {
85
+ if (type === "name" || type === "path") {
86
+ continue;
87
+ }
88
+
89
+ value = metadata[test][type];
90
+ testpath = metadata[test].path;
91
+
92
+ if (Array.isArray(value)) {
93
+ for (i = 0, j = value.length; i < j; i++) {
94
+ this.findStringMatches(value[i], file, data, testpath);
95
+ }
96
+ } else {
97
+ this.findStringMatches(value, file, data, testpath);
98
+ }
99
+ }
100
+ }
101
+
102
+ var matchedTests = this.matchedTestsInFile[file];
103
+
104
+ if (!settings.quiet && matchedTests && matchedTests.length) {
105
+ utils.log.writeln();
106
+
107
+ var testCount = matchedTests.length;
108
+ var testText = " match" + (testCount > 1 ? "es" : "") + " in ";
109
+
110
+ utils.log.ok(testCount.toString().green + testText + file);
111
+ utils.log.ok(matchedTests.sort().join(", ").grey);
112
+ }
113
+ },
114
+
115
+ readFile : function (file, metadata, deferred) {
116
+ var stream = fs.createReadStream(file);
117
+
118
+ stream.on("data", function (data) {
119
+ this.parseData(file, data, metadata);
120
+ }.bind(this));
121
+
122
+ stream.on("end", function () {
123
+ if ((++this.currentFile) === this.totalFiles) {
124
+ return deferred.resolve();
125
+ }
126
+ }.bind(this));
127
+ },
128
+
129
+ readFilesAsync : function (files, metadata) {
130
+ var deferred = new promise.Deferred(),
131
+ i, j, last;
132
+
133
+ this.currentFile = 0;
134
+ this.totalFiles = files.length;
135
+
136
+ for (i = 0, j = files.length; i < j; i++) {
137
+ this.readFile(files[i], metadata, deferred);
138
+ }
139
+
140
+ return deferred.promise;
141
+ },
142
+
143
+ parseCodeFromBuffers : function (buffers, metadata) {
144
+ var i, j, file;
145
+
146
+ for (i = 0, j = buffers.length; i < j; i++) {
147
+ file = buffers[i];
148
+ this.parseData(file.path, String(file.contents), metadata);
149
+ }
150
+ },
151
+
152
+ init : function (metadata) {
153
+ // Cache utils
154
+ utils = this.utils;
155
+ settings = utils.getSettings();
156
+
157
+ var _private = utils.getDefaults().private;
158
+
159
+ var deferred = new promise.Deferred(),
160
+ buildPath = path.join(modernizrPath, "build"),
161
+ files;
162
+
163
+ var tests = settings.tests.map(function (test) {
164
+ var data = metadata.filter(function (data) {
165
+ if (Array.isArray(test)) {
166
+ return test.indexOf(data) !== -1 || _.isEqual(test, data.property);
167
+ }
168
+ return data.property === test;
169
+ });
170
+
171
+ return data[0] || {};
172
+ }).filter(function (test) {
173
+ return test.path;
174
+ });
175
+
176
+ if (!settings.quiet && tests && tests.length) {
177
+ utils.log.writeln();
178
+ utils.log.ok("Explicitly including these tests:");
179
+ utils.log.ok(tests.map(function (test) {
180
+ return test.property;
181
+ }).sort().join(", ").grey);
182
+ }
183
+
184
+ var excludedTests = settings.excludeTests.map(function (test) {
185
+ var data = metadata.filter(function (data) {
186
+ if (Array.isArray(data.property)) {
187
+ return data.property.indexOf(test) !== -1;
188
+ } else {
189
+ return data.property === test;
190
+ }
191
+ });
192
+
193
+ return data[0] || {};
194
+ }).filter(function (test) {
195
+ return test.path;
196
+ });
197
+
198
+ if (!settings.quiet && excludedTests && excludedTests.length) {
199
+ utils.log.writeln();
200
+ utils.log.ok("Explicitly excluding these tests:");
201
+ utils.log.ok(excludedTests.map(function (test) {
202
+ return test.property;
203
+ }).sort().join(", ").grey);
204
+ }
205
+
206
+ tests = tests.map(function (test) {
207
+ return test.path;
208
+ }).filter(function (test) {
209
+ return excludedTests.map(function (test) {
210
+ return test.path;
211
+ }).indexOf(test) === -1;
212
+ }).concat(settings.customTests.map(function (test) {
213
+ return path.relative(buildPath, fs.realpathSync(test));
214
+ }));
215
+
216
+ metadata = metadata.filter(function (data) {
217
+ return excludedTests.map(function (test) {
218
+ return test.path;
219
+ }).indexOf(data.path) === -1;
220
+ });
221
+
222
+ if (settings.crawl !== true && settings.useBuffers !== true) {
223
+ tests = this.crawler.filterTests(tests);
224
+
225
+ if (!settings.quiet) {
226
+ utils.log.subhead("Skipping file traversal");
227
+ }
228
+
229
+ setTimeout(function () {
230
+ return deferred.resolve(tests);
231
+ }, 0);
232
+
233
+ return deferred.promise;
234
+ }
235
+
236
+ if (!settings.quiet) {
237
+ utils.log.subhead("Looking for Modernizr references");
238
+ }
239
+
240
+ // Support including code via string rather than reading a file.
241
+ if (settings.useBuffers === true) {
242
+ this.crawler.parseCodeFromBuffers(settings.files.src, metadata);
243
+
244
+ for (var key in this.crawler.stringMatches) {
245
+ tests.push(key);
246
+ }
247
+
248
+ tests = this.crawler.filterTests(tests);
249
+
250
+ setTimeout(function () {
251
+ return deferred.resolve(tests);
252
+ });
253
+
254
+ return deferred.promise;
255
+ }
256
+
257
+ // Exclude developer build
258
+ if (settings.devFile !== "remote" && settings.devFile !== false) {
259
+ if (!fs.existsSync(settings.devFile)) {
260
+ utils.log.warn([
261
+ "Can't find your Modernizr development build at " + settings.devFile,
262
+ "this tool needs this path to avoid false positives",
263
+ "",
264
+ "Update your settings via the modernizr.devFile config option",
265
+ "See %s#devfile-string for more details".replace("%s", _private.url.github),
266
+ "",
267
+ ""
268
+ ].join("\n ").replace(/\s$/, ""));
269
+ } else {
270
+ settings.files.src.push("!" + settings.devFile);
271
+ }
272
+ }
273
+
274
+ // Exclude generated file
275
+ if (settings.dest) {
276
+ settings.files.src.push("!" + settings.dest);
277
+ }
278
+
279
+ // And exclude all files in this current directory
280
+ settings.files.src.push("!" + path.join(__dirname.replace(cwd + path.sep, ""), "**", "*"));
281
+
282
+ files = utils.file.expand({
283
+ filter: "isFile"
284
+ }, settings.files.src);
285
+
286
+ this.crawler.readFilesAsync(files, metadata).then(function () {
287
+ for (var key in this.crawler.stringMatches) {
288
+ tests.push(key);
289
+ }
290
+
291
+ tests = this.crawler.filterTests(tests);
292
+ return deferred.resolve(tests);
293
+ }.bind(this));
294
+
295
+ return deferred.promise;
296
+ }
297
+ };
298
+ };