mirror of
https://github.com/whoisclebs/lodash.git
synced 2026-01-29 06:27:49 +00:00
118 lines
4.3 KiB
JavaScript
118 lines
4.3 KiB
JavaScript
#!/usr/bin/env node
|
|
;(function() {
|
|
'use strict';
|
|
|
|
/** Load Node.js modules */
|
|
var fs = require('fs'),
|
|
vm = require('vm');
|
|
|
|
/** The minimal license/copyright template */
|
|
var licenseTemplate = [
|
|
'/**',
|
|
' * @license',
|
|
' * Lo-Dash <%= VERSION %> lodash.com/license | Underscore.js 1.5.1 underscorejs.org/LICENSE',
|
|
' */'
|
|
].join('\n');
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
/**
|
|
* Post-process a given minified Lo-Dash `source`, preparing it for
|
|
* deployment.
|
|
*
|
|
* @param {string} source The source to process.
|
|
* @returns {string} Returns the processed source.
|
|
*/
|
|
function postprocess(source) {
|
|
// correct overly aggressive Closure Compiler advanced optimization
|
|
source = source
|
|
.replace(/(document[^&]+&&)\s*(?:\w+|!\d)/, '$1!({toString:0}+"")')
|
|
.replace(/"\t"/g, '"\\t"')
|
|
.replace(/"[^"]*?\\f[^"]*?"/g,
|
|
'" \\t\\x0B\\f\\xa0\\ufeff' +
|
|
'\\n\\r\\u2028\\u2029' +
|
|
'\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000"'
|
|
);
|
|
|
|
try {
|
|
var context = vm.createContext({});
|
|
vm.runInContext(source, context);
|
|
} catch(e) { }
|
|
|
|
['forEach', 'forIn', 'forOwn'].forEach(function(methodName) {
|
|
var pairs = /[!=]==\s*([a-zA-Z]+)(?!\()|([a-zA-Z]+)\s*[!=]==/.exec((context._ || {})[methodName]),
|
|
varName = pairs && (pairs[1] || pairs[2]),
|
|
value = (value = varName && RegExp('\\b' + varName + '\\s*=\\s*!([01])\\b').exec(source)) && !+value[1];
|
|
|
|
if (typeof value == 'boolean') {
|
|
// replace vars for `false` and `true` with boolean literals
|
|
source = source.replace(RegExp('([!=]==\\s*)' + varName + '\\b(?!\\()|\\b' + varName + '(\\s*[!=]==)', 'g'), function(match, prelude, postlude, at) {
|
|
// avoid replacing local variables with the same name
|
|
return RegExp('\\b' + varName + '\\s*(?:,|=[^=])').test(source.slice(at - 10, at))
|
|
? match
|
|
: (prelude || '') + value + (postlude || '');
|
|
});
|
|
}
|
|
});
|
|
|
|
// replace `!1` and `!0` in expressions with `false` and `true` values
|
|
[/([!=]==)\s*!1\b|(.)!1\s*([!=]==)/g, /([!=]==)\s*!0\b|(.)!0\s*([!=]==)/g].forEach(function(regexp, index) {
|
|
source = source.replace(regexp, function(match, prelude, chr, postlude) {
|
|
return (prelude || chr + (/\w/.test(chr) ? ' ' : '')) + !!index + (postlude || '');
|
|
});
|
|
});
|
|
|
|
// flip `typeof` expressions to help optimize Safari and
|
|
// correct the AMD module definition for AMD build optimizers
|
|
// (e.g. from `"number" == typeof x` to `typeof x == "number")
|
|
source = source.replace(/(\w)?("[^"]+")\s*([!=]=)\s*(typeof(?:\s*\([^)]+\)|\s+[.\w]+(?!\[)))/g, function(match, other, type, equality, expression) {
|
|
return (other ? other + ' ' : '') + expression + equality + type;
|
|
});
|
|
|
|
// add a space so `define` is detected by the Dojo builder
|
|
source = source.replace(/(.)(define\()/, function(match, prelude, define) {
|
|
return prelude + (/^\S/.test(prelude) ? ' ' : '') + define;
|
|
});
|
|
|
|
// add trailing semicolon
|
|
if (source) {
|
|
source = source.replace(/[\s;]*?(\s*\/\/.*\s*|\s*\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\s*)*$/, ';$1');
|
|
}
|
|
// exit early if version snippet isn't found
|
|
var snippet = /VERSION\s*[=:]\s*([\'"])(.*?)\1/.exec(source);
|
|
if (!snippet) {
|
|
return source;
|
|
}
|
|
// remove copyright header
|
|
source = source.replace(/^\/\**[\s\S]+?\*\/\n/, '');
|
|
|
|
// add new copyright header
|
|
var version = snippet[2];
|
|
source = licenseTemplate.replace('<%= VERSION %>', version) + '\n;' + source;
|
|
|
|
return source;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
|
|
// expose `postprocess`
|
|
if (module != require.main) {
|
|
module.exports = postprocess;
|
|
}
|
|
else {
|
|
// read the Lo-Dash source file from the first argument if the script
|
|
// was invoked directly (e.g. `node post-compile.js source.js`) and write to
|
|
// the same file
|
|
(function() {
|
|
var options = process.argv;
|
|
if (options.length < 3) {
|
|
return;
|
|
}
|
|
var filePath = options[options.length - 1],
|
|
source = fs.readFileSync(filePath, 'utf8');
|
|
|
|
fs.writeFileSync(filePath, postprocess(source), 'utf8');
|
|
}());
|
|
}
|
|
}());
|