Fixes #241 - incorrect handling of :not() selectors.
authorJakub Pawlowicz <jakub@goalsmashers.com>
Wed, 19 Feb 2014 07:38:15 +0000 (07:38 +0000)
committerJakub Pawlowicz <jakub@goalsmashers.com>
Wed, 19 Feb 2014 07:38:15 +0000 (07:38 +0000)
Since :not() can have multiple selectors passed in, e.g. :not(div,span),
commas need to be handled in a more clever way.

History.md
lib/selectors/optimizer.js
test/data/issue-241-min.css [new file with mode: 0644]
test/data/issue-241.css [new file with mode: 0644]

index 0415f48..5486e30 100644 (file)
@@ -1,3 +1,8 @@
+[2.1.1 / 2014-xx-xx (UNRELEASED)](https://github.com/GoalSmashers/clean-css/compare/v2.1.0...v2.1.1)
+==================
+
+* Fixed issue [#241](https://github.com/GoalSmashers/clean-css/issues/241) - incorrect handling of :not() selectors.
+
 [2.1.0 / 2014-02-13](https://github.com/GoalSmashers/clean-css/compare/v2.0.8...v2.1.0)
 ==================
 
index df1c867..6fc3898 100644 (file)
@@ -14,13 +14,42 @@ module.exports = function Optimizer(data, context, options) {
 
   var cleanUpSelector = function(selectors) {
     var plain = [];
-    selectors = selectors.split(',');
+    var cursor = 0;
+    var lastComma = 0;
+    var noBrackets = selectors.indexOf('(') == -1;
+    var withinBrackets = function(idx) {
+      if (noBrackets)
+        return false;
+
+      var previousOpening = selectors.lastIndexOf('(', idx);
+      var previousClosing = selectors.lastIndexOf(')', idx);
+
+      if (previousOpening == -1)
+        return false;
+      if (previousClosing > 0 && previousClosing < idx)
+        return false;
+
+      return true;
+    };
 
-    for (var i = 0, l = selectors.length; i < l; i++) {
-      var sel = selectors[i];
+    while (true) {
+      var nextComma = selectors.indexOf(',', cursor + 1);
+      var selector;
 
-      if (plain.indexOf(sel) == -1)
-        plain.push(sel);
+      if (nextComma === -1) {
+        nextComma = selectors.length;
+      } else if (withinBrackets(nextComma)) {
+        cursor = nextComma + 1;
+        continue;
+      }
+      selector = selectors.substring(lastComma, nextComma);
+      lastComma = cursor = nextComma + 1;
+
+      if (plain.indexOf(selector) == -1)
+        plain.push(selector);
+
+      if (nextComma === selectors.length)
+        break;
     }
 
     return plain.sort().join(',');
diff --git a/test/data/issue-241-min.css b/test/data/issue-241-min.css
new file mode 100644 (file)
index 0000000..2ca7642
--- /dev/null
@@ -0,0 +1,2 @@
+.c4:not(.c1,.c2){width:1px}
+@media (min-width:1px){.c3{width:1px}}
diff --git a/test/data/issue-241.css b/test/data/issue-241.css
new file mode 100644 (file)
index 0000000..5ac7875
--- /dev/null
@@ -0,0 +1,2 @@
+.c4:not(.c1, .c2){width: 1px;}
+@media  (min-width: 1px) { .c3{width: 1px;} }