UNPKG

sussy-util

Version:
492 lines (491 loc) 20.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.slugify = exports.randomString = exports.isEmpty = exports.reverse = void 0; const _1 = require("."); class StringUtil { static dedupeChars(s) { return Array.from(new Set(s.split(''))).join(''); } static safeCharset(charset) { return charset && charset.length > 0 ? StringUtil.dedupeChars(charset) : 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; } /** * It takes a string, splits it into an array of characters, reverses the array, and joins the * array back into a string * @param {string} input - The string to be reversed. * @returns The reverse of the input string. */ static reverse(input) { return input.split('').reverse().join(''); } /** * It takes a string of characters and returns a random character from that string. * @param {string} [charset] - The characters to choose from. Defaults to all alphanumeric * characters. * @returns A random character from the charset. */ static randomCharacter(charset) { const cs = StringUtil.safeCharset(charset); const idx = _1.Random.randomInt(0, cs.length); return cs.charAt(idx); } /** * Generate a random string of a given length, using a given character set. * @param {number} length - number - The length of the string to generate * @param {string} [characterset] - The characterset to use for the random string. * @returns A string of random characters. */ static randomString(length, characterset) { if (!Number.isFinite(length) || length <= 0) return ''; const cs = StringUtil.safeCharset(characterset); return Array.from({ length }, () => StringUtil.randomCharacter(cs)).join(''); } /** * It generates a random string, checks if it's a valid discord username, if it's not, it generates * another one, if it is, it returns it. * @param [withSuffix=false] - boolean * @returns A random string that is a valid discord username. * @deprecated */ static randomDiscordUsername(withSuffix = false) { const length = _1.Random.randomInt(4, 33); let name = StringUtil.randomString(length); if (!StringUtil.isDiscordUsername(`${name}#0000`)) { name = StringUtil.randomDiscordUsername(false); } if (!withSuffix) return name; return `${name}#${_1.Random.randomInt(0, 10)}${_1.Random.randomInt(0, 10)}${_1.Random.randomInt(0, 10)}${_1.Random.randomInt(0, 10)}`; } /** * It returns true if the username is a valid Discord username, and false if it isn't * @param {string} username - The username to check. * @returns A boolean value. * @deprecated */ static isDiscordUsername(username) { return !!username.match(/^.{4,32}#\d{4}$/); } /** * If the value is a string, and the string contains only digits, then return true. Otherwise, * return false * @param {string} value - The value to be tested. * @returns A boolean value. */ static isInteger(value) { return /^(-)?\d+$/.test(value); } /** * It returns true if the value is a float, otherwise it returns false * @param {string} value - string - The value to check * @returns A boolean value. */ static isFloat(value) { return /^-?(?:\d+|\d+\.\d+|\.\d+)$/.test(value); } /** * The password must be at least eight characters long and contain at least one lowercase letter, * one uppercase letter, one numeric digit, and one special character * @param {string} value - string - The value to check * @returns A boolean value. */ static isStrongPassword(value) { return /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/.test(value); } /** * If the password is not strong, then it is weak. * @param {string} value - string - The value to check. * @returns The return value is a boolean. */ static isWeakPassword(value) { return !StringUtil.isStrongPassword(value); } /** * It checks if the value is a string, and if it is, it checks if the string is at least 4 * characters long, contains an @ symbol, and ends with a . followed by at least 2 characters * @param {string} value - string - The value to be tested. * @returns A boolean value. */ static isEmail(value) { return /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/.test(value); } /** * It checks if the value is a valid HTTP URL. * @param {string} value - The value to be tested. * @returns A boolean value. */ static isHTTPUrl(value) { if (!value) return false; try { const u = new URL(value); return u.protocol === 'http:' || u.protocol === 'https:'; } catch (_a) { return false; } } /** * It checks if the value is a valid URL without the HTTP or HTTPS prefix * @param {string} value - string - The value to be tested. * @returns A boolean value. */ static isUrlWithoutHTTP(value) { return /[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&/=]*)/.test(value); } /** * If the string is a URL, return true, otherwise return false. * @param {string} value - string * @returns A boolean value. */ static isURL(value) { return StringUtil.isHTTPUrl(value) || StringUtil.isUrlWithoutHTTP(value); } /** * It takes a string, a length, and an ellipsis count, and returns a string that is the original * string shortened to the length, with the ellipsis count number of ellipses appended to the end. * * @param {string} value - The string to shorten * @param {number} length - The length of the string you want to return. * @param {number} ellipsisCount - The number of dots to use in the ellipsis. * @returns The value of the string is being returned. */ static shorten(value, length, ellipsisCount) { if (length >= value.length) return value; const ellipsis = '.'.repeat(Math.max(0, ellipsisCount)); return value.substring(0, length) + ellipsis; } /** * It takes a string, converts it to lowercase, trims it, removes all non-word characters, replaces * all whitespace and underscores with a dash, and removes all leading and trailing dashes * @param {string} str - string - The string to slugify * @returns A string */ static slugify(str) { return str .toLowerCase() .trim() .replace(/[^\w\s-]/g, '') .replace(/[\s_-]+/g, '-') .replace(/^-+|-+$/g, ''); } /** * Capitalize the first letter of a string and lowercase the rest. * @param {string} value - string - The string to be capitalized. * @returns The first character of the string is being returned in uppercase and the rest of the * string is being returned in lowercase. */ static capitalize(value) { return value.charAt(0).toUpperCase() + value.slice(1).toLowerCase(); } /** * It takes a string and returns the same string with the first letter lowercase. * @param {string} value - string - The string to uncapitalize. * @returns The first character of the string is converted to lowercase and then concatenated with * the rest of the string. */ static uncapitalize(value) { return value.charAt(0).toLowerCase() + value.slice(1); } /** * It returns true if the value is a valid IPv4 address, otherwise it returns false. * @param {string} value - The value to check. * @returns A boolean value. */ static isIPv4(value) { return /^(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(value); } /** * It checks if the value is a valid IPv6 address. * @param {string} value - The value to check. * @returns A boolean value. */ static isIPv6(value) { return /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]+|::(ffff(:0{1,4})?:)?((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1?[0-9])?[0-9])\.){3}(25[0-5]|(2[0-4]|1?[0-9])?[0-9]))$/.test(value); } /** * If the value is an IPv4 address, return true. Otherwise, if the value is an IPv6 address, * return true. Otherwise, return false. * @param {string} value - string * @returns A boolean value. */ static isIP(value) { return StringUtil.isIPv4(value) || StringUtil.isIPv6(value); } /** * It returns true if the value is a valid MAC address, otherwise it returns false * @param {string} value - The value to check. * @returns A boolean value. */ static isMacAddress(value) { return /^(?:[0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}$/.test(value); } /** * If the value is a string that matches the regular expression, then return true, otherwise return * false. * @param {string} value - string - The value to be tested. * @returns A boolean value. */ static isPhoneNumber(value) { return /^[\\(]\d{3}[\\)]\s\d{3}-\d{4}$/.test(value); } /** * It takes a string, gets the first character, makes it uppercase, and then adds the rest of the * string to it * @param {string} str - string - The string to be converted. * @returns The first character of the string is being returned in uppercase, and the rest of the * string is being returned in lowercase. */ static upperFirst(str) { return str.charAt(0).toUpperCase() + str.substring(1); } /** * It takes a string, and returns a new string with the first character lowercased * @param {string} str - string - The string to be converted. * @returns The first character of the string is being returned in lowercase, and the rest of the * string is being returned in its original case. */ static lowerFirst(str) { return str.charAt(0).toLowerCase() + str.substring(1); } /** * It takes a string, splits it on non-word characters and underscores, capitalizes each word, and * joins them together * @param {string} str - string - The string to be converted to camelCase * @returns The first letter of the string is being returned in lowercase. */ static camelCase(str) { return StringUtil.lowerFirst(str .split(/[^\w]|_+/) .map((val) => StringUtil.capitalize(val)) .join('')); } /** * It takes a string, trims it, splits it into an array of words, filters out any empty words, and * then joins the array back into a string * @param {string} str - string - The string to be collapsed. * @returns A string */ static collaps(str) { return str .trim() .split(' ') .filter((part) => part.length > 0) .join(' '); } /** * It takes a string, trims it, splits it into an array of strings, and then joins it back together * @param {string} str - string - The string to be trimmed. * @returns The string with no spaces. */ static noSpaces(str) { return str.trim().split(' ').join(''); } /** * It takes a string, splits it into an array of characters, maps each character to its charCode, * and then joins the array of charCodes into a string * @param {string} str - string - The string to convert to char codes. * @returns The charCodeAt() method returns an integer between 0 and 65535 representing the UTF-16 * code unit at the given index. */ static toCharCode(str) { return str .split('') .map((val) => val.charCodeAt(0)) .join(''); } /** * It takes a string, checks if it's an email, splits it in half, shortens the first half, and * returns the result. * @param {string} str - string - The string to protect * @returns The email address with the first half of the email address shortened to 3 characters. */ static protectEmail(str) { if (!StringUtil.isEmail(str)) return str; const half = str.split('@'); half[0] = StringUtil.shorten(half[0], half[0].length / 2, 3); return half.join('@'); } /** * It takes a string, and returns a string with the first letter of each word capitalized, and the * rest of the letters lowercase. * @param {string} str - string - The string to be swapped. * @returns the string with the first letter of each word capitalized. */ static swapCase(str) { return str .split('') .map((ch) => { if (ch >= 'a' && ch <= 'z') return ch.toUpperCase(); if (ch >= 'A' && ch <= 'Z') return ch.toLowerCase(); return ch; }) .join(''); } /** * It generates a random string of a given length, using a given set of characters, and if the * generated string is not strong enough, it generates another one * @param {number} length - number - The length of the password to generate * @param {string} [characters] - string = * "ascdefghijklmnopqrstuvwxyzABCDEFGHIJLMOPRSTUVWXYZ1234567890!$$%&?#*+~'" * @returns A string of length `length` that is a strong password. */ static generatePassword(length, characters) { characters = characters || "ascdefghijklmnopqrstuvwxyzABCDEFGHIJLMOPRSTUVWXYZ1234567890!§$%&?#*+~'"; const uniqueChars = [...new Set(characters.split(''))].join(''); if (uniqueChars.length < 8) throw new Error('Not enough characters to generate password'); const maxAttempts = 500; for (let attempt = 0; attempt < maxAttempts; attempt++) { const result = StringUtil.randomString(length, characters); if (StringUtil.isStrongPassword(result)) return result; } throw new Error('Failed to generate a strong password'); } /** * It returns a random color code in hexadecimal format. * @returns A random color code. */ static randomColorCode() { const num = Math.floor(Math.random() * 0xffffff); return `#${num.toString(16).padStart(6, '0')}`; } /** * It returns the number of words in a string. * @param {string} str - string - The string to count the words in. * @returns The number of words in the string. */ static wordCount(str) { const words = str.match(/\b\w+\b/g); if (!words) { return 0; } return words.length; } static getRatingString(rate) { return '★'.repeat(rate) + '☆'.repeat(5 - rate); } /** * It replaces all line breaks with the lineEnd parameter. * @param {string} str - string - The string to normalize. * @param {string} [lineEnd] - The line ending to normalize to (defaults to \n). * @returns A string with all line breaks normalized to the specified lineEnd string, or the * default lineEnd string. */ static normalizeLineBreaks(str, lineEnd) { lineEnd = lineEnd || '\n'; return str.replace(/\r\n/g, lineEnd).replace(/\r/g, lineEnd).replace(/\n/g, lineEnd); } /** * It returns true if the string contains the substring, otherwise it returns false * @param {string} str - The string to search in. * @param {string} substring - The substring to search for. * @param {number} fromIndex - The index at which to begin searching the String object. If omitted, * search starts at the beginning of the string. * @returns The index of the first occurrence of the specified substring, or -1 if there is no such * occurrence. */ static contains(str, substring, fromIndex) { return str.indexOf(substring, fromIndex) !== -1; } /** * @param {string} str - string - The string to pad. * @param {number} minLen - The minimum length of the string. * @param {string} [ch] - The character to pad the string with. * @returns The string with the padding added to it. */ static rpad(str, minLen, ch) { ch = ch || ' '; return str.length < minLen ? str + ch.repeat(minLen - str.length) : str; } /** * @param {string} str - string - The string to pad. * @param {number} minLen - The minimum length of the string. * @param {string} [ch] - The character to pad the string with. * @returns The string with the padding. */ static lpad(str, minLen, ch) { ch = ch || ' '; return str.length < minLen ? ch.repeat(minLen - str.length) + str : str; } /** * It takes a string, an offset, a removeCount, and a text, and returns a string. * @param {string} str - string - The string to be spliced. * @param {number} offset - The index of the string to start replacing at. * @param {number | undefined} removeCount - The amount of characters to remove from the string. * @param [text] - The text to insert into the string. * @returns The string with the text inserted at the offset. */ static splice(str, offset, removeCount, text = '') { if (offset > str.length) return ''; const calculatedOffset = offset < 0 ? StringUtil.length + offset : offset; return (str.substring(0, calculatedOffset) + text + str.substring(calculatedOffset + (removeCount ? removeCount : 0))); } /** * If the string is null, empty, or equal to an empty string, then it is empty * @param {string} str - string - The string to check if it's empty. * @returns a boolean value. */ static isEmpty(str) { return !str || str.length === 0 || str === ''; } /** * It removes all the leading white spaces from a string. * @param {string} str - The string to be trimmed. * @returns The string with the leading whitespace removed. */ static ltrim(str) { return str.replace(/^\s+/, ''); } /** * It replaces all the spaces at the end of the string with nothing * @param {string} str - The string to trim. * @returns The string with the whitespace removed from the end. */ static rtrim(str) { return str.replace(/\s+$/, ''); } /** * It takes a string and replaces any lowercase letter followed by an uppercase letter with the * lowercase letter followed by a dash followed by the uppercase letter. * @param {string} str - string - The string to convert * @returns The string with the first letter lowercase. */ static camelToKebab(str) { return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); } /** * We take a string, convert it to lowercase, split it into an array, reverse the array, join the * array back into a string, and then compare the reversed string to the original string. * @param {string} str - string - the string to check if it's a palindrome * @returns A boolean value. */ static isPalindrome(str) { const lowerCaseStr = str.toLowerCase(); const strArray = lowerCaseStr.split(''); const reversedArray = strArray.reverse(); const reversedStr = reversedArray.join(''); return reversedStr === lowerCaseStr; } } exports.default = StringUtil; const reverse = (s) => StringUtil.reverse(s); exports.reverse = reverse; const isEmpty = (s) => StringUtil.isEmpty(s); exports.isEmpty = isEmpty; const randomString = (len, cs) => StringUtil.randomString(len, cs); exports.randomString = randomString; const slugify = (s) => StringUtil.slugify(s); exports.slugify = slugify;