Remove build from this repo to move to lodash-cli.

Former-commit-id: 0f9e802dd744a97494a10537442a28aae40dc72a
This commit is contained in:
John-David Dalton
2013-08-27 23:28:45 -07:00
parent c6e2e33e87
commit 8f9c4cd217
17 changed files with 9 additions and 7895 deletions

2
.gitignore vendored
View File

@@ -6,5 +6,3 @@
*.map
modularize
node_modules
vendor/closure-compiler
vendor/uglifyjs

View File

@@ -11,7 +11,6 @@ lodash.js
index.js
bower.json
component.json
build
doc
modularize
node_modules

View File

@@ -8,15 +8,12 @@ env:
- TEST_COMMAND="phantomjs ./test/test.js ../dist/lodash.compat.min.js"
- TEST_COMMAND="node ./test/test.js ../dist/lodash.js"
- TEST_COMMAND="node ./test/test.js ../dist/lodash.min.js"
- TEST_COMMAND="node ./test/test-build.js --time-limit 48m"
git:
depth: 1
branches:
only:
- master
before_script:
- "tar -xzvf vendor/closure-compiler.tar.gz -C vendor"
- "tar -xzvf vendor/uglifyjs.tar.gz -C vendor"
- "npm install -g istanbul"
script:
$TEST_COMMAND

View File

@@ -11,11 +11,9 @@
"*.map",
"*.md",
"*.txt",
"build.js",
"index.js",
"component.json",
"package.json",
"build",
"doc",
"node_modules",
"perf",

4563
build.js

File diff suppressed because it is too large Load Diff

View File

