Utils.escape = (text) => { // https://codereview.stackexchange.com/a/126722 var table = { '<': 'lt', '>': 'gt', '"': 'quot', '\'': 'apos', '&': 'amp', '\r': '#10', '\n': '#13' }; return text.toString().replace(/[<>"'\r\n&]/g, (chr) => { return '&' + table[chr] + ';'; }); }; Utils.unescape = (escapedText) => { var table = { 'lt': '<', 'gt': '>', 'quot': '"', 'apos': "'", 'amp': '&', '#10': '\r', '#13': '\n' }; return escapedText.replace(/&(#?\w+);/g, (match, entity) => { if (table.hasOwnProperty(entity)) { return table[entity]; } return match; }); }; Utils.HTMLToElement = (HTMLString) => { let templateElement = document.createElement('template'); templateElement.innerHTML = HTMLString.trim(); return templateElement.content.firstChild; }; Utils.generateElementId = (prefix='', suffix='') => { for (let i = 0; true; i++) { if (document.querySelector(`#${prefix}${i}${suffix}`) !== null) {continue;} return `${prefix}${i}${suffix}`; } }; Utils.isObject = (object) => { return object !== null && typeof object === 'object' && !Array.isArray(object); }; Utils.mergeObjectsDeep = (...objects) => { let mergedObject = {}; if (objects.length === 0) { return mergedObject; } if (!Utils.isObject(objects[0])) {throw 'Cannot merge non-object';} if (objects.length === 1) { return Utils.mergeObjectsDeep(mergedObject, objects[0]); } if (!Utils.isObject(objects[1])) {throw 'Cannot merge non-object';} for (let key in objects[0]) { if (objects[0].hasOwnProperty(key)) { if (objects[1].hasOwnProperty(key)) { if (Utils.isObject(objects[0][key]) && Utils.isObject(objects[1][key])) { mergedObject[key] = Utils.mergeObjectsDeep(objects[0][key], objects[1][key]); } else { mergedObject[key] = objects[1][key]; } } else { mergedObject[key] = objects[0][key]; } } } for (let key in objects[1]) { if (objects[1].hasOwnProperty(key)) { if (!objects[0].hasOwnProperty(key)) { mergedObject[key] = objects[1][key]; } } } if (objects.length === 2) { return mergedObject; } return Utils.mergeObjectsDeep(mergedObject, ...objects.slice(2)); };