From e3712ac14032b79a2cb0909b54012777650ca335 Mon Sep 17 00:00:00 2001 From: Jakub Pawlowicz Date: Fri, 6 Jan 2017 11:56:57 +0100 Subject: [PATCH] See #850 - allows overriding all options. 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 | 52 +++++++++--- test/options/optimization-level-test.js | 100 ++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 11 deletions(-) diff --git a/lib/options/optimization-level.js b/lib/options/optimization-level.js index eb47f553..d8cbfbbc 100644 --- a/lib/options/optimization-level.js +++ b/lib/options/optimization-level.js @@ -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; diff --git a/test/options/optimization-level-test.js b/test/options/optimization-level-test.js index 0cb5dcf4..fbf1adfb 100644 --- a/test/options/optimization-level-test.js +++ b/test/options/optimization-level-test.js @@ -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 }); -- 2.34.1