Add support for _.camelCase, _.endsWith, _.escapeRegExp, _.kebabCase, _.pad, _.padLeft, _.padRight, _.repeat, _.snakeCase, _.startsWith, and _.truncate. [closes #425]

This commit is contained in:
John-David Dalton
2014-03-02 23:48:48 -08:00
parent ce65c3113a
commit 2a017c3a7c
2 changed files with 538 additions and 69 deletions

605
lodash.js
View File

@@ -57,15 +57,28 @@
/** Used to detect hexadecimal string values */ /** Used to detect hexadecimal string values */
var reHexPrefix = /^0[xX]/; var reHexPrefix = /^0[xX]/;
/** Used to match latin-1 supplement letters */
var reLatin1 = /[\xC0-\xFF]/g;
/** Used to ensure capturing order of template delimiters */ /** Used to ensure capturing order of template delimiters */
var reNoMatch = /($^)/; var reNoMatch = /($^)/;
/**
* Used to match RegExp special characters.
* See this [article on RegExp characters](http://www.regular-expressions.info/characters.html#special)
* for more details.
*/
var reRegExpChars =/[.*+?^${()|[\\]/g;
/** Used to detect functions containing a `this` reference */ /** Used to detect functions containing a `this` reference */
var reThis = /\bthis\b/; var reThis = /\bthis\b/;
/** Used to match unescaped characters in compiled string literals */ /** Used to match unescaped characters in compiled string literals */
var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g; var reUnescapedString = /['\n\r\t\u2028\u2029\\]/g;
/** Used to match words to create compound words */
var reWords = /[a-z0-9]+/g;
/** Used to detect and test whitespace */ /** Used to detect and test whitespace */
var whitespace = ( var whitespace = (
// whitespace // whitespace
@@ -114,7 +127,7 @@
cloneableClasses[numberClass] = cloneableClasses[objectClass] = cloneableClasses[numberClass] = cloneableClasses[objectClass] =
cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true; cloneableClasses[regexpClass] = cloneableClasses[stringClass] = true;
/** Used as an internal `_.debounce` options object */ /** Used as an internal `_.debounce` options object by `_.throttle` */
var debounceOptions = { var debounceOptions = {
'leading': false, 'leading': false,
'maxWait': 0, 'maxWait': 0,
@@ -155,6 +168,31 @@
''': "'" ''': "'"
}; };
/**
* Used to convert latin-1 supplement letters to basic latin (ASCII) letters.
* See [Wikipedia](http://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
* for more details.
*/
var deburredLetters = {
'\xC0': 'A', '\xC1': 'A', '\xC2': 'A', '\xC3': 'A', '\xC4': 'A', '\xC5': 'A',
'\xE0': 'a', '\xE1': 'a', '\xE2': 'a', '\xE3': 'a', '\xE4': 'a', '\xE5': 'a',
'\xC7': 'C', '\xE7': 'c',
'\xD0': 'D', '\xF0': 'd',
'\xC8': 'E', '\xC9': 'E', '\xCA': 'E', '\xCB': 'E',
'\xE8': 'e', '\xE9': 'e', '\xEA': 'e', '\xEB': 'e',
'\xCC': 'I', '\xCD': 'I', '\xCE': 'I', '\xCF': 'I',
'\xEC': 'i', '\xED': 'i', '\xEE': 'i', '\xEF': 'i',
'\xD1': 'N', '\xF1': 'n',
'\xD2': 'O', '\xD3': 'O', '\xD4': 'O', '\xD5': 'O', '\xD6': 'O', '\xD8': 'O',
'\xF2': 'o', '\xF3': 'o', '\xF4': 'o', '\xF5': 'o', '\xF6': 'o', '\xF8': 'o',
'\xD9': 'U', '\xDA': 'U', '\xDB': 'U', '\xDC': 'U',
'\xF9': 'u', '\xFA': 'u', '\xFB': 'u', '\xFC': 'u',
'\xDD': 'Y', '\xFD': 'y', '\xFF': 'y',
'\xC6': 'AE', '\xE6': 'ae',
'\xDE': 'Th', '\xFE': 'th',
'\xDF': 'ss', '\xD7': ' ', '\xF7': ' '
};
/** Used to determine if values are of the language type Object */ /** Used to determine if values are of the language type Object */
var objectTypes = { var objectTypes = {
'function': true, 'function': true,
@@ -338,15 +376,49 @@
return a.index - b.index; return a.index - b.index;
} }
/**
* Creates a function that produces compound words out of the words in a
* given string.
*
* @private
* @param {Function} callback The function called to combine each word.
* @returns {Function} Returns the new compounder function.
*/
function createCompounder(callback) {
return function(string) {
var index = -1,
words = string != null && String(string).replace(reLatin1, deburrLetter).match(reWords),
length = words ? words.length : 0,
result = '';
while (++index < length) {
result = callback(result, words[index], index, words);
}
return result;
};
}
/**
* Used by `createCompounder` to convert latin-1 supplement letters to basic
* latin (ASCII) letters.
*
* @private
* @param {string} letter The matched letter to deburr.
* @returns {string} Returns the deburred letter.
*/
function deburrLetter(letter) {
return deburredLetters[letter];
}
/** /**
* Used by `escape` to convert characters to HTML entities. * Used by `escape` to convert characters to HTML entities.
* *
* @private * @private
* @param {string} match The matched character to escape. * @param {string} chr The matched character to escape.
* @returns {string} Returns the escaped character. * @returns {string} Returns the escaped character.
*/ */
function escapeHtmlChar(match) { function escapeHtmlChar(chr) {
return htmlEscapes[match]; return htmlEscapes[chr];
} }
/** /**
@@ -354,11 +426,11 @@
* string literals. * string literals.
* *
* @private * @private
* @param {string} match The matched character to escape. * @param {string} chr The matched character to escape.
* @returns {string} Returns the escaped character. * @returns {string} Returns the escaped character.
*/ */
function escapeStringChar(match) { function escapeStringChar(chr) {
return '\\' + stringEscapes[match]; return '\\' + stringEscapes[chr];
} }
/** /**
@@ -481,11 +553,11 @@
* Used by `unescape` to convert HTML entities to characters. * Used by `unescape` to convert HTML entities to characters.
* *
* @private * @private
* @param {string} match The matched character to unescape. * @param {string} chr The matched character to unescape.
* @returns {string} Returns the unescaped character. * @returns {string} Returns the unescaped character.
*/ */
function unescapeHtmlChar(match) { function unescapeHtmlChar(chr) {
return htmlUnescapes[match]; return htmlUnescapes[chr];
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@@ -536,9 +608,8 @@
/** Used to detect if a method is native */ /** Used to detect if a method is native */
var reNative = RegExp('^' + var reNative = RegExp('^' +
String(toString) escapeRegExp(toString)
.replace(/[.*+?^${}()|[\]\\]/g, '\\$&') .replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
.replace(/toString|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
); );
/** Native method shortcuts */ /** Native method shortcuts */
@@ -1833,7 +1904,7 @@
/** /**
* Creates a function that aggregates a collection, creating an object or * Creates a function that aggregates a collection, creating an object or
* array composed from the results of running each element of the collection * array composed from the results of running each element of the collection
* through a callback. The given `setter` function sets the keys and values * through a callback. The given setter function sets the keys and values
* of the composed object or array. * of the composed object or array.
* *
* @private * @private
@@ -1882,6 +1953,29 @@
return cache; return cache;
}; };
/**
* Creates the pad required for `string` based on the given padding length.
* The `chars` string may be truncated if the number of padding characters
* exceeds the padding length.
*
* @private
* @param {string} string The string to create padding for.
* @param {number} [length=0] The padding length.
* @param {string} [chars=' '] The string used as padding.
* @returns {string} Returns the pad for `string`.
*/
function createPad(string, length, chars) {
var strLength = string.length;
length = +length || 0;
if (strLength >= length) {
return '';
}
var padLength = length - strLength;
chars = chars == null ? ' ' : String(chars);
return repeat(chars, ceil(padLength / chars.length)).slice(0, padLength);
}
/** /**
* Creates a function that, when called, either curries or invokes `func` * Creates a function that, when called, either curries or invokes `func`
* with an optional `this` binding and partially applied arguments. * with an optional `this` binding and partially applied arguments.
@@ -2017,7 +2111,7 @@
} }
/** /**
* Finds the indexes of all placeholder elements in a given array. * Finds the indexes of all placeholder elements in `array`.
* *
* @private * @private
* @param {Array} array The array to inspect. * @param {Array} array The array to inspect.
@@ -2073,10 +2167,10 @@
}; };
/** /**
* A fallback implementation of `isPlainObject` which checks if a given value * A fallback implementation of `isPlainObject` which checks if `value` is
* is an object created by the `Object` constructor, assuming objects created * an object created by the `Object` constructor, assuming objects created
* by the `Object` constructor have no inherited enumerable properties and that * by the `Object` constructor have no inherited enumerable properties and
* there are no `Object.prototype` extensions. * that there are no `Object.prototype` extensions.
* *
* @private * @private
* @param {*} value The value to check. * @param {*} value The value to check.
@@ -2423,9 +2517,9 @@
* @category Arrays * @category Arrays
* @param {Array} array The array to flatten. * @param {Array} array The array to flatten.
* @param {boolean} [isShallow=false] A flag to restrict flattening to a single level. * @param {boolean} [isShallow=false] A flag to restrict flattening to a single level.
* @param {Function|Object|string} [callback=identity] The function called * @param {Function|Object|string} [callback] The function called per iteration.
* per iteration. If a property name or object is provided it will be used * If a property name or object is provided it will be used to create a "_.pluck"
* to create a "_.pluck" or "_.where" style callback, respectively. * or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`. * @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new flattened array. * @returns {Array} Returns a new flattened array.
* @example * @example
@@ -3103,9 +3197,9 @@
* @category Arrays * @category Arrays
* @param {Array} array The array to process. * @param {Array} array The array to process.
* @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted. * @param {boolean} [isSorted=false] A flag to indicate that `array` is sorted.
* @param {Function|Object|string} [callback=identity] The function called * @param {Function|Object|string} [callback] The function called per iteration.
* per iteration. If a property name or object is provided it will be used * If a property name or object is provided it will be used to create a "_.pluck"
* to create a "_.pluck" or "_.where" style callback, respectively. * or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`. * @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a duplicate-value-free array. * @returns {Array} Returns a duplicate-value-free array.
* @example * @example
@@ -3173,7 +3267,8 @@
/** /**
* Creates an array that is the symmetric difference of the provided arrays. * Creates an array that is the symmetric difference of the provided arrays.
* See [Wikipedia](http://en.wikipedia.org/wiki/Symmetric_difference) for more details. * See [Wikipedia](http://en.wikipedia.org/wiki/Symmetric_difference) for
* more details.
* *
* @static * @static
* @memberOf _ * @memberOf _
@@ -3447,10 +3542,10 @@
* @memberOf _ * @memberOf _
* @alias include * @alias include
* @category Collections * @category Collections
* @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Object|string} collection The collection to search.
* @param {*} target The value to check for. * @param {*} target The value to check for.
* @param {number} [fromIndex=0] The index to search from. * @param {number} [fromIndex=0] The index to search from.
* @returns {boolean} Returns `true` if the `target` element is found, else `false`. * @returns {boolean} Returns `true` if the target element is found, else `false`.
* @example * @example
* *
* _.contains([1, 2, 3], 1); * _.contains([1, 2, 3], 1);
@@ -3674,7 +3769,7 @@
* @memberOf _ * @memberOf _
* @alias detect, findWhere * @alias detect, findWhere
* @category Collections * @category Collections
* @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Object|string} collection The collection to search.
* @param {Function|Object|string} [callback=identity] The function called * @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used * per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively. * to create a "_.pluck" or "_.where" style callback, respectively.
@@ -3732,7 +3827,7 @@
* @static * @static
* @memberOf _ * @memberOf _
* @category Collections * @category Collections
* @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Object|string} collection The collection to search.
* @param {Function|Object|string} [callback=identity] The function called * @param {Function|Object|string} [callback=identity] The function called
* per iteration. If a property name or object is provided it will be used * per iteration. If a property name or object is provided it will be used
* to create a "_.pluck" or "_.where" style callback, respectively. * to create a "_.pluck" or "_.where" style callback, respectively.
@@ -4034,9 +4129,9 @@
* @memberOf _ * @memberOf _
* @category Collections * @category Collections
* @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called * @param {Function|Object|string} [callback] The function called per iteration.
* per iteration. If a property name or object is provided it will be used * If a property name or object is provided it will be used to create a "_.pluck"
* to create a "_.pluck" or "_.where" style callback, respectively. * or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`. * @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the maximum value. * @returns {*} Returns the maximum value.
* @example * @example
@@ -4109,9 +4204,9 @@
* @memberOf _ * @memberOf _
* @category Collections * @category Collections
* @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Object|string} collection The collection to iterate over.
* @param {Function|Object|string} [callback=identity] The function called * @param {Function|Object|string} [callback] The function called per iteration.
* per iteration. If a property name or object is provided it will be used * If a property name or object is provided it will be used to create a "_.pluck"
* to create a "_.pluck" or "_.where" style callback, respectively. * or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`. * @param {*} [thisArg] The `this` binding of `callback`.
* @returns {*} Returns the minimum value. * @returns {*} Returns the minimum value.
* @example * @example
@@ -4400,7 +4495,8 @@
/** /**
* Creates an array of shuffled values, using a version of the Fisher-Yates * Creates an array of shuffled values, using a version of the Fisher-Yates
* shuffle. See [Wikipedia](http://en.wikipedia.org/wiki/Fisher-Yates_shuffle) for more details. * shuffle. See [Wikipedia](http://en.wikipedia.org/wiki/Fisher-Yates_shuffle)
* for more details.
* *
* @static * @static
* @memberOf _ * @memberOf _
@@ -4535,9 +4631,9 @@
* @memberOf _ * @memberOf _
* @category Collections * @category Collections
* @param {Array|Object|string} collection The collection to iterate over. * @param {Array|Object|string} collection The collection to iterate over.
* @param {Array|Function|Object|string} [callback=identity] The function called * @param {Array|Function|Object|string} [callback=identity] The function
* per iteration. If a property name or object is provided it will be used * called per iteration. If a property name or object is provided it will
* to create a "_.pluck" or "_.where" style callback, respectively. * be used to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`. * @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns a new array of sorted elements. * @returns {Array} Returns a new array of sorted elements.
* @example * @example
@@ -4939,7 +5035,7 @@
if (!isFunction(func)) { if (!isFunction(func)) {
throw new TypeError; throw new TypeError;
} }
wait = nativeMax(0, wait) || 0; wait = wait > 0 ? wait : 0;
if (options === true) { if (options === true) {
var leading = true; var leading = true;
trailing = false; trailing = false;
@@ -5274,11 +5370,11 @@
if (options === false) { if (options === false) {
leading = false; leading = false;
} else if (isObject(options)) { } else if (isObject(options)) {
leading = 'leading' in options ? options.leading : leading; leading = 'leading' in options ? !!options.leading : leading;
trailing = 'trailing' in options ? options.trailing : trailing; trailing = 'trailing' in options ? !!options.trailing : trailing;
} }
debounceOptions.leading = leading; debounceOptions.leading = leading;
debounceOptions.maxWait = wait; debounceOptions.maxWait = +wait;
debounceOptions.trailing = trailing; debounceOptions.trailing = trailing;
return debounce(func, wait, debounceOptions); return debounce(func, wait, debounceOptions);
@@ -5579,9 +5675,9 @@
* @memberOf _ * @memberOf _
* @category Objects * @category Objects
* @param {Object} object The object to search. * @param {Object} object The object to search.
* @param {Function|Object|string} [callback=identity] The function called per * @param {Function|Object|string} [callback=identity] The function called
* iteration. If a property name or object is provided it will be used to * per iteration. If a property name or object is provided it will be used
* create a "_.pluck" or "_.where" style callback, respectively. * to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`. * @param {*} [thisArg] The `this` binding of `callback`.
* @returns {string|undefined} Returns the key of the found element, else `undefined`. * @returns {string|undefined} Returns the key of the found element, else `undefined`.
* @example * @example
@@ -5633,9 +5729,9 @@
* @memberOf _ * @memberOf _
* @category Objects * @category Objects
* @param {Object} object The object to search. * @param {Object} object The object to search.
* @param {Function|Object|string} [callback=identity] The function called per * @param {Function|Object|string} [callback=identity] The function called
* iteration. If a property name or object is provided it will be used to * per iteration. If a property name or object is provided it will be used
* create a "_.pluck" or "_.where" style callback, respectively. * to create a "_.pluck" or "_.where" style callback, respectively.
* @param {*} [thisArg] The `this` binding of `callback`. * @param {*} [thisArg] The `this` binding of `callback`.
* @returns {string|undefined} Returns the key of the found element, else `undefined`. * @returns {string|undefined} Returns the key of the found element, else `undefined`.
* @example * @example
@@ -6333,7 +6429,7 @@
} }
/** /**
* Creates an array composed of the own enumerable property names of an object. * Creates an array composed of the own enumerable property names of `object`.
* *
* @static * @static
* @memberOf _ * @memberOf _
@@ -6544,7 +6640,7 @@
} }
/** /**
* Creates a two dimensional array of an object's key-value pairs, * Creates a two dimensional array of a given object's key-value pairs,
* i.e. `[[key1, value1], [key2, value2]]`. * i.e. `[[key1, value1], [key2, value2]]`.
* *
* @static * @static
@@ -6702,12 +6798,36 @@
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
/** /**
* Converts the first character of `string` to upper case. * Converts `string` to camel case.
* See [Wikipedia](http://en.wikipedia.org/wiki/CamelCase) for more details.
* *
* @static * @static
* @memberOf _ * @memberOf _
* @category Strings * @category Strings
* @param {string} string The string to capitalize. * @param {string} [string=''] The string to camel case.
* @returns {string} Returns the camel cased string.
* @example
*
* _.camelCase('Hello world');
* // => 'helloWorld'
*
* _.camelCase('hello-world');
* // => 'helloWorld'
*
* _.camelCase('hello_world');
* // => 'helloWorld'
*/
var camelCase = createCompounder(function(result, words, index) {
return result + words.charAt(0)[index ? 'toUpperCase' : 'toLowerCase']() + words.slice(1);
});
/**
* Capitalizes the first character of `string`.
*
* @static
* @memberOf _
* @category Strings
* @param {string} [string=''] The string to capitalize.
* @returns {string} Returns the capitalized string. * @returns {string} Returns the capitalized string.
* @example * @example
* *
@@ -6722,6 +6842,37 @@
return string.charAt(0).toUpperCase() + string.slice(1); return string.charAt(0).toUpperCase() + string.slice(1);
} }
/**
* Checks if `string` ends with a given target string.
*
* @static
* @memberOf _
* @category Strings
* @param {string} [string=''] The string to search.
* @param {string} [target] The string to search for.
* @param {number} [position=string.length] The position to search from.
* @returns {boolean} Returns `true` if the given string ends with the
* target string, else `false`.
* @example
*
* _.endsWith('abc', 'c');
* // => true
*
* _.endsWith('abc', 'b');
* // => false
*
* _.endsWith('abc', 'b', 2);
* // => true
*/
function endsWith(string, target, position) {
string = string == null ? '' : String(string);
target = String(target);
var length = string.length;
position = (typeof position == 'number' ? nativeMin(nativeMax(position, 0), length) : length) - target.length;
return position >= 0 && string.indexOf(target, position) == position;
}
/** /**
* Converts the characters "&", "<", ">", '"', and "'" in `string` to * Converts the characters "&", "<", ">", '"', and "'" in `string` to
* their corresponding HTML entities. * their corresponding HTML entities.
@@ -6736,7 +6887,7 @@
* @static * @static
* @memberOf _ * @memberOf _
* @category Strings * @category Strings
* @param {string} string The string to escape. * @param {string} [string=''] The string to escape.
* @returns {string} Returns the escaped string. * @returns {string} Returns the escaped string.
* @example * @example
* *
@@ -6747,6 +6898,234 @@
return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar); return string == null ? '' : String(string).replace(reUnescapedHtml, escapeHtmlChar);
} }
/**
* Escapes the RegExp special characters "\", "^", "$", ".", "|", "?", "*",
* "+", "(", ")", "[", and "{" in `string`.
*
* @static
* @memberOf _
* @category Strings
* @param {string} [string=''] The string to escape.
* @returns {string} Returns the escaped string.
* @example
*
* _.escapeRegExp('[lodash](http://lodash.com)');
* // => '\[lodash]\(http://lodash\.com\)'
*/
function escapeRegExp(string) {
return string == null ? '' : String(string).replace(reRegExpChars, '\\$&');
}
/**
* Converts `string` to kebab case (a.k.a. spinal case).
* See [Wikipedia](http://en.wikipedia.org/wiki/Letter_case#Computers) for
* more details.
*
* @static
* @memberOf _
* @category Strings
* @param {string} [string=''] The string to kebab case.
* @returns {string} Returns the kebab cased string.
* @example
*
* _.kebabCase('Hello world');
* // => 'hello-world'
*
* _.kebabCase('helloWorld');
* // => 'hello-world'
*
* _.kebabCase('hello_world');
* // => 'hello-world'
*/
var kebabCase = createCompounder(function(result, words, index) {
return result + (index ? '-' : '') + words.toLowerCase();
});
/**
* Pads `string` on the left and right sides if it is shorter then the given
* padding length. The `chars` string may be truncated if the number of padding
* characters can't be evenly divided by the padding length.
*
* @static
* @memberOf _
* @category Strings
* @param {string} [string=''] The string to pad.
* @param {number} [length=0] The padding length.
* @param {string} [chars=' '] The string used as padding.
* @returns {string} Returns the padded string.
* @example
*
* _.pad('abc', 8);
* // => ' abc '
*
* _.pad('abc', 8, '_-');
* // => '_-abc_-_'
*
* _.pad('abc', 3);
* // => 'abc'
*/
function pad(string, length, chars) {
string = string == null ? '' : String(string);
length = +length || 0;
var strLength = string.length;
if (strLength >= length) {
return string;
}
var mid = (length - strLength) / 2,
leftLength = floor(mid),
rightLength = ceil(mid);
chars = createPad('', rightLength, chars);
return chars.slice(0, leftLength) + string + chars;
}
/**
* Pads `string` on the left side if it is shorter then the given padding
* length. The `chars` string may be truncated if the number of padding
* characters exceeds the padding length.
*
* @static
* @memberOf _
* @category Strings
* @param {string} [string=''] The string to pad.
* @param {number} [length=0] The padding length.
* @param {string} [chars=' '] The string used as padding.
* @returns {string} Returns the padded string.
* @example
*
* _.padLeft('abc', 6);
* // => ' abc'
*
* _.padLeft('abc', 6, '_-');
* // => '_-_abc'
*
* _.padLeft('abc', 3);
* // => 'abc'
*/
function padLeft(string, length, chars) {
string = string == null ? '' : String(string);
return createPad(string, length, chars) + string;
}
/**
* Pads `string` on the right side if it is shorter then the given padding
* length. The `chars` string may be truncated if the number of padding
* characters exceeds the padding length.
*
* @static
* @memberOf _
* @category Strings
* @param {string} [string=''] The string to pad.
* @param {number} [length=0] The padding length.
* @param {string} [chars=' '] The string used as padding.
* @returns {string} Returns the padded string.
* @example
*
* _.padRight('abc', 6);
* // => 'abc '
*
* _.padRight('abc', 6, '_-');
* // => 'abc_-_'
*
* _.padRight('abc', 3);
* // => 'abc'
*/
function padRight(string, length, chars) {
string = string == null ? '' : String(string);
return string + createPad(string, length, chars);
}
/**
* Repeats the given string `n` times.
*
* @static
* @memberOf _
* @category Strings
* @param {string} [string=''] The string to repeat.
* @param {number} [n=0] The number of times to repeat the string.
* @returns {string} Returns the repeated string.
* @example
*
* _.repeat('*', 3);
* // => '***'
*
* _.repeat('abc', 2);
* // => 'abcabc'
*
* _.repeat('abc', 0);
* // => ''
*/
function repeat(string, n) {
var result = '';
n = +n || 0;
if (n < 1 || string == null) {
return result;
}
string = String(string);
while (n > 0) {
if (n % 2) {
result += string;
}
n = floor(n / 2);
result += result;
}
return result;
}
/**
* Converts `string` to snake case.
* See [Wikipedia](http://en.wikipedia.org/wiki/Snake_case) for more details.
*
* @static
* @memberOf _
* @category Strings
* @param {string} [string=''] The string to snake case.
* @returns {string} Returns the snake cased string.
* @example
*
* _.snakeCase('Hello world');
* // => 'hello_world'
*
* _.snakeCase('hello-world');
* // => 'hello_world'
*
* _.snakeCase('helloWorld');
* // => 'hello_world'
*/
var snakeCase = createCompounder(function(result, words, index) {
return result + (index ? '_' : '') + words.toLowerCase();
});
/**
* Checks if `string` starts with a given target string.
*
* @static
* @memberOf _
* @category Strings
* @param {string} [string=''] The string to search.
* @param {string} [target] The string to search for.
* @param {number} [position=0] The position to search from.
* @returns {boolean} Returns `true` if the given string starts with the
* target string, else `false`.
* @example
*
* _.startsWith('abc', 'a');
* // => true
*
* _.startsWith('abc', 'b');
* // => false
*
* _.startsWith('abc', 'b', 1);
* // => true
*/
function startsWith(string, target, position) {
string = string == null ? '' : String(string);
position = typeof position == 'number' ? nativeMin(nativeMax(position, 0), string.length) : 0;
return string.lastIndexOf(target, position) == position;
}
/** /**
* Creates a compiled template function that can interpolate data properties * Creates a compiled template function that can interpolate data properties
* in "interpolate" delimiters, HTML-escaped interpolated data properties in * in "interpolate" delimiters, HTML-escaped interpolated data properties in
@@ -6756,8 +7135,8 @@
* settings object is provided it will override `_.templateSettings` for the * settings object is provided it will override `_.templateSettings` for the
* template. * template.
* *
* Note: In the development build, `_.template` utilizes sourceURLs for easier * Note: In the development build, `_.template` utilizes sourceURLs for easier debugging.
* debugging. See [HTML5 Rocks' article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl) * See the [HTML5 Rocks article on sourcemaps](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
* for more details. * for more details.
* *
* For more information on precompiling templates see * For more information on precompiling templates see
@@ -6769,8 +7148,8 @@
* @static * @static
* @memberOf _ * @memberOf _
* @category Strings * @category Strings
* @param {string} text The template text. * @param {string} [string=''] The template string.
* @param {Object} [data] The data object used to populate the text. * @param {Object} [data] The data object used to populate the template string.
* @param {Object} [options] The options object. * @param {Object} [options] The options object.
* @param {RegExp} [options.escape] The HTML "escape" delimiter. * @param {RegExp} [options.escape] The HTML "escape" delimiter.
* @param {RegExp} [options.evaluate] The "evaluate" delimiter. * @param {RegExp} [options.evaluate] The "evaluate" delimiter.
@@ -6836,13 +7215,13 @@
* };\ * };\
* '); * ');
*/ */
function template(text, data, options) { function template(string, data, options) {
// based on John Resig's `tmpl` implementation // based on John Resig's `tmpl` implementation
// http://ejohn.org/blog/javascript-micro-templating/ // http://ejohn.org/blog/javascript-micro-templating/
// and Laura Doktorova's doT.js // and Laura Doktorova's doT.js
// https://github.com/olado/doT // https://github.com/olado/doT
var settings = lodash.templateSettings; var settings = lodash.templateSettings;
text = String(text || ''); string = String(string == null ? '' : string);
// avoid missing dependencies when `iteratorTemplate` is not defined // avoid missing dependencies when `iteratorTemplate` is not defined
options = iteratorTemplate ? defaults({}, options, settings) : settings; options = iteratorTemplate ? defaults({}, options, settings) : settings;
@@ -6865,11 +7244,11 @@
(options.evaluate || reNoMatch).source + '|$' (options.evaluate || reNoMatch).source + '|$'
, 'g'); , 'g');
text.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) { string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
interpolateValue || (interpolateValue = esTemplateValue); interpolateValue || (interpolateValue = esTemplateValue);
// escape characters that cannot be included in string literals // escape characters that cannot be included in string literals
source += text.slice(index, offset).replace(reUnescapedString, escapeStringChar); source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
// replace delimiters with snippets // replace delimiters with snippets
if (escapeValue) { if (escapeValue) {
@@ -6948,7 +7327,7 @@
* @static * @static
* @memberOf _ * @memberOf _
* @category Strings * @category Strings
* @param {string} string The string to trim. * @param {string} [string=''] The string to trim.
* @param {string} [chars=whitespace] The characters to trim. * @param {string} [chars=whitespace] The characters to trim.
* @returns {string} Returns the trimmed string. * @returns {string} Returns the trimmed string.
* @example * @example
@@ -6972,7 +7351,7 @@
* @static * @static
* @memberOf _ * @memberOf _
* @category Strings * @category Strings
* @param {string} string The string to trim. * @param {string} [string=''] The string to trim.
* @param {string} [chars=whitespace] The characters to trim. * @param {string} [chars=whitespace] The characters to trim.
* @returns {string} Returns the trimmed string. * @returns {string} Returns the trimmed string.
* @example * @example
@@ -6996,7 +7375,7 @@
* @static * @static
* @memberOf _ * @memberOf _
* @category Strings * @category Strings
* @param {string} string The string to trim. * @param {string} [string=''] The string to trim.
* @param {string} [chars=whitespace] The characters to trim. * @param {string} [chars=whitespace] The characters to trim.
* @returns {string} Returns the trimmed string. * @returns {string} Returns the trimmed string.
* @example * @example
@@ -7014,6 +7393,85 @@
return chars == null ? nativeTrimRight.call(string) : shimTrimRight(string, chars); return chars == null ? nativeTrimRight.call(string) : shimTrimRight(string, chars);
}; };
/**
* Truncates `string` if it is longer than the given maximum string length.
* The last characters of the truncated string will be replaced with the
* omission string which defaults to "...".
*
* @static
* @memberOf _
* @category Strings
* @param {string} [string=''] The string to trim.
* @param {Object|number} [options] The options object or maximum string length.
* @param {number} [options.length=30] The maximum string length.
* @param {string} [options.omission='...'] The string used to indicate text is omitted.
* @param {RegExp|string} [options.separator] The separator pattern to truncate to.
* @returns {string} Returns the truncated string.
* @example
*
* _.truncate('hi-diddly-ho there, neighborino');
* // => 'hi-diddly-ho there, neighbo...'
*
* _.truncate('hi-diddly-ho there, neighborino', 24);
* // => 'hi-diddly-ho there, n...'
*
* _.truncate('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': ' ' });
* // => 'hi-diddly-ho there,...'
*
* _.truncate('hi-diddly-ho there, neighborino', { 'length': 24, 'separator': /,? +/ });
* //=> 'hi-diddly-ho there...'
*
* _.truncate('hi-diddly-ho there, neighborino', { 'omission': ' [...]' });
* // => 'hi-diddly-ho there, neig [...]'
*/
function truncate(string, options) {
var length = 30,
omission = '...';
if (options && isObject(options)) {
var separator = 'separator' in options ? options.separator : separator;
length = 'length' in options ? +options.length || 0 : length;
omission = 'omission' in options ? String(options.omission) : omission;
}
else if (options != null) {
length = +options || 0;
}
string = string == null ? '' : String(string);
if (length > string.length) {
return string;
}
var end = length - omission.length;
if (end < 1) {
return omission;
}
var result = string.slice(0, end);
if (separator == null) {
return result + omission;
}
if (isRegExp(separator)) {
if (string.slice(end).search(separator)) {
var match,
newEnd,
substring = string.slice(0, end);
if (!separator.global) {
separator = RegExp(separator.source, (reFlags.exec(separator) || '') + 'g');
}
separator.lastIndex = 0;
while ((match = separator.exec(substring))) {
newEnd = match.index;
}
result = result.slice(0, newEnd == null ? end : newEnd);
}
} else if (string.indexOf(separator, end) != end) {
var index = result.lastIndexOf(separator);
if (index > -1) {
result = result.slice(0, index);
}
}
return result + omission;
}
/** /**
* The inverse of `_.escape`; this method converts the HTML entities * The inverse of `_.escape`; this method converts the HTML entities
* `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to their
@@ -7025,7 +7483,7 @@
* @static * @static
* @memberOf _ * @memberOf _
* @category Strings * @category Strings
* @param {string} string The string to unescape. * @param {string} [string=''] The string to unescape.
* @returns {string} Returns the unescaped string. * @returns {string} Returns the unescaped string.
* @example * @example
* *
@@ -7477,7 +7935,7 @@
* @memberOf _ * @memberOf _
* @category Utilities * @category Utilities
* @param {number} n The number of times to execute the callback. * @param {number} n The number of times to execute the callback.
* @param {Function} callback The function called per iteration. * @param {Function} [callback=identity] The function called per iteration.
* @param {*} [thisArg] The `this` binding of `callback`. * @param {*} [thisArg] The `this` binding of `callback`.
* @returns {Array} Returns an array of the results of each `callback` execution. * @returns {Array} Returns an array of the results of each `callback` execution.
* @example * @example
@@ -7621,11 +8079,14 @@
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
// add functions that return unwrapped values when chaining // add functions that return unwrapped values when chaining
lodash.camelCase = camelCase;
lodash.capitalize = capitalize; lodash.capitalize = capitalize;
lodash.clone = clone; lodash.clone = clone;
lodash.cloneDeep = cloneDeep; lodash.cloneDeep = cloneDeep;
lodash.contains = contains; lodash.contains = contains;
lodash.endsWith = endsWith;
lodash.escape = escape; lodash.escape = escape;
lodash.escapeRegExp = escapeRegExp;
lodash.every = every; lodash.every = every;
lodash.find = find; lodash.find = find;
lodash.findIndex = findIndex; lodash.findIndex = findIndex;
@@ -7653,24 +8114,32 @@
lodash.isRegExp = isRegExp; lodash.isRegExp = isRegExp;
lodash.isString = isString; lodash.isString = isString;
lodash.isUndefined = isUndefined; lodash.isUndefined = isUndefined;
lodash.kebabCase = kebabCase;
lodash.lastIndexOf = lastIndexOf; lodash.lastIndexOf = lastIndexOf;
lodash.mixin = mixin; lodash.mixin = mixin;
lodash.noConflict = noConflict; lodash.noConflict = noConflict;
lodash.noop = noop; lodash.noop = noop;
lodash.now = now; lodash.now = now;
lodash.pad = pad;
lodash.padLeft = padLeft;
lodash.padRight = padRight;
lodash.parseInt = parseInt; lodash.parseInt = parseInt;
lodash.random = random; lodash.random = random;
lodash.reduce = reduce; lodash.reduce = reduce;
lodash.reduceRight = reduceRight; lodash.reduceRight = reduceRight;
lodash.repeat = repeat;
lodash.result = result; lodash.result = result;
lodash.runInContext = runInContext; lodash.runInContext = runInContext;
lodash.size = size; lodash.size = size;
lodash.some = some; lodash.some = some;
lodash.sortedIndex = sortedIndex; lodash.sortedIndex = sortedIndex;
lodash.snakeCase = snakeCase;
lodash.startsWith = startsWith;
lodash.template = template; lodash.template = template;
lodash.trim = trim; lodash.trim = trim;
lodash.trimLeft = trimLeft; lodash.trimLeft = trimLeft;
lodash.trimRight = trimRight; lodash.trimRight = trimRight;
lodash.truncate = truncate;
lodash.unescape = unescape; lodash.unescape = unescape;
lodash.uniqueId = uniqueId; lodash.uniqueId = uniqueId;

View File

@@ -9274,7 +9274,7 @@
var acceptFalsey = _.difference(allMethods, rejectFalsey); var acceptFalsey = _.difference(allMethods, rejectFalsey);
test('should accept falsey arguments', 165, function() { test('should accept falsey arguments', 176, function() {
var emptyArrays = _.map(falsey, function() { return []; }), var emptyArrays = _.map(falsey, function() { return []; }),
isExposed = '_' in root, isExposed = '_' in root,
oldDash = root._; oldDash = root._;