@publidata/utils-core
Version:
Collection of methods
450 lines (376 loc) • 13.8 kB
JavaScript
// Transform my-text to My-Text
const capitalize = (string = "") =>
string
.replace(/\b\w/g, l => l.toUpperCase())
.replace(/([à-ùÀ-Ù])\b\w/g, l => l.toLowerCase());
exports.capitalize = capitalize;
// Transform my-text to myText
const toCamelCase = (string = "") =>
string.replace(/(-|_)([a-z])/g, g => g[1].toUpperCase());
exports.toCamelCase = toCamelCase;
const toSnakeCase = string =>
string
.replace(/[\w]([A-Z])/g, juncture => `${juncture[0]}_${juncture[1]}`)
.toLowerCase();
exports.toSnakeCase = toSnakeCase;
const toPascalCase = string =>
string
.match(/[a-z]+/gi)
.map(word => word.charAt(0).toUpperCase() + word.substr(1).toLowerCase())
.join("");
exports.toPascalCase = toPascalCase;
// Remove all "-" or "_" in a string
const removeHyphen = (string, replaceBy = "") =>
string.replace(/-|_/g, replaceBy);
exports.removeHyphen = removeHyphen;
// Remove all HTML tags such as <span> and so from a string
const removeHTML = string =>
(string || "")
.replace(/<\/p>\s*<p[^>]*>/g, " ")
.replace(/<(?:.|\n)*?>/gm, "")
.replace(/ /gm, " ");
exports.removeHTML = removeHTML;
// Transform my-text to MyText
exports.classify = (string = "") =>
removeHyphen(capitalize(toCamelCase(string)));
const capitalizeFirstLetter = string =>
string && string.length && string.charAt(0).toUpperCase() + string.slice(1);
exports.capitalizeFirstLetter = capitalizeFirstLetter;
// Adds a leading 0 to a time in Int when it's < 10
const addLeadingZeroToNumber = number =>
`${number < 10 ? `0${number}` : number}`;
exports.addLeadingZeroToNumber = addLeadingZeroToNumber;
/* global window */
// Return IE version - null if not IE or below v6
const isIe = () => {
if (typeof window !== "undefined") {
const win = window;
const doc = win.document;
const input = doc.createElement("input");
// "!win.ActiveXObject" is evaluated to true in IE11
if (win.ActiveXObject === undefined) return null;
if (!win.XMLHttpRequest) return 6;
if (!doc.querySelector) return 7;
if (!doc.addEventListener) return 8;
if (!win.atob) return 9;
// "!doc.body.dataset" is faster but the body is null when the DOM is not
// ready. Anyway, an input tag needs to be created to check if IE is being
// emulated
if (!input.dataset) return 10;
return 11;
}
return null;
};
exports.isIe = isIe;
/* global document */
const canUseWebP = () => {
const elem = document.createElement("canvas");
if (elem.getContext && elem.getContext("2d")) {
// was able or not to get WebP representation
return elem.toDataURL("image/webp").indexOf("data:image/webp") === 0;
}
// very old browser like IE 8, canvas not supported
return false;
};
exports.canUseWebP = canUseWebP;
// Syntax shortcut for JSON.parse
const parse = json => {
if (typeof json === "object") return json;
if (json && json !== "") return JSON.parse(json);
return {};
};
exports.parse = parse;
function strAttr(name, value, depth) {
return `${"\t".repeat(depth)}${name}: ${value};\n`;
}
exports.strAttr = strAttr;
const toCSS = (node, depth = 0, breaks = false) => {
let cssString = "";
if (node.attributes) {
node.attributes.forEach((attribute, i) => {
if (attribute instanceof Array) {
for (let j = 0; j < attribute.length; j++) {
cssString += strAttr(i, attribute[j], depth);
}
} else {
cssString += strAttr(i, attribute, depth);
}
});
}
if (node.children) {
let first = true;
node.children.forEach((child, i) => {
if (breaks && !first) {
cssString += "\n";
} else {
first = false;
}
cssString += strNode(i, child, depth); // eslint-disable-line
});
}
return cssString;
};
exports.toCSS = toCSS;
function strNode(name, value, depth) {
let cssString = `${"\t".repeat(depth)}${name} {\n`;
cssString += toCSS(value, depth + 1);
cssString += `${"\t".repeat(depth)}}\n`;
return cssString;
}
// Transform json css data to react compliant css properties
exports.css = json => {
if (!json) return "";
return toCSS(parse(json));
};
// // Loop all property following this JSON structure : https://github.com/aramk/CSSJSON
// function formatJSONCss(css) {
// for (let key in css) {
// if (key === "attributes") {
// let attributes = css["attributes"]
// if (attributes) attributes = setAttributeKeyToCamelCase(attributes)
// } else {
// css[key] = formatJSONCss(css[key])
// }
// }
// return css
// }
//
// // Change every background-color to backgroundColor
// function setAttributeKeyToCamelCase(attributes) {
// let newAttributes = {}
// for (let key in attributes) {
// newAttributes[toCamelCase(key)] = attributes[key]
// }
// return newAttributes
// }
const hashCode = string => {
let hash = 0;
let i;
let chr;
if (string.length === 0) return hash;
for (i = 0; i < string.length; i++) {
chr = string.charCodeAt(i);
hash = (hash << 5) - hash + chr; // eslint-disable-line no-bitwise
hash |= 0; // eslint-disable-line no-bitwise
}
return hash;
};
/* Generate react item key from array of items
* array : array of whatever you want
* @return : array[{
* value: item,
* key: randomkey
* }]
*/
const keygen = array => {
if (!array) return [];
return array.map((item, index) => {
const newObject = {
value: item,
key: ""
};
if (typeof item === "object") {
if (item.props !== undefined)
newObject.key = hashCode(`${JSON.stringify(item.props)}`);
else newObject.key = hashCode(`${JSON.stringify(item)}`);
} else newObject.key = hashCode(`${JSON.stringify(item)}`);
newObject.key = `${newObject.key}${index}`;
return newObject;
});
};
exports.keygen = keygen;
/* eslint-disable */
function isComputer() {
if(typeof window === "undefined") return true;
let check = true;
(function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = false;})(navigator.userAgent||navigator.vendor||window.opera);
return check;
}
function isWide() {
if(typeof window === "undefined") return false;
if (window.innerWidth >= 1200 && isComputer()) return true;
return false;
}
exports.isWide = isWide;
function isMobile() {
if(typeof window === "undefined") return false;
// if (window.innerWidth <= 480) return true;
return !isComputer();
}
exports.isMobile = isMobile;
function isMobileAndTablet() {
if(typeof window === "undefined") return false;
// if (window.innerWidth <= 768) return true;
return !isComputer();
}
exports.isMobileAndTablet = isMobileAndTablet;
function isTablet() {
if(isMobileAndTablet() && !isMobile()) return true;
return false;
}
exports.isTablet = isTablet;
function pluralize(object, string) {
if(object.length > 1) return `${string}s`; // Plural case
else if(object.length === 0) return `${string}s`;
return string;
}
exports.pluralize = pluralize;
/**
* Return value of CSS variable from a type or a variable string
* @param { String } str type (Ex: "facility" --> var(--facility))
*/
function getColorVar(str) {
return `var(--${str})`;
}
exports.getColorVar = getColorVar;
/**
* Return array of unique objects
* @param { Array<Object> } myArr Array you want to check
* @param { String } prop Property you want to be unique
*/
function removeDuplicates(myArr, prop) {
return myArr.filter((obj, pos, arr) => arr.map(item => item[prop]).indexOf(obj[prop]) === pos);
}
exports.removeDuplicates = removeDuplicates;
/**
* Return simple unique ID
* @return { String } ID
*/
function getUniqueID() {
return `id-${Math.random().toString(36).substr(2, 16)}`;
}
exports.getUniqueID = getUniqueID;
/**
*
* @param {Object} object
* @param {String} oldKey
* @param {String} newKey
*/
function renameObjectKey(object, oldKey, newKey) {
if (oldKey !== newKey) {
delete Object.assign(object, {[newKey]: object[oldKey]})[oldKey];
}
}
exports.renameObjectKey = renameObjectKey;
/*
* Instead of imbricate functions, pipe them.
* Usage : method3(method2(method1(string))) becomes pipe(method1, method2, method3)(string)
*/
const pipe = (...functions) => variable =>
functions.reduce(
(resultOfPreviousChange, currentFunction) =>
currentFunction(resultOfPreviousChange),
variable
);
exports.pipe = pipe;
/*
* Returns a function, that, as long as it continues to be invoked, will not
* be triggered. The function will be called after it stops being called for
* 'delay' milliseconds.
*/
const debounce = (callback, context, delay) => {
let timeout;
return function() {
const args = arguments;
const later = function() {
timeout = null;
callback.apply(context, args);
};
clearTimeout(timeout);
timeout = setTimeout(later, delay)
}
}
exports.debounce = debounce;
/* Create a unique identifier
* @return {String} - uuid
*/
function createUuid(){
var dt = new Date().getTime();
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = (dt + Math.random()*16)%16 | 0;
dt = Math.floor(dt/16);
return (c=='x' ? r :(r&0x3|0x8)).toString(16);
});
return uuid;
}
exports.createUuid = createUuid;
/* Escape special characters from a string to be used as a pattern in a RegExp
* these characters : \ ^ $ * + ? . ( ) | { } [ ]
* should be escaped : \\ \^ \$ \* \+ \? \. \( \) \| \{ \} \[ \]
*/
const escapeRegExp = string => {
if (typeof string !== "string") return "";
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
}
exports.escapeRegExp = escapeRegExp;
/**
* Removes duplicates objects from an array.
* @param {Array} array Array to be processed.
* @param {String} [key] Base key to be used to check for duplicates. "id" by default.
* @return {Array} Return the array without duplicates.
*/
const arrayOfUniqsObject = (array, key = "id") => {
if (!array) return null;
const uniqueArray = [];
array.forEach(item => {
if (
!uniqueArray.some(objectToCompare => objectToCompare[key] === item[key])
) {
uniqueArray.push(item);
}
});
return uniqueArray;
};
exports.arrayOfUniqsObject = arrayOfUniqsObject;
/**
* Truncate a string if it exceeds a maximum length
*
* @param {string} str Text to truncate
* @param {number} maxLength Maximum length of the truncated text (excluding suffix length)
* @param {string} suffix Suffix to append to the truncated text (default: "...")
* @returns {string}
*
* @example
*
* ```js
* truncate("Lorem ipsum dolor sit amet", 10); // => "Lorem ipsu..."
* truncate("Lorem ipsum dolor sit amet", 10, "... 🏁"); // => "Lorem ipsu... 🏁"
* ```
*/
function truncate(str, maxLength, suffix = "...") {
if (str.length > maxLength) {
return str.slice(0, maxLength) + suffix;
}
return str;
};
exports.truncate = truncate;
/**
* Fully decode a URI component
* @param {String} param The URI component to decode
* @returns {String} The decoded URI component
*/
const fullyDecodeComponent = param => {
let decodedParam = param;
let iterationCount = 0;
const MAX_ITERATIONS = 10;
try {
while (
decodedParam !== decodeURIComponent(decodedParam) &&
iterationCount < MAX_ITERATIONS
) {
decodedParam = decodeURIComponent(decodedParam);
iterationCount++;
}
} catch (error) {
console.error("Error decoding URI component:", error);
return param; // Return the original param if decoding fails
}
if (iterationCount === MAX_ITERATIONS) {
// eslint-disable-next-line no-console
console.warn(
"Maximum iteration limit reached while decoding URI component."
);
}
return decodedParam;
};
exports.fullyDecodeComponent = fullyDecodeComponent;