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
JavaScript
;
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(' ')
: '');
}