219 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			219 lines
		
	
	
		
			5.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| var roundingPrecisionFrom = require('./rounding-precision').roundingPrecisionFrom;
 | |
| 
 | |
| var override = require('../utils/override');
 | |
| 
 | |
| var OptimizationLevel = {
 | |
|   Zero: '0',
 | |
|   One: '1',
 | |
|   Two: '2'
 | |
| };
 | |
| 
 | |
| var DEFAULTS = {};
 | |
| 
 | |
| DEFAULTS[OptimizationLevel.Zero] = {};
 | |
| DEFAULTS[OptimizationLevel.One] = {
 | |
|   cleanupCharsets: true,
 | |
|   normalizeUrls: true,
 | |
|   optimizeBackground: true,
 | |
|   optimizeBorderRadius: true,
 | |
|   optimizeFilter: true,
 | |
|   optimizeFontWeight: true,
 | |
|   optimizeOutline: true,
 | |
|   removeEmpty: true,
 | |
|   removeNegativePaddings: true,
 | |
|   removeQuotes: true,
 | |
|   removeWhitespace: true,
 | |
|   replaceMultipleZeros: true,
 | |
|   replaceTimeUnits: true,
 | |
|   replaceZeroUnits: true,
 | |
|   roundingPrecision: roundingPrecisionFrom(undefined),
 | |
|   selectorsSortingMethod: 'standard',
 | |
|   specialComments: 'all',
 | |
|   tidyAtRules: true,
 | |
|   tidyBlockScopes: true,
 | |
|   tidySelectors: true,
 | |
|   variableValueOptimizers: []
 | |
| };
 | |
| DEFAULTS[OptimizationLevel.Two] = {
 | |
|   mergeAdjacentRules: true,
 | |
|   mergeIntoShorthands: true,
 | |
|   mergeMedia: true,
 | |
|   mergeNonAdjacentRules: true,
 | |
|   mergeSemantically: false,
 | |
|   overrideProperties: true,
 | |
|   removeEmpty: true,
 | |
|   reduceNonAdjacentRules: true,
 | |
|   removeDuplicateFontRules: true,
 | |
|   removeDuplicateMediaBlocks: true,
 | |
|   removeDuplicateRules: true,
 | |
|   removeUnusedAtRules: false,
 | |
|   restructureRules: false,
 | |
|   skipProperties: []
 | |
| };
 | |
| 
 | |
| var ALL_KEYWORD_1 = '*';
 | |
| var ALL_KEYWORD_2 = 'all';
 | |
| var FALSE_KEYWORD_1 = 'false';
 | |
| var FALSE_KEYWORD_2 = 'off';
 | |
| var TRUE_KEYWORD_1 = 'true';
 | |
| var TRUE_KEYWORD_2 = 'on';
 | |
| 
 | |
| var LIST_VALUE_SEPARATOR = ',';
 | |
| var OPTION_SEPARATOR = ';';
 | |
| var OPTION_VALUE_SEPARATOR = ':';
 | |
| 
 | |
