Adds much faster removal of empty selectors & @media elements.
authorGoalSmashers <jakub@goalsmashers.com>
Sat, 26 Oct 2013 22:09:55 +0000 (00:09 +0200)
committerGoalSmashers <jakub@goalsmashers.com>
Sat, 26 Oct 2013 22:09:55 +0000 (00:09 +0200)
* Adds supports for removing empty nested @media elements.

History.md
lib/clean.js
lib/selectors/empty-removal.js [new file with mode: 0644]
test/unit-test.js

index 3325d15..2019cd2 100644 (file)
@@ -2,6 +2,7 @@
 ==================
 
 * Adds simplified and more advanced text escaping / restoring via `EscapeStore` class.
+* Adds simplified and much faster empty elements removal.
 
 1.1.6 / 2013-10-26
 ==================
index 7366e60..27f4e6e 100644 (file)
@@ -13,6 +13,7 @@ var ColorLongToShortHex = require('./colors/long-to-short-hex');
 var ShorthandNotations = require('./properties/shorthand-notations');
 var ImportInliner = require('./imports/inliner');
 var UrlRebase = require('./images/url-rebase');
+var EmptyRemoval = require('./selectors/empty-removal');
 
 var CommentsProcessor = require('./text/comments');
 var ExpressionsProcessor = require('./text/expressions');
@@ -274,11 +275,9 @@ var CleanCSS = {
     });
 
     if (options.removeEmpty) {
-      // empty elements
-      replace(/[^\{\}]+\{\}/g, '');
-
-      // empty @media declarations
-      replace(/@media [^\{]+\{\}/g, '');
+      replace(function removeEmptySelectors() {
+        data = new EmptyRemoval(data).process();
+      });
     }
 
     // trim spaces at beginning and end
diff --git a/lib/selectors/empty-removal.js b/lib/selectors/empty-removal.js
new file mode 100644 (file)
index 0000000..ee193c1
--- /dev/null
@@ -0,0 +1,30 @@
+module.exports = function EmptyRemoval(data) {
+  var stripEmpty = function(cssData) {
+    var tempData = [];
+    var nextEmpty = 0;
+    var cursor = 0;
+
+    for (; nextEmpty < cssData.length; ) {
+      nextEmpty = cssData.indexOf('{}', cursor);
+      if (nextEmpty == -1)
+        break;
+
+      var startsAt = nextEmpty - 1;
+      while (cssData[startsAt] && cssData[startsAt] != '}' && cssData[startsAt] != '{')
+        startsAt--;
+
+      tempData.push(cssData.substring(cursor, startsAt + 1));
+      cursor = nextEmpty + 2;
+    }
+
+    return tempData.length > 0 ?
+      stripEmpty(tempData.join('') + cssData.substring(cursor, cssData.length)) :
+      cssData;
+  };
+
+  return {
+    process: function() {
+      return stripEmpty(data);
+    }
+  };
+};
index 17d74b1..0faf673 100644 (file)
@@ -852,9 +852,17 @@ title']",
       "@media screen { .test {} } .test1 { color: green; }",
       ".test1{color:green}"
     ],
+    'inside nested @media': [
+      '@media screen { @media (orientation:landscape) { @media (max-width:999px) { .test {} } } }',
+      ''
+    ],
     'inside not empty @media': [
       "@media screen { .test {} .some { display:none } }",
       "@media screen{.some{display:none}}"
+    ],
+    'inside nested not empty @media': [
+      '@media screen { @media (orientation:landscape) { @media (max-width:999px) { .test {} } a {color:red} } }',
+      '@media screen{@media (orientation:landscape){a{color:red}}}'
     ]
   }, { removeEmpty: true }),
   'empty @media': cssContext({