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
 | 
						|
};
 |