UNPKG

5.56 kBJavaScriptView Raw
1var roundingPrecisionFrom = require('./rounding-precision').roundingPrecisionFrom;
2
3var override = require('../utils/override');
4
5var OptimizationLevel = {
6 Zero: '0',
7 One: '1',
8 Two: '2'
9};
10
11var DEFAULTS = {};
12
13DEFAULTS[OptimizationLevel.Zero] = {};
14DEFAULTS[OptimizationLevel.One] = {
15 cleanupCharsets: true,
16 normalizeUrls: true,
17 optimizeBackground: true,
18 optimizeBorderRadius: true,
19 optimizeFilter: true,
20 optimizeFontWeight: true,
21 optimizeOutline: true,
22 removeEmpty: true,
23 removeNegativePaddings: true,
24 removeQuotes: true,
25 removeWhitespace: true,
26 replaceMultipleZeros: true,
27 replaceTimeUnits: true,
28 replaceZeroUnits: true,
29 roundingPrecision: roundingPrecisionFrom(undefined),
30 selectorsSortingMethod: 'standard',
31 specialComments: 'all',
32 tidyAtRules: true,
33 tidyBlockScopes: true,
34 tidySelectors: true,
35 transform: noop
36};
37DEFAULTS[OptimizationLevel.Two] = {
38 mergeAdjacentRules: true,
39 mergeIntoShorthands: true,
40 mergeMedia: true,
41 mergeNonAdjacentRules: true,
42 mergeSemantically: false,
43 overrideProperties: true,
44 removeEmpty: true,
45 reduceNonAdjacentRules: true,
46 removeDuplicateFontRules: true,
47 removeDuplicateMediaBlocks: true,
48 removeDuplicateRules: true,
49 removeUnusedAtRules: false,
50 restructureRules: false,
51 skipProperties: []
52};
53
54var ALL_KEYWORD_1 = '*';
55var ALL_KEYWORD_2 = 'all';
56var FALSE_KEYWORD_1 = 'false';
57var FALSE_KEYWORD_2 = 'off';
58var TRUE_KEYWORD_1 = 'true';
59var TRUE_KEYWORD_2 = 'on';
60
61var LIST_VALUE_SEPARATOR = ',';
62var OPTION_SEPARATOR = ';';
63var OPTION_VALUE_SEPARATOR = ':';
64
65function noop() {}
66
67function optimizationLevelFrom(source) {
68 var level = override(DEFAULTS, {});
69 var Zero = OptimizationLevel.Zero;
70 var One = OptimizationLevel.One;
71 var Two = OptimizationLevel.Two;
72
73
74 if (undefined === source) {
75 delete level[Two];
76 return level;
77 }
78
79 if (typeof source == 'string') {
80 source = parseInt(source);
81 }
82
83 if (typeof source == 'number' && source === parseInt(Two)) {
84 return level;
85 }
86
87 if (typeof source == 'number' && source === parseInt(One)) {
88 delete level[Two];
89 return level;
90 }
91
92 if (typeof source == 'number' && source === parseInt(Zero)) {
93 delete level[Two];
94 delete level[One];
95 return level;
96 }
97
98 if (typeof source == 'object') {
99 source = covertValuesToHashes(source);
100 }
101
102 if (One in source && 'roundingPrecision' in source[One]) {
103 source[One].roundingPrecision = roundingPrecisionFrom(source[One].roundingPrecision);
104 }
105
106 if (Two in source && 'skipProperties' in source[Two] && typeof(source[Two].skipProperties) == 'string') {
107 source[Two].skipProperties = source[Two].skipProperties.split(LIST_VALUE_SEPARATOR);
108 }
109
110 if (Zero in source || One in source || Two in source) {
111 level[Zero] = override(level[Zero], source[Zero]);
112 }
113
114 if (One in source && ALL_KEYWORD_1 in source[One]) {
115 level[One] = override(level[One], defaults(One, normalizeValue(source[One][ALL_KEYWORD_1])));
116 delete source[One][ALL_KEYWORD_1];
117 }
118
119 if (One in source && ALL_KEYWORD_2 in source[One]) {
120 level[One] = override(level[One], defaults(One, normalizeValue(source[One][ALL_KEYWORD_2])));
121 delete source[One][ALL_KEYWORD_2];
122 }
123
124 if (One in source || Two in source) {
125 level[One] = override(level[One], source[One]);
126 } else {
127 delete level[One];
128 }
129
130 if (Two in source && ALL_KEYWORD_1 in source[Two]) {
131 level[Two] = override(level[Two], defaults(Two, normalizeValue(source[Two][ALL_KEYWORD_1])));
132 delete source[Two][ALL_KEYWORD_1];
133 }
134
135 if (Two in source && ALL_KEYWORD_2 in source[Two]) {
136 level[Two] = override(level[Two], defaults(Two, normalizeValue(source[Two][ALL_KEYWORD_2])));
137 delete source[Two][ALL_KEYWORD_2];
138 }
139
140 if (Two in source) {
141 level[Two] = override(level[Two], source[Two]);
142 } else {
143 delete level[Two];
144 }
145
146 return level;
147}
148
149function defaults(level, value) {
150 var options = override(DEFAULTS[level], {});
151 var key;
152
153 for (key in options) {
154 if (typeof options[key] == 'boolean') {
155 options[key] = value;
156 }
157 }
158
159 return options;
160}
161
162function normalizeValue(value) {
163 switch (value) {
164 case FALSE_KEYWORD_1:
165 case FALSE_KEYWORD_2:
166 return false;
167 case TRUE_KEYWORD_1:
168 case TRUE_KEYWORD_2:
169 return true;
170 default:
171 return value;
172 }
173}
174
175function covertValuesToHashes(source) {
176 var clonedSource = override(source, {});
177 var level;
178 var i;
179
180 for (i = 0; i <= 2; i++) {
181 level = '' + i;
182
183 if (level in clonedSource && (clonedSource[level] === undefined || clonedSource[level] === false)) {
184 delete clonedSource[level];
185 }
186
187 if (level in clonedSource && clonedSource[level] === true) {
188 clonedSource[level] = {};
189 }
190
191 if (level in clonedSource && typeof clonedSource[level] == 'string') {
192 clonedSource[level] = covertToHash(clonedSource[level], level);
193 }
194 }
195
196 return clonedSource;
197}
198
199function covertToHash(asString, level) {
200 return asString
201 .split(OPTION_SEPARATOR)
202 .reduce(function (accumulator, directive) {
203 var parts = directive.split(OPTION_VALUE_SEPARATOR);
204 var name = parts[0];
205 var value = parts[1];
206 var normalizedValue = normalizeValue(value);
207
208 if (ALL_KEYWORD_1 == name || ALL_KEYWORD_2 == name) {
209 accumulator = override(accumulator, defaults(level, normalizedValue));
210 } else {
211 accumulator[name] = normalizedValue;
212 }
213
214 return accumulator;
215 }, {});
216}
217
218module.exports = {
219 OptimizationLevel: OptimizationLevel,
220 optimizationLevelFrom: optimizationLevelFrom,
221};