1 | var through = require('through');
|
2 | var estraverse = require('estraverse');
|
3 | var esprima = require('esprima');
|
4 | var path = require('path');
|
5 | var minimatch = require('minimatch');
|
6 | var typeName = require('type-name');
|
7 |
|
8 | function debug() {
|
9 | if (process.env.DEBUG) { console.log.apply(console, arguments); }
|
10 | }
|
11 |
|
12 | function isDynamicModule(moduleName, options) {
|
13 | if (options.targetModules) {
|
14 | if (moduleName[0] === ".") {
|
15 | moduleName = path.resolve(path.dirname(options.file), moduleName);
|
16 | moduleName = "./" + path.relative(options.baseDir, moduleName);
|
17 | }
|
18 | var patterns = options.targetModules;
|
19 | patterns = typeName(patterns) === 'Array' ? patterns : [ patterns ];
|
20 | for (var i=0, len=patterns.length; i<len; i++) {
|
21 | var pattern = patterns[i];
|
22 | debug("**** pattern : ", pattern, " => module : ", moduleName, "*****");
|
23 | if (/[\*\?\!\{\}]/.test(pattern) ? minimatch(moduleName, pattern) : moduleName === pattern) {
|
24 | debug(" <<< matched >>> ");
|
25 | return true;
|
26 | }
|
27 | }
|
28 | } else {
|
29 | return true;
|
30 | }
|
31 | }
|
32 |
|
33 | function fixModulePath(moduleName, options) {
|
34 | if (moduleName[0] === ".") {
|
35 | moduleName = path.resolve(path.dirname(options.file), moduleName);
|
36 | moduleName = "./" + path.relative(options.baseDir, moduleName);
|
37 | }
|
38 | return moduleName;
|
39 | }
|
40 |
|
41 | function swapRequire(code, newRequireName, options) {
|
42 | var chunks = [], start = 0;
|
43 | var ast = esprima.parse(code, { range: true });
|
44 | estraverse.traverse(ast, {
|
45 | enter: function(node, parent, parent2) {
|
46 | if (parent && parent.type === 'CallExpression' &&
|
47 | node.type === 'Identifier' && node.name === 'require' &&
|
48 | parent.arguments.length === 1 && parent.arguments[0].type === 'Literal') {
|
49 | var moduleName = parent.arguments[0].value;
|
50 | if (isDynamicModule(moduleName, options)) {
|
51 | console.log(moduleName, ' is dynamic');
|
52 | chunks.push(code.substring(start, parent.range[0]));
|
53 | chunks.push(newRequireName + "('" + fixModulePath(moduleName, options) + "')");
|
54 | start = parent.range[1];
|
55 | } else {
|
56 | console.log(moduleName, ' is not dynamic');
|
57 | }
|
58 | }
|
59 | }
|
60 | });
|
61 | chunks.push(code.substring(start));
|
62 | return chunks.join('');
|
63 | }
|
64 |
|
65 | function swap(file, options) {
|
66 | if (/\.json$/.test(file)) {
|
67 | return through();
|
68 | }
|
69 | var swappingTo = options.fn || 'dynRequire';
|
70 | var chunks = [];
|
71 | var stream = through(write, end);
|
72 | function write(chunk, enc) {
|
73 | chunks.push(chunk.toString(enc));
|
74 | }
|
75 | function end() {
|
76 | var code = chunks.join('');
|
77 | try {
|
78 | code = swapRequire(code, swappingTo, {
|
79 | baseDir: options.baseDir || process.cwd(),
|
80 | targetModules: options.module || options.modules,
|
81 | file: file
|
82 | });
|
83 | } catch(e) {
|
84 | stream.emit('error', e);
|
85 | }
|
86 | stream.queue(code);
|
87 | stream.queue(null);
|
88 | }
|
89 | return stream;
|
90 | }
|
91 |
|
92 | module.exports = swap;
|