1 | var Core = function() {
|
2 |
|
3 | var registry = {}
|
4 | var seen = {}
|
5 | var helpers = {}
|
6 | var customRequireDepsHandler = {
|
7 | requireDeps: function (name, submodule, referrer) {
|
8 | return require(name, submodule, referrer)
|
9 | },
|
10 | catchErrors: function (err, name, referrer) {
|
11 | helpers.throwError('Could not find module ' + name + ' required by: ' + referrer)
|
12 | }
|
13 | }
|
14 |
|
15 | helpers.isArray = function(myArray) {
|
16 | return Object.prototype.toString.call(myArray).indexOf('Array') > -1;
|
17 | }
|
18 | helpers.isPlainObject = function(value) {
|
19 | return value && (value.constructor === Object || value.constructor === undefined);
|
20 | }
|
21 | helpers.unreferencePlainObjectsAndArrays = function(source) {
|
22 |
|
23 | if(helpers.isArray(source)) {
|
24 |
|
25 | var length = source.length;
|
26 | var unreferencedArray = [];
|
27 |
|
28 | for (var i = 0; i < length; i++) {
|
29 | unreferencedArray.push(helpers.unreferencePlainObjectsAndArrays(source[i]))
|
30 | }
|
31 |
|
32 | return unreferencedArray;
|
33 |
|
34 | } else if(helpers.isPlainObject(source)) {
|
35 |
|
36 | var name, s, empty = {}, dest = {};
|
37 |
|
38 | for(name in source) {
|
39 |
|
40 |
|
41 |
|
42 |
|
43 | s = source[name];
|
44 | if(!(name in dest) || (dest[name] !== s && (!(name in empty) || empty[name] !== s))) {
|
45 | dest[name] = helpers.unreferencePlainObjectsAndArrays(s);
|
46 | }
|
47 | }
|
48 |
|
49 |
|
50 | if(source.__esModule){
|
51 | dest.__esModule = source.__esModule;
|
52 | }
|
53 |
|
54 | return dest;
|
55 | }
|
56 |
|
57 | return source;
|
58 | }
|
59 | helpers.internalRequire = function(name) {
|
60 |
|
61 | if (seen[name]) {
|
62 | return seen[name];
|
63 | }
|
64 |
|
65 | if(!registry[name]) {
|
66 | helpers.throwError('Could not find module: ' + name)
|
67 | }
|
68 |
|
69 | var exports = {};
|
70 | var reified = helpers.getDependenciesValues(exports, name);
|
71 |
|
72 | registry[name].callback.apply(this, reified);
|
73 | seen[name] = exports
|
74 |
|
75 | return exports;
|
76 | }
|
77 | helpers.getDependenciesValues = function(exports, name) {
|
78 | var deps = registry[name].deps;
|
79 | var reified = [];
|
80 | var length = deps.length;
|
81 | var dep;
|
82 |
|
83 | for (var i = 0; i < length; i++) {
|
84 |
|
85 | if (deps[i] === 'exports') {
|
86 |
|
87 | reified.push(exports);
|
88 |
|
89 | } else {
|
90 | try {
|
91 |
|
92 | dep = customRequireDepsHandler.requireDeps(deps[i], null, name)
|
93 |
|
94 | reified.push(dep)
|
95 |
|
96 | } catch(err) {
|
97 | customRequireDepsHandler.catchErrors(err, deps[i], name)
|
98 | }
|
99 | }
|
100 |
|
101 | }
|
102 |
|
103 | return reified;
|
104 | }
|
105 | helpers.throwError = function(msg) {
|
106 | throw new Error(msg);
|
107 | }
|
108 |
|
109 | var define = function(name, deps, callback) {
|
110 |
|
111 | var value = {};
|
112 |
|
113 | if (!callback) {
|
114 |
|
115 | value.deps = [];
|
116 | value.callback = deps;
|
117 |
|
118 | } else {
|
119 |
|
120 | value.deps = deps;
|
121 | value.callback = callback;
|
122 |
|
123 | }
|
124 |
|
125 | if(registry[name]) {
|
126 | helpers.throwError('duplicatedModule ' + name);
|
127 | }
|
128 |
|
129 | registry[name] = value;
|
130 | }
|
131 |
|
132 | var require = function(name, submodule) {
|
133 | var module = helpers.internalRequire(name);
|
134 | var amd_package = submodule ? module[submodule] : module;
|
135 | var result = helpers.unreferencePlainObjectsAndArrays(amd_package);
|
136 |
|
137 | return result;
|
138 | }
|
139 |
|
140 | var list_entries = function(options) {
|
141 |
|
142 | var names = [];
|
143 | var moduleName;
|
144 | var regex = options && options.regex ? options.regex : '';
|
145 | var shouldAddModule;
|
146 |
|
147 | for (moduleName in registry) {
|
148 |
|
149 | shouldAddModule = (regex && moduleName.match(regex)) || !regex;
|
150 |
|
151 | if(shouldAddModule) {
|
152 |
|
153 | names.push(moduleName);
|
154 |
|
155 | }
|
156 |
|
157 | }
|
158 |
|
159 | return names;
|
160 |
|
161 | }
|
162 |
|
163 | var setCustomRequireDeps = function(handler){
|
164 | customRequireDepsHandler = handler
|
165 | }
|
166 |
|
167 | return {
|
168 | define: define,
|
169 | require: require,
|
170 | list_entries: list_entries,
|
171 | setCustomRequireDeps: setCustomRequireDeps
|
172 | }
|
173 | }
|
174 |
|
175 | var Errar = function() {
|
176 |
|
177 | this.errors = [];
|
178 | this.delimiter = '{{DELIMITER}}';
|
179 | this.stackDelimiter = '{{>>>}}';
|
180 | this.template = [
|
181 | '{{title}}',
|
182 | 'PLUGINS:',
|
183 | '{{plugins}}',
|
184 | 'STACKTRACE:',
|
185 | '{{stacktrace}}'
|
186 | ].join('\n');
|
187 |
|
188 | };
|
189 |
|
190 | Errar.prototype.hasErrors = function() {
|
191 | return !!this.errors.length;
|
192 | };
|
193 |
|
194 | Errar.prototype.add = function(obj) {
|
195 | this.errors.push(obj);
|
196 | };
|
197 |
|
198 | Errar.prototype.stringify = function() {
|
199 |
|
200 | var summary = this.summary();
|
201 | var template = this.template;
|
202 | var isArray = function(myArray) {return Object.prototype.toString.call(myArray).indexOf('Array') > -1;};
|
203 |
|
204 | for(var key in summary) {
|
205 | template = template.replace('{{' + key + '}}', isArray(summary[key]) ? summary[key].join('\n') : summary[key]);
|
206 | }
|
207 |
|
208 | return template;
|
209 | };
|
210 |
|
211 | Errar.prototype.submodulesStringify = function() {
|
212 |
|
213 | var hasDelimiter;
|
214 | var nestedErrors = '';
|
215 |
|
216 | for (var i = 0; i < this.errors.length; i++) {
|
217 |
|
218 | if(this.errors[i].content.indexOf(this.delimiter) > -1) {
|
219 | hasDelimiter = true;
|
220 | nestedErrors = this.errors[i].content;
|
221 | }
|
222 |
|
223 | }
|
224 |
|
225 | var moduleName = this.errors[0].name;
|
226 | var result = hasDelimiter ? moduleName + this.stackDelimiter + nestedErrors : this.delimiter + JSON.stringify(this.errors);
|
227 |
|
228 | return result;
|
229 | };
|
230 |
|
231 | Errar.prototype.summary = function() {
|
232 |
|
233 | if(!this.errors.length) {
|
234 |
|
235 | var defaultMessage = 'No errors available';
|
236 |
|
237 | return {
|
238 | title: defaultMessage,
|
239 | plugins: defaultMessage,
|
240 | stacktrace: defaultMessage
|
241 | };
|
242 | }
|
243 |
|
244 | var errors = this.getRelevantErrors();
|
245 |
|
246 | var result = {
|
247 | title: this.formatTitle(errors),
|
248 | plugins: this.formatPlugins(errors),
|
249 | stacktrace: this.parseStacktrace(errors)
|
250 | };
|
251 |
|
252 | return result;
|
253 | };
|
254 |
|
255 | Errar.prototype.getRelevantErrors = function() {
|
256 |
|
257 | var errors;
|
258 |
|
259 | for (var i = 0; i < this.errors.length; i++) {
|
260 |
|
261 | if(this.errors[i].content.indexOf(this.delimiter) > -1) {
|
262 | errors = JSON.parse(this.errors[i].content.split(this.delimiter)[1]);
|
263 | break;
|
264 | }
|
265 |
|
266 | }
|
267 |
|
268 | if(!errors) {
|
269 | errors = this.errors;
|
270 | }
|
271 |
|
272 | return errors;
|
273 | };
|
274 |
|
275 | Errar.prototype.formatTitle = function(errors) {
|
276 |
|
277 | var last_error = errors[errors.length - 1];
|
278 | var requiredBy = last_error.referrer ? ' required by ' + last_error.referrer : '';
|
279 | var result = 'Error at the module: ' + last_error.name + requiredBy;
|
280 |
|
281 | return result;
|
282 | };
|
283 |
|
284 | Errar.prototype.formatPlugins = function(errors) {
|
285 |
|
286 | var result = [];
|
287 |
|
288 | for (var i = 0; i < errors.length; i++) {
|
289 | result.push('(' + errors[i].plugin + ') ' + errors[i].content);
|
290 | }
|
291 |
|
292 | return result;
|
293 | };
|
294 |
|
295 | Errar.prototype.parseStacktrace = function(errors) {
|
296 |
|
297 | var first_module_from_trace = this.errors[0].name;
|
298 | var middle_stack = this.getMiddleStacktrace();
|
299 | var last_module_from_trace = errors[errors.length - 1].name;
|
300 |
|
301 | var result = [];
|
302 |
|
303 | for (var i = 0; i < middle_stack.length; i++) {
|
304 |
|
305 | if(middle_stack[i]) {
|
306 | result.push(middle_stack[i]);
|
307 | }
|
308 |
|
309 | }
|
310 |
|
311 | if(first_module_from_trace && first_module_from_trace !== result[0]) {
|
312 | result.splice(0, 0, first_module_from_trace);
|
313 | }
|
314 |
|
315 | if(last_module_from_trace && last_module_from_trace !== result[result.length - 1]) {
|
316 | result.push(last_module_from_trace);
|
317 | }
|
318 |
|
319 | return result.reverse();
|
320 | };
|
321 |
|
322 | Errar.prototype.getMiddleStacktrace = function() {
|
323 |
|
324 | var stacktrace = '';
|
325 |
|
326 | for (var i = 0; i < this.errors.length; i++) {
|
327 |
|
328 | if(this.errors[i].content.indexOf(this.delimiter) > -1) {
|
329 | stacktrace = this.errors[i].content.split(this.delimiter)[0];
|
330 | break;
|
331 | }
|
332 |
|
333 | }
|
334 |
|
335 | var result = stacktrace.length ? stacktrace.split(this.stackDelimiter) : [];
|
336 |
|
337 | return result;
|
338 | };
|
339 |
|
340 |
|
341 | var NMD = function() {
|
342 |
|
343 | var amd = new Core();
|
344 | var pipeline = ['default'];
|
345 | var PLUGINS_configs = {};
|
346 |
|
347 | var define = function(name, deps, callback) {
|
348 | amd.define(name, deps, callback);
|
349 | }
|
350 |
|
351 | var require = function(name, submodule, referrer) {
|
352 | |
353 |
|
354 |
|
355 |
|
356 |
|
357 | var result;
|
358 | var hasResult;
|
359 | var errorManager = new Errar();
|
360 |
|
361 | for (var i = 0; i < pipeline.length; i++) {
|
362 |
|
363 | try {
|
364 |
|
365 | if(!NMD_PLUGINS[pipeline[i]]) {
|
366 | throw new Error('Missing plugin definition for: ' + pipeline[i]);
|
367 | }
|
368 |
|
369 | result = NMD_PLUGINS[pipeline[i]].call(this, amd.require, PLUGINS_configs[pipeline[i]], name, submodule, referrer);
|
370 | hasResult = true;
|
371 |
|
372 | } catch(err) {
|
373 |
|
374 | errorManager.add({
|
375 | name: name,
|
376 | plugin: pipeline[i],
|
377 | submodule: submodule,
|
378 | referrer: referrer,
|
379 | content: err.message,
|
380 | stack: err.stack
|
381 | });
|
382 |
|
383 | continue;
|
384 | }
|
385 |
|
386 | break;
|
387 |
|
388 | }
|
389 |
|
390 | if(!hasResult) {
|
391 |
|
392 | throw new Error(referrer ? errorManager.submodulesStringify() : errorManager.stringify());
|
393 |
|
394 | }
|
395 |
|
396 | return result;
|
397 | }
|
398 |
|
399 | var catchErrors = function(err/*, name, referrer*/) {
|
400 | throw new Error(err.message);
|
401 | }
|
402 |
|
403 | amd.setCustomRequireDeps({requireDeps: require, catchErrors: catchErrors})
|
404 |
|
405 | return {
|
406 | define: define,
|
407 | require: require,
|
408 | list_entries: amd.list_entries,
|
409 | plugins: function(obj) {
|
410 |
|
411 | for (var name in obj) {
|
412 | PLUGINS_configs[name] = obj[name]
|
413 | }
|
414 |
|
415 | },
|
416 | pipeline: function(list) {
|
417 |
|
418 | if(list) {
|
419 | pipeline = list
|
420 | }
|
421 |
|
422 | return pipeline
|
423 |
|
424 | },
|
425 | version: '0.4.3'
|
426 | };
|
427 |
|
428 | };
|
429 |
|
430 | var NMD_PLUGINS = {}
|
431 |
|
432 | NMD_PLUGINS['default'] = function(amd_require, config, name, submodule, referrer) {
|
433 | return amd_require(name, submodule, referrer)
|
434 | }
|
435 |
|
436 | NMD_PLUGINS.shortcuts = function(amd_require, config, name, submodule) {
|
437 |
|
438 | var isShortcut = name.indexOf('@') === 0
|
439 |
|
440 | if(!isShortcut) {
|
441 | throw new Error(name + ' is not a shortcut')
|
442 | }
|
443 |
|
444 | var split = name.substring(1).split('/')
|
445 | var shortcut = {
|
446 | name: split[0],
|
447 | value: split.slice(1).join('/')
|
448 | }
|
449 | var result = amd_require(config[shortcut.name] + shortcut.value, submodule)
|
450 |
|
451 | return result
|
452 |
|
453 | }
|
454 |
|
455 | NMD_PLUGINS.defaultFile = function(amd_require, config, name, submodule) {
|
456 |
|
457 | var hasDelimiter = name.lastIndexOf('/') === (name.length - 1)
|
458 | var newModulePath = name + (hasDelimiter ? '' : '/') + config
|
459 |
|
460 | return amd_require(newModulePath, submodule)
|
461 |
|
462 | }
|
463 |
|
464 | NMD_PLUGINS.relativePaths = function(amd_require, config, name, submodule, referrer) {
|
465 |
|
466 | if (name.charAt(0) !== '.') {
|
467 | throw new Error(name + ' is not a relative path')
|
468 | }
|
469 |
|
470 | if(!config) {
|
471 | throw new Error('Relative paths are not allowed: ' + name)
|
472 | }
|
473 |
|
474 | var parts = name.split('/')
|
475 | var parentBase = referrer.split('/').slice(0, -1)
|
476 |
|
477 | for (var i = 0; i < parts.length; i++) {
|
478 |
|
479 | var part = parts[i];
|
480 |
|
481 | if (part === '..') {
|
482 |
|
483 | parentBase.pop();
|
484 |
|
485 | } else if (part === '.') {
|
486 |
|
487 | continue;
|
488 |
|
489 | } else {
|
490 |
|
491 | parentBase.push(part);
|
492 |
|
493 | }
|
494 |
|
495 | }
|
496 |
|
497 | var result = parentBase.join('/')
|
498 |
|
499 | return amd_require(result, submodule, referrer)
|
500 |
|
501 | }
|
502 |
|
503 | module.exports = NMD; |
\ | No newline at end of file |