From: GoalSmashers Date: Wed, 20 Mar 2013 07:14:33 +0000 (+0100) Subject: Fixes #83 - HSL to hex color conversions. X-Git-Url: https://git.ndcode.org/public/gitweb.cgi?a=commitdiff_plain;h=8cf8283adf5fe185227f4492db2cc28f446590b1;p=clean-css.git Fixes #83 - HSL to hex color conversions. --- diff --git a/History.md b/History.md index f6b55e1c..ac79b0d4 100644 --- a/History.md +++ b/History.md @@ -3,7 +3,8 @@ * Fixed issue [#46](https://github.com/GoalSmashers/clean-css/issues/46) - preserving special characters in URLs and attributes. -* Fixed issue [#44](https://github.com/GoalSmashers/clean-css/issues/46) - examples in --help. +* Fixed issue [#44](https://github.com/GoalSmashers/clean-css/issues/44) - examples in --help. +* Fixed issue [#83](https://github.com/GoalSmashers/clean-css/issues/83) - HSL to hex color conversions. 0.10.2 / 2013-03-19 ================== diff --git a/lib/clean.js b/lib/clean.js index 5b5fdf4e..120f5c17 100644 --- a/lib/clean.js +++ b/lib/clean.js @@ -156,6 +156,19 @@ var CleanCSS = { // trailing semicolons replace(/;\}/g, '}'); + // hsl to hex colors + replace(/hsl\((\d+),(\d+)%?,(\d+)%?\)/g, function(match, hue, saturation, lightness) { + var asRgb = CleanCSS._hslToRgb(hue, saturation, lightness); + var redAsHex = asRgb[0].toString(16); + var greenAsHex = asRgb[1].toString(16); + var blueAsHex = asRgb[2].toString(16); + + return '#' + + ((redAsHex.length == 1 ? '0' : '') + redAsHex) + + ((greenAsHex.length == 1 ? '0' : '') + greenAsHex) + + ((blueAsHex.length == 1 ? '0' : '') + blueAsHex); + }); + // rgb to hex colors replace(/rgb\s*\(([^\)]+)\)/g, function(match, color) { var parts = color.split(','); @@ -167,7 +180,7 @@ var CleanCSS = { return encoded; }); - // long color hex to short hex + // long hex to short hex colors replace(/([,: \(])#([0-9a-f]{6})/gi, function(match, prefix, color) { if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5]) return prefix + '#' + color[0] + color[2] + color[4]; @@ -424,6 +437,39 @@ var CleanCSS = { return tempData.length > 0 ? tempData.join('') + data.substring(cursor, data.length) : data; + }, + + // HSL to RGB converter. Both methods taken and adapted from: + // http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript + _hslToRgb: function(h, s, l) { + var r, g, b; + + h = ~~h / 360; + s = ~~s / 100; + l = ~~l / 100; + + if (s === 0) { + r = g = b = l; // achromatic + } else { + var q = l < 0.5 ? + l * (1 + s) : + l + s - l * s; + var p = 2 * l - q; + r = this._hueToRgb(p, q, h + 1/3); + g = this._hueToRgb(p, q, h); + b = this._hueToRgb(p, q, h - 1/3); + } + + return [~~(r * 255), ~~(g * 255), ~~(b * 255)]; + }, + + _hueToRgb: function(p, q, t) { + if (t < 0) t += 1; + if (t > 1) t -= 1; + if (t < 1/6) return p + (q - p) * 6 * t; + if (t < 1/2) return q; + if (t < 2/3) return p + (q - p) * (2/3 - t) * 6; + return p; } }; diff --git a/test/unit-test.js b/test/unit-test.js index ff6dcdaa..667c08ca 100644 --- a/test/unit-test.js +++ b/test/unit-test.js @@ -481,13 +481,40 @@ vows.describe('clean-units').addBatch({ ], 'colors and colons': 'a{background-image:linear-gradient(top,red,#e6e6e6)}', 'colors and parentheses': 'a{background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6))}', - 'hsl percents': 'a{color:hsl(1,0%,0%)}', - 'hsla percents': 'a{color:hsl(1,0%,0%)}', - 'hsl one percent': 'a{color:hsl(80,100%,0%)}', - 'hsla custom ': 'a{color:hsl(80,30%,50%,.5)}', 'colors in ie filters': 'a{filter:chroma(color=#ffffff)}', 'colors in ie filters 2': "a{progid:DXImageTransform.Microsoft.gradient(startColorstr='#cccccc', endColorstr='#000000')}", - 'colors in ie filters 3': "a{progid:DXImageTransform.Microsoft.gradient(startColorstr='#DDDDDD', endColorstr='#333333')}" + 'colors in ie filters 3': "a{progid:DXImageTransform.Microsoft.gradient(startColorstr='#DDDDDD', endColorstr='#333333')}", + 'hsla percents': 'a{color:hsla(1,0%,0%,.5)}', + 'hsla custom ': 'a{color:hsl(80,30%,50%,.5)}', + 'hsl to hex #1': [ + 'a{color:hsl(360,100%,50%)}', + 'a{color:red}' + ], + 'hsl to hex #1': [ + 'a{color:hsl(0,0%,0%)}', + 'a{color:#000}' + ], + 'hsl to hex #2': [ + 'a{color:hsl(0,100%,100%)}', + 'a{color:#fff}' + ], + 'hsl to hex #3': [ + 'a{color:hsl(240,100%,50%)}', + 'a{color:#00f}' + ], + 'hsl to hex #4': [ + 'a{color:hsl(240,100%,50%)}', + 'a{color:#00f}' + ], + 'hsl to hex #5': [ + 'a{color:hsl(120,100%,25%)}', + 'a{color:#007f00}' + ], + 'hsl to hex #6': [ + 'a{color:hsl(99,66%,33%)}', + 'a{color:#438b1c}' + ], + 'hsla not to hex': 'a{color:hsl(99,66%,33%,.5)}' }), 'font weights': cssContext({ 'font-weight:normal to 400': [