// ...................................... //// compose // ...................................... const lineBreakPattern = /(\r\n|\n|\r)/gm; //--- regex const newRegexExp = (pattern, flag = '') => { const regex = new RegExp(pattern, flag); regex.lastIndex = 0; return regex; }; const regExp = { regex: (pattern, flag) => newRegexExp(pattern, flag), match: (str, pattern, flag) => str.match(regExp.regex(pattern, flag)) || [], test: (str, pattern, flag) => regExp.regex(pattern, flag).test(str), exec: (str, pattern, flag) => regExp.regex(pattern, flag).exec(str) || [], }; //--- remove const removeDoubleSpace = (x) => isArray(x) ? x.map((str) => str.replace(/\s{2,}/g, ' ')) : x.replace(/\s{2,}/g, ' '); const removeSpace = (str) => str.split(/\s+/).join(''); const removeLineBreak = (str) => str.replaceAll(lineBreakPattern, ''); //--- is const isArray = (x) => Array.isArray(x); // ...................................... //// critical Decl Char // ...................................... /*--- prevents replacing class names with colons e.g. &.classname p:not(.classic) */ const preventClassnameColons = (str) => { const index = str.indexOf('{'); const noReplaceable = str.substring(0, index); const replaceable = str.substring(index); return `${noReplaceable}${replaceable .replaceAll(':', ': ') .replaceAll(';', '; ')}`; }; const replacementCriticalDecl = (match, p1, p2, p3) => { if (match.includes('{')) { return preventClassnameColons(match); } return match.replaceAll(':', ': ').replaceAll(';', '; '); }; // ...................................... //// critical Class Char // ...................................... const criticalDeclChar = (str) => { return str.replaceAll(/[a-z\-\s]+:.*?;/gm, replacementCriticalDecl); }; // ...................................... //// critical Class Char // ...................................... const criticalClassChar = (str) => { return str .replaceAll(/\{|\}/g, ' $& ') .replaceAll('&', ' &'); }; // ...................................... //// sanitize Critical Chars // ...................................... const sanitizeCriticalChars = (str) => { const string = removeDoubleSpace( removeLineBreak(str).trim() ); return criticalDeclChar(criticalClassChar(string)); }; // ...................................... //// prettify Attributes // ...................................... const attributePattern = /\(.*?\)|\[.*?\]/gm; const replacementPrettifyAttrs = (match, p1, p2) => { if (match.includes('[')) { return removeSpace(match); //--- match.includes('(') } else { //--- hyphenated compound words e.g. min-width: if (regExp.test(match, /[a-z]-[a-z]/gm)) { return removeSpace(match); } // no replace return match; } }; /*--- prevents substitution in case of declaration value e.g. translate3d(0, 100, 0) , calc(100% - 30px) and in case of classes with attributes or atrules e.g. @media (min-width:760px) */ const prettifyAttributes = (str) => { return str.replaceAll(attributePattern, replacementPrettifyAttrs); }; // ...................................... //// prettify Atrules // ...................................... const replacementPrettifyAtrules = (match, p1, p2) => { return removeSpace(match).replace('{', ' {') }; const prettifyAtrules = (str) => { return str.replaceAll(/@.*?\{/gm, replacementPrettifyAtrules); }; // ...................................... //// prettify // ...................................... const prettify = (str) => { const string = removeDoubleSpace(str) .replaceAll(' ;', ';') .replaceAll(' :', ':') .replaceAll(' (', '(') .replaceAll('( ', '(') .replaceAll(' )', ')') .replaceAll(' [', '[') .replaceAll('[ ', '[') .replaceAll(' ]', ']') .replaceAll(/(;){1,}/gm, '; ') .replaceAll(/;\s{1,};/gm, '; ') .replaceAll('};', '}'); const attrPrettified = prettifyAttributes(string); const atrulesPrettified =prettifyAtrules(attrPrettified); return removeDoubleSpace(atrulesPrettified).trim(); }; // ...................................... //// sanitizeString // ...................................... const sanitizeString = (str) => { const sanitized = sanitizeCriticalChars(str); const string = prettify(sanitized); return string }; // ...................................... //// sanitize // ...................................... const sanitize = (x) => { if (!x) { return isArray(x) ? [] : ''; } return isArray(x) ? x.map((_x) => sanitizeString(_x)) : sanitizeString(x); }; export { sanitize as default };