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,
|
|
transform: noop
|
|
};
|
|
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 noop() {}
|
|
|
|
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,
|
|
};
|