voca
Version:
The ultimate JavaScript string library
1,793 lines (1,550 loc) • 119 kB
JavaScript
/*!
* Voca string library 1.4.1
* https://vocajs.pages.dev
*
* Copyright Dmitri Pavlutin and other contributors
* Released under the MIT license
*/
function _extends() {
_extends = Object.assign || function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
function _slicedToArray(arr, i) {
return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
}
function _toConsumableArray(arr) {
return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
}
function _arrayWithoutHoles(arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
}
}
function _arrayWithHoles(arr) {
if (Array.isArray(arr)) return arr;
}
function _iterableToArray(iter) {
if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
}
function _iterableToArrayLimit(arr, i) {
if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) {
return;
}
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"] != null) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
function _nonIterableSpread() {
throw new TypeError("Invalid attempt to spread non-iterable instance");
}
function _nonIterableRest() {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
/**
* Checks if `value` is `null` or `undefined`
*
* @ignore
* @function isNil
* @param {*} value The object to check
* @return {boolean} Returns `true` is `value` is `undefined` or `null`, `false` otherwise
*/
function isNil(value) {
return value === undefined || value === null;
}
/**
* Converts the `value` to a boolean. If `value` is `undefined` or `null`, returns `defaultValue`.
*
* @ignore
* @function toBoolean
* @param {*} value The value to convert.
* @param {boolean} [defaultValue=false] The default value.
* @return {boolean} Returns the coercion to boolean.
*/
function coerceToBoolean(value) {
var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
if (isNil(value)) {
return defaultValue;
}
return Boolean(value);
}
/**
* Checks whether `subject` is a string primitive type.
*
* @function isString
* @static
* @since 1.0.0
* @memberOf Query
* @param {string} subject The value to verify.
* @return {boolean} Returns `true` if `subject` is string primitive type or `false` otherwise.
* @example
* v.isString('vacation');
* // => true
*
* v.isString(560);
* // => false
*/
function isString(subject) {
return typeof subject === 'string';
}
/**
* Get the string representation of the `value`.
* Converts the `value` to string.
* If `value` is `null` or `undefined`, return `defaultValue`.
*
* @ignore
* @function toString
* @param {*} value The value to convert.
* @param {*} [defaultValue=''] The default value to return.
* @return {string|null} Returns the string representation of `value`. Returns `defaultValue` if `value` is
* `null` or `undefined`.
*/
function coerceToString(value) {
var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
if (isNil(value)) {
return defaultValue;
}
if (isString(value)) {
return value;
}
return String(value);
}
/**
* Converts the first character of `subject` to upper case. If `restToLower` is `true`, convert the rest of
* `subject` to lower case.
*
* @function capitalize
* @static
* @since 1.0.0
* @memberOf Case
* @param {string} [subject=''] The string to capitalize.
* @param {boolean} [restToLower=false] Convert the rest of `subject` to lower case.
* @return {string} Returns the capitalized string.
* @example
* v.capitalize('apple');
* // => 'Apple'
*
* v.capitalize('aPPle', true);
* // => 'Apple'
*/
function capitalize(subject, restToLower) {
var subjectString = coerceToString(subject);
var restToLowerCaseBoolean = coerceToBoolean(restToLower);
if (subjectString === '') {
return '';
}
if (restToLowerCaseBoolean) {
subjectString = subjectString.toLowerCase();
}
return subjectString.substr(0, 1).toUpperCase() + subjectString.substr(1);
}
/**
* Converts the `subject` to lower case.
*
* @function lowerCase
* @static
* @since 1.0.0
* @memberOf Case
* @param {string} [subject=''] The string to convert to lower case.
* @return {string} Returns the lower case string.
* @example
* v.lowerCase('Green');
* // => 'green'
*
* v.lowerCase('BLUE');
* // => 'blue'
*/
function lowerCase(subject) {
var subjectString = coerceToString(subject, '');
return subjectString.toLowerCase();
}
/**
* A regular expression string matching digits
*
* @type {string}
* @ignore
*/
var digit = '\\d';
/**
* A regular expression string matching whitespace
*
* @type {string}
* @ignore
*/
var whitespace = '\\s\\uFEFF\\xA0';
/**
* A regular expression string matching high surrogate
*
* @type {string}
* @ignore
*/
var highSurrogate = '\\uD800-\\uDBFF';
/**
* A regular expression string matching low surrogate
*
* @type {string}
* @ignore
*/
var lowSurrogate = '\\uDC00-\\uDFFF';
/**
* A regular expression string matching diacritical mark
*
* @type {string}
* @ignore
*/
var diacriticalMark = '\\u0300-\\u036F\\u1AB0-\\u1AFF\\u1DC0-\\u1DFF\\u20D0-\\u20FF\\uFE20-\\uFE2F';
/**
* A regular expression to match the base character for a combining mark
*
* @type {string}
* @ignore
*/
var base = '\\0-\\u02FF\\u0370-\\u1AAF\\u1B00-\\u1DBF\\u1E00-\\u20CF\\u2100-\\uD7FF\\uE000-\\uFE1F\\uFE30-\\uFFFF';
/**
* Regular expression to match combining marks
*
* @see http://unicode.org/faq/char_combmark.html
* @type {RegExp}
* @ignore
*/
var REGEXP_COMBINING_MARKS = new RegExp('([' + base + ']|[' + highSurrogate + '][' + lowSurrogate + ']|[' + highSurrogate + '](?![' + lowSurrogate + '])|(?:[^' + highSurrogate + ']|^)[' + lowSurrogate + '])([' + diacriticalMark + ']+)', 'g');
/**
* Regular expression to match surrogate pairs
*
* @see http://www.unicode.org/faq/utf_bom.html#utf16-2
* @type {RegExp}
* @ignore
*/
var REGEXP_SURROGATE_PAIRS = new RegExp('([' + highSurrogate + '])([' + lowSurrogate + '])', 'g');
/**
* Regular expression to match a unicode character
*
* @type {RegExp}
* @ignore
*/
var REGEXP_UNICODE_CHARACTER = new RegExp('((?:[' + base + ']|[' + highSurrogate + '][' + lowSurrogate + ']|[' + highSurrogate + '](?![' + lowSurrogate + '])|(?:[^' + highSurrogate + ']|^)[' + lowSurrogate + '])(?:[' + diacriticalMark + ']+))|\
([' + highSurrogate + '][' + lowSurrogate + '])|\
([\\n\\r\\u2028\\u2029])|\
(.)', 'g');
/**
* Regular expression to match whitespaces
*
* @type {RegExp}
* @ignore
*/
var REGEXP_WHITESPACE = new RegExp('[' + whitespace + ']');
/**
* Regular expression to match whitespaces from the left side
*
* @type {RegExp}
* @ignore
*/
var REGEXP_TRIM_LEFT = new RegExp('^[' + whitespace + ']+');
/**
* Regular expression to match whitespaces from the right side
*
* @type {RegExp}
* @ignore
*/
var REGEXP_TRIM_RIGHT = new RegExp('[' + whitespace + ']+$');
/**
* Regular expression to match digit characters
*
* @type {RegExp}
* @ignore
*/
var REGEXP_DIGIT = new RegExp('^' + digit + '+$');
/**
* Regular expression to match regular expression special characters
*
* @type {RegExp}
* @ignore
*/
var REGEXP_SPECIAL_CHARACTERS = /[-[\]{}()*+!<=:?./\\^$|#,]/g;
/**
* Regular expression to match not latin characters
*
* @type {RegExp}
* @ignore
*/
var REGEXP_NON_LATIN = /[^A-Za-z0-9]/g;
/**
* Regular expression to match HTML special characters.
*
* @type {RegExp}
* @ignore
*/
var REGEXP_HTML_SPECIAL_CHARACTERS = /[<>&"'`]/g;
/**
* Regular expression to match sprintf format string
*
* @type {RegExp}
* @ignore
*/
var REGEXP_CONVERSION_SPECIFICATION = /(%{1,2})(?:(\d+)\$)?(\+)?([ 0]|'.{1})?(-)?(\d+)?(?:\.(\d+))?([bcdiouxXeEfgGs])?/g;
/**
* Regular expression to match trailing zeros in a number
*
* @type {RegExp}
* @ignore
*/
var REGEXP_TRAILING_ZEROS = /\.?0+$/g;
/**
* Regular expression to match a list of tags.
*
* @see https://html.spec.whatwg.org/multipage/syntax.html#syntax-tag-name
* @type {RegExp}
* @ignore
*/
var REGEXP_TAG_LIST = /<([A-Za-z0-9]+)>/g;
/**
* A regular expression to match the General Punctuation Unicode block
*
* @type {string}
* @ignore
*/
var generalPunctuationBlock = '\\u2000-\\u206F';
/**
* A regular expression to match non characters from from Basic Latin and Latin-1 Supplement Unicode blocks
*
* @type {string}
* @ignore
*/
var nonCharacter = '\\x00-\\x2F\\x3A-\\x40\\x5B-\\x60\\x7b-\\xBF\\xD7\\xF7';
/**
* A regular expression to match the dingbat Unicode block
*
* @type {string}
* @ignore
*/
var dingbatBlock = '\\u2700-\\u27BF';
/**
* A regular expression string that matches lower case letters: LATIN
*
* @type {string}
* @ignore
*/
var lowerCaseLetter = 'a-z\\xB5\\xDF-\\xF6\\xF8-\\xFF\\u0101\\u0103\\u0105\\u0107\\u0109\\u010B\\u010D\\u010F\\u0111\\u0113\\u0115\\u0117\\u0119\\u011B\\u011D\\u011F\\u0121\\u0123\\u0125\\u0127\\u0129\\u012B\\u012D\\u012F\\u0131\\u0133\\u0135\\u0137\\u0138\\u013A\\u013C\\u013E\\u0140\\u0142\\u0144\\u0146\\u0148\\u0149\\u014B\\u014D\\u014F\\u0151\\u0153\\u0155\\u0157\\u0159\\u015B\\u015D\\u015F\\u0161\\u0163\\u0165\\u0167\\u0169\\u016B\\u016D\\u016F\\u0171\\u0173\\u0175\\u0177\\u017A\\u017C\\u017E-\\u0180\\u0183\\u0185\\u0188\\u018C\\u018D\\u0192\\u0195\\u0199-\\u019B\\u019E\\u01A1\\u01A3\\u01A5\\u01A8\\u01AA\\u01AB\\u01AD\\u01B0\\u01B4\\u01B6\\u01B9\\u01BA\\u01BD-\\u01BF\\u01C6\\u01C9\\u01CC\\u01CE\\u01D0\\u01D2\\u01D4\\u01D6\\u01D8\\u01DA\\u01DC\\u01DD\\u01DF\\u01E1\\u01E3\\u01E5\\u01E7\\u01E9\\u01EB\\u01ED\\u01EF\\u01F0\\u01F3\\u01F5\\u01F9\\u01FB\\u01FD\\u01FF\\u0201\\u0203\\u0205\\u0207\\u0209\\u020B\\u020D\\u020F\\u0211\\u0213\\u0215\\u0217\\u0219\\u021B\\u021D\\u021F\\u0221\\u0223\\u0225\\u0227\\u0229\\u022B\\u022D\\u022F\\u0231\\u0233-\\u0239\\u023C\\u023F\\u0240\\u0242\\u0247\\u0249\\u024B\\u024D\\u024F';
/**
* A regular expression string that matches upper case letters: LATIN
*
* @type {string}
* @ignore
*/
var upperCaseLetter = '\\x41-\\x5a\\xc0-\\xd6\\xd8-\\xde\\u0100\\u0102\\u0104\\u0106\\u0108\\u010a\\u010c\\u010e\\u0110\\u0112\\u0114\\u0116\\u0118\\u011a\\u011c\\u011e\\u0120\\u0122\\u0124\\u0126\\u0128\\u012a\\u012c\\u012e\\u0130\\u0132\\u0134\\u0136\\u0139\\u013b\\u013d\\u013f\\u0141\\u0143\\u0145\\u0147\\u014a\\u014c\\u014e\\u0150\\u0152\\u0154\\u0156\\u0158\\u015a\\u015c\\u015e\\u0160\\u0162\\u0164\\u0166\\u0168\\u016a\\u016c\\u016e\\u0170\\u0172\\u0174\\u0176\\u0178\\u0179\\u017b\\u017d\\u0181\\u0182\\u0184\\u0186\\u0187\\u0189-\\u018b\\u018e-\\u0191\\u0193\\u0194\\u0196-\\u0198\\u019c\\u019d\\u019f\\u01a0\\u01a2\\u01a4\\u01a6\\u01a7\\u01a9\\u01ac\\u01ae\\u01af\\u01b1-\\u01b3\\u01b5\\u01b7\\u01b8\\u01bc\\u01c4\\u01c5\\u01c7\\u01c8\\u01ca\\u01cb\\u01cd\\u01cf\\u01d1\\u01d3\\u01d5\\u01d7\\u01d9\\u01db\\u01de\\u01e0\\u01e2\\u01e4\\u01e6\\u01e8\\u01ea\\u01ec\\u01ee\\u01f1\\u01f2\\u01f4\\u01f6-\\u01f8\\u01fa\\u01fc\\u01fe\\u0200\\u0202\\u0204\\u0206\\u0208\\u020a\\u020c\\u020e\\u0210\\u0212\\u0214\\u0216\\u0218\\u021a\\u021c\\u021e\\u0220\\u0222\\u0224\\u0226\\u0228\\u022a\\u022c\\u022e\\u0230\\u0232\\u023a\\u023b\\u023d\\u023e\\u0241\\u0243-\\u0246\\u0248\\u024a\\u024c\\u024e';
/**
* Regular expression to match Unicode words
*
* @type {RegExp}
* @ignore
*/
var REGEXP_WORD = new RegExp('(?:[' + upperCaseLetter + '][' + diacriticalMark + ']*)?(?:[' + lowerCaseLetter + '][' + diacriticalMark + ']*)+|\
(?:[' + upperCaseLetter + '][' + diacriticalMark + ']*)+(?![' + lowerCaseLetter + '])|\
[' + digit + ']+|\
[' + dingbatBlock + ']|\
[^' + nonCharacter + generalPunctuationBlock + whitespace + ']+', 'g');
/**
* Regular expression to match words from Basic Latin and Latin-1 Supplement blocks
*
* @type {RegExp}
* @ignore
*/
var REGEXP_LATIN_WORD = /[A-Z\xC0-\xD6\xD8-\xDE]?[a-z\xDF-\xF6\xF8-\xFF]+|[A-Z\xC0-\xD6\xD8-\xDE]+(?![a-z\xDF-\xF6\xF8-\xFF])|\d+/g;
/**
* Regular expression to match alpha characters
*
* @see http://stackoverflow.com/a/22075070/1894471
* @type {RegExp}
* @ignore
*/
var REGEXP_ALPHA = new RegExp('^(?:[' + lowerCaseLetter + upperCaseLetter + '][' + diacriticalMark + ']*)+$');
/**
* Regular expression to match alpha and digit characters
*
* @see http://stackoverflow.com/a/22075070/1894471
* @type {RegExp}
* @ignore
*/
var REGEXP_ALPHA_DIGIT = new RegExp('^((?:[' + lowerCaseLetter + upperCaseLetter + '][' + diacriticalMark + ']*)|[' + digit + '])+$');
/**
* Regular expression to match Extended ASCII characters, i.e. the first 255
*
* @type {RegExp}
* @ignore
*/
var REGEXP_EXTENDED_ASCII = /^[\x01-\xFF]*$/;
/**
* Verifies if `value` is `undefined` or `null` and returns `defaultValue`. In other case returns `value`.
*
* @ignore
* @function nilDefault
* @param {*} value The value to verify.
* @param {*} defaultValue The default value.
* @return {*} Returns `defaultValue` if `value` is `undefined` or `null`, otherwise `defaultValue`.
*/
function nilDefault(value, defaultValue) {
return value == null ? defaultValue : value;
}
/**
* Get the string representation of the `value`.
* Converts the `value` to string.
*
* @ignore
* @function toString
* @param {*} value The value to convert.
* @return {string|null} Returns the string representation of `value`.
*/
function toString(value) {
if (isNil(value)) {
return null;
}
if (isString(value)) {
return value;
}
return String(value);
}
/**
* Splits `subject` into an array of words.
*
* @function words
* @static
* @since 1.0.0
* @memberOf Split
* @param {string} [subject=''] The string to split into words.
* @param {string|RegExp} [pattern] The pattern to watch words. If `pattern` is not RegExp, it is transformed to `new RegExp(pattern, flags)`.
* @param {string} [flags=''] The regular expression flags. Applies when `pattern` is string type.
* @return {Array} Returns the array of words.
* @example
* v.words('gravity can cross dimensions');
* // => ['gravity', 'can', 'cross', 'dimensions']
*
* v.words('GravityCanCrossDimensions');
* // => ['Gravity', 'Can', 'Cross', 'Dimensions']
*
* v.words('Gravity - can cross dimensions!');
* // => ['Gravity', 'can', 'cross', 'dimensions']
*
* v.words('Earth gravity', /[^\s]+/g);
* // => ['Earth', 'gravity']
*/
function words(subject, pattern, flags) {
var subjectString = coerceToString(subject);
var patternRegExp;
if (isNil(pattern)) {
patternRegExp = REGEXP_EXTENDED_ASCII.test(subjectString) ? REGEXP_LATIN_WORD : REGEXP_WORD;
} else if (pattern instanceof RegExp) {
patternRegExp = pattern;
} else {
var flagsString = toString(nilDefault(flags, ''));
patternRegExp = new RegExp(toString(pattern), flagsString);
}
return nilDefault(subjectString.match(patternRegExp), []);
}
/**
* Transforms the `word` into camel case chunk.
*
* @param {string} word The word string
* @param {number} index The index of the word in phrase.
* @return {string} The transformed word.
* @ignore
*/
function wordToCamel(word, index) {
return index === 0 ? lowerCase(word) : capitalize(word, true);
}
/**
* Converts the `subject` to <a href="https://en.wikipedia.org/wiki/CamelCase">camel case</a>.
*
* @function camelCase
* @static
* @since 1.0.0
* @memberOf Case
* @param {string} [subject=''] The string to convert to camel case.
* @return {string} The camel case string.
* @example
* v.camelCase('bird flight');
* // => 'birdFlight'
*
* v.camelCase('BirdFlight');
* // => 'birdFlight'
*
* v.camelCase('-BIRD-FLIGHT-');
* // => 'birdFlight'
*/
function camelCase(subject) {
var subjectString = coerceToString(subject);
if (subjectString === '') {
return '';
}
return words(subjectString).map(wordToCamel).join('');
}
/**
* Converts the first character of `subject` to lower case.
*
* @function decapitalize
* @static
* @since 1.0.0
* @memberOf Case
* @param {string} [subject=''] The string to decapitalize.
* @return {string} Returns the decapitalized string.
* @example
* v.decapitalize('Sun');
* // => 'sun'
*
* v.decapitalize('moon');
* // => 'moon'
*/
function decapitalize(subject) {
var subjectString = coerceToString(subject);
if (subjectString === '') {
return '';
}
return subjectString.substr(0, 1).toLowerCase() + subjectString.substr(1);
}
/**
* Converts the `subject` to <a href="https://en.wikipedia.org/wiki/Letter_case#cite_ref-13">kebab case</a>,
* also called <i>spinal case</i> or <i>lisp case</i>.
*
* @function kebabCase
* @static
* @since 1.0.0
* @memberOf Case
* @param {string} [subject=''] The string to convert to kebab case.
* @return {string} Returns the kebab case string.
* @example
* v.kebabCase('goodbye blue sky');
* // => 'goodbye-blue-sky'
*
* v.kebabCase('GoodbyeBlueSky');
* // => 'goodbye-blue-sky'
*
* v.kebabCase('-Goodbye-Blue-Sky-');
* // => 'goodbye-blue-sky'
*/
function kebabCase(subject) {
var subjectString = coerceToString(subject);
if (subjectString === '') {
return '';
}
return words(subjectString).map(lowerCase).join('-');
}
/**
* Converts the `subject` to <a href="https://en.wikipedia.org/wiki/Snake_case">snake case</a>.
*
* @function snakeCase
* @static
* @since 1.0.0
* @memberOf Case
* @param {string} [subject=''] The string to convert to snake case.
* @return {string} Returns the snake case string.
* @example
* v.snakeCase('learning to fly');
* // => 'learning_to_fly'
*
* v.snakeCase('LearningToFly');
* // => 'learning_to_fly'
*
* v.snakeCase('-Learning-To-Fly-');
* // => 'learning_to_fly'
*/
function snakeCase(subject) {
var subjectString = coerceToString(subject);
if (subjectString === '') {
return '';
}
return words(subjectString).map(lowerCase).join('_');
}
/**
* Converts the `subject` to upper case.
*
* @function upperCase
* @static
* @since 1.0.0
* @memberOf Case
* @param {string} [subject=''] The string to convert to upper case.
* @return {string} Returns the upper case string.
* @example
* v.upperCase('school');
* // => 'SCHOOL'
*/
function upperCase(subject) {
var subjectString = coerceToString(subject);
return subjectString.toUpperCase();
}
/**
* Converts the uppercase alpha characters of `subject` to lowercase and lowercase
* characters to uppercase.
*
* @function swapCase
* @static
* @since 1.3.0
* @memberOf Case
* @param {string} [subject=''] The string to swap the case.
* @return {string} Returns the converted string.
* @example
* v.swapCase('League of Shadows');
* // => 'lEAGUE OF sHADOWS'
*
* v.swapCase('2 Bees');
* // => '2 bEES'
*/
function swapCase(subject) {
var subjectString = coerceToString(subject);
return subjectString.split('').reduce(swapAndConcat, '');
}
function swapAndConcat(swapped, character) {
var lowerCase = character.toLowerCase();
var upperCase = character.toUpperCase();
return swapped + (character === lowerCase ? upperCase : lowerCase);
}
/**
* Converts the subject to title case.
*
* @function titleCase
* @static
* @since 1.4.0
* @memberOf Case
* @param {string} [subject=''] The string to convert to title case.
* @param {Array} [noSplit] Do not split words at the specified characters.
* @return {string} Returns the title case string.
* @example
* v.titleCase('learning to fly');
* // => 'Learning To Fly'
*
* v.titleCase('jean-luc is good-looking', ['-']);
* // => 'Jean-luc Is Good-looking'
*/
function titleCase(subject, noSplit) {
var subjectString = coerceToString(subject);
var noSplitArray = Array.isArray(noSplit) ? noSplit : [];
var wordsRegExp = REGEXP_EXTENDED_ASCII.test(subjectString) ? REGEXP_LATIN_WORD : REGEXP_WORD;
return subjectString.replace(wordsRegExp, function (word, index) {
var isNoSplit = index > 0 && noSplitArray.indexOf(subjectString[index - 1]) >= 0;
return isNoSplit ? word.toLowerCase() : capitalize(word, true);
});
}
/**
* Clip the number to interval `downLimit` to `upLimit`.
*
* @ignore
* @function clipNumber
* @param {number} value The number to clip
* @param {number} downLimit The down limit
* @param {number} upLimit The upper limit
* @return {number} The clipped number
*/
function clipNumber(value, downLimit, upLimit) {
if (value <= downLimit) {
return downLimit;
}
if (value >= upLimit) {
return upLimit;
}
return value;
}
/**
* Max save integer value
*
* @ignore
* @type {number}
*/
var MAX_SAFE_INTEGER = 0x1fffffffffffff;
/**
* Transforms `value` to an integer.
*
* @ignore
* @function toInteger
* @param {number} value The number to transform.
* @returns {number} Returns the transformed integer.
*/
function toInteger(value) {
if (value === Infinity) {
return MAX_SAFE_INTEGER;
}
if (value === -Infinity) {
return -MAX_SAFE_INTEGER;
}
return ~~value;
}
/**
* Truncates `subject` to a new `length`.
*
* @function truncate
* @static
* @since 1.0.0
* @memberOf Chop
* @param {string} [subject=''] The string to truncate.
* @param {int} length The length to truncate the string.
* @param {string} [end='...'] The string to be added at the end.
* @return {string} Returns the truncated string.
* @example
* v.truncate('Once upon a time', 7);
* // => 'Once...'
*
* v.truncate('Good day, Little Red Riding Hood', 14, ' (...)');
* // => 'Good day (...)'
*
* v.truncate('Once upon', 10);
* // => 'Once upon'
*/
function truncate(subject, length, end) {
var subjectString = coerceToString(subject);
var lengthInt = isNil(length) ? subjectString.length : clipNumber(toInteger(length), 0, MAX_SAFE_INTEGER);
var endString = coerceToString(end, '...');
if (lengthInt >= subjectString.length) {
return subjectString;
}
return subjectString.substr(0, length - endString.length) + endString;
}
/**
* Access a character from `subject` at specified `position`.
*
* @function charAt
* @static
* @since 1.0.0
* @memberOf Chop
* @param {string} [subject=''] The string to extract from.
* @param {numbers} position The position to get the character.
* @return {string} Returns the character at specified position.
* @example
* v.charAt('helicopter', 0);
* // => 'h'
*
* v.charAt('helicopter', 1);
* // => 'e'
*/
function charAt(subject, position) {
var subjectString = coerceToString(subject);
return subjectString.charAt(position);
}
var HIGH_SURROGATE_START = 0xd800;
var HIGH_SURROGATE_END = 0xdbff;
var LOW_SURROGATE_START = 0xdc00;
var LOW_SURROGATE_END = 0xdfff;
/**
* Checks if `codePoint` is a high-surrogate number from range 0xD800 to 0xDBFF.
*
* @ignore
* @param {number} codePoint The code point number to be verified
* @return {boolean} Returns a boolean whether `codePoint` is a high-surrogate number.
*/
function isHighSurrogate(codePoint) {
return codePoint >= HIGH_SURROGATE_START && codePoint <= HIGH_SURROGATE_END;
}
/**
* Checks if `codePoint` is a low-surrogate number from range 0xDC00 to 0xDFFF.
*
* @ignore
* @param {number} codePoint The code point number to be verified
* @return {boolean} Returns a boolean whether `codePoint` is a low-surrogate number.
*/
function isLowSurrogate(codePoint) {
return codePoint >= LOW_SURROGATE_START && codePoint <= LOW_SURROGATE_END;
}
/**
* Get the astral code point number based on surrogate pair numbers.
*
* @ignore
* @param {number} highSurrogate The high-surrogate code point number.
* @param {number} lowSurrogate The low-surrogate code point number.
* @return {number} Returns the astral symbol number.
*/
function getAstralNumberFromSurrogatePair(highSurrogate, lowSurrogate) {
return (highSurrogate - HIGH_SURROGATE_START) * 0x400 + lowSurrogate - LOW_SURROGATE_START + 0x10000;
}
/**
* Get the number representation of the `value`.
* Converts the `value` to number.
* If `value` is `null` or `undefined`, return `defaultValue`.
*
* @ignore
* @function toString
* @param {*} value The value to convert.
* @param {*} [defaultValue=''] The default value to return.
* @return {number|null} Returns the number representation of `value`. Returns `defaultValue` if `value` is
* `null` or `undefined`.
*/
function coerceToNumber(value) {
var defaultValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
if (isNil(value)) {
return defaultValue;
}
if (typeof value === 'number') {
return value;
}
return Number(value);
}
/**
* If `value` is `NaN`, return `defaultValue`. In other case returns `value`.
*
* @ignore
* @function nanDefault
* @param {*} value The value to verify.
* @param {*} defaultValue The default value.
* @return {*} Returns `defaultValue` if `value` is `NaN`, otherwise `defaultValue`.
*/
function nanDefault(value, defaultValue) {
return value !== value ? defaultValue : value;
}
/**
* Get the Unicode code point value of the character at `position`. <br/>
* If a valid UTF-16 <a href="https://rainsoft.io/what-every-javascript-developer-should-know-about-unicode/#24surrogatepairs">
* surrogate pair</a> starts at `position`, the
* <a href="https://rainsoft.io/what-every-javascript-developer-should-know-about-unicode/#astralplanes">astral code point</a>
* value at `position` is returned.
*
* @function codePointAt
* @static
* @since 1.0.0
* @memberOf Chop
* @param {string} [subject=''] The string to extract from.
* @param {number} position The position to get the code point number.
* @return {number} Returns a non-negative number less than or equal to `0x10FFFF`.
* @example
* v.codePointAt('rain', 1);
* // => 97, or 0x0061
*
* v.codePointAt('\uD83D\uDE00 is smile', 0); // or '😀 is smile'
* // => 128512, or 0x1F600
*/
function codePointAt(subject, position) {
var subjectString = coerceToString(subject);
var subjectStringLength = subjectString.length;
var positionNumber = coerceToNumber(position);
positionNumber = nanDefault(positionNumber, 0);
if (positionNumber < 0 || positionNumber >= subjectStringLength) {
return undefined;
}
var firstCodePoint = subjectString.charCodeAt(positionNumber);
var secondCodePoint;
if (isHighSurrogate(firstCodePoint) && subjectStringLength > positionNumber + 1) {
secondCodePoint = subjectString.charCodeAt(positionNumber + 1);
if (isLowSurrogate(secondCodePoint)) {
return getAstralNumberFromSurrogatePair(firstCodePoint, secondCodePoint);
}
}
return firstCodePoint;
}
/**
* Extracts the first `length` characters from `subject`.
*
* @function first
* @static
* @since 1.0.0
* @memberOf Chop
* @param {string} [subject=''] The string to extract from.
* @param {int} [length=1] The number of characters to extract.
* @return {string} Returns the first characters string.
* @example
* v.first('helicopter');
* // => 'h'
*
* v.first('vehicle', 2);
* // => 've'
*
* v.first('car', 5);
* // => 'car'
*/
function first(subject, length) {
var subjectString = coerceToString(subject);
var lengthInt = isNil(length) ? 1 : clipNumber(toInteger(length), 0, MAX_SAFE_INTEGER);
if (subjectString.length <= lengthInt) {
return subjectString;
}
return subjectString.substr(0, lengthInt);
}
/**
* Get a grapheme from `subject` at specified `position` taking care of
* <a href="https://rainsoft.io/what-every-javascript-developer-should-know-about-unicode/#24surrogatepairs">surrogate pairs</a> and
* <a href="https://rainsoft.io/what-every-javascript-developer-should-know-about-unicode/#25combiningmarks">combining marks</a>.
*
* @function graphemeAt
* @static
* @since 1.0.0
* @memberOf Chop
* @param {string} [subject=''] The string to extract from.
* @param {number} position The position to get the grapheme.
* @return {string} Returns the grapheme at specified position.
* @example
* v.graphemeAt('\uD835\uDC00\uD835\uDC01', 0); // or '𝐀𝐁'
* // => 'A'
*
* v.graphemeAt('cafe\u0301', 3); // or 'café'
* // => 'é'
*/
function graphemeAt(subject, position) {
var subjectString = coerceToString(subject);
var positionNumber = coerceToNumber(position);
var graphemeMatch;
var graphemeMatchIndex = 0;
positionNumber = nanDefault(positionNumber, 0);
while ((graphemeMatch = REGEXP_UNICODE_CHARACTER.exec(subjectString)) !== null) {
if (graphemeMatchIndex === positionNumber) {
REGEXP_UNICODE_CHARACTER.lastIndex = 0;
return graphemeMatch[0];
}
graphemeMatchIndex++;
}
return '';
}
/**
* Extracts the last `length` characters from `subject`.
*
* @function last
* @static
* @since 1.0.0
* @memberOf Chop
* @param {string} [subject=''] The string to extract from.
* @param {int} [length=1] The number of characters to extract.
* @return {string} Returns the last characters string.
* @example
* v.last('helicopter');
* // => 'r'
*
* v.last('vehicle', 2);
* // => 'le'
*
* v.last('car', 5);
* // => 'car'
*/
function last(subject, length) {
var subjectString = coerceToString(subject);
var lengthInt = isNil(length) ? 1 : clipNumber(toInteger(length), 0, MAX_SAFE_INTEGER);
if (subjectString.length <= lengthInt) {
return subjectString;
}
return subjectString.substr(subjectString.length - lengthInt, lengthInt);
}
/**
* Truncates `subject` to a new `length` and does not break the words. Guarantees that the truncated string is no longer
* than `length`.
*
* @static
* @function prune
* @since 1.0.0
* @memberOf Chop
* @param {string} [subject=''] The string to prune.
* @param {int} length The length to prune the string.
* @param {string} [end='...'] The string to be added at the end.
* @return {string} Returns the pruned string.
* @example
* v.prune('Once upon a time', 7);
* // => 'Once...'
*
* v.prune('Good day, Little Red Riding Hood', 16, ' (more)');
* // => 'Good day (more)'
*
* v.prune('Once upon', 10);
* // => 'Once upon'
*/
function prune(subject, length, end) {
var subjectString = coerceToString(subject);
var lengthInt = isNil(length) ? subjectString.length : clipNumber(toInteger(length), 0, MAX_SAFE_INTEGER);
var endString = coerceToString(end, '...');
if (lengthInt >= subjectString.length) {
return subjectString;
}
var pattern = REGEXP_EXTENDED_ASCII.test(subjectString) ? REGEXP_LATIN_WORD : REGEXP_WORD;
var truncatedLength = 0;
subjectString.replace(pattern, function (word, offset) {
var wordInsertLength = offset + word.length;
if (wordInsertLength <= lengthInt - endString.length) {
truncatedLength = wordInsertLength;
}
});
return subjectString.substr(0, truncatedLength) + endString;
}
/**
* Extracts from `subject` a string from `start` position up to `end` position. The character at `end` position is not
* included.
*
* @function slice
* @static
* @since 1.0.0
* @memberOf Chop
* @param {string} [subject=''] The string to extract from.
* @param {number} start The position to start extraction. If negative use `subject.length + start`.
* @param {number} [end=subject.length] The position to end extraction. If negative use `subject.length + end`.
* @return {string} Returns the extracted string.
* @note Uses native `String.prototype.slice()`
* @example
* v.slice('miami', 1);
* // => 'iami'
*
* v.slice('florida', -4);
* // => 'rida'
*
* v.slice('florida', 1, 4);
* // => "lor"
*/
function slice(subject, start, end) {
return coerceToString(subject).slice(start, end);
}
/**
* Extracts from `subject` a string from `start` position a number of `length` characters.
*
* @function substr
* @static
* @since 1.0.0
* @memberOf Chop
* @param {string} [subject=''] The string to extract from.
* @param {number} start The position to start extraction.
* @param {number} [length=subject.endOfString] The number of characters to extract. If omitted, extract to the end of `subject`.
* @return {string} Returns the extracted string.
* @note Uses native `String.prototype.substr()`
* @example
* v.substr('infinite loop', 9);
* // => 'loop'
*
* v.substr('dreams', 2, 2);
* // => 'ea'
*/
function substr(subject, start, length) {
return coerceToString(subject).substr(start, length);
}
/**
* Extracts from `subject` a string from `start` position up to `end` position. The character at `end` position is not
* included.
*
* @function substring
* @static
* @since 1.0.0
* @memberOf Chop
* @param {string} [subject=''] The string to extract from.
* @param {number} start The position to start extraction.
* @param {number} [end=subject.length] The position to end extraction.
* @return {string} Returns the extracted string.
* @note Uses native `String.prototype.substring()`
* @example
* v.substring('beach', 1);
* // => 'each'
*
* v.substring('ocean', 1, 3);
* // => 'ea'
*/
function substring(subject, start, end) {
return coerceToString(subject).substring(start, end);
}
/**
* Counts the characters in `subject`.<br/>
*
* @function count
* @static
* @since 1.0.0
* @memberOf Count
* @param {string} [subject=''] The string to count characters.
* @return {number} Returns the number of characters in `subject`.
* @example
* v.count('rain');
* // => 4
*/
function count(subject) {
return coerceToString(subject).length;
}
/**
* Counts the graphemes in `subject` taking care of
* <a href="https://rainsoft.io/what-every-javascript-developer-should-know-about-unicode/#24surrogatepairs">surrogate pairs</a> and
* <a href="https://rainsoft.io/what-every-javascript-developer-should-know-about-unicode/#25combiningmarks">combining marks</a>.
*
* @function countGraphemes
* @static
* @since 1.0.0
* @memberOf Count
* @param {string} [subject=''] The string to count graphemes.
* @return {number} Returns the number of graphemes in `subject`.
* @example
* v.countGraphemes('cafe\u0301'); // or 'café'
* // => 4
*
* v.countGraphemes('\uD835\uDC00\uD835\uDC01'); // or '𝐀𝐁'
* // => 2
*
* v.countGraphemes('rain');
* // => 4
*/
function countGrapheme(subject) {
return coerceToString(subject).replace(REGEXP_COMBINING_MARKS, '*').replace(REGEXP_SURROGATE_PAIRS, '*').length;
}
/**
* Counts the number of `substring` appearances in `subject`.
*
* @function countSubstrings
* @static
* @since 1.0.0
* @memberOf Count
* @param {string} [subject=''] The string where to count.
* @param {string} substring The substring to be counted.
* @return {number} Returns the number of `substring` appearances.
* @example
* v.countSubstrings('bad boys, bad boys whatcha gonna do?', 'boys');
* // => 2
*
* v.countSubstrings('every dog has its day', 'cat');
* // => 0
*/
function countSubstrings(subject, substring) {
var subjectString = coerceToString(subject);
var substringString = coerceToString(substring);
var substringLength = substringString.length;
var count = 0;
var matchIndex = 0;
if (subjectString === '' || substringString === '') {
return count;
}
do {
matchIndex = subjectString.indexOf(substringString, matchIndex);
if (matchIndex !== -1) {
count++;
matchIndex += substringLength;
}
} while (matchIndex !== -1);
return count;
}
var reduce = Array.prototype.reduce;
/**
* Counts the characters in `subject` for which `predicate` returns truthy.
*
* @function countWhere
* @static
* @since 1.0.0
* @memberOf Count
* @param {string} [subject=''] The string to count characters.
* @param {Function} predicate The predicate function invoked on each character with parameters `(character, index, string)`.
* @param {Object} [context] The context to invoke the `predicate`.
* @return {number} Returns the number of characters for which `predicate` returns truthy.
* @example
* v.countWhere('hola!', v.isAlpha);
* // => 4
*
* v.countWhere('2022', function(character, index, str) {
* return character === '2';
* });
* // => 3
*/
function countWhere(subject, predicate, context) {
var subjectString = coerceToString(subject);
if (subjectString === '' || typeof predicate !== 'function') {
return 0;
}
var predicateWithContext = predicate.bind(context);
return reduce.call(subjectString, function (countTruthy, character, index) {
return predicateWithContext(character, index, subjectString) ? countTruthy + 1 : countTruthy;
}, 0);
}
/**
* Counts the number of words in `subject`.
*
* @function countWords
* @static
* @since 1.0.0
* @memberOf Count
* @param {string} [subject=''] The string to split into words.
* @param {string|RegExp} [pattern] The pattern to watch words. If `pattern` is not RegExp, it is transformed to `new RegExp(pattern, flags)`.
* @param {string} [flags=''] The regular expression flags. Applies when `pattern` is string type.
* @return {number} Returns the number of words.
* @example
* v.countWords('gravity can cross dimensions');
* // => 4
*
* v.countWords('GravityCanCrossDimensions');
* // => 4
*
* v.countWords('Gravity - can cross dimensions!');
* // => 4
*
* v.words('Earth gravity', /[^\s]+/g);
* // => 2
*/
function countWords(subject, pattern, flags) {
return words(subject, pattern, flags).length;
}
/**
* The current index.
*
* @ignore
* @name ReplacementIndex#index
* @type {number}
* @return {ReplacementIndex} ReplacementIndex instance.
*/
function ReplacementIndex() {
this.index = 0;
}
/**
* Increment the current index.
*
* @ignore
* @return {undefined}
*/
ReplacementIndex.prototype.increment = function () {
this.index++;
};
/**
* Increment the current index by position.
*
* @ignore
* @param {number} [position] The replacement position.
* @return {undefined}
*/
ReplacementIndex.prototype.incrementOnEmptyPosition = function (position) {
if (isNil(position)) {
this.increment();
}
};
/**
* Get the replacement index by position.
*
* @ignore
* @param {number} [position] The replacement position.
* @return {number} The replacement index.
*/
ReplacementIndex.prototype.getIndexByPosition = function (position) {
return isNil(position) ? this.index : position - 1;
};
// Type specifiers
var TYPE_INTEGER = 'i';
var TYPE_INTEGER_BINARY = 'b';
var TYPE_INTEGER_ASCII_CHARACTER = 'c';
var TYPE_INTEGER_DECIMAL = 'd';
var TYPE_INTEGER_OCTAL = 'o';
var TYPE_INTEGER_UNSIGNED_DECIMAL = 'u';
var TYPE_INTEGER_HEXADECIMAL = 'x';
var TYPE_INTEGER_HEXADECIMAL_UPPERCASE = 'X';
var TYPE_FLOAT_SCIENTIFIC = 'e';
var TYPE_FLOAT_SCIENTIFIC_UPPERCASE = 'E';
var TYPE_FLOAT = 'f';
var TYPE_FLOAT_SHORT = 'g';
var TYPE_FLOAT_SHORT_UPPERCASE = 'G';
var TYPE_STRING = 's'; // Simple literals
var LITERAL_SINGLE_QUOTE = "'";
var LITERAL_PLUS = '+';
var LITERAL_MINUS = '-';
var LITERAL_PERCENT_SPECIFIER = '%%'; // Radix constants to format numbers
var RADIX_BINARY = 2;
var RADIX_OCTAL = 8;
var RADIX_HEXADECIMAL = 16;
/**
* Repeats the `subject` number of `times`.
*
* @function repeat
* @static
* @since 1.0.0
* @memberOf Manipulate
* @param {string} [subject=''] The string to repeat.
* @param {number} [times=1] The number of times to repeat.
* @return {string} Returns the repeated string.
* @example
* v.repeat('w', 3);
* // => 'www'
*
* v.repeat('world', 0);
* // => ''
*/
function repeat(subject, times) {
var subjectString = coerceToString(subject);
var timesInt = isNil(times) ? 1 : clipNumber(toInteger(times), 0, MAX_SAFE_INTEGER);
var repeatString = '';
while (timesInt) {
if (timesInt & 1) {
repeatString += subjectString;
}
if (timesInt > 1) {
subjectString += subjectString;
}
timesInt >>= 1;
}
return repeatString;
}
/**
* Creates the padding string.
*
* @ignore
* @param {string} padCharacters The characters to create padding string.
* @param {number} length The padding string length.
* @return {string} The padding string.
*/
function buildPadding(padCharacters, length) {
var padStringRepeat = toInteger(length / padCharacters.length);
var padStringRest = length % padCharacters.length;
return repeat(padCharacters, padStringRepeat + padStringRest).substr(0, length);
}
/**
* Pads `subject` from left to a new `length`.
*
* @function padLeft
* @static
* @since 1.0.0
* @memberOf Manipulate
* @param {string} [subject=''] The string to pad.
* @param {int} [length=0] The length to left pad the string. No changes are made if `length` is less than `subject.length`.
* @param {string} [pad=' '] The string to be used for padding.
* @return {string} Returns the left padded string.
* @example
* v.padLeft('dog', 5);
* // => ' dog'
*
* v.padLeft('bird', 6, '-');
* // => '--bird'
*
* v.padLeft('cat', 6, '-=');
* // => '-=-cat'
*/
function padLeft(subject, length, pad) {
var subjectString = coerceToString(subject);
var lengthInt = isNil(length) ? 0 : clipNumber(toInteger(length), 0, MAX_SAFE_INTEGER);
var padString = coerceToString(pad, ' ');
if (lengthInt <= subjectString.length) {
return subjectString;
}
return buildPadding(padString, lengthInt - subjectString.length) + subjectString;
}
/**
* Pads `subject` from right to a new `length`.
*
* @function padRight
* @static
* @since 1.0.0
* @memberOf Manipulate
* @param {string} [subject=''] The string to pad.
* @param {int} [length=0] The length to right pad the string. No changes are made if `length` is less than `subject.length`.
* @param {string} [pad=' '] The string to be used for padding.
* @return {string} Returns the right padded string.
* @example
* v.padRight('dog', 5);
* // => 'dog '
*
* v.padRight('bird', 6, '-');
* // => 'bird--'
*
* v.padRight('cat', 6, '-=');
* // => 'cat-=-'
*/
function padRight(subject, length, pad) {
var subjectString = coerceToString(subject);
var lengthInt = isNil(length) ? 0 : clipNumber(toInteger(length), 0, MAX_SAFE_INTEGER);
var padString = coerceToString(pad, ' ');
if (lengthInt <= subjectString.length) {
return subjectString;
}
return subjectString + buildPadding(padString, lengthInt - subjectString.length);
}
/**
* Aligns and pads `subject` string.
*
* @ignore
* @param {string} subject The subject string.
* @param {ConversionSpecification} conversion The conversion specification object.
* @return {string} Returns the aligned and padded string.
*/
function alignAndPad(subject, conversion) {
var width = conversion.width;
if (isNil(width) || subject.length >= width) {
return subject;
}
var padType = conversion.alignmentSpecifier === LITERAL_MINUS ? padRight : padLeft;
return padType(subject, width, conversion.getPaddingCharacter());
}
/**
* Add sign to the formatted number.
*
* @ignore
* @name addSignToFormattedNumber
* @param {number} replacementNumber The number to be replaced.
* @param {string} formattedReplacement The formatted version of number.
* @param {ConversionSpecification} conversion The conversion specification object.
* @return {string} Returns the formatted number string with a sign.
*/
function addSignToFormattedNumber(replacementNumber, formattedReplacement, conversion) {
if (conversion.signSpecifier === LITERAL_PLUS && replacementNumber >= 0) {
formattedReplacement = LITERAL_PLUS + formattedReplacement;
}
return formattedReplacement;
}
/**
* Formats a float type according to specifiers.
*
* @ignore
* @param {string} replacement The string to be formatted.
* @param {ConversionSpecification} conversion The conversion specification object.
* @return {string} Returns the formatted string.
*/
function float(replacement, conversion) {
var replacementNumber = parseFloat(replacement);
var formattedReplacement;
if (isNaN(replacementNumber)) {
replacementNumber = 0;
}
var precision = coerceToNumber(conversion.precision, 6);
switch (conversion.typeSpecifier) {
case TYPE_FLOAT:
formattedReplacement = replacementNumber.toFixed(precision);
break;
case TYPE_FLOAT_SCIENTIFIC:
formattedReplacement = replacementNumber.toExponential(precision);
break;
case TYPE_FLOAT_SCIENTIFIC_UPPERCASE:
formattedReplacement = replacementNumber.toExponential(precision).toUpperCase();
break;
case TYPE_FLOAT_SHORT:
case TYPE_FLOAT_SHORT_UPPERCASE:
formattedReplacement = formatFloatAsShort(replacementNumber, precision, conversion);
break;
}
formattedReplacement = addSignToFormattedNumber(replacementNumber, formattedReplacement, conversion);
return coerceToString(formattedReplacement);
}
/**
* Formats the short float.
*
* @ignore
* @param {number} replacementNumber The number to format.
* @param {number} precision The precision to format the float.
* @param {ConversionSpecification} conversion The conversion specification object.
* @return {string} Returns the formatted short float.
*/
function formatFloatAsShort(replacementNumber, precision, conversion) {
if (replacementNumber === 0) {
return '0';
}
var nonZeroPrecision = precision === 0 ? 1 : precision;
var formattedReplacement = replacementNumber.toPrecision(nonZeroPrecision).replace(REGEXP_TRAILING_ZEROS, '');
if (conversion.typeSpecifier === TYPE_FLOAT_SHORT_UPPERCASE) {
formattedReplacement = formattedReplacement.toUpperCase();
}
return formattedReplacement;
}
/**
* Formats an integer type according to specifiers.
*
* @ignore
* @param {string} replacement The string to be formatted.
* @param {ConversionSpecification} conversion The conversion specification object.
* @return {string} Returns the formatted string.
*/
function integerBase(replacement, conversion) {
var integer = parseInt(replacement);
if (isNaN(integer)) {
integer = 0;
}
integer = integer >>> 0;
switch (conversion.typeSpecifier) {
case TYPE_INTEGER_ASCII_CHARACTER:
integer = String.fromCharCode(integer);
break;
case TYPE_INTEGER_BINARY:
integer = integer.toString(RADIX_BINARY);
break;
case TYPE_INTEGER_OCTAL:
integer = integer.toString(RADIX_OCTAL);
break;
case TYPE_INTEGER_HEXADECIMAL:
integer = integer.toString(RADIX_HEXADECIMAL);
break;
case TYPE_INTEGER_HEXADECIMAL_UPPERCASE:
integer = integer.toString(RADIX_HEXADECIMAL).toUpperCase();
break;
}
return coerceToString(integer);
}
/**
* Formats a decimal integer type according to specifiers.
*
* @ignore
* @param {string} replacement The string to be formatted.
* @param {ConversionSpecification} conversion The conversion specification object.
* @return {string} Returns the formatted string.
*/
function integerDecimal(replacement, conversion) {
var integer = parseInt(replacement);
if (isNaN(integer)) {
integer = 0;
}
return addSignToFormattedNumber(integer, toString(integer), conversion);
}
/**
* Formats a string type according to specifiers.
*
* @ignore
* @param {string} replacement The string to be formatted.
* @param {ConversionSpecification} conversion The conversion specification object.
* @return {string} Returns the formatted string.
*/
function stringFormat(replacement, conversion) {
var formattedReplacement = replacement;
var precision = conversion.precision;
if (!isNil(precision) && formattedReplacement.length > precision) {
formattedReplacement = truncate(formattedReplacement, precision, '');
}
return formattedReplacement;
}
/**
* Returns the computed string based on format specifiers.
*
* @ignore
* @name computeReplacement
* @param {string} replacement The replacement value.
* @param {ConversionSpecification} conversion The conversion specification object.
* @return {string} Returns the computed string.
*/
function compute(replacement, conversion) {
var formatFunction;
switch (conversion.typeSpecifier) {
case TYPE_STRING:
formatFunction = stringFormat;
break;
case TYPE_INTEGER_DECIMAL:
case TYPE_INTEGER:
formatFunction = integerDecimal;
break;
case TYPE_INTEGER_ASCII_CHARACTER:
case TYPE_INTEGER_BINARY:
case TYPE_INTEGER_OCTAL:
case TYPE_INTEGER_HEXADECIMAL:
case TYPE_INTEGER_HEXADECIMAL_UPPERCASE:
case TYPE_INTEGER_UNSIGNED_DECIMAL:
formatFunction = integerBase;
break;
case TYPE_FLOAT:
case TYPE_FLOAT_SCIENTIFIC:
case TYPE_FLOAT_SCIENTIFIC_UPPERCASE:
case TYPE_FLOAT_SHORT:
case TYPE_FLOAT_SHORT_UPPERCASE:
formatFunction = float;
break;
}
var formattedString = formatFunction(replacement, conversion);
return alignAndPad(formattedString, conversion);
}
/**
* Construct the new conversion specification object.
*
* @ignore
* @param {Object} properties An object with properties to initialize.
* @return {ConversionSpecification} ConversionSpecification instance.
*/
function ConversionSpecification(proper