Fixes #83 - HSL to hex color conversions.
authorGoalSmashers <jakub@goalsmashers.com>
Wed, 20 Mar 2013 07:14:33 +0000 (08:14 +0100)
committerGoalSmashers <jakub@goalsmashers.com>
Wed, 20 Mar 2013 07:14:33 +0000 (08:14 +0100)
History.md
lib/clean.js
test/unit-test.js

index f6b55e1..ac79b0d 100644 (file)
@@ -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
 ==================
index 5b5fdf4..120f5c1 100644 (file)
@@ -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;
   }
 };
 
index ff6dcda..667c08c 100644 (file)
@@ -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': [