| function optimizationLevelFrom(source) {
 | |
|   var level = override(DEFAULTS, {});
 | |
|   var Zero = OptimizationLevel.Zero;
 | |
|   var One = OptimizationLevel.One;
 | |
|   var Two = OptimizationLevel.Two;
 | |
| 
 | |
|   if (undefined === source) {
 | |
|     delete level[Two];
 | |
|     return level;
 | |
|   }
 | |
| 
 | |
|   if (typeof source == 'string') {
 | |
|     source = parseInt(source);
 | |
|   }
 | |
| 
 | |
|   if (typeof source == 'number' && source === parseInt(Two)) {
 | |
|     return level;
 | |
|   }
 | |
| 
 | |
|   if (typeof source == 'number' && source === parseInt(One)) {
 | |
|     delete level[Two];
 | |
|     return level;
 | |
|   }
 | |
| 
 | |
|   if (typeof source == 'number' && source === parseInt(Zero)) {
 | |
|     delete level[Two];
 | |
|     delete level[One];
 | |
|     return level;
 | |
|   }
 | |
| 
 | |
|   if (typeof source == 'object') {
 | |
|     source = covertValuesToHashes(source);
 | |
|   }
 | |
| 
 | |
|   if (One in source && 'roundingPrecision' in source[One]) {
 | |
|     source[One].roundingPrecision = roundingPrecisionFrom(source[One].roundingPrecision);
 | |
|   }
 | |
| 
 | |
|   if (Two in source && 'skipProperties' in source[Two] && typeof (source[Two].skipProperties) == 'string') {
 | |
|     source[Two].skipProperties = source[Two].skipProperties.split(LIST_VALUE_SEPARATOR);
 | |
|   }
 | |
| 
 | |
|   if (Zero in source || One in source || Two in source) {
 | |
|     level[Zero] = override(level[Zero], source[Zero]);
 | |
|   }
 | |
| 
 | |
|   if (One in source && ALL_KEYWORD_1 in source[One]) {
 | |
|     level[One] = override(level[One], defaults(One, normalizeValue(source[One][ALL_KEYWORD_1])));
 | |
|     delete source[One][ALL_KEYWORD_1];
 | |
|   }
 | |
| 
 | |
|   if (One in source && ALL_KEYWORD_2 in source[One]) {
 | |
|     level[One] = override(level[One], defaults(One, normalizeValue(source[One][ALL_KEYWORD_2])));
 | |
|     delete source[One][ALL_KEYWORD_2];
 | |
|   }
 | |
| 
 | |
|   if (One in source || Two in source) {
 | |
|     level[One] = override(level[One], source[One]);
 | |
|   } else {
 | |
|     delete level[One];
 | |
|   }
 | |
| 
 | |
|   if (Two in source && ALL_KEYWORD_1 in source[Two]) {
 | |
|     level[Two] = override(level[Two], defaults(Two, normalizeValue(source[Two][ALL_KEYWORD_1])));
 | |
|     delete source[Two][ALL_KEYWORD_1];
 | |
|   }
 | |
| 
 | |
|   if (Two in source && ALL_KEYWORD_2 in source[Two]) {
 | |
|     level[Two] = override(level[Two], defaults(Two, normalizeValue(source[Two][ALL_KEYWORD_2])));
 | |
|     delete source[Two][ALL_KEYWORD_2];
 | |
|   }
 | |
| 
 | |
|   if (Two in source) {
 | |
|     level[Two] = override(level[Two], source[Two]);
 | |
|   } else {
 | |
|     delete level[Two];
 | |
|   }
 | |
| 
 | |
|   return level;
 | |
| }
 | |
| 
 | |
| function defaults(level, value) {
 | |
|   var options = override(DEFAULTS[level], {});
 | |
|   var key;
 | |
| 
 | |
|   for (key in options) {
 | |
|     if (typeof options[key] == 'boolean') {
 | |
|       options[key] = value;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return options;
 | |
| }
 | |
| 
 | |
| function normalizeValue(value) {
 | |
|   switch (value) {
 | |
|   case FALSE_KEYWORD_1:
 | |
|   case FALSE_KEYWORD_2:
 | |
|     return false;
 | |
|   case TRUE_KEYWORD_1:
 | |
|   case TRUE_KEYWORD_2:
 | |
|     return true;
 | |
|   default:
 | |
|     return value;
 | |
|   }
 | |
| }
 | |
| 
 | |
| function covertValuesToHashes(source) {
 | |
|   var clonedSource = override(source, {});
 | |
|   var level;
 | |
|   var i;
 | |
| 
 | |
|   for (i = 0; i <= 2; i++) {
 | |
|     level = '' + i;
 | |
| 
 | |
|     if (level in clonedSource && (clonedSource[level] === undefined || clonedSource[level] === false)) {
 | |
|       delete clonedSource[level];
 | |
|     }
 | |
| 
 | |
|     if (level in clonedSource && clonedSource[level] === true) {
 | |
|       clonedSource[level] = {};
 | |
|     }
 | |
| 
 | |
|     if (level in clonedSource && typeof clonedSource[level] == 'string') {
 | |
|       clonedSource[level] = covertToHash(clonedSource[level], level);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return clonedSource;
 | |
| }
 | |
| 
 | |
| 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);
 | |
| 
 | |
|       if (ALL_KEYWORD_1 == name || ALL_KEYWORD_2 == name) {
 | |
|         accumulator = override(accumulator, defaults(level, normalizedValue));
 | |
|       } else {
 | |
|         accumulator[name] = normalizedValue;
 | |
|       }
 | |
| 
 | |
|       return accumulator;
 | |
|     }, {});
 | |
| }
 | |
| 
 | |
| module.exports = {
 | |
|   OptimizationLevel: OptimizationLevel,
 | |
|   optimizationLevelFrom: optimizationLevelFrom
 | |
| };
 |