@selenite/commons
Version:
This typescript package provides a set of frequently used utilities, types and svelte actions for building projects with Typescript and Svelte.
210 lines (209 loc) • 6.03 kB
JavaScript
/**
* String utils for common string manipulation.
*
* Examples are {@link capitalize} and {@link splitCamelCase}....
* @module
*/
// polyfill for set intersection
import 'core-js/actual/set/intersection';
import { escapeRegExp, upperFirst } from 'lodash-es';
// Can't export pluralize functions directly
// because pluralize is common js
import pluralizePackage from 'pluralize';
const pluralize = pluralizePackage;
const { singular, isPlural, isSingular, plural } = pluralizePackage;
export { singular, isPlural, isSingular, plural, pluralize };
export function capitalize(str) {
return upperFirst(str);
}
export function capitalizeWords(str) {
return str.split(' ').map(upperFirst).join(' ');
}
export function isAlphaNumChar(str) {
return /^[a-z0-9]$/i.test(str);
}
export const words = capitalizeWords;
// split on capital letters that are followed by non capital letters or
// preceded by non capital letters
// and join with spaces
export function titlelize(str) {
return str
.split(/(?=(?<=[^A-Z])[A-Z])/)
.map(capitalize)
.join(' ');
}
// returns the first two capital letters of a string or the first two letters if there is not enough capital letters
export function initials(str) {
str = capitalizeWords(str);
const capitalLetters = str.match(/^([A-Z])(?:\S*?\s+|\S*?)([A-Z])/);
if (capitalLetters == null) {
return str.slice(0, 2);
}
return capitalLetters[1] + capitalLetters[2];
}
// export function titlelize(str: string): string {
// return str
// .split(/(?=[A-Z])/)
// .map(capitalize)
// .join(' ');
// }
/** Transforms a string into CamelCase. */
export function camlelcaseize(str) {
const capitalized = str
.split(' ')
.map((s, i) => {
if (i === 0) {
const pieces = splitCamelCase(s);
if (pieces.length > 0) {
pieces[0] = pieces[0].toLowerCase();
}
return pieces.join('');
}
return upperFirst(s);
})
.join('');
return capitalized;
}
/** Transforms a Camelcase string into a normal space seperated string. */
export function unCamelCase(str) {
return splitCamelCase(str).join(' ');
}
function isWhitespaceChar(c) {
return (c === ' ' ||
c === '\n' ||
c === '\t' ||
c === '\r' ||
c === '\f' ||
c === '\v' ||
c === '\u00a0' ||
c === '\u1680' ||
c === '\u2000' ||
c === '\u200a' ||
c === '\u2028' ||
c === '\u2029' ||
c === '\u202f' ||
c === '\u205f' ||
c === '\u3000' ||
c === '\ufeff');
}
/**
* Splits a camel case string into an array of words.
* @param str Camel case string to split.
* @returns Array of words.
*/
export function splitCamelCase(str) {
const res = [];
let i = 0;
let nextCapIsWordStart = false;
let nextLowerAfterCapIsWordEnd = false;
for (let j = 0; j < str.length; j++) {
const c = str[j];
// Whitespace
if (isWhitespaceChar(c)) {
if (nextCapIsWordStart) {
res.push(str.slice(i, j));
nextCapIsWordStart = false;
}
i = j + 1;
continue;
}
// Lowercase letter
if (c === c.toLowerCase()) {
if (!isNaN(parseInt(c)))
continue;
nextCapIsWordStart = true;
if (nextLowerAfterCapIsWordEnd) {
const k = j - 1;
if (k - i > 0) {
nextLowerAfterCapIsWordEnd = false;
res.push(str.slice(i, k));
i = k;
}
}
nextLowerAfterCapIsWordEnd = false;
}
// Uppercase letter
else {
nextLowerAfterCapIsWordEnd = true;
if (nextCapIsWordStart) {
res.push(str.slice(i, j));
i = j;
nextCapIsWordStart = false;
}
}
}
if (i < str.length) {
res.push(str.slice(i));
}
return res;
}
/** @ignore */
export function getSharedWords(strings) {
if (strings.length === 0)
return [];
let stringsWords;
if (!Array.isArray(strings[0])) {
stringsWords = strings.map((s) => s
.split(' ')
.flatMap(splitCamelCase)
.map((s) => singular(s)));
}
else {
stringsWords = strings;
}
let res = new Set(stringsWords[0]);
for (const [i, words] of stringsWords.entries()) {
if (i === 0)
continue;
res = res.intersection(new Set(words));
}
return Array.from(res);
}
export function getSharedString(strings, options = {}) {
const words = getSharedWords(strings);
let res;
if (options.camelcase) {
if (words.length === 0)
return '';
const firstWord = words.splice(0, 1)[0];
res = words.reduce((acc, s) => acc + upperFirst(s), firstWord);
}
else {
res = words.join(' ');
}
return options.pluralize ? plural(res) : res;
}
export function getVarsFromFormatString(formatString) {
// return all matches of the regex
return Array.from(formatString.matchAll(/{(\w+).*?}/g)).map((match) => match[1]);
}
export function matchingParts(s, ref, options = {}) {
let flags = 's';
if (options.caseInsensitive) {
flags += 'i';
}
const re = new RegExp(`(.*?)(${escapeRegExp(ref)})`, flags);
let remainder = s;
const res = [];
let match;
while ((match = re.exec(remainder))) {
if (match[0].length === 0)
break;
if (match[1])
res.push({
part: match[1],
match: false
});
res.push({
part: match[2],
match: true
});
remainder = remainder.slice(match[0].length);
}
if (remainder)
res.push({
part: remainder,
match: false
});
return res;
}