nhb-toolbox
Version:
A versatile collection of smart, efficient, and reusable utility functions and classes for everyday development needs.
192 lines (191 loc) • 8.99 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.reverseString = exports.maskString = exports.slugifyString = exports.replaceAllInString = void 0;
exports.convertStringCase = convertStringCase;
exports.normalizeString = normalizeString;
exports.extractEmails = extractEmails;
exports.extractURLs = extractURLs;
exports.formatUnitWithPlural = formatUnitWithPlural;
const basics_1 = require("./basics");
const constants_1 = require("./constants");
/**
* * Converts a string to a specified case format such as `camelCase`, `snake_case`, `kebab-case`, `PascalCase`, `Title Case`, `lowercase`, or `UPPERCASE`.
*
* - This function handles non-alphanumeric characters (e.g., spaces, hyphens, underscores, dots, slashes) as word delimiters. For `Title Case`, prepositions, articles, conjunctions, and auxiliary verbs are not capitalized unless they appear at the start of the title.
* - You can also convert the string to `lowercase` or `UPPERCASE`, but it's recommended to use default string methods like `string.toLowerCase()` and `string.toUpperCase()` for these cases.
*
* @param string The input string to be converted. The string should have words separated by non-alphanumeric characters (e.g., spaces, hyphens, underscores, etc.).
* @param format The format to convert the string to. The available formats are:
* - `'camelCase'`: Converts to camelCase (e.g., `myVariableName`).
* - `'snake_case'`: Converts to snake_case (e.g., `my_variable_name`).
* - `'kebab-case'`: Converts to kebab-case (e.g., `my-variable-name`).
* - `'PascalCase'`: Converts to PascalCase (e.g., `MyVariableName`).
* - `'Title Case'`: Converts to Title Case (e.g., `My Variable Name`), where certain words like `prepositions, articles, conjunctions and auxiliary verbs` are not capitalized unless at the start.
* - `'lowercase'`: Converts the string to all lowercase characters.
* - `'UPPERCASE'`: Converts the string to all uppercase characters.
* @returns The formatted string in the specified case format.
* @example
* convertStringCase('my-example_string', 'camelCase'); // returns 'myExampleString'
* convertStringCase('my-example_string', 'snake_case'); // returns 'my_example_string'
* convertStringCase('my-example_string', 'kebab-case'); // returns 'my-example-string'
* convertStringCase('my example string', 'Title Case'); // returns 'My Example String'
* convertStringCase('my example string', 'lowercase'); // returns 'my example string'
* convertStringCase('my example string', 'UPPERCASE'); // returns 'MY EXAMPLE STRING'
*/
function convertStringCase(string, format) {
if (!string || typeof string !== 'string')
return '';
const start = string?.match(/^[^\d\w\s]+/)?.[0] || '';
const end = string?.match(/[^\d\w\s]+$/)?.[0] || '';
const core = string?.replace(/^[^\d\w\s]+|[^\w\s]+$/g, '').trim();
const titleCase = core
?.split(/\s+/g)
?.map((part) => {
const startSymbol = part.match(/^[^\d\w\s]+/)?.[0] || ''; // Capture leading symbols
const endSymbol = part.match(/[^\d\w\s]+$/)?.[0] || ''; // Capture trailing symbols
const coreWord = part.replace(/^[^\d\w\s]+|[^\d\w\s]+$/g, ''); // Remove them for processing
if (constants_1.LOWERCASE.includes(coreWord?.toLowerCase())) {
return startSymbol + coreWord?.toLowerCase() + endSymbol;
}
return (startSymbol +
coreWord?.charAt(0)?.toUpperCase() +
coreWord?.slice(1)?.toLowerCase() +
endSymbol);
})
.join(' ');
const formattedString = string?.replace(/[^a-zA-Z0-9]+(.)?/g, (_, chr) => (chr ? chr?.toUpperCase() : ''));
if (!formattedString)
return '';
switch (format) {
case 'camelCase':
// return formattedString.replace(/[A-Z]/g, (letter, index) =>
// index === 0 ? letter.toUpperCase() : letter.toLowerCase(),
// );
return (formattedString.charAt(0).toLowerCase() +
formattedString.slice(1));
case 'snake_case':
return /[^a-zA-Z0-9]/.test(string) ?
string.split(/\W+/g).join('_').toLowerCase()
: formattedString.replace(/[A-Z]/g, (letter, index) => index === 0 ?
letter.toLowerCase()
: `_${letter.toLowerCase()}`);
case 'kebab-case':
return /[^a-zA-Z0-9]/.test(string) ?
string.split(/\W+/g).join('-').toLowerCase()
: formattedString.replace(/[A-Z]/g, (letter, index) => index === 0 ?
letter.toLowerCase()
: `-${letter.toLowerCase()}`);
case 'PascalCase':
return (formattedString.charAt(0).toUpperCase() +
formattedString.slice(1));
case 'Title Case':
return (start +
titleCase.charAt(0).toUpperCase() +
titleCase.slice(1) +
end);
case 'lowercase':
return start + core.toLowerCase() + end;
case 'UPPERCASE':
return start + core.toUpperCase() + end;
default:
return formattedString;
}
}
/**
* * Replaces all occurrences of a string or pattern in the given input string.
*
* - If `find` is a string, it is converted into a global regular expression (`/find/g`).
* - If `find` is a `RegExp`, the global (`g`) flag is ensured.
* - Trims the input before performing replacements.
*
* @param input - The string in which replacements should be performed.
* @param find - The substring or regex pattern to search for.
* @param replace - The string to replace matches with.
* @returns The modified/refined string with replacements applied.
*/
const replaceAllInString = (input, find, replace) => {
const trimmedString = (0, basics_1.trimString)(input);
const regex = typeof find === 'string' ?
new RegExp(find, 'g')
: new RegExp(find, find?.flags.includes('g') ? find?.flags : find?.flags + 'g');
return trimmedString?.replace(regex, replace);
};
exports.replaceAllInString = replaceAllInString;
/**
* * Converts a string into a URL-friendly slug.
* @param input - The string to be converted.
* @returns The slugified string.
*/
const slugifyString = (input) => {
return (0, basics_1.trimString)(input)
?.toLowerCase()
?.replace(/[^a-z0-9]+/g, '-')
?.replace(/^-+|-+$/g, '');
};
exports.slugifyString = slugifyString;
/**
* * Masks part of a string for privacy.
* @param input - The string to mask.
* @param options - Options for masking a string.
* @returns The masked string.
*/
const maskString = (input, options) => {
const { start = 1, end = 1, maskCharacter: maskChar = '*' } = options || {};
const trimmedString = (0, basics_1.trimString)(input);
if (trimmedString?.length <= start + end) {
return maskChar?.repeat(trimmedString?.length);
}
return (trimmedString.slice(0, start) +
maskChar?.repeat(trimmedString?.length - start - end) +
(end > 0 ? trimmedString.slice(-end) : ''));
};
exports.maskString = maskString;
/**
* * Reverses a given string.
* @param input - The string to reverse.
* @returns The reversed string.
*/
const reverseString = (input) => {
const trimmedString = (0, basics_1.trimString)(input);
return trimmedString?.split('')?.reverse()?.join('');
};
exports.reverseString = reverseString;
/**
* * Normalizes a string by removing diacritics (accents).
* @param str The input string.
* @returns The normalized string.
*/
function normalizeString(str) {
return str.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
}
/**
* * Extracts all email addresses from a string.
* @param str The input string.
* @returns An array of extracted email addresses.
*/
function extractEmails(str) {
return str.match(/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g) || [];
}
/**
* * Extracts all URLs from a string.
* @param str The input string.
* @returns An array of extracted URLs.
*/
function extractURLs(str) {
return str?.match(/https?:\/\/[^\s/$.?#].[^\s]*/g) || [];
}
/**
* * Returns a grammatically correct unit string, optionally prefixed with the number.
*
* @remarks For complex and versatile pluralization, please refer to {@link https://nhb-toolbox.vercel.app/docs/utilities/string/pluralizer pluralizer} or {@link https://nhb-toolbox.vercel.app/docs/classes/Pluralizer Pluralizer Class} instead.
*
* @param count The numeric value to determine singular or plural.
* @param unit The unit name (e.g., "day", "hour").
* @param withNumber Whether to prefix the count before the unit. Defaults to `true`.
* @returns Formatted unit string like `"1 day"`, `"2 months"`, or `"hour"`.
*/
function formatUnitWithPlural(count, unit, withNumber = true) {
const abs = Math.abs(count);
const pluralized = abs === 1 ? unit : `${unit}s`;
return withNumber ? `${count} ${pluralized}` : pluralized;
}