Cleans up advanced optimizer implementation.
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Sun, 21 Jun 2015 14:18:37 +0000 (15:18 +0100)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Sun, 21 Jun 2015 14:18:37 +0000 (15:18 +0100)
It gets rid of AdvancedOptimizer class in favour to simpler
functional style.

lib/clean.js
lib/selectors/advanced.js
test/selectors/advanced-test.js

index b3c0a44..87522ec 100644 (file)
@@ -10,7 +10,7 @@ var rebaseUrls = require('./urls/rebase');
 
 var tokenize = require('./tokenizer/tokenize');
 var SimpleOptimizer = require('./selectors/simple');
-var AdvancedOptimizer = require('./selectors/advanced');
+var advancedOptimize = require('./selectors/advanced');
 var addOptimizationMetadata = require('./selectors/optimization-metadata');
 
 var simpleStringify = require('./stringifier/simple');
@@ -206,7 +206,7 @@ function minify(context, data) {
   new SimpleOptimizer(options).optimize(tokens);
 
   if (options.advanced)
-    new AdvancedOptimizer(options, context).optimize(tokens);
+    advancedOptimize(tokens, options, context.validator, true);
 
   return stringify(tokens, options, restoreEscapes, context.inputSourceMapTracker);
 }
index 48e55fe..f03b11f 100644 (file)
@@ -9,12 +9,7 @@ var restructure = require('./restructure');
 var removeDuplicateMediaQueries = require('./remove-duplicate-media-queries');
 var mergeMediaQueries = require('./merge-media-queries');
 