@@ -1,793 +0,0 @@
#!/usr/bin/env node
;(function() {
'use strict';
/** Load Node.js modules */
var cp = require('child_process'),
https = require('https'),
zlib = require('zlib');
/** Load other modules */
var _ = require('../lodash.js'),
preprocess = require('./pre-compile.js'),
postprocess = require('./post-compile.js'),
tar = require('../vendor/tar/tar.js'),
util = require('./util.js');
/** Module shortcuts */
var fs = util.fs,
path = util.path;
/** The Git object ID of `closure-compiler.tar.gz` */
var closureId = '9fd5d61c1b706e7505aeb5187941c2c5497e5fd8';
/** The Git object ID of `uglifyjs.tar.gz` */
var uglifyId = '7de2795a3af58d1b293e3b0e83cdbc994f4941dc';
/** The path of the directory that is the base of the repository */
var basePath = fs.realpathSync(path.join(__dirname, '..'));
/** The path of the `vendor` directory */
var vendorPath = path.join(basePath, 'vendor');
/** The path to the Closure Compiler `.jar` */
var closurePath = path.join(vendorPath, 'closure-compiler', 'compiler.jar');
/** The path to the UglifyJS module */
var uglifyPath = path.join(vendorPath, 'uglifyjs', 'tools', 'node.js');
/** The Closure Compiler command-line options */
var closureOptions = ['--warning_level=QUIET'];
/** The media type for raw blob data */
var mediaType = 'application/vnd.github.v3.raw';
/** Used to detect the Node.js executable in command-line arguments */
var reNode = RegExp('(?:^|' + path.sepEscaped + ')node(?:\\.exe)?$', 'i');
/** Used to reference parts of the blob href */
var location = (function() {
var host = 'api.github.com',
origin = 'https://api.github.com',
pathname = '/repos/bestiejs/lodash/git/blobs';
return {
'host': host,
'href': origin + pathname,
'origin': origin,
'pathname': pathname
};
}());
/** The Closure Compiler optimization modes */
var optimizationModes = {
'simple': 'SIMPLE_OPTIMIZATIONS',
'advanced': 'ADVANCED_OPTIMIZATIONS'
};
/*--------------------------------------------------------------------------*/
/**
* Minifies a given Lo-Dash `source` and invokes the `options.onComplete`
* callback when finished. The `onComplete` callback is invoked with one
* argument; (outputSource).
*
* @param {string|string[]} [source=''] The source to minify or array of commands.
* -o, --output - Write output to a given path/filename.
* -s, --silent - Skip status updates normally logged to the console.
* -t, --template - Applies template specific minifier options.
*
* @param {Object} [options={}] The options object.
* @param {string} [options.outputPath] Write output to a given path/filename.
* @param {boolean} [options.isSilent] Skip status updates normally logged to the console.
* @param {boolean} [options.isTemplate] Applies template specific minifier options.
* @param {Function} [options.onComplete] The function called once minification has finished.
*/
function minify(source, options) {
// used to specify the source map URL
var sourceMapURL;
// used to specify the default minifer modes
var modes = ['simple', 'advanced', 'hybrid'];
source || (source = '');
options || (options = {});
// juggle arguments
if (Array.isArray(source)) {
// convert commands to an options object
options = source;
// used to report invalid command-line arguments
var invalidArgs = _.reject(options.slice(reNode.test(options[0]) ? 2 : 0), function(value, index, options) {
if (/^(?:-o|--output)$/.test(options[index - 1]) ||
/^modes=.*$/.test(value)) {
return true;
}
var result = [
'-o', '--output',
'-p', '--source-map',
'-s', '--silent',
'-t', '--template'
].indexOf(value) > -1;
if (!result && /^(?:-p|--source-map)$/.test(options[index - 1])) {
result = true;
sourceMapURL = value;
}
return result;
});
// report invalid arguments
if (invalidArgs.length) {
console.log(
'\n' +
'Invalid argument' + (invalidArgs.length > 1 ? 's' : '') +
' passed: ' + invalidArgs.join(', ')
);
return;
}
var filePath = options[options.length - 1],
isMapped = _.contains(options, '-p') || _.contains(options, '--source-map'),
isSilent = _.contains(options, '-s') || _.contains(options, '--silent'),
isTemplate = _.contains(options, '-t') || _.contains(options, '--template'),
outputPath = path.join(path.dirname(filePath), path.basename(filePath, '.js') + '.min.js');
modes = options.reduce(function(result, value) {
var match = value.match(/modes=(.*)$/);
return match ? match[1].split(/, */) : result;
}, modes);
outputPath = options.reduce(function(result, value, index) {
if (/-o|--output/.test(value)) {
result = options[index + 1];
var dirname = path.dirname(result);
fs.mkdirpSync(dirname);
result = path.join(fs.realpathSync(dirname), path.basename(result));
}
return result;
}, outputPath);
options = {
'filePath': filePath,
'isMapped': isMapped,
'isSilent': isSilent,
'isTemplate': isTemplate,
'modes': modes,
'outputPath': outputPath,
'sourceMapURL': sourceMapURL
};
source = fs.readFileSync(filePath, 'utf8');
}
modes = options.modes || modes;
if (options.isMapped) {
modes = modes.filter(function(mode) {
return mode != 'hybrid';
});
}
if (options.isTemplate) {
modes = modes.filter(function(mode) {
return mode != 'advanced';
});
}
options.modes = modes;
// fetch the Closure Compiler
getDependency({
'id': 'closure-compiler',
'hashId': closureId,
'path': vendorPath,
'title': 'the Closure Compiler',
'onComplete': function(exception) {
var error = exception;
// fetch UglifyJS
getDependency({
'id': 'uglifyjs',
'hashId': uglifyId,
'title': 'UglifyJS',
'path': vendorPath,
'onComplete': function(exception) {
error || (error = exception);
if (!error) {
new Minify(source, options);
}
}
});
}
});
}
/**
* The Minify constructor used to keep state of each `minify` invocation.
*
* @private
* @constructor
* @param {string} source The source to minify.
* @param {Object} options The options object.
* outputPath - Write output to a given path/filename.
* isSilent - Skip status updates normally logged to the console.
* isTemplate - Applies template specific minifier options.
* onComplete - The function called once minification has finished.
*/
function Minify(source, options) {
// juggle arguments
if (typeof source == 'object' && source) {
options = source || options;
source = options.source || '';
}
this.compiled = { 'simple': {}, 'advanced': {} };
this.hybrid = { 'simple': {}, 'advanced': {} };
this.uglified = {};
this.filePath = options.filePath;
this.isMapped = !!options.isMapped;
this.isSilent = !!options.isSilent;
this.isTemplate = !!options.isTemplate;
this.outputPath = options.outputPath;
this.sourceMapURL = options.sourceMapURL;
var modes = this.modes = options.modes;
source = this.source = preprocess(source, options);
this.onComplete = options.onComplete || function(data) {
var outputPath = this.outputPath,
sourceMap = data.sourceMap;
fs.writeFileSync(outputPath, data.source, 'utf8');
if (sourceMap) {
fs.writeFileSync(getMapPath(outputPath), sourceMap, 'utf8');
}
};
// begin the minification process
if (_.contains(modes, 'simple')) {
closureCompile.call(this, source, 'simple', onClosureSimpleCompile.bind(this));
} else if (_.contains(modes, 'advanced')) {
onClosureSimpleGzip.call(this);
} else {
onClosureAdvancedGzip.call(this);
}
}
/*--------------------------------------------------------------------------*/
/**
* Fetches a required `.tar.gz` dependency with the given Git object ID from
* the Lo-Dash repo on GitHub. The object ID may be obtained by running
* `git hash-object path/to/dependency.tar.gz`.
*
* @private
* @param {Object} options The options object.
* id - The Git object ID of the `.tar.gz` file.
* onComplete - The function called once the extraction has finished.
* path - The path of the extraction directory.
* title - The dependency's title used in status updates logged to the console.
*/
function getDependency(options) {
options || (options = {});
var ran,
destPath = options.path,
hashId = options.hashId,
id = options.id,
onComplete = options.onComplete,
title = options.title;
// exit early if dependency exists
if (fs.existsSync(path.join(destPath, id))) {
onComplete();
return;
}
var callback = function(exception) {
if (ran) {
return;
}
if (exception) {
console.error([
'There was a problem installing ' + title + '.',
'Try running the command as root, via `sudo`, or manually install by running:',
'',
"curl -H 'Accept: " + mediaType + "' " + location.href + '/' + hashId + " | tar xvz -C '" + destPath + "'",
''
].join('\n'));
}
ran = true;
process.removeListener('uncaughtException', callback);
onComplete(exception);
};
console.log('Downloading ' + title + '...');
process.on('uncaughtException', callback);
https.get({
'host': location.host,
'path': location.pathname + '/' + hashId,
'headers': {
// By default, all GitHub blob API endpoints return a JSON document
// containing Base64-encoded blob data. Overriding the `Accept` header
// with the GitHub raw media type returns the blob data directly.
// See http://developer.github.com/v3/media/.
'Accept': mediaType,
// As of 2013-04-24, the GitHub API mandates the `User-Agent` header
// for all requests.
'User-Agent': 'Lo-Dash/' + _.VERSION
}
}, function(response) {
var decompressor = zlib.createUnzip(),
parser = new tar.Extract({ 'path': destPath });
parser.on('end', callback);
response.pipe(decompressor).pipe(parser);
});
}
/**
* Retrieves the Java command-line options used for faster minification by
* the Closure Compiler, invoking the `callback` when finished. Subsequent
* calls will lazily return the previously retrieved options. The `callback`
* is invoked with one argument; (options).
*
* See https://code.google.com/p/closure-compiler/wiki/FAQ#What_are_the_recommended_Java_VM_command-line_options?.
*
* @private
* @param {Function} callback The function called once the options have been retrieved.
*/
function getJavaOptions(callback) {
var result = [];
cp.exec('java -version -client -d32', function(error) {
if (!error && process.platform != 'win32') {
result.push('-client', '-d32');
}
getJavaOptions = function(callback) {
_.defer(callback, result);
};
callback(result);
});
}
/**
* Resolves the source map path from the given output path.
*
* @private
* @param {string} outputPath The output path.
* @returns {string} Returns the source map path.
*/
function getMapPath(outputPath) {
return path.join(path.dirname(outputPath), path.basename(outputPath, '.js') + '.map');
}
/*--------------------------------------------------------------------------*/
/**
* Compresses a `source` string using the Closure Compiler. Yields the
* minified result, and any exceptions encountered, to a `callback` function.
*
* @private
* @param {string} source The JavaScript source to minify.
* @param {string} mode The optimization mode.
* @param {Function} callback The function called once the process has completed.
*/
function closureCompile(source, mode, callback) {
var filePath = this.filePath,
isAdvanced = mode == 'advanced',
isMapped = this.isMapped,
isSilent = this.isSilent,
isTemplate = this.isTemplate,
options = closureOptions.slice(),
outputPath = this.outputPath,
mapPath = getMapPath(outputPath),
sourceMapURL = this.sourceMapURL || path.basename(mapPath);
// remove copyright header to make other modifications easier
var license = (/^(?:\s*\/\/.*\s*|\s*\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\s*)*/.exec(source) || [''])[0];
if (license) {
source = source.replace(license, '');
}
var hasIIFE = /^;?\(function[^{]+{/.test(source),
isStrict = hasIIFE && /^;?\(function[^{]+{\s*["']use strict["']/.test(source);
// to avoid stripping the IIFE, convert it to a function call
if (hasIIFE && isAdvanced) {
source = source
.replace(/\(function/, '__iife__$&')
.replace(/\(this\)\)([\s;]*(\n\/\/.+)?)$/, ', this)$1');
}
options.push('--compilation_level=' + optimizationModes[mode]);
if (isMapped) {
options.push('--create_source_map=' + mapPath, '--source_map_format=V3');
}
if (isTemplate) {
options.push('--charset=UTF-8');
}
getJavaOptions(function(javaOptions) {
var compiler = cp.spawn('java', javaOptions.concat('-jar', closurePath, options));
if (!isSilent) {
console.log('Compressing ' + path.basename(outputPath, '.js') + ' using the Closure Compiler (' + mode + ')...');
}
var error = '';
compiler.stderr.on('data', function(data) {
error += data;
});
var output = '';
compiler.stdout.on('data', function(data) {
output += data;
});
compiler.on('exit', function(status) {
// `status` contains the process exit code
if (status) {
var exception = new Error(error);
exception.status = status;
}
// restore IIFE and move exposed vars inside the IIFE
if (hasIIFE && isAdvanced) {
output = output
.replace(/__iife__\(/, '(')
.replace(/,\s*this\)([\s;]*(\n\/\/.+)?)$/, '(this))$1')
.replace(/^((?:var (?:\w+=(?:!0|!1|null)[,;])+)?)([\s\S]*?function[^{]+{)/, '$2$1');
}
// inject "use strict" directive
if (isStrict) {
output = output.replace(/^[\s\S]*?function[^{]+{/, '$&"use strict";');
}
// restore copyright header
if (license) {
output = license + output;
}
if (isMapped) {
var mapOutput = fs.readFileSync(mapPath, 'utf8');
fs.unlinkSync(mapPath);
output = output.replace(/[\s;]*$/, '\n//# sourceMappingURL=' + sourceMapURL);
mapOutput = JSON.parse(mapOutput);
mapOutput.file = path.basename(outputPath);
mapOutput.sources = [path.basename(filePath)];
mapOutput = JSON.stringify(mapOutput, null, 2);
}
callback(exception, output, mapOutput);
});
// proxy the standard input to the Closure Compiler
compiler.stdin.end(source);
});
}
/**
* Compresses a `source` string using UglifyJS. Yields the result to a
* `callback` function. This function is synchronous; the `callback` is used
* for symmetry.
*
* @private
* @param {string} source The JavaScript source to minify.
* @param {string} label The label to log.
* @param {Function} callback The function called once the process has completed.
*/
function uglify(source, label, callback) {
if (!this.isSilent) {
console.log('Compressing ' + path.basename(this.outputPath, '.js') + ' using ' + label + '...');
}
try {
var uglifyJS = require(uglifyPath);
// 1. parse
var toplevel = uglifyJS.parse(source);
// 2. compress
// enable unsafe comparisons
toplevel.figure_out_scope();
toplevel = toplevel.transform(uglifyJS.Compressor({
'comparisons': false,
'unsafe': true,
'unsafe_comps': true,
'warnings': false
}));
// 3. mangle
// excluding the `define` function exposed by AMD loaders
toplevel.figure_out_scope();
toplevel.compute_char_frequency();
toplevel.mangle_names({
'except': ['define']
});
// 4. output
// restrict lines to 500 characters for consistency with the Closure Compiler
var stream = uglifyJS.OutputStream({
'ascii_only': !this.isTemplate,
'comments': /^!|@cc_on|@license|@preserve/i,
'max_line_len': 500,
});
toplevel.print(stream);
}
catch(e) {
var exception = e;
}
callback(exception, stream && String(stream));
}
/*--------------------------------------------------------------------------*/
/**
* The Closure Compiler callback for simple optimizations.
*
* @private
* @param {Object} [exception] The error object.
* @param {string} result The resulting minified source.
* @param {string} map The source map output.
*/
function onClosureSimpleCompile(exception, result, map) {
if (exception) {
throw exception;
}
result = postprocess(result);
var simple = this.compiled.simple;
simple.source = result;
simple.sourceMap = map;
zlib.gzip(result, onClosureSimpleGzip.bind(this));
}
/**
* The Closure Compiler `gzip` callback for simple optimizations.
*
* @private
* @param {Object} [exception] The error object.
* @param {Buffer} result The resulting gzipped source.
*/
function onClosureSimpleGzip(exception, result) {
if (exception) {
throw exception;
}
if (result != null) {
if (!this.isSilent) {
console.log('Done. Size: %d bytes.', result.length);
}
this.compiled.simple.gzip = result;
}
// compile the source using advanced optimizations
if (_.contains(this.modes, 'advanced')) {
closureCompile.call(this, this.source, 'advanced', onClosureAdvancedCompile.bind(this));
} else {
onClosureAdvancedGzip.call(this);
}
}
/**
* The Closure Compiler callback for advanced optimizations.
*
* @private
* @param {Object} [exception] The error object.
* @param {string} result The resulting minified source.
* @param {string} map The source map output.
*/
function onClosureAdvancedCompile(exception, result, map) {
if (exception) {
throw exception;
}
result = postprocess(result);
var advanced = this.compiled.advanced;
advanced.source = result;
advanced.sourceMap = map;
zlib.gzip(result, onClosureAdvancedGzip.bind(this));
}
/**
* The Closure Compiler `gzip` callback for advanced optimizations.
*
* @private
* @param {Object} [exception] The error object.
* @param {Buffer} result The resulting gzipped source.
*/
function onClosureAdvancedGzip(exception, result) {
if (exception) {
throw exception;
}
if (result != null) {
if (!this.isSilent) {
console.log('Done. Size: %d bytes.', result.length);
}
this.compiled.advanced.gzip = result;
}
// minify the source using UglifyJS
if (!this.isMapped) {
uglify.call(this, this.source, 'UglifyJS', onUglify.bind(this));
} else {
onComplete.call(this);
}
}
/**
* The UglifyJS callback.
*
* @private
* @param {Object} [exception] The error object.
* @param {string} result The resulting minified source.
*/
function onUglify(exception, result) {
if (exception) {
throw exception;
}
result = postprocess(result);
this.uglified.source = result;
zlib.gzip(result, onUglifyGzip.bind(this));
}
/**
* The UglifyJS `gzip` callback.
*
* @private
* @param {Object} [exception] The error object.
* @param {Buffer} result The resulting gzipped source.
*/
function onUglifyGzip(exception, result) {
if (exception) {
throw exception;
}
if (result != null) {
if (!this.isSilent) {
console.log('Done. Size: %d bytes.', result.length);
}
this.uglified.gzip = result;
}
// minify the already Closure Compiler simple optimized source using UglifyJS
var modes = this.modes;
if (_.contains(modes, 'hybrid')) {
if (_.contains(modes, 'simple')) {
uglify.call(this, this.compiled.simple.source, 'hybrid (simple)', onSimpleHybrid.bind(this));
} else if (_.contains(modes, 'advanced')) {
onSimpleHybridGzip.call(this);
}
} else {
onComplete.call(this);
}
}
/**
* The hybrid callback for simple optimizations.
*
* @private
* @param {Object} [exception] The error object.
* @param {string} result The resulting minified source.
*/
function onSimpleHybrid(exception, result) {
if (exception) {
throw exception;
}
result = postprocess(result);
this.hybrid.simple.source = result;
zlib.gzip(result, onSimpleHybridGzip.bind(this));
}
/**
* The hybrid `gzip` callback for simple optimizations.
*
* @private
* @param {Object} [exception] The error object.
* @param {Buffer} result The resulting gzipped source.
*/
function onSimpleHybridGzip(exception, result) {
if (exception) {
throw exception;
}
if (result != null) {
if (!this.isSilent) {
console.log('Done. Size: %d bytes.', result.length);
}
this.hybrid.simple.gzip = result;
}
// minify the already Closure Compiler advance optimized source using UglifyJS
if (_.contains(this.modes, 'advanced')) {
uglify.call(this, this.compiled.advanced.source, 'hybrid (advanced)', onAdvancedHybrid.bind(this));
} else {
onComplete.call(this);
}
}
/**
* The hybrid callback for advanced optimizations.
*
* @private
* @param {Object} [exception] The error object.
* @param {string} result The resulting minified source.
*/
function onAdvancedHybrid(exception, result) {
if (exception) {
throw exception;
}
result = postprocess(result);
this.hybrid.advanced.source = result;
zlib.gzip(result, onAdvancedHybridGzip.bind(this));
}
/**
* The hybrid `gzip` callback for advanced optimizations.
*
* @private
* @param {Object} [exception] The error object.
* @param {Buffer} result The resulting gzipped source.
*/
function onAdvancedHybridGzip(exception, result) {
if (exception) {
throw exception;
}
if (result != null) {
if (!this.isSilent) {
console.log('Done. Size: %d bytes.', result.length);
}
this.hybrid.advanced.gzip = result;
}
// finish by choosing the smallest compressed file
onComplete.call(this);
}
/**
* The callback executed after the source is minified and gzipped.
*
* @private
*/
function onComplete() {
var compiledSimple = this.compiled.simple,
compiledAdvanced = this.compiled.advanced,
uglified = this.uglified,
hybridSimple = this.hybrid.simple,
hybridAdvanced = this.hybrid.advanced;
var objects = [
compiledSimple,
compiledAdvanced,
uglified,
hybridSimple,
hybridAdvanced
];
var gzips = objects
.map(function(data) { return data.gzip; })
.filter(Boolean);
// select the smallest gzipped file and use its minified counterpart as the
// official minified release (ties go to the Closure Compiler)
var min = gzips.reduce(function(min, gzip) {
var length = gzip.length;
return min > length ? length : min;
}, Infinity);
// pass the minified source to the "onComplete" callback
objects.some(function(data) {
var gzip = data.gzip;
if (gzip && gzip.length == min) {
data.outputPath = this.outputPath;
this.onComplete(data);
return true;
}
}, this);
}
/*--------------------------------------------------------------------------*/
// expose `minify`
if (module != require.main) {
module.exports = minify;
}
else {
// read the Lo-Dash source file from the first argument if the script
// was invoked directly (e.g. `node minify.js source.js`) and write to
// `<filename>.min.js`
(function() {
var options = process.argv;
if (options.length < 3) {
return;
}
minify(options);
}());
}
}());

View File

@@ -1,117 +0,0 @@
#!/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');
}());
}
}());

View File

@@ -1,461 +0,0 @@
#!/usr/bin/env node
;(function() {
'use strict';
/** The Node.js filesystem module */
var fs = require('fs');
/** Used to minify variables embedded in compiled strings */
var compiledVars = [
'args',
'argsIndex',
'argsLength',
'baseCreateCallback',
'callback',
'className',
'collection',
'conditions',
'ctor',
'errorClass',
'errorProto',
'guard',
'hasOwnProperty',
'index',
'indicatorObject',
'isArguments',
'isArray',
'isProto',
'isString',
'iterable',
'length',
'keys',
'lodash',
'nonEnum',
'nonEnumProps',
'object',
'objectProto',
'objectTypes',
'ownIndex',
'ownProps',
'result',
'skipErrorProps',
'skipProto',
'source',
'stringClass',
'stringProto',
'thisArg',
'toString'
];
/** Used to minify `iteratorTemplate` data properties */
var iteratorOptions = [
'args',
'array',
'bottom',
'firstArg',
'init',
'keys',
'loop',
'shadowedProps',
'top',
'useHas'
];
/** Used to minify variables and string values to a single character */
var minNames = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');
minNames.push.apply(minNames, minNames.map(function(value) {
return value + value;
}));
/** Used to protect the specified properties from getting minified */
var propWhitelist = [
'Array',
'Boolean',
'Date',
'Error',
'Function',
'Math',
'Number',
'Object',
'RegExp',
'String',
'TypeError',
'VERSION',
'_',
'__bindData__',
'__chain__',
'__wrapped__',
'after',
'all',
'amd',
'any',
'argsClass',
'argsObject',
'array',
'assign',
'at',
'attachEvent',
'bind',
'bindAll',
'bindKey',
'cache',
'chain',
'clearTimeout',
'clone',
'cloneDeep',
'collect',
'compact',
'compose',
'configurable',
'contains',
'countBy',
'createCallback',
'criteria',
'curry',
'debounce',
'defaults',
'defer',
'delay',
'detect',
'difference',
'drop',
'each',
'enumerable',
'enumErrorProps',
'enumPrototypes',
'environment',
'escape',
'evaluate',
'every',
'exports',
'extend',
'fastBind',
'fastKeys',
'filter',
'find',
'findIndex',
'findKey',
'findLast',
'findLastIndex',
'findLastKey',
'findWhere',
'first',
'flatten',
'foldl',
'foldr',
'forEach',
'forEachRight',
'forIn',
'forInRight',
'forOwn',
'forOwnRight',
'function',
'functions',
'global',
'groupBy',
'has',
'head',
'identity',
'imports',
'include',
'index',
'indexBy',
'indexOf',
'initial',
'inject',
'interpolate',
'intersection',
'invert',
'invoke',
'isArguments',
'isArray',
'isBoolean',
'isDate',
'isElement',
'isEmpty',
'isEqual',
'isEqual',
'isFinite',
'isFinite',
'isFunction',
'isNaN',
'isNull',
'isNumber',
'isObject',
'isPlainObject',
'isRegExp',
'isString',
'isUndefined',
'keys',
'last',
'lastIndexOf',
'leading',
'map',
'max',
'maxWait',
'memoize',
'merge',
'methods',
'min',
'mixin',
'name',
'noConflict',
'nodeClass',
'nonEnumArgs',
'nonEnumShadows',
'now',
'null',
'number',
'object',
'omit',
'once',
'ownLast',
'pairs',
'parseInt',
'partial',
'partialRight',
'pick',
'pluck',
'pull',
'random',
'range',
'reduce',
'reduceRight',
'reject',
'remove',
'rest',
'result',
'runInContext',
'sample',
'select',
'setImmediate',
'setTimeout',
'shuffle',
'size',
'some',
'sortBy',
'sortedIndex',
'source',
'spliceObjects',
'string',
'support',
'tail',
'take',
'tap',
'template',
'templateSettings',
'throttle',
'times',
'toArray',
'trailing',
'transform',
'undefined',
'unescape',
'unindexedChars',
'union',
'uniq',
'unique',
'uniqueId',
'unzip',
'value',
'values',
'variable',
'where',
'window',
'without',
'wrap',
'writable',
'zip',
'zipObject'
];
/*--------------------------------------------------------------------------*/
/**
* Pre-process a given Lo-Dash `source`, preparing it for minification.
*
* @param {string} [source=''] The source to process.
* @param {Object} [options={}] The options object.
* @returns {string} Returns the processed source.
*/
function preprocess(source, options) {
source || (source = '');
options || (options = {});
// remove unrecognized JSDoc tags so the Closure Compiler won't complain
source = source.replace(/@(?:alias|category)\b.*/g, '');
if (options.isTemplate) {
return source;
}
// remove whitespace from string literals
source = source.replace(/^((?:[ "'\w]+:)? *)"[^"\n\\]*?(?:\\.[^"\n\\]*?)*"|'[^'\n\\]*?(?:\\.[^'\n\\]*?)*'/gm, function(string, left) {
// clip after an object literal property name or leading spaces
if (left) {
string = string.slice(left.length);
}
// avoids removing the '\n' of the `stringEscapes` object
string = string.replace(/\[object |delete |else (?!{)|function | in | instanceof |return\s+[\w"']|throw |typeof |use strict|var |@ |(["'])\\n\1|\\\\n|\\n|\s+/g, function(match) {
return match == false || match == '\\n' ? '' : match;
});
// unclip
return (left || '') + string;
});
// remove whitespace from `_.template` related regexes
source = source.replace(/reEmptyString\w+ *=.+/g, function(match) {
return match.replace(/ |\\n/g, '');
});
// remove newline from double-quoted strings in `_.template`
source = source
.replace('"__p += \'"', '"__p+=\'"')
.replace('"\';\n"', '"\';"')
// remove debug sourceURL use in `_.template`
source = source.replace(/(?:\s*\/\/.*\n)* *var sourceURL[^;]+;|\+ *sourceURL/g, '');
// minify internal properties
(function() {
var funcNames = [
'cacheIndexOf',
'cachePush',
'compareAscending',
'createCache',
'getObject',
'releaseObject',
'sortBy'
];
var props = [
'cache',
'criteria',
'index',
'value'
];
// minify other properties used in functions
var snippets = source.match(RegExp('^( *)(?:var|function) +(?:' + funcNames.join('|') + ')\\b[\\s\\S]+?\\n\\1}', 'gm'));
if (!snippets) {
return;
}
snippets.forEach(function(snippet) {
var modified = snippet;
props.forEach(function(prop, index) {
// use minified names different than those chosen for `iteratorOptions`
var minName = minNames[iteratorOptions.length + index],
reBracketProp = RegExp("\\['(" + prop + ")'\\]", 'g'),
reDotProp = RegExp('\\.' + prop + '\\b', 'g'),
rePropColon = RegExp("([^?\\s])\\s*([\"'])?\\b" + prop + "\\2 *:", 'g');
modified = modified
.replace(reBracketProp, "['" + minName + "']")
.replace(reDotProp, "['" + minName + "']")
.replace(rePropColon, "$1'" + minName + "':");
});
// replace with modified snippet
source = source.replace(snippet, function() {
return modified;
});
});
}());
// minify all compilable snippets
var snippets = source.match(
RegExp([
// match the `iteratorTemplate`
'^( *)var iteratorTemplate\\b[\\s\\S]+?\\n\\1}',
// match methods created by `createIterator` calls
'createIterator\\((?:{|[a-zA-Z]+)[\\s\\S]*?\\);\\n',
// match variables storing `createIterator` options
'^( *)var [a-zA-Z]+IteratorOptions\\b[\\s\\S]+?\\n\\2}',
// match `baseUniq`, `cachePush`, `createCache`, `createIterator`, `getObject`, and `releaseObject` functions
'^( *)(?:var|function) +(?:baseUniq|cachePush|createCache|createIterator|getObject|releaseObject)\\b[\\s\\S]+?\\n\\3}'
].join('|'), 'gm')
) || [];
snippets.forEach(function(snippet, index) {
var isFunc = /\bfunction *[ \w]*\(/.test(snippet),
isIteratorTemplate = /var iteratorTemplate\b/.test(snippet),
modified = snippet;
// remove unnecessary semicolons in strings
modified = modified.replace(/;(?:}["']|(?:\\n|\s)*["']\s*\+\s*["'](?:\\n|\s)*})/g, function(match) {
return match.slice(1);
});
// minify snippet variables / arguments
compiledVars.forEach(function(varName, index) {
var minName = minNames[index];
modified = modified.replace(/(["'])(?:(?!\1)[^\n\\]|\\.)*\1/g, function(match) {
return match.replace(RegExp('([^.])\\b' + varName + '\\b', 'g'), '$1' + minName);
});
// correct `typeof` string values
if (/^(?:boolean|function|object|number|string|undefined)$/.test(varName)) {
modified = modified.replace(RegExp('(= *)(["\'])' + minName + '\\2|(["\'])' + minName + '\\3( *=)', 'g'), function(match, prelude, preQuote, postQuote, postlude) {
return prelude
? prelude + preQuote + varName + preQuote
: postQuote + varName + postQuote + postlude;
});
}
});
// minify `createIterator` option property names
iteratorOptions.forEach(function(property, index) {
var minName = minNames[index];
// minify iterator option variables
modified = modified.replace(/(["'])(?:(?!\1)[^\n\\]|\\.)*\1/g, function(match, quote) {
return match.replace(RegExp('([^.])\\b' + property + '\\b', 'g'), '$1' + minName)
});
// minify iterator option properties, adding brackets so the Closure Compiler won't mung them
modified = modified.replace(RegExp('(["\'])(?:(?!\\1)[^\\n\\\\]|\\\\.)*\\1|\\.' + property + '\\b', 'g'), function(match, quote) {
return quote ? match : "['" + minName + "']";
});
});
// replace with modified snippet
source = source.replace(snippet, function() {
return modified;
});
});
// add brackets to whitelisted properties so the Closure Compiler won't mung them
// http://code.google.com/closure/compiler/docs/api-tutorial3.html#export
source = source.replace(RegExp('(["\'])(?:(?!\\1)[^\\n\\\\]|\\\\.)*\\1|\\.(' + propWhitelist.join('|') + ')\\b', 'g'), function(match, quote, prop) {
return quote ? match : "['" + prop + "']";
});
return source;
}
/*--------------------------------------------------------------------------*/
// expose `preprocess`
if (module != require.main) {
module.exports = preprocess;
}
else {
// read the Lo-Dash source file from the first argument if the script
// was invoked directly (e.g. `node pre-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],
isTemplate = options.indexOf('-t') > -1 || options.indexOf('--template') > -1,
source = fs.readFileSync(filePath, 'utf8');
fs.writeFileSync(filePath, preprocess(source, {
'isTemplate': isTemplate
}), 'utf8');
}());
}
}());

View File

@@ -1,98 +0,0 @@
#!/usr/bin/env node
;(function() {
'use strict';
/** Load Node.js modules */
var fs = require('fs'),
path = require('path');
/** Load other modules */
var _ = require('../lodash.js');
/** Used to indicate if running in Windows */
var isWindows = process.platform == 'win32';
/*--------------------------------------------------------------------------*/
/**
* The path separator.
*
* @memberOf util.path
* @type string
*/
var sep = path.sep || (isWindows ? '\\' : '/');
/**
* The escaped path separator used for inclusion in RegExp strings.
*
* @memberOf util.path
* @type string
*/
var sepEscaped = sep.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
/** Used to determine if a path is prefixed with a drive letter, dot, or slash */
var rePrefixed = RegExp('^(?:' + (isWindows ? '[a-zA-Z]:|' : '') + '\\.?)' + sepEscaped);
/*--------------------------------------------------------------------------*/
/**
* Makes the given `dirname` directory, without throwing errors for existing
* directories and making parent directories as needed.
*
* @memberOf util.fs
* @param {string} dirname The path of the directory.
* @param {number|string} [mode='0777'] The permission mode.
*/
function mkdirpSync(dirname, mode) {
// ensure relative paths are prefixed with `./`
if (!rePrefixed.test(dirname)) {
dirname = '.' + sep + dirname;
}
dirname.split(sep).reduce(function(currPath, segment) {
currPath += sep + segment;
try {
currPath = fs.realpathSync(currPath);
} catch(e) {
fs.mkdirSync(currPath, mode);
}
return currPath;
});
}
/*--------------------------------------------------------------------------*/
/**
* The utility object.
*
* @type Object
*/
var util = {
/**
* The file system object.
*
* @memberOf util
* @type Object
*/
'fs': _.defaults(_.cloneDeep(fs), {
'existsSync': fs.existsSync || path.existsSync,
'mkdirpSync': mkdirpSync
}),
/**
* The path object.
*
* @memberOf util
* @type Object
*/
'path': _.defaults(_.cloneDeep(path), {
'sep': sep,
'sepEscaped': sepEscaped
})
};
/*--------------------------------------------------------------------------*/
// expose
module.exports = util;
}());

View File

@@ -2,7 +2,7 @@
"name": "lodash",
"repo": "bestiejs/lodash",
"version": "1.3.1",
"description": "A low-level utility library delivering consistency, customization, performance, and extra features.",
"description": "A utility library delivering consistency, customization, performance, and extras.",
"license": "MIT",
"scripts": [
"index.js",

View File

@@ -43,18 +43,21 @@
"type": "git",
"url": "https://github.com/bestiejs/lodash.git"
},
"bin": {
"lodash": "./build.js"
},
"engines": [
"node",
"rhino"
],
"files": [
"build.js",
"LICENSE.txt",
"dist/lodash.js",
"dist/lodash.min.js",
"dist/lodash.backbone.js",
"dist/lodash.backbone.min.js",
"dist/lodash.compat.js",
"dist/lodash.compat.min.js",
"dist/lodash.legacy.js",
"dist/lodash.legacy.min.js",
"dist/lodash.mobile.js",
"dist/lodash.mobile.min.js",
"dist/lodash.underscore.js",
"dist/lodash.underscore.min.js"
],
@@ -75,12 +78,10 @@
"*.map",
"*.md",
"*.txt",
"build.js",
"lodash.js",
"index.js",
"bower.json",
"component.json",
"build",
"doc",
"modularize",
"node_modules",

View File

@@ -9,10 +9,6 @@ done
echo "Testing in node..."
node test.js ../dist/lodash.js && node test.js ../dist/lodash.min.js
echo ""
echo "Testing build..."
node test-build.js
echo ""
echo "Testing in a browser..."
open index.html

View File

@@ -1,3 +0,0 @@
<ul>
<% _.forEach(people, function(name) { %><li><%- name %></li><% }); %>
</ul>

View File

@@ -1 +0,0 @@
<% print("Hello " + epithet); %>.

View File

@@ -1 +0,0 @@
Hello ${ name }!

View File

@@ -1 +0,0 @@
Hallå {{ name }}!

File diff suppressed because it is too large Load Diff