1 | var Path = require('path');
|
2 | var required = require('required');
|
3 | var fs = require('fs-extra');
|
4 | require('colors');
|
5 | var debugMode;
|
6 |
|
7 | var crypto = require('crypto');
|
8 |
|
9 | var modules;
|
10 | var index;
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 | function pushSet(arr, el) {
|
28 | arr = arr || [];
|
29 | if (arr.indexOf(el) === -1) arr.push(el);
|
30 | return arr;
|
31 | }
|
32 |
|
33 | function reset() {
|
34 | modules = [];
|
35 | index = 0;
|
36 | }
|
37 |
|
38 | function getList(module) {
|
39 |
|
40 |
|
41 | var path = [];
|
42 |
|
43 | function walk(module) {
|
44 | if (module.core) {
|
45 |
|
46 |
|
47 |
|
48 | modules[module.id] = module;
|
49 | return;
|
50 | }
|
51 | if (module.walked) return;
|
52 | modules[module.filename] = module;
|
53 | path.push(module.id);
|
54 | module.walked = true;
|
55 | module.index = -1;
|
56 | module.deps.forEach(function(d) {
|
57 | var dep_id = d.id;
|
58 | d = modules[d.filename] || d;
|
59 | d.requirers = pushSet(d.requirers, module.filename);
|
60 | d.ids = pushSet(d.ids, dep_id);
|
61 |
|
62 | walk(d);
|
63 | if (d.index < 0) {
|
64 | var str = "Module " + module.id + " is dependent on module " + d.id +
|
65 | '. However, module ' + d.id + ' is also directly or indirectly dependent on module ' +
|
66 | module.id + ".\nDependency path to this point: \n" + path.join(' relies on \n') +
|
67 | ' relies on ' + d.id;
|
68 | console.log(str.red);
|
69 | }
|
70 | });
|
71 | module.index = index++;
|
72 | path.pop();
|
73 | }
|
74 | walk(module);
|
75 | return modules;
|
76 | }
|
77 |
|
78 | function endsWith(str, trail) {
|
79 | return (str.substr(str.length-trail.length, str.length-1) === trail);
|
80 | };
|
81 |
|
82 | function trailWith(str, trail) {
|
83 | return str ? (str + (!endsWith(str, trail) ? trail : '')) : undefined;
|
84 | };
|
85 |
|
86 | function resolve(www, parent, id, cb, tags, isDebug) {
|
87 |
|
88 | debugMode = isDebug;
|
89 | try
|
90 | { www = Path.resolve(www);
|
91 | parent = Path.resolve(www, parent);
|
92 | console.log('Resolving: ' + id + ' in directory ' + parent);
|
93 | var fileName = Path.resolve(parent, trailWith(id, '.js'));
|
94 | try {
|
95 | fs.statSync(fileName);
|
96 | } catch(e) { cb(e,null);
|
97 | return;}
|
98 |
|
99 | required(fileName, {
|
100 | includeSource: false,
|
101 | ignoreMissing: function(name, parent) {
|
102 | var out = name + ' in ' + parent;
|
103 | console.log('Missing module:'.red.bold, out.yellow);
|
104 | }
|
105 |
|
106 | }, function(err, deps) {
|
107 | if (err) throw err;
|
108 | else {
|
109 | var modules = getList(
|
110 | { id: id,
|
111 | filename: fileName,
|
112 | deps: deps,
|
113 | index: -1
|
114 | }
|
115 | );
|
116 |
|
117 | var list = Object.keys(modules).map(function(m) {
|
118 | m = modules[m];
|
119 | if (m.core) {
|
120 | m.route = '_core_modules/' + m.id;
|
121 | }
|
122 | else {
|
123 | var startWithWwwPath = m.filename.indexOf(www) === 0;
|
124 | if (!startWithWwwPath) {
|
125 | var hash = crypto.createHash('md5').update(m.filename).digest('hex');
|
126 | m.route = '_node_modules/' + hash + '_' + Path.basename(m.filename);
|
127 | m.lib = true;
|
128 |
|
129 |
|
130 |
|
131 |
|
132 | }
|
133 | else m.route = m.filename.slice(www.length+1);
|
134 |
|
135 | m.deps = m.deps.map(function(d) { return d.id; });
|
136 | }
|
137 |
|
138 | delete m.id;
|
139 | return m;
|
140 | }).sort(function(a, b) {
|
141 | return a.index > b.index;
|
142 | }).map(function(m) {
|
143 | return !tags ?
|
144 | m :
|
145 |
|
146 | "<script type=\"text/javascript\" src=\"" + m.route + "\"></script>";
|
147 | });
|
148 |
|
149 | cb(null, list);
|
150 | }
|
151 | });
|
152 | } catch(e) {
|
153 | cb(e, null);
|
154 | }
|
155 | };
|
156 |
|
157 | function debug() {
|
158 | if (debugMode) console.log.apply(console, arguments);
|
159 | }
|
160 |
|
161 | module.exports = {
|
162 | resolve: resolve,
|
163 | reset: reset
|
164 |
|
165 | };
|
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
|
173 |
|