Update build to add _.chain and _#chain for backbone and underscore builds.

Former-commit-id: 2c910de419904a1285d246a3b08d87cb4daafa18
This commit is contained in:
John-David Dalton
2012-12-08 18:46:09 -08:00
parent a451861bf1
commit cf5e5dbe55
3 changed files with 176 additions and 73 deletions

171
build.js
View File

@@ -70,7 +70,6 @@
'bind': ['isFunction', 'isObject'],
'bindAll': ['bind', 'functions'],
'bindKey': ['isFunction', 'isObject'],
'chain': ['mixin'],
'clone': ['assign', 'forEach', 'forOwn', 'isArray', 'isObject'],
'compact': [],
'compose': [],
@@ -159,7 +158,10 @@
'where': ['filter', 'keys'],
'without': ['indexOf'],
'wrap': [],
'zip': ['max', 'pluck']
'zip': ['max', 'pluck'],
// method used by the `backbone` and `underscore` builds
'chain': ['mixin']
};
/** Used to inline `iteratorTemplate` */
@@ -1175,7 +1177,117 @@
source = replaceVar(source, 'noArgsClass', 'true');
source = removeKeysOptimization(source);
}
else if (isUnderscore) {
// add Underscore's chaining API
if (isBackbone || isUnderscore) {
// add `_.chain`
source = source.replace(matchFunction(source, 'tap'), function(match) {
return [
'',
' /**',
' * Creates a `lodash` object that wraps the given `value`.',
' *',
' * @static',
' * @memberOf _',
' * @category Chaining',
' * @param {Mixed} value The value to wrap.',
' * @returns {Object} Returns the wrapper object.',
' * @example',
' *',
' * var stooges = [',
" * { 'name': 'moe', 'age': 40 },",
" * { 'name': 'larry', 'age': 50 },",
" * { 'name': 'curly', 'age': 60 }",
' * ];',
' *',
' * var youngest = _.chain(stooges)',
' * .sortBy(function(stooge) { return stooge.age; })',
" * .map(function(stooge) { return stooge.name + ' is ' + stooge.age; })",
' * .first();',
" * // => 'moe is 40'",
' */',
' function chain(value) {',
' value = new lodash(value);',
' value.__chain__ = true;',
' return value;',
' }',
'',
match
].join('\n');
});
// add `wrapperChain`
source = source.replace(matchFunction(source, 'wrapperToString'), function(match) {
return [
'',
' /**',
' * Enables method chaining on the wrapper object.',
' *',
' * @name chain',
' * @memberOf _',
' * @category Chaining',
' * @returns {Mixed} Returns the wrapper object.',
' * @example',
' *',
' * var sum = _([1, 2, 3])',
' * .chain()',
' * .reduce(function(sum, num) { return sum + num; })',
' * .value()',
' * // => 6`',
' */',
' function wrapperChain() {',
' this.__chain__ = true;',
' return this;',
' }',
'',
match
].join('\n');
});
// add `__chain__` checks to `_.mixin` and `Array` function wrappers
_.each([
matchFunction(source, 'mixin'),
/(?:\s*\/\/.*)*\n( *)forEach\(\['[\s\S]+?\n\1}.+/g
], function(pattern) {
source = source.replace(pattern, function(match) {
return match.replace(/( *)return new lodash\(([^)]+)\).+/, function(submatch, indent, varName) {
return indent + [
'if (this.__chain__) {',
' varName = new lodash(varName);',
' varName.__chain__ = true;',
'}',
'return varName;'
].join('\n' + indent)
.replace(/varName/g, varName);
});
});
});
// add `lodash.chain` assignment
source = source.replace(getMethodAssignments(source), function(match) {
return match.replace(/^(?: *\/\*[^*]*\*+(?:[^\/][^*]*\*+)*\/\n)?( *)lodash\.VERSION *=/m, '$1lodash.chain = chain;\n\n$&');
});
// add `lodash.prototype.chain` assignment
source = source.replace(/^( *)lodash\.prototype\.value *=.+\n/m, '$1lodash.prototype.chain = wrapperChain;\n$&');
// remove `lodash.prototype.toString` and `lodash.prototype.valueOf` assignments
source = source.replace(/^ *lodash\.prototype\.(?:toString|valueOf) *=.+\n/gm, '');
// remove `lodash.prototype` batch method assignments
source = source.replace(/(?:\s*\/\/.*)*\n( *)forOwn\(lodash, *function\(func, *methodName\)[\s\S]+?\n\1}.+/g, '');
// move `mixin(lodash)` to after the method assignments
source = source.replace(/(?:\s*\/\/.*)*\s*mixin\(lodash\).+/, '');
source = source.replace(getMethodAssignments(source), function(match) {
return match + [
'',
'',
' // add functions to `lodash.prototype`',
' mixin(lodash);'
].join('\n');
});
}
if (isUnderscore) {
// remove unneeded variables
source = removeVar(source, 'cloneableClasses');
source = removeVar(source, 'ctorByClass');
@@ -1202,15 +1314,6 @@
' }'
].join('\n'));
// replace `_.chain`
source = replaceFunction(source, 'chain', [
' function chain(value) {',
' value = new lodash(value);',
' value.__chain__ = true;',
' return value;',
' }'
].join('\n'));
// replace `_.clone`
if (useUnderscoreClone) {
source = replaceFunction(source, 'clone', [
@@ -1460,33 +1563,6 @@
' }'
].join('\n'));
// replace `wrapperChain`
source = replaceFunction(source, 'wrapperChain', [
' function wrapperChain() {',
' this.__chain__ = true;',
' return this;',
' }'
].join('\n'));
// add `__chain__` checks to `_.mixin` and `Array` function wrappers
_.each([
matchFunction(source, 'mixin'),
/(?:\s*\/\/.*)*\n( *)forEach\(\['[\s\S]+?\n\1}.+/g
], function(pattern) {
source = source.replace(pattern, function(match) {
return match.replace(/( *)return new lodash\(([^)]+)\).+/, function(submatch, indent, varName) {
return indent + [
'if (this.__chain__) {',
' varName = new lodash(varName);',
' varName.__chain__ = true;',
'}',
'return varName;'
].join('\n' + indent)
.replace(/varName/g, varName);
});
});
});
// remove `arguments` object check from `_.isEqual`
source = source.replace(matchFunction(source, 'isEqual'), function(match) {
return match.replace(/^ *if *\(.+== argsClass[^}]+}\n/gm, '')
@@ -1499,23 +1575,6 @@
});
});
// remove `lodash.prototype.toString` and `lodash.prototype.valueOf` assignments
source = source.replace(/^ *lodash\.prototype\.(?:toString|valueOf) *=.+\n/gm, '');
// remove `lodash.prototype` batch method assignments
source = source.replace(/(?:\s*\/\/.*)*\n( *)forOwn\(lodash, *function\(func, *methodName\)[\s\S]+?\n\1}.+/g, '');
// move `mixin(lodash)` to after the method assignments
source = source.replace(/(?:\s*\/\/.*)*\s*mixin\(lodash\).+/, '');
source = source.replace(getMethodAssignments(source), function(match) {
return match + [
'',
'',
' // add functions to `lodash.prototype`',
' mixin(lodash);'
].join('\n');
});
// remove unused features from `createBound`
if (buildMethods.indexOf('partial') == -1) {
source = source.replace(matchFunction(source, 'createBound'), function(match) {

View File

@@ -68,7 +68,6 @@
'bind',
'bindAll',
'bindKey',
'chain',
'clone',
'collect',
'compact',
@@ -188,8 +187,9 @@
'wrap',
'zip',
// property used by the `lodash underscore` build
// properties used by the `backbone` and `underscore` builds
'__chain__',
'chain',
// properties used by underscore.js
'_chain',

View File

@@ -54,9 +54,9 @@
};
/** List of all Lo-Dash methods */
var allMethods = _.functions(_).filter(function(methodName) {
return !/^_/.test(methodName);
});
var allMethods = _.functions(_)
.filter(function(methodName) { return !/^_/.test(methodName); })
.concat('chain');
/** List of "Arrays" category methods */
var arraysMethods = [
@@ -86,7 +86,6 @@
/** List of "Chaining" category methods */
var chainingMethods = [
'chain',
'mixin',
'tap',
'value'
@@ -498,7 +497,12 @@
});
});
['', 'moduleId=underscore'].forEach(function(command) {
var commands = [
'',
'moduleId=underscore'
];
commands.forEach(function(command) {
asyncTest('`lodash template=*.jst` exports=amd' + (command ? ' ' + command : ''), function() {
var start = _.after(2, _.once(QUnit.start));
@@ -637,6 +641,44 @@
/*--------------------------------------------------------------------------*/
QUnit.module('underscore chaining methods');
(function() {
var commands = [
'backbone',
'underscore'
];
commands.forEach(function(command) {
asyncTest('`lodash ' + command +'`', function() {
var start = _.after(2, _.once(QUnit.start));
build(['-s', command], function(source, filePath) {
var basename = path.basename(filePath, '.js'),
context = createContext();
vm.runInContext(source, context);
var lodash = context._;
ok(lodash.chain(1) instanceof lodash, '_.chain: ' + basename);
ok(lodash(1).chain() instanceof lodash, '_#chain: ' + basename);
var wrapped = lodash(1);
equal(wrapped.clone() instanceof lodash, false, '_(...) wrapped values are not chainable by default: ' + basename);
equal(String(wrapped) === '1', false, '_#toString should not be implemented: ' + basename);
equal(Number(wrapped) === 1 , false, '_#valueOf should not be implemented: ' + basename);
wrapped.chain();
equal(wrapped.has('x') instanceof lodash, true, '_#has returns wrapped values when chaining: ' + basename);
start();
});
});
});
}());
/*--------------------------------------------------------------------------*/
QUnit.module('underscore modifier');
(function() {
@@ -701,14 +743,6 @@
equal(lodash.template('${a}', object), '${a}', '_.template should ignore ES6 delimiters: ' + basename);
equal(lodash.uniqueId(0), '1', '_.uniqueId should ignore a prefix of `0`: ' + basename);
var wrapped = lodash(1);
equal(wrapped.clone() instanceof lodash, false, '_(...) wrapped values are not chainable by default: ' + basename);
equal(String(wrapped) === '1', false, '_#toString should not be implemented: ' + basename);
equal(Number(wrapped) === 1 , false, '_#valueOf should not be implemented: ' + basename);
wrapped.chain();
equal(wrapped.has('x') instanceof lodash, true, '_#has returns wrapped values when chaining: ' + basename);
start();
});
});
@@ -877,7 +911,12 @@
QUnit.module('output options');
(function() {
['-o a.js', '--output a.js'].forEach(function(command, index) {
var commands = [
'-o a.js',
'--output a.js'
];
commands.forEach(function(command, index) {
asyncTest('`lodash ' + command +'`', function() {
var start = _.once(QUnit.start);
@@ -894,7 +933,12 @@
QUnit.module('stdout options');
(function() {
['-c', '--stdout'].forEach(function(command, index) {
var commands = [
'-c',
'--stdout'
];
commands.forEach(function(command, index) {
asyncTest('`lodash ' + command +'`', function() {
var written,
start = _.once(QUnit.start),