-function AdvancedOptimizer(options, context) {
-  this.options = options;
-  this.validator = context.validator;
-}
-
-AdvancedOptimizer.prototype.removeEmpty = function (tokens) {
+function removeEmpty(tokens) {
   for (var i = 0, l = tokens.length; i < l; i++) {
     var token = tokens[i];
     var isEmpty = false;
@@ -24,7 +19,7 @@ AdvancedOptimizer.prototype.removeEmpty = function (tokens) {
         isEmpty = token[1].length === 0 || token[2].length === 0;
         break;
       case 'block':
-        this.removeEmpty(token[2]);
+        removeEmpty(token[2]);
         isEmpty = token[2].length === 0;
     }
 
@@ -34,7 +29,18 @@ AdvancedOptimizer.prototype.removeEmpty = function (tokens) {
       l--;
     }
   }
-};
+}
+
+function recursivelyOptimizeBlocks(tokens, options, validator) {
+  for (var i = 0, l = tokens.length; i < l; i++) {
+    var token = tokens[i];
+
+    if (token[0] == 'block') {
+      var isKeyframes = /@(-moz-|-o-|-webkit-)?keyframes/.test(token[1][0]);
+      optimize(token[2], options, validator, !isKeyframes);
+    }
+  }
+}
 
 function recursivelyOptimizeProperties(tokens, options, validator) {
   for (var i = 0, l = tokens.length; i < l; i++) {
@@ -50,43 +56,31 @@ function recursivelyOptimizeProperties(tokens, options, validator) {
   }
 }
 
-AdvancedOptimizer.prototype.optimize = function (tokens) {
-  var self = this;
-
-  function _optimize(tokens, withRestructuring) {
-    tokens.forEach(function (token) {
-      if (token[0] == 'block') {
-        var isKeyframes = /@(-moz-|-o-|-webkit-)?keyframes/.test(token[1][0]);
-        _optimize(token[2], !isKeyframes);
-      }
-    });
-
-    recursivelyOptimizeProperties(tokens, self.options, self.validator);
+function optimize(tokens, options, validator, withRestructuring) {
+  recursivelyOptimizeBlocks(tokens, options, validator);
+  recursivelyOptimizeProperties(tokens, options, validator);
 
-    removeDuplicates(tokens);
-    mergeAdjacent(tokens, self.options, self.validator);
-    reduceNonAdjacent(tokens, self.options, self.validator);
+  removeDuplicates(tokens);
+  mergeAdjacent(tokens, options, validator);
+  reduceNonAdjacent(tokens, options, validator);
 
-    mergeNonAdjacentBySelector(tokens, self.options, self.validator);
-    mergeNonAdjacentByBody(tokens, self.options);
+  mergeNonAdjacentBySelector(tokens, options, validator);
+  mergeNonAdjacentByBody(tokens, options);
 
-    if (self.options.restructuring && withRestructuring) {
-      restructure(tokens, self.options);
-      mergeAdjacent(tokens, self.options, self.validator);
-    }
+  if (options.restructuring && withRestructuring) {
+    restructure(tokens, options);
+    mergeAdjacent(tokens, options, validator);
+  }
 
-    if (self.options.mediaMerging) {
-      removeDuplicateMediaQueries(tokens);
-      var reduced = mergeMediaQueries(tokens);
-      for (var i = reduced.length - 1; i >= 0; i--) {
-        _optimize(reduced[i][2]);
-      }
+  if (options.mediaMerging) {
+    removeDuplicateMediaQueries(tokens);
+    var reduced = mergeMediaQueries(tokens);
+    for (var i = reduced.length - 1; i >= 0; i--) {
+      optimize(reduced[i][2], options, validator, false);
     }
-
-    self.removeEmpty(tokens);
   }
 
-  _optimize(tokens, true);
-};
+  removeEmpty(tokens);
+}
 
-module.exports = AdvancedOptimizer;
+module.exports = optimize;
index f5409bd..c909652 100644 (file)
@@ -2,34 +2,6 @@ var vows = require('vows');
 var optimizerContext = require('../test-helper').optimizerContext;
 
 vows.describe('advanced optimizer')
-  .addBatch(
-    optimizerContext('@media', {
-      'empty': [
-        '@media (min-width:980px){}',
-        ''
-      ],
-      'whitespace': [
-        ' @media   ( min-width:  980px ){}',
-        ''
-      ],
-      'body': [
-        '@media (min-width:980px){\na\n{color:red}}',
-        '@media (min-width:980px){a{color:red}}'
-      ],
-      'multiple': [
-        '@media screen, print, (min-width:980px){a{color:red}}',
-        '@media screen,print,(min-width:980px){a{color:red}}'
-      ],
-      'nested once': [
-        '@media screen { @media print { a{color:red} } }',
-        '@media screen{@media print{a{color:red}}}'
-      ],
-      'nested twice': [
-        '@media screen { @media print { @media (min-width:980px) { a{color:red} } } }',
-        '@media screen{@media print{@media (min-width:980px){a{color:red}}}}'
-      ]
-    })
-  )
   .addBatch(
     optimizerContext('advanced on & aggressive merging on', {
       'repeated' : [
@@ -62,6 +34,34 @@ vows.describe('advanced optimizer')
       ]
     }, { advanced: false })
   )
+  .addBatch(
+    optimizerContext('@media', {
+      'empty': [
+        '@media (min-width:980px){}',
+        ''
+      ],
+      'whitespace': [
+        ' @media   ( min-width:  980px ){}',
+        ''
+      ],
+      'body': [
+        '@media (min-width:980px){\na\n{color:red}}',
+        '@media (min-width:980px){a{color:red}}'
+      ],
+      'multiple': [
+        '@media screen, print, (min-width:980px){a{color:red}}',
+        '@media screen,print,(min-width:980px){a{color:red}}'
+      ],
+      'nested once': [
+        '@media screen { @media print { a{color:red} } }',
+        '@media screen{@media print{a{color:red}}}'
+      ],
+      'nested twice': [
+        '@media screen { @media print { @media (min-width:980px) { a{color:red} } } }',
+        '@media screen{@media print{@media (min-width:980px){a{color:red}}}}'
+      ]
+    })
+  )
   .addBatch(
     optimizerContext('@font-face', {
       'rebuilding': [