You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
85 lines
2.4 KiB
JavaScript
85 lines
2.4 KiB
JavaScript
7 years ago
|
var through = require('through');
|
||
|
var rfile = require('rfile');
|
||
|
var templateSTR = rfile('./template.js');
|
||
|
var uglify = require('uglify-js');
|
||
|
function template(moduleName, cjs) {
|
||
|
var str = uglify.minify(
|
||
|
templateSTR.replace(/\{\{defineNamespace\}\}/g, compileNamespace(moduleName)),
|
||
|
{fromString: true}).code
|
||
|
.split('source()')
|
||
|
str[0] = str[0].trim();
|
||
|
//make sure these are undefined so as to not get confused if modules have inner UMD systems
|
||
|
str[0] += 'var define,module,exports;';
|
||
|
if (cjs) str[0] += 'module={exports:(exports={})};';
|
||
|
str[0] += '\n';
|
||
|
if (cjs) str[1] = 'return module.exports;' + str[1];
|
||
|
str[1] = '\n' + str[1];
|
||
|
return str;
|
||
|
}
|
||
|
|
||
|
exports = module.exports = function (name, cjs, src) {
|
||
|
if (typeof cjs === 'string') {
|
||
|
var tmp = cjs;
|
||
|
cjs = src;
|
||
|
src = tmp;
|
||
|
}
|
||
|
if (src) {
|
||
|
return exports.prelude(name, cjs) + src + exports.postlude(name, cjs);
|
||
|
} else {
|
||
|
var strm = through(write, end);
|
||
|
var first = true;
|
||
|
function write(chunk) {
|
||
|
if (first) strm.queue(exports.prelude(name, cjs));
|
||
|
first = false;
|
||
|
strm.queue(chunk);
|
||
|
}
|
||
|
function end() {
|
||
|
if (first) strm.queue(exports.prelude(name, cjs));
|
||
|
strm.queue(exports.postlude(name, cjs));
|
||
|
strm.queue(null);
|
||
|
}
|
||
|
return strm;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
exports.prelude = function (moduleName, cjs) {
|
||
|
return template(moduleName, cjs)[0];
|
||
|
};
|
||
|
exports.postlude = function (moduleName, cjs) {
|
||
|
return template(moduleName, cjs)[1];
|
||
|
};
|
||
|
|
||
|
|
||
|
function camelCase(name) {
|
||
|
name = name.replace(/\-([a-z])/g, function (_, char) { return char.toUpperCase(); });
|
||
|
return name.replace(/[^a-zA-Z0-9]+/g, '')
|
||
|
}
|
||
|
|
||
|
|
||
|
function compileNamespace(name) {
|
||
|
var names = name.split('.')
|
||
|
|
||
|
// No namespaces, yield the best case 'global.NAME = VALUE'
|
||
|
if (names.length === 1) {
|
||
|
return 'g.' + camelCase(name) + ' = f()';
|
||
|
|
||
|
// Acceptable case, with reasonable compilation
|
||
|
} else if (names.length === 2) {
|
||
|
names = names.map(camelCase);
|
||
|
return '(g.' + names[0] + ' || (g.' + names[0] + ' = {})).' + names[1] + ' = f()';
|
||
|
|
||
|
// Worst case, too many namespaces to care about
|
||
|
} else {
|
||
|
var valueContainer = names.pop()
|
||
|
return names.reduce(compileNamespaceStep, ['var ref$ = g'])
|
||
|
.concat(['ref$.' + camelCase(valueContainer) + ' = f()'])
|
||
|
.join(';\n ');
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function compileNamespaceStep(code, name, i, names) {
|
||
|
name = camelCase(name);
|
||
|
code.push('ref$ = (ref$.' + name + ' || (ref$.' + name + ' = {}))')
|
||
|
return code
|
||
|
}
|