See #850 - allows overriding all options.
authorJakub Pawlowicz <contact@jakubpawlowicz.com>
Fri, 6 Jan 2017 10:56:57 +0000 (11:56 +0100)
committerJakub Pawlowicz <contact@jakubpawlowicz.com>
Fri, 6 Jan 2017 14:02:11 +0000 (15:02 +0100)
Why:

* Use `all` or `*` to reset all options to a given value.

Example:

```js
new CleanCSS({
  level: {
    2: {
      all: false,
      mediaMerging: true
    }
  }
});
```

lib/options/optimization-level.js
test/options/optimization-level-test.js

index eb47f55..d8cbfbb 100644 (file)
@@ -21,6 +21,8 @@ DEFAULTS[OptimizationLevel.Two] = {
   shorthandCompacting: true
 };
 
+var ALL_KEYWORD_1 = '*';
+var ALL_KEYWORD_2 = 'all';
 var OPTION_SEPARATOR = ';';
 var OPTION_VALUE_SEPARATOR = ':';
 
@@ -68,6 +70,16 @@ function optimizationLevelOptionsFrom(source) {
     delete options[OptimizationLevel.One];
   }
 
+  if (OptimizationLevel.Two in source && ALL_KEYWORD_1 in source[OptimizationLevel.Two]) {
+    options[2] = override(options[2], defaults(OptimizationLevel.Two, normalizeValue(source[OptimizationLevel.Two][ALL_KEYWORD_1])));
+    delete source[2][ALL_KEYWORD_1];
+  }
+
+  if (OptimizationLevel.Two in source && ALL_KEYWORD_2 in source[OptimizationLevel.Two]) {
+    options[2] = override(options[2], defaults(OptimizationLevel.Two, normalizeValue(source[OptimizationLevel.Two][ALL_KEYWORD_2])));
+    delete source[2][ALL_KEYWORD_2];
+  }
+
   if (OptimizationLevel.Two in source) {
     options[2] = override(options[2], source[2]);
   } else {
@@ -77,6 +89,28 @@ function optimizationLevelOptionsFrom(source) {
   return options;
 }
 
+function defaults(level, value) {
+  var options = override(DEFAULTS[level], {});
+  var key;
+
+  for (key in options) {
+    options[key] = value;
+  }
+
+  return options;
+}
+
+function normalizeValue(value) {
+  switch (value) {
+    case 'false':
+      return false;
+    case 'true':
+      return true;
+    default:
+      return value;
+  }
+}
+
 function covertValuesToHashes(source) {
   var clonedSource = override(source, {});
   var key;
@@ -94,30 +128,26 @@ function covertValuesToHashes(source) {
     }
 
     if (key in clonedSource && typeof clonedSource[key] == 'string') {
-      clonedSource[key] = covertToHash(clonedSource[key]);
+      clonedSource[key] = covertToHash(clonedSource[key], key);
     }
   }
 
   return clonedSource;
 }
 
