Simplifies unit optimizations code.
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Tue, 23 Jun 2015 05:42:53 +0000 (06:42 +0100)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Tue, 23 Jun 2015 05:43:26 +0000 (06:43 +0100)
It follows a much simpler functional style, which is also easier to
grasp.

lib/clean.js
lib/selectors/simple.js
test/test-helper.js

index 87522ec..5ca4634 100644 (file)
@@ -9,7 +9,7 @@ var ImportInliner = require('./imports/inliner');
 var rebaseUrls = require('./urls/rebase');
 
 var tokenize = require('./tokenizer/tokenize');
-var SimpleOptimizer = require('./selectors/simple');
+var simpleOptimize = require('./selectors/simple');
 var advancedOptimize = require('./selectors/advanced');
 var addOptimizationMetadata = require('./selectors/optimization-metadata');
 
@@ -203,7 +203,7 @@ function minify(context, data) {
 
   addOptimizationMetadata(tokens);
 
-  new SimpleOptimizer(options).optimize(tokens);
+  simpleOptimize(tokens, options);
 
   if (options.advanced)
     advancedOptimize(tokens, options, context.validator, true);
index 45acecf..6dcff70 100644 (file)
@@ -1,4 +1,6 @@
-var CleanUp = require('./clean-up');
+var cleanUpSelectors = require('./clean-up').selectors;
+var cleanUpBlock = require('./clean-up').block;
+var cleanUpAtRule = require('./clean-up').atRule;
 var Splitter = require('../utils/splitter');
 
 var RGB = require('../colors/rgb');
@@ -12,27 +14,6 @@ var CHARSET_REGEXP = new RegExp('^' + CHARSET_TOKEN, 'i');
 var FONT_NUMERAL_WEIGHTS = ['100', '200', '300', '400', '500', '600', '700', '800', '900'];
 var FONT_NAME_WEIGHTS = ['normal', 'bold', 'bolder', 'lighter'];
 
-function SimpleOptimizer(options) {
-  this.options = options;
-
-  var units = ['px', 'em', 'ex', 'cm', 'mm', 'in', 'pt', 'pc', '%'];
-  var otherUnits = ['ch', 'rem', 'vh', 'vm', 'vmax', 'vmin', 'vw'];
-
-  otherUnits.forEach(function (unit) {
-    if (options.compatibility.units[unit])
-      units.push(unit);
-  });
-
-  options.unitsRegexp = new RegExp('(^|\\s|\\(|,)0(?:' + units.join('|') + ')(\\W|$)', 'g');
-
-  options.precision = {};
-  options.precision.value = options.roundingPrecision === undefined ?
-    DEFAULT_ROUNDING_PRECISION :
-    options.roundingPrecision;
-  options.precision.multiplier = Math.pow(10, options.precision.value);
-  options.precision.regexp = new RegExp('(\\d*\\.\\d{' + (options.precision.value + 1) + ',})px', 'g');
-}
-
 var valueMinifiers = {
   'background': function (value, index, total) {
     return index == 1 && total == 2 && (value == 'none' || value == 'transparent') ? '0 0' : value;
@@ -289,71 +270,93 @@ function optimizeBody(properties, options) {
   }
 }
 
-SimpleOptimizer.prototype.optimize = function (tokens) {
-  var self = this;
+function cleanupCharsets(tokens) {
   var hasCharset = false;
-  var options = this.options;
-  var ie7Hack = options.compatibility.selectors.ie7Hack;
-  var adjacentSpace = options.compatibility.selectors.adjacentSpace;
-  var spaceAfterClosingBrace = options.compatibility.properties.spaceAfterClosingBrace;
 
-  function _cleanupCharsets(tokens) {
-    for (var i = 0, l = tokens.length; i < l; i++) {
-      var token = tokens[i];
-
-      if (token[0] != 'at-rule')
-        continue;
-
-      if (CHARSET_REGEXP.test(token[1][0])) {
-        if (hasCharset || token[1][0].indexOf(CHARSET_TOKEN) == -1) {
-          tokens.splice(i, 1);
-          i--;
-          l--;
-        } else {
-          hasCharset = true;
-          tokens.splice(i, 1);
-          tokens.unshift(['at-rule', [token[1][0].replace(CHARSET_REGEXP, CHARSET_TOKEN)]]);
-        }
-      }
+  for (var i = 0, l = tokens.length; i < l; i++) {
+    var token = tokens[i];
+
+    if (token[0] != 'at-rule')
+      continue;
+
+    if (!CHARSET_REGEXP.test(token[1][0]))
+      continue;
+
+    if (hasCharset || token[1][0].indexOf(CHARSET_TOKEN) == -1) {
+      tokens.splice(i, 1);
+      i--;
+      l--;
+    } else {
+      hasCharset = true;
+      tokens.splice(i, 1);
+      tokens.unshift(['at-rule', [token[1][0].replace(CHARSET_REGEXP, CHARSET_TOKEN)]]);
     }
   }
+}
 
-  function _optimize(tokens) {
-    var mayHaveCharset = false;
-
-    for (var i = 0, l = tokens.length; i < l; i++) {
-      var token = tokens[i];
-
-      switch (token[0]) {
-        case 'selector':
-          token[1] = CleanUp.selectors(token[1], !ie7Hack, adjacentSpace);
-          optimizeBody(token[2], self.options);
-          break;
-        case 'block':
-          CleanUp.block(token[1], spaceAfterClosingBrace);
-          _optimize(token[2]);
-          break;
-        case 'flat-block':
-          CleanUp.block(token[1], spaceAfterClosingBrace);
-          optimizeBody(token[2], self.options);
-          break;
-        case 'at-rule':
-          CleanUp.atRule(token[1]);
-          mayHaveCharset = true;
-      }
+function buildUnitRegexp(options) {
+  var units = ['px', 'em', 'ex', 'cm', 'mm', 'in', 'pt', 'pc', '%'];
+  var otherUnits = ['ch', 'rem', 'vh', 'vm', 'vmax', 'vmin', 'vw'];
 
-      if (token[1].length === 0 || (token[2] && token[2].length === 0)) {
-        tokens.splice(i, 1);
-        i--;
-        l--;
-      }
+  otherUnits.forEach(function (unit) {
+    if (options.compatibility.units[unit])
+      units.push(unit);
+  });
+
+  return new RegExp('(^|\\s|\\(|,)0(?:' + units.join('|') + ')(\\W|$)', 'g');
+}
+
+function buildPrecision(options) {
+  var precision = {};
+
+  precision.value = options.roundingPrecision === undefined ?
+    DEFAULT_ROUNDING_PRECISION :
+    options.roundingPrecision;
+  precision.multiplier = Math.pow(10, precision.value);
+  precision.regexp = new RegExp('(\\d*\\.\\d{' + (precision.value + 1) + ',})px', 'g');
+
+  return precision;
+}
+
+function optimize(tokens, options) {
+  var ie7Hack = options.compatibility.selectors.ie7Hack;
+  var adjacentSpace = options.compatibility.selectors.adjacentSpace;
+  var spaceAfterClosingBrace = options.compatibility.properties.spaceAfterClosingBrace;
+  var mayHaveCharset = false;
+
+  options.unitsRegexp = buildUnitRegexp(options);
+  options.precision = buildPrecision(options);
+
+  for (var i = 0, l = tokens.length; i < l; i++) {
+    var token = tokens[i];
+
+    switch (token[0]) {
+      case 'selector':
+        token[1] = cleanUpSelectors(token[1], !ie7Hack, adjacentSpace);
+        optimizeBody(token[2], options);
+        break;
+      case 'block':
+        cleanUpBlock(token[1], spaceAfterClosingBrace);
+        optimize(token[2], options);
+        break;
+      case 'flat-block':
+        cleanUpBlock(token[1], spaceAfterClosingBrace);
+        optimizeBody(token[2], options);
+        break;
+      case 'at-rule':
+        cleanUpAtRule(token[1]);
+        mayHaveCharset = true;
     }
 
-    if (mayHaveCharset)
-      _cleanupCharsets(tokens);
+    if (token[1].length === 0 || (token[2] && token[2].length === 0)) {
+      tokens.splice(i, 1);
+      i--;
+      l--;
+    }
   }
 
-  _optimize(tokens);
-};
+  if (mayHaveCharset)
+    cleanupCharsets(tokens);
+}
 
-module.exports = SimpleOptimizer;
+module.exports = optimize;
index 0f3376b..7ff5f0d 100644 (file)
@@ -2,7 +2,7 @@ var assert = require('assert');
 
 var CleanCSS = require('../lib/clean');
 var tokenize = require('../lib/tokenizer/tokenize');
-var SimpleOptimizer = require('../lib/selectors/simple');
+var simpleOptimize = require('../lib/selectors/simple');
 var Compatibility = require('../lib/utils/compatibility');
 var addOptimizationMetadata = require('../lib/selectors/optimization-metadata');
 
@@ -36,7 +36,7 @@ function selectorContext(group, specs, options) {
   function optimized(selectors) {
     return function (source) {
       var tokens = tokenize(source, { options: {} });
-      new SimpleOptimizer(options).optimize(tokens);
+      simpleOptimize(tokens, options);
 
       assert.deepEqual(tokens[0] ? tokens[0][1] : null, selectors);
     };
@@ -61,7 +61,7 @@ function propertyContext(group, specs, options) {
     return function (source) {
       var tokens = tokenize(source, { options: {} });
       addOptimizationMetadata(tokens);
-      new SimpleOptimizer(options).optimize(tokens);
+      simpleOptimize(tokens, options);
 
       var value = tokens[0] ?
         tokens[0][2].map(function (property) {