@toolpad/utils
Version:
Shared utilities used by Toolpad packages.
191 lines (172 loc) • 5.05 kB
JavaScript
import title from 'title';
/**
* Makes the first letter of [str] uppercase.
* Not locale aware.
*/
export function uncapitalize(str) {
return str.length > 0 ? str[0].toLowerCase() + str.slice(1) : '';
}
/**
* Makes the first letter of [str] lowercase.
* Not locale aware.
*/
export function capitalize(str) {
return str.length > 0 ? str[0].toUpperCase() + str.slice(1) : '';
}
/**
* Capitalizes and joins all [parts].
*/
export function pascalCase(...parts) {
return parts.map(part => capitalize(part.toLowerCase())).join('');
}
/**
* Joins all [parts] and camelcases the result
*/
export function camelCase(...parts) {
if (parts.length > 0) {
const [first, ...rest] = parts;
return uncapitalize(first) + pascalCase(...rest);
}
return '';
}
/**
* Turns a kebab-case string into a constant case string.
*/
export function kebabToConstant(input) {
return input.split('-').map(part => part.toUpperCase()).join('_');
}
/**
* Turns a kebab-case string into a PascalCase string.
*/
export function kebabToPascal(input) {
return input.split('-').map(part => capitalize(part)).join('');
}
/**
* Generates a string for `base` by add a number until it's unique amongst a set of predefined names.
*/
export function generateUniqueString(base, existingNames) {
let i = 1;
if (!existingNames.has(base)) {
return base;
}
const newBase = base.replace(/\d+$/, '');
let suggestion = newBase;
while (existingNames.has(suggestion)) {
suggestion = newBase + String(i);
i += 1;
}
return suggestion;
}
/**
* Escape string for use in HTML.
*/
export function escapeHtml(unsafe) {
return unsafe.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''');
}
/**
* Normalizes and removes all diacritics from a javascript string.
*
* See https://stackoverflow.com/a/37511463
*/
export function removeDiacritics(input) {
return input.normalize('NFD').replace(/[\u0300-\u036f]/g, '');
}
export function isAbsoluteUrl(maybeUrl) {
try {
return !!new URL(maybeUrl);
} catch {
return false;
}
}
/**
* Removes a prefix from a string if it starts with it.
*/
export function removePrefix(input, prefix) {
return input.startsWith(prefix) ? input.slice(prefix.length) : input;
}
/**
* Removes a suffix from a string if it ends with it.
*/
export function removeSuffix(input, suffix) {
return input.endsWith(suffix) ? input.slice(0, -suffix.length) : input;
}
/**
* Adds a prefix to a string if it doesn't start with it.
*/
export function ensurePrefix(input, prefix) {
return input.startsWith(prefix) ? input : prefix + input;
}
/**
* Adds a suffix to a string if it doesn't end with it.
*/
export function ensureSuffix(input, suffix) {
return input.endsWith(suffix) ? input : input + suffix;
}
/**
* Regex to statically find all static import statements
*
* Tested against:
* import {
* Component
* } from '@angular2/core';
* import defaultMember from "module-name";
* import * as name from "module-name ";
* import { member } from " module-name";
* import { member as alias } from "module-name";
* import { member1 ,
* member2 } from "module-name";
* import { member1 , member2 as alias2 , member3 as alias3 } from "module-name";
* import defaultMember, { member, member } from "module-name";
* import defaultMember, * as name from "module-name";
* import "module-name";
* import * from './smdn';
*/
const IMPORT_STATEMENT_REGEX = /^\s*import(?:["'\s]*([\w*{}\n, ]+)from\s*)?["'\s]*([^"']+)["'\s].*/gm;
/**
* Statically analyses a javascript source code for import statements and return the specifiers.
*
* NOTE: This function does a best effort without parsing the code. The result may contain false
* positives
*/
export function findImports(src) {
return Array.from(src.matchAll(IMPORT_STATEMENT_REGEX), match => match[2]);
}
/**
* Limits the length of a string and adds ellipsis if necessary.
*/
export function truncate(str, maxLength, dots = '...') {
if (str.length <= maxLength) {
return str;
}
return str.slice(0, maxLength) + dots;
}
/**
* Prepend a prefix to each line in the text
*/
export function prependLines(text, prefix) {
return text.split('\n').map(line => prefix + line).join('\n');
}
/**
* Indent the text with [length] number of spaces
*/
export function indent(text, length = 2) {
return prependLines(text, ' '.repeat(length));
}
/**
* Returns true if the string is a valid javascript identifier
*/
export function isValidJsIdentifier(base) {
return /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(base);
}
export function guessTitle(str) {
// Replace snake_case with space
str = str.replace(/[_-]/g, ' ');
// Split camelCase
str = str.replace(/([a-z0-9])([A-Z])/g, '$1 $2');
// Split acronyms
str = str.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2');
// Split numbers
str = str.replace(/([a-zA-Z])(\d+)/g, '$1 $2');
str = str.replace(/(\d+)([a-zA-Z])/g, '$1 $2');
return title(str);
}