-function covertToHash(asString) {
+function covertToHash(asString, level) {
   return asString
     .split(OPTION_SEPARATOR)
     .reduce(function (accumulator, directive) {
       var parts = directive.split(OPTION_VALUE_SEPARATOR);
       var name = parts[0];
       var value = parts[1];
+      var normalizedValue = normalizeValue(value);
 
-      switch (value) {
-        case 'false':
-          accumulator[name] = false;
-          break;
-        case 'true':
-          accumulator[name] = true;
-          break;
-        default:
-          accumulator[name] = value;
+      if (ALL_KEYWORD_1 == name || ALL_KEYWORD_2 == name) {
+        accumulator = override(accumulator, defaults(level, normalizedValue));
+      } else {
+        accumulator[name] = normalizedValue;
       }
 
       return accumulator;
index 0cb5dcf..fbf1adf 100644 (file)
@@ -121,6 +121,56 @@ vows.describe(optimizationLevelOptionsFrom)
         });
       }
     },
+    'a hash with all keyword': {
+      'topic': function () {
+        return optimizationLevelOptionsFrom({ 1: { specialComments: 0 }, 2: { all: false, mediaMerging: true } });
+      },
+      'has all options': function (levelOptions) {
+        assert.deepEqual(Object.keys(levelOptions), ['0', '1', '2']);
+      },
+      'has level 0 options': function (levelOptions) {
+        assert.deepEqual(levelOptions['0'], {});
+      },
+      'has level 1 options': function (levelOptions) {
+        assert.deepEqual(levelOptions['1'], {
+          roundingPrecision: roundingPrecisionFrom(undefined),
+          specialComments: 0
+        });
+      },
+      'has level 2 options': function (levelOptions) {
+        assert.deepEqual(levelOptions['2'], {
+          mediaMerging: true,
+          restructuring: false,
+          semanticMerging: false,
+          shorthandCompacting: false
+        });
+      }
+    },
+    'a hash with * keyword': {
+      'topic': function () {
+        return optimizationLevelOptionsFrom({ 1: { specialComments: 0 }, 2: { '*': false, mediaMerging: true } });
+      },
+      'has all options': function (levelOptions) {
+        assert.deepEqual(Object.keys(levelOptions), ['0', '1', '2']);
+      },
+      'has level 0 options': function (levelOptions) {
+        assert.deepEqual(levelOptions['0'], {});
+      },
+      'has level 1 options': function (levelOptions) {
+        assert.deepEqual(levelOptions['1'], {
+          roundingPrecision: roundingPrecisionFrom(undefined),
+          specialComments: 0
+        });
+      },
+      'has level 2 options': function (levelOptions) {
+        assert.deepEqual(levelOptions['2'], {
+          mediaMerging: true,
+          restructuring: false,
+          semanticMerging: false,
+          shorthandCompacting: false
+        });
+      }
+    },
     'a hash with options as strings': {
       'topic': function () {
         return optimizationLevelOptionsFrom({ 1: 'roundingPrecision:3;specialComments:0' });
@@ -163,6 +213,56 @@ vows.describe(optimizationLevelOptionsFrom)
         });
       }
     },
+    'a hash with options as strings with all keyword': {
+      'topic': function () {
+        return optimizationLevelOptionsFrom({ 2: 'all:false;mediaMerging:true;semanticMerging:true' });
+      },
+      'has all options': function (levelOptions) {
+        assert.deepEqual(Object.keys(levelOptions), ['0', '1', '2']);
+      },
+      'has level 0 options': function (levelOptions) {
+        assert.deepEqual(levelOptions['0'], {});
+      },
+      'has level 1 options': function (levelOptions) {
+        assert.deepEqual(levelOptions['1'], {
+          roundingPrecision: roundingPrecisionFrom(undefined),
+          specialComments: 'all'
+        });
+      },
+      'has level 2 options': function (levelOptions) {
+        assert.deepEqual(levelOptions['2'], {
+          mediaMerging: true,
+          restructuring: false,
+          semanticMerging: true,
+          shorthandCompacting: false
+        });
+      }
+    },
+    'a hash with options as strings with * keyword': {
+      'topic': function () {
+        return optimizationLevelOptionsFrom({ 2: '*:false;mediaMerging:true;semanticMerging:true' });
+      },
+      'has all options': function (levelOptions) {
+        assert.deepEqual(Object.keys(levelOptions), ['0', '1', '2']);
+      },
+      'has level 0 options': function (levelOptions) {
+        assert.deepEqual(levelOptions['0'], {});
+      },
+      'has level 1 options': function (levelOptions) {
+        assert.deepEqual(levelOptions['1'], {
+          roundingPrecision: roundingPrecisionFrom(undefined),
+          specialComments: 'all'
+        });
+      },
+      'has level 2 options': function (levelOptions) {
+        assert.deepEqual(levelOptions['2'], {
+          mediaMerging: true,
+          restructuring: false,
+          semanticMerging: true,
+          shorthandCompacting: false
+        });
+      }
+    },
     'a hash with options as undefined/boolean': {
       'topic': function () {
         return optimizationLevelOptionsFrom({ 0: undefined, 1: true, 2: undefined });