diff --git a/lib/parsers.js b/lib/parsers.js index 887bd51..76b6e31 100644 --- a/lib/parsers.js +++ b/lib/parsers.js @@ -28,9 +28,10 @@ var lengthRegEx = /^(0|[-+]?[0-9]*\.?[0-9]+(in|cm|em|mm|pt|pc|px|ex|rem|vh|vw|ch var percentRegEx = /^[-+]?[0-9]*\.?[0-9]+%$/; var urlRegEx = /^url\(\s*([^)]*)\s*\)$/; var stringRegEx = /^("[^"]*"|'[^']*')$/; -var colorRegEx1 = /^#([0-9a-fA-F]{3,4}){1,2}$/; -var colorRegEx2 = /^rgb\(([^)]*)\)$/; -var colorRegEx3 = /^rgba\(([^)]*)\)$/; +var colorRegEx1 = /^#((?:[0-9A-F]{3,4}){1,2})$/i; +var colorRegEx2 = + /^rgba?\(\s*((?:(?:none|[-+]?\d*\.?\d+%?)[\s,]+){2,3}[\s,/]*(?:none|[-+]?\d*\.?\d+%?))\s*\)$/; +var rgbdelimiters = /[\s,/]+/; var calcRegEx = /^calc\(([^)]*)\)$/; var colorRegEx4 = /^hsla?\(\s*(-?\d+|-?\d*.\d+)\s*,\s*(-?\d+|-?\d*.\d+)%\s*,\s*(-?\d+|-?\d*.\d+)%\s*(,\s*(-?\d+|-?\d*.\d+)\s*)?\)/; @@ -76,37 +77,8 @@ exports.valueType = function valueType(val) { if (colorRegEx1.test(val)) { return exports.TYPES.COLOR; } - - var res = colorRegEx2.exec(val); - var parts; - if (res !== null) { - parts = res[1].split(/\s*,\s*/); - if (parts.length !== 3) { - return undefined; - } - if ( - parts.every(percentRegEx.test.bind(percentRegEx)) || - parts.every(integerRegEx.test.bind(integerRegEx)) - ) { - return exports.TYPES.COLOR; - } - return undefined; - } - res = colorRegEx3.exec(val); - if (res !== null) { - parts = res[1].split(/\s*,\s*/); - if (parts.length !== 4) { - return undefined; - } - if ( - parts.slice(0, 3).every(percentRegEx.test.bind(percentRegEx)) || - parts.slice(0, 3).every(integerRegEx.test.bind(integerRegEx)) - ) { - if (numberRegEx.test(parts[3])) { - return exports.TYPES.COLOR; - } - } - return undefined; + if (colorRegEx2.exec(val) !== null) { + return exports.TYPES.COLOR; } if (colorRegEx4.test(val)) { @@ -302,80 +274,53 @@ exports.parseColor = function parseColor(val) { var res = colorRegEx1.exec(val); // is it #aaa, #ababab, #aaaa, #abababaa if (res) { - var defaultHex = val.substr(1); - var hex = val.substr(1); - if (hex.length === 3 || hex.length === 4) { - hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2]; - - if (defaultHex.length === 4) { - hex = hex + defaultHex[3] + defaultHex[3]; - } + var hex = res[1]; + if ([3, 4].includes(hex.length)) { + hex = [...hex].map((el) => el + el).join(''); } - red = parseInt(hex.substr(0, 2), 16); - green = parseInt(hex.substr(2, 2), 16); - blue = parseInt(hex.substr(4, 2), 16); + var output = [red, green, blue]; + output = output.map((_, i) => parseInt(hex.substr(i * 2, 2), 16)); if (hex.length === 8) { - var hexAlpha = hex.substr(6, 2); - var hexAlphaToRgbaAlpha = Number((parseInt(hexAlpha, 16) / 255).toFixed(3)); - - return 'rgba(' + red + ', ' + green + ', ' + blue + ', ' + hexAlphaToRgbaAlpha + ')'; + alpha = Number((parseInt(hex.substr(6, 2), 16) / 255).toFixed(3)); + //if (alpha !== 1) { + output.push(alpha); + //} } - return 'rgb(' + red + ', ' + green + ', ' + blue + ')'; + return (output.length == 4 ? 'rgba(' : 'rgb(') + output.join(', ') + ')'; } res = colorRegEx2.exec(val); if (res) { - parts = res[1].split(/\s*,\s*/); - if (parts.length !== 3) { - return undefined; - } - if (parts.every(percentRegEx.test.bind(percentRegEx))) { - red = Math.floor((parseFloat(parts[0].slice(0, -1)) * 255) / 100); - green = Math.floor((parseFloat(parts[1].slice(0, -1)) * 255) / 100); - blue = Math.floor((parseFloat(parts[2].slice(0, -1)) * 255) / 100); - } else if (parts.every(integerRegEx.test.bind(integerRegEx))) { - red = parseInt(parts[0], 10); - green = parseInt(parts[1], 10); - blue = parseInt(parts[2], 10); - } else { - return undefined; - } - red = Math.min(255, Math.max(0, red)); - green = Math.min(255, Math.max(0, green)); - blue = Math.min(255, Math.max(0, blue)); - return 'rgb(' + red + ', ' + green + ', ' + blue + ')'; - } - - res = colorRegEx3.exec(val); - if (res) { - parts = res[1].split(/\s*,\s*/); - if (parts.length !== 4) { - return undefined; - } - if (parts.slice(0, 3).every(percentRegEx.test.bind(percentRegEx))) { - red = Math.floor((parseFloat(parts[0].slice(0, -1)) * 255) / 100); - green = Math.floor((parseFloat(parts[1].slice(0, -1)) * 255) / 100); - blue = Math.floor((parseFloat(parts[2].slice(0, -1)) * 255) / 100); - alpha = parseFloat(parts[3]); - } else if (parts.slice(0, 3).every(integerRegEx.test.bind(integerRegEx))) { - red = parseInt(parts[0], 10); - green = parseInt(parts[1], 10); - blue = parseInt(parts[2], 10); - alpha = parseFloat(parts[3]); - } else { - return undefined; - } - if (isNaN(alpha)) { - alpha = 1; - } - red = Math.min(255, Math.max(0, red)); - green = Math.min(255, Math.max(0, green)); - blue = Math.min(255, Math.max(0, blue)); - alpha = Math.min(1, Math.max(0, alpha)); - if (alpha === 1) { - return 'rgb(' + red + ', ' + green + ', ' + blue + ')'; + parts = res[1].split(rgbdelimiters); + [red, green, blue] = parts.slice(0, 3).map((code) => + code.toLowerCase() == 'none' + ? 0 + : Math.min( + 255, + Math.max( + 0, + percentRegEx.test(code) + ? Math.floor((parseFloat(code.slice(0, -1)) * 255) / 100) //Math.round + : integerRegEx.test(code) + ? parseInt(code, 10) + : undefined + ) + ) + ); + var base = [red, green, blue]; + if (parts.length == 4) { + alpha = + parts[3] == 'none' + ? 0 + : percentRegEx.test(parts[3]) + ? parseFloat(parts[3].slice(0, -1)) / 100 + : parseFloat(parts[3]); + alpha = isNaN(alpha) ? 1 : Math.min(1, Math.max(0, alpha)); + if (alpha >= 0 && alpha < 1) { + base.push(alpha); + } } - return 'rgba(' + red + ', ' + green + ', ' + blue + ', ' + alpha + ')'; + return (base.length == 4 ? 'rgba(' : 'rgb(') + base.join(', ') + ')'; } res = colorRegEx4.exec(val);