UNPKG

nhb-toolbox

Version:

A versatile collection of smart, efficient, and reusable utility functions, classes and types for everyday development needs.

244 lines (243 loc) 9.07 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.convertStringCase = convertStringCase; exports.capitalizeString = capitalizeString; exports.toCamelCase = toCamelCase; exports.toPascalCase = toPascalCase; exports.toSnakeCase = toSnakeCase; exports.toKebabCase = toKebabCase; exports.toTrainCase = toTrainCase; exports.toDotCase = toDotCase; exports.toPathCase = toPathCase; exports.toConstantCase = toConstantCase; exports.toPascalSnakeCase = toPascalSnakeCase; exports.toTitleCase = toTitleCase; exports.toSentenceCase = toSentenceCase; const primitives_1 = require("../guards/primitives"); const constants_1 = require("./constants"); const smallSet = new Set(constants_1.LOWERCASE); function convertStringCase(value, format, options) { if (!(0, primitives_1.isNonEmptyString)(value)) return ''; const { preserveAcronyms = false } = options ?? {}; const LEADING_PUNCTUATION = /^[^\p{L}\p{N}\s]+/u; const TRAILING_PUNCTUATION = /[^\p{L}\p{N}\s]+$/u; const SEPARATOR = format === 'Title Case' ? /[^\p{L}\p{N}-]+/gu : /[^\p{L}\p{N}]+/gu; const CAMEL_BOUNDARY = /(?<=[\p{Ll}\p{N}])(?=\p{Lu})|(?<=[\p{Lu}])(?=\p{Lu}[\p{Ll}])/u; const LETTER_NUMBER_BOUNDARY = /(?<=[\p{L}])(?=\p{N})|(?<=[\p{N}])(?=\p{L})/u; const start = value.match(LEADING_PUNCTUATION)?.[0] ?? ''; const end = value.match(TRAILING_PUNCTUATION)?.[0] ?? ''; const core = value.replace(/^[^\p{L}\p{N}\s]+|[^\p{L}\p{N}\s]+$/gu, '').trim(); const lowerCase = (s) => s.toLowerCase(); const isAcronym = (s) => s.length >= 2 && /^[\p{Lu}]+$/u.test(s); const capitalize = (s) => (s.length === 0 ? '' : _capitalize(s)); let tokens = core.length > 0 ? core.split(SEPARATOR).filter(Boolean) : []; if (tokens.length <= 1 && core.length > 0) { if (CAMEL_BOUNDARY.test(core)) { tokens = core.split(CAMEL_BOUNDARY).filter(Boolean); } else if (LETTER_NUMBER_BOUNDARY.test(core)) { tokens = core.split(LETTER_NUMBER_BOUNDARY).filter(Boolean); } else { tokens = [core]; } } if (tokens.length === 0) { return start.concat(end); } switch (format) { case 'camelCase': { const middle = tokens .slice(1) .map((token) => { if (preserveAcronyms && isAcronym(token)) { return token; } return capitalize(token); }) .join(''); return start.concat(lowerCase(tokens[0]).concat(middle), end); } case 'PascalCase': { const body = tokens .map((token) => { if (preserveAcronyms && isAcronym(token)) return token; return capitalize(token); }) .join(''); return start.concat(body, end); } case 'snake_case': { const body = tokens.map(lowerCase).join('_'); return start.concat(body, end); } case 'kebab-case': { const body = tokens.map(lowerCase).join('-'); return start.concat(body, end); } case 'Title Case': { const title = tokens .map((token, idx, self) => { const tokenLower = token.toLowerCase(); if (idx !== 0 && idx !== self.length - 1 && smallSet.has(tokenLower)) { return tokenLower; } if (preserveAcronyms && token.includes('-')) { return token .split('-') .map((sub) => (isAcronym(sub) ? sub : capitalize(sub))) .join('-'); } if (preserveAcronyms && isAcronym(token)) { return token.split('-'); } return capitalize(token); }) .join(' '); return start.concat(title, end); } case 'Sentence case': { const word = tokens .map((token, idx) => { if (preserveAcronyms && token.includes('-')) { return token .split('-') .map((sub) => isAcronym(sub) ? sub : idx === 0 ? capitalize(sub) : sub.toLowerCase()) .join('-'); } if (preserveAcronyms && isAcronym(token)) { return token.split('-'); } return idx === 0 ? capitalize(token) : token.toLowerCase(); }) .join(' '); return start.concat(word, end); } case 'lowercase': { return start.concat(core.toLowerCase(), end); } case 'UPPERCASE': { return start.concat(core.toUpperCase(), end); } default: { return start.concat(core, end); } } } function capitalizeString(string, options) { if (!(0, primitives_1.isNonEmptyString)(string)) return ''; const trimmedString = string.trim(); if (!trimmedString) return ''; const { capitalizeAll = false, capitalizeEachFirst = false, lowerCaseRest = true, } = options || {}; if (capitalizeAll) { return trimmedString.toUpperCase(); } if (capitalizeEachFirst) { return trimmedString ?.split(/\s+/) ?.map((word) => capitalizeString(word, { lowerCaseRest })) ?.join(' '); } const matchArray = trimmedString.match(/^(\W*)(\w)(.*)$/); if (matchArray && matchArray?.length === 4) { const [_, leadingSymbols, firstLetter, rest] = matchArray; return leadingSymbols .concat(firstLetter.toUpperCase()) .concat(lowerCaseRest ? rest.toLowerCase() : rest); } return trimmedString .charAt(0) .toUpperCase() .concat(lowerCaseRest ? trimmedString.slice(1).toLowerCase() : trimmedString.slice(1)); } const REGEX_CACHE = new Map(); function _getDelimiterRegex(delims) { const key = delims.sort().join(''); if (!REGEX_CACHE.has(key)) { REGEX_CACHE.set(key, new RegExp(`[-_./${delims.join('')}]`, 'g')); } return REGEX_CACHE.get(key); } function _normalizeDelimiters(str, delims) { const delRegExp = _getDelimiterRegex(delims); return str .replace(/(\p{Ll}?\d+|(?<=\p{Lu}|\p{Ll}))(\p{Lu})/gu, '$1 $2') .replace(delRegExp, ' ') .replace(/\s+/g, ' ') .trim() .split(' ') .filter(Boolean); } function _capitalize(str) { return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase(); } function toCamelCase(str, ...del) { if (!(0, primitives_1.isNonEmptyString)(str)) return ''; const parts = _normalizeDelimiters(str, del); return (parts[0].toLowerCase() + parts.slice(1).map(_capitalize).join('')); } function toPascalCase(str, ...del) { return ((0, primitives_1.isNonEmptyString)(str) ? _normalizeDelimiters(str, del).map(_capitalize).join('') : ''); } function toSnakeCase(str, ...del) { return ((0, primitives_1.isNonEmptyString)(str) ? _normalizeDelimiters(str, del) .map((w) => w.toLowerCase()) .join('_') : ''); } function toKebabCase(str, ...del) { return ((0, primitives_1.isNonEmptyString)(str) ? _normalizeDelimiters(str, del) .map((w) => w.toLowerCase()) .join('-') : ''); } function toTrainCase(str, ...del) { return ((0, primitives_1.isNonEmptyString)(str) ? _normalizeDelimiters(str, del).map(_capitalize).join('-') : ''); } function toDotCase(str, ...del) { return ((0, primitives_1.isNonEmptyString)(str) ? _normalizeDelimiters(str, del).join('.') : ''); } function toPathCase(str, ...del) { return ((0, primitives_1.isNonEmptyString)(str) ? _normalizeDelimiters(str, del) .map((w) => w.toLowerCase()) .join('/') : ''); } function toConstantCase(str, ...del) { return ((0, primitives_1.isNonEmptyString)(str) ? _normalizeDelimiters(str, del) .map((w) => w.toUpperCase()) .join('_') : ''); } function toPascalSnakeCase(str, ...del) { return ((0, primitives_1.isNonEmptyString)(str) ? _normalizeDelimiters(str, del).map(_capitalize).join('_') : ''); } function toTitleCase(str, ...del) { return ((0, primitives_1.isNonEmptyString)(str) ? _normalizeDelimiters(str, del) .map((w, i) => i !== 0 && smallSet.has(w) ? w.toLowerCase() : _capitalize(w)) .join(' ') : ''); } function toSentenceCase(str, ...del) { return ((0, primitives_1.isNonEmptyString)(str) ? _normalizeDelimiters(str, del) .map((w, i) => (i === 0 ? _capitalize(w) : w.toLowerCase())) .join(' ') : ''); }