UNPKG

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