'use strict';
if ( ( 0, eval )( 'this' ).XtraUtils && ( 0, eval )( 'this' ).XtraUtils.Utility ) {
/**
* @type {Utility}
* @property {function} aidsIn The String class
* @property {Object} aidsIn.prototype the String prototype
* @namespace
* @memberof XtraUtils
*/
XtraUtils.String = new XtraUtils.Utility( String );
const { min, ceil, round, random, pow } = Math,
words = str => str.match( /((?:^_*)?(?:[A-Z][-_A-Z]*|[^-\s_A-Z]+)(?:_*$)?)/gi ),
repeat = ( string, times ) => somethinghacky.call( string, ceil( times ) ).slice( 0, Math.round( times * string.length ) ),
toUpperCase = str => ''.toUpperCase.call( str ),
toLowerCase = str => ''.toLowerCase.call( str ),
somethinghacky = XtraUtils.String.aidsIn.prototype.repeat;
XtraUtils.String.addMethod( 'generateRandom', ( function(){
function generateRandom( len = 7 ) {
return ( random() * pow( 36, len ) ).toString( 36 ).split( '.' )[0];
}
} )() );
XtraUtils.String.addUtil( 'reverse', ( function(){
/**
* Reverses a string
* @returns {string} The reversed string.
* @memberof XtraUtils.String#
*/
function reverse(){
return this.split( '' ).reverse().join( '' );
}
return reverse;
} )() );
XtraUtils.String.addUtil( 'sort', ( function(){
/**
* Sorts a string by character.
* @param {CallBack} [sortFunction=(str1,str2)=>{return str1.charCodeAt(0) - str2.charCodeAt(0)}] The function to sort it with. By default, it sorts by character code.
* @returns {string} The sorted string.
* @memberof XtraUtils.String#
*/
function sort( sortFunction = ( str1,str2 )=>{return str1.charCodeAt( 0 ) - str2.charCodeAt( 0 );} ){
return this.split( '' ).sort( sortFunction ).join( '' );
}
return sort;
} )() );
XtraUtils.String.addMethod( 'rot13', ( function(){
const translate = x => index( x ) > -1 ? output[index( x )] : x,
index = x => input.indexOf( x ),
input = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
output = 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm';
/**
* Reverses the famous rot13 cipher.
* @param {string} str The string to perform rot13 on.
* @returns {string} The de-ciphered string.
* @memberof XtraUtils.String.
*/
return function rot13( str ) {
return str.split( '' ).map( translate ).join( '' );
};
return rot13;
} )() );
XtraUtils.String.addMethod( 'levenshtein', ( function(){
const last = arr => arr[arr.length - 1];
/**
* Finds the [Levenshtein distance]{@link https://en.wikipedia.org/wiki/Levenshtein_distance} between a string and another string.
* @param {string} str1 The first string to find the distance between.
* @param {string} str2 The second string.
* @returns {number} The Levenshtein distance.
* @memberof XtraUtils.String.
*/
function levenshtein( str1, str2 ){
let charArr1 = str1.split( '' ),
charArr2 = str2.split( '' ),
Vector0 = [],
Vector1 = [],
deletionCost, insertionCost, substitutionCost;
charArr2.forEach( ( _,index ) => {
Vector0[index] = index;
} );
charArr1.forEach( ( item1, index1 ) => {
if( item1 !== last( charArr1 ) ) {
Vector1[0] = index1 + 1;
charArr2.forEach( ( item2, index2 ) => {
deletionCost = Vector0[index2 + 1] + 1;
insertionCost = Vector1[index2] + 1;
if( charArr1[index2] === charArr2[index2] ) {
substitutionCost = Vector0[index2];
} else {
substitutionCost = Vector0[index2] + 1;
}
Vector1[index2 + 1] = min( deletionCost,insertionCost,substitutionCost );
} );
const temp1 = Vector1,
temp2 = Vector0;
Vector0 = temp1;
Vector1 = temp2;
}
} );
return Vector0[charArr2.length - 1];
}
return levenshtein;
} )() );
XtraUtils.String.addUtil( 'words', ( function(){
/**
* Finds the words in a string, per the following regex:
* ````javascript
* /((?:^_*)?(?:[A-Z][-_A-Z]*|[^-\s_A-Z]+)(?:_*$)?)/gi
* ````.
* @returns {Array.<string>} The words.
* @memberof XtraUtils.String#
*/
function words() {
/*
This regex is to match all words in the string
/((?:^_*)?(?:[A-Z][-_A-Z]*|[^-\s_A-Z]+)(?:_*$)?)/gi : Regex to match words
((?:^_*)?(?:[A-Z][-_A-Z]*|[^-\s_A-Z]+)(?:_*$)?) : Main group
(?:^_*) : Match all '_' in the string, non-capturing
(?: ) : Non-capturing
^ : Position at start of string
_* : Match '_' as many times as needed
( )? : Match this group between 0 and 1 times, giving back as needed
(?:[A-Z][-_A-Z]*|[^-\s_A-Z]+) : Find all matches for letters A-Z and anything that is not a space
(?: ) : Non-capturing
[A-Z] : Match the characters A-Z
[-_A-Z]* : Match the characters A-Z, hyphen, and underscore as many times as needed
| : Regex OR
[^-\s_A-Z]+ : Match anything that is not a space or a letter or a hyphen or an underscore
(?:_*$)? : Match underscore as many times as needed at the end of the string but only count as one match
(?: ) : Non-capturing
_* : Match underscore as many times as needed
$ : Match at end of string
( )? : Match this group only once
gi : Global and case-Insesensitive flags
*/
return this.match( /((?:^_*)?(?:[A-Z][-_A-Z]*|[^-\s_A-Z]+)(?:_*$)?)/gi );
}
return words;
} )() );
XtraUtils.String.addUtil( 'toCamelCase', ( function(){
/**
* Converts the string to camelCase.
* @returns {string} The camelCase form of the string.
* @memberof XtraUtils.String#
* @example
* // returns 'myCat'
* let str = 'my cat';
* str.toCamelCase();
*/
function toCamelCase() {
return words( this )
.map( function( _ ) { return _.replace( /^./, function( match ) { return toUpperCase( match ); } );} )
.join( '' )
.replace( /^./, function( match ) { return toLowerCase( match ); } );
}
return toCamelCase;
} )() );
XtraUtils.String.addUtil( 'ToPascalCase', ( function(){
/**
* Converts the string to PascalCase.
* @returns {string} The PascalCase form of the string.
* @memberof XtraUtils.String#
* @example
* // returns 'MyCat'
* let str = 'my cat';
* str.ToPascalCase();
*/
function ToPascalCase() {
return words( this )
.map( function( _ ) { return _.replace( /^./, function( match ) { return toUpperCase( match ); } );} )
.join( '' );
}
return ToPascalCase;
} )() );
XtraUtils.String.addUtil( 'to_snake_case', ( function(){
/**
* Converts the string to snake_case.
* @returns {string} The snake_case form of the string.
* @memberof XtraUtils.String#
* @example
* // returns 'my_cat'
* let str = 'my cat';
* str.to_snake_case();
*/
function to_snake_case() {
return words( this )
.map( function( _ ) { return _.replace( /^./, function( match ) { return toLowerCase( match ); } );} )
.join( '_' );
}
return to_snake_case;
} )() );
XtraUtils.String.addUtil( 'TO_CONSTANT_CASE', ( function(){
/**
* Converts the string to CONSTANT_CASE.
* @returns {string} The CONSTANT_CASE form of the string.
* @memberof XtraUtils.String#
* @example
* // returns 'my_cat'
* let str = 'my cat';
* str.to_snake_case();
*/
function TO_CONSTANT_CASE() {
return words( toUpperCase( this ) )
.join( '_' );
}
return TO_CONSTANT_CASE;
} )() );
XtraUtils.String.addUtil( 'to_seperated_case', ( function(){
/**
* Converts the string to a seperated case, where the seperator is defined by the user.
* @param {string} [seperator="-"] The seperator to seperate the string with.
* @returns {string} The resulting seperated form of the string.
* @memberof XtraUtils.String#
* @example
* // returns 'my-cat'
* let str = 'my cat';
* str.to-seperated-case();
* @example
* // returns 'my|cat'
* let str = 'my cat';
* str.to-seperated-case('|');
*/
function to_seperated_case( seperator = '-' ) {
return this.words()
.map( function( _ ){ return _.replace( /^./, function( match ) { return toLowerCase( match ); } );} )
.join( seperator );
}
return to_seperated_case;
} )() );
XtraUtils.String.addUtil( 'ToTitleCase', ( function(){
/**
* Converts the string to a seperated case, where the seperator is defined by the user.
* @returns {string} The resulting Title Case form of the string.
* @memberof XtraUtils.String#
* @example
* // returns 'My Cat'
* let str = 'my cat';
* str.ToTitleCase();
*/
function ToTitleCase(){
return this.words()
.map( function( _ ){ return _.replace( /^./, function( match ){ return toUpperCase( match ); } );} )
.join( ' ' );
}
return ToTitleCase;
} )() );
XtraUtils.String.addUtil( 'repeat', ( function(){
/**
* An extension of the native repeat, this one takes decimals as a parameter, and splits the string accordingly.
* @param {number} times How many times to repeat the string. Splits string if it is a decimal.
* @returns {string} The repeated string.
* @memberof XtraUtils.String#
* @example
* // returns 'my catmy cat'
* let str = 'my cat';
* str.repeat(2);
* @example
* // returns 'my catmy '
* let str = 'my cat';
* str.repeat(1.5);
*/
function repeat( times ){
return somethinghacky.call( this, ceil( times ) ).slice( 0, round( times * this.length ) );
}
return repeat;
} )() );
XtraUtils.String.addUtil( 'padLeft', ( function(){
return function padLeft( len = this.length, char = ' ' ){
if( this.length >= len ){
return this;
}
return repeat( char, len - this.length ) + this;
};
} )() );
XtraUtils.String.addUtil( 'padRight', ( function(){
return function padRight( len, char ){
if( this.length >= len ){
return this;
}
char = char || ' ';
return this + repeat( char, len - this.length );
};
} )() );
} else {
console.warn( 'XtraUtils is not defined. For more details, please visit ' +
'https://github.com/FreezePhoenix/XtraUtils/. If your issue still occurs, submit an issue here:' +
'https://github.com/FreezePhoenix/XtraUtils/issues/new' );
}
/**
* @callback CallBack
* @param {string} str The string being passed
* @returns {*}
* @memberof XtraUtils.String
*/