/**
* @module string
*/
import { htmlTag, multiSpace } from "./regex.js";
/**
* Capitalize First Letter
* @param {String} string String to capitalize
* @returns {String}
*/
export function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
/**
* Convert string to characters safe for URL
* @param {String} string The string to convert
* @returns {String}
*/
export function urlize(string) {
var newString;
string = string.replace(/^[^-_a-zA-Z]+/, "").replace(/^-(?:[-0-9]+)/, "-");
newString = string && string.replace(/[^-_a-zA-Z0-9]+/g, "-");
return newString.toLowerCase();
}
/**
* Will return an object with the separation details
* @param {String} string CSS number with unit
* @return {Object} keys: value, original, unit
*/
export function separateCssUnit(original) {
const pattern = /(px|vw|vh|%|em|rem)/i;
return {
original,
value: parseFloat(original.replace(pattern, "")),
unit: original.match(pattern)[0]
};
}
/**
* Converts a duration string to a unitless millisecond value.
*
* If the input string contains 'ms', it is parsed as milliseconds.
* Otherwise, it is assumed to be in seconds and converted to milliseconds.
* Note if a multi value list of durations is passed only the first duration is used (ie. "200ms, 1s")
*
* @param {string} value - The duration string (e.g., "2s", "500ms", "200ms, 1s").
* @returns {number} The duration in milliseconds as a number.
*/
export function cssDurationToMs(value) {
if (typeof value !== "string") {
throw new Error("Expected string");
}
const resolved = value.split(",")[0];
const duration = parseFloat(resolved);
return resolved.toLowerCase().includes("ms") ? duration : duration * 1000;
}
/**
* Removes HTML tags from string (can be used in Node)
* - Different than DOM version
* - Note you can use document.createElement and grab textContent (but this could execute code in browser)
* - The method below will just use regex without creating Nodes
* @param {String} html HTML string to find/replace
*/
export function stripTags(html) {
return html.replace(htmlTag, "");
}
/**
* Remove double spaces
* @param {String} string String to trim
* @returns {String}
*/
export function trimDoubleSpaces(string) {
return string.replace(multiSpace, "");
}
/**
* Remove all line breaks from string
* @param {String} string
* @returns {String}
*/
export function removeLineBreaks(string) {
return string.replace(/[\r\n]+/g, "");
}
/**
* Remove line breaks
* @deprecated Please use 'removeLineBreaks' this will be removed in the future
* @param {String} string String to trim
* @returns {String}
*/
export function trimLineBreaks(string) {
return removeLineBreaks(string);
}
/**
* Remove line breaks and double or more spaces from string
* @param {String} string String to trim
* @returns {String}
*/
export function flatten(string) {
return removeLineBreaks(string)
.replace(multiSpace, " ")
.trim();
}
/**
* Designed originally to flatten style definitions
* @deprecated Please use 'flatten' this will be removed in the future
* @param {String} string String to trim
* @returns {String}
*/
export function trimWhitespace(string) {
return flatten(string);
}
/**
* Truncates string with ellipsis if over the max, note use framework function
* if you need to know the effects of the truncate process (returns an object
* with info instead) this function only modifies the string
* @param {string} string String to possibly truncate
* @param {number} max How many characters max?
* @return {string}
*/
export function truncate(string, max, overflowChar = "…") {
return string.length <= max ? string : string.slice(0, max) + overflowChar;
}
/**
* Converts a string to initials
* - Example "Jane Allen-Doe" --> "JAD"
* - Example (short) "Jane Allen-Doe" --> "JD"
* - Example "Wow this part-time" --> "WTPT"
* - Example "Wow There are 2 !! People." --> "WTA2P"
* @param {String} string String to convert
* @param {Boolean} short If true the initials will be limited to two letters, unless it's only one word which would be single letter
* @returns {String}
*/
export function toInitials(string, short) {
const notAllowed = /[^A-Z0-9\s-]/gi;
const separators = /[\s-]+/g;
const parts = string.replace(notAllowed, "").split(separators);
const isShort = short && parts.length > 2;
const final = isShort ? [parts.shift(), parts.pop()] : parts;
return final.map(part => part.substring(0, 1).toUpperCase()).join("");
}
/**
* Convert string to title case
* @param {String} string String to convert to title case
* @param {Array} exceptions Array of words that shouldn't be title case, common words are included by default
* @param {Array} defaults Default exceptions incase you want full control
* @returns {String}
*/
export function titleCase(
string,
exceptions = [],
defaults = [
"a", "an", "or", "nor", "is", "and", "to", "in", "per", "on", "for", "by",
"at", "as", "the", "etc"
]
) {
const all = [...defaults, ...exceptions];
// Change each word to uppercase if given word isn't an exception
return string.replace(/\w\S*/g, (txt, offset) => {
// The following uses an regular expression to match words in the replace method
// The ternary return is checking if (the matched word is an exception) and then if
// it is not the first word for a given sentence (offset)
// return it in uppercase. If not it was an exception and is not the first word.
return all.indexOf(txt) > -1 && offset !== 0 ?
txt : txt.charAt(0).toUpperCase() + txt.substring(1).toLowerCase();
});
}
/**
* Function that matches regex against string and returns details helpful for replacing/using/highlighting a single match within a string
* @param {String} string The string to extract from
* @param {Regex} regex The regular expression to match against
* @returns {Object|Null} If match return object with { matched, startIndex, endIndex, before, after }, when no match is found this return null
*/
export function extractMatchDetails(string, regex) {
const match = string.match(regex);
if (match) {
const matched = match[0];
const startIndex = match.index;
const endIndex = startIndex + matched.length;
return {
matched,
startIndex,
endIndex,
before: string.slice(0, startIndex),
after: string.slice(endIndex)
};
} else {
return null;
}
}
/**
* Convert kebab string to camel casing
* @param {string} string - String to convert
* @returns {string} - Camel case version of string
*/
export function kebabToCamel(string) {
return string.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
}