/**
* @module string
*/
import { htmlTag, multiSpace, linebreaks } from "./regex.js";
/**
* Capitalize First Letter
* @param {String} string String to capitolize
* @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]
};
}
/**
* 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 line breaks
* @param {String} string String to trim
* @returns {String}
*/
export function trimLineBreaks(string) {
return string.replace(linebreaks, "");
}
/**
* Designed originally to flatten style definitions
* @param {String} string String to trim
* @returns {String}
*/
export function trimWhitespace(string) {
return string.replace(linebreaks, "")
.replace(multiSpace, " ")
.trim();
}
/**
* 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 seperators = /[\s-]+/g;
const parts = string.replace(notAllowed, "").split(seperators);
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;
}
}