source: imaps-frontend/node_modules/clean-css/lib/optimizer/level-2/properties/override-properties.js@ 79a0317

main
Last change on this file since 79a0317 was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 4 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 14.4 KB
Line 
1var hasInherit = require('./has-inherit');
2var hasUnset = require('./has-unset');
3var everyValuesPair = require('./every-values-pair');
4var findComponentIn = require('./find-component-in');
5var isComponentOf = require('./is-component-of');
6var isMergeableShorthand = require('./is-mergeable-shorthand');
7var overridesNonComponentShorthand = require('./overrides-non-component-shorthand');
8var sameVendorPrefixesIn = require('./../../vendor-prefixes').same;
9
10var configuration = require('../../configuration');
11var deepClone = require('../../clone').deep;
12var restoreWithComponents = require('../restore-with-components');
13var shallowClone = require('../../clone').shallow;
14
15var restoreFromOptimizing = require('../../restore-from-optimizing');
16
17var Token = require('../../../tokenizer/token');
18var Marker = require('../../../tokenizer/marker');
19
20var serializeProperty = require('../../../writer/one-time').property;
21
22function sameValue(_validator, value1, value2) {
23 return value1 === value2;
24}
25
26function wouldBreakCompatibility(property, validator) {
27 for (var i = 0; i < property.components.length; i++) {
28 var component = property.components[i];
29 var descriptor = configuration[component.name];
30 var canOverride = descriptor && descriptor.canOverride || sameValue;
31
32 var _component = shallowClone(component);
33 _component.value = [[Token.PROPERTY_VALUE, descriptor.defaultValue]];
34
35 if (!everyValuesPair(canOverride.bind(null, validator), _component, component)) {
36 return true;
37 }
38 }
39
40 return false;
41}
42
43function overrideIntoMultiplex(property, by) {
44 by.unused = true;
45
46 turnIntoMultiplex(by, multiplexSize(property));
47 property.value = by.value;
48}
49
50function overrideByMultiplex(property, by) {
51 by.unused = true;
52 property.multiplex = true;
53 property.value = by.value;
54}
55
56function overrideSimple(property, by) {
57 by.unused = true;
58 property.value = by.value;
59}
60
61function override(property, by) {
62 if (by.multiplex) {
63 overrideByMultiplex(property, by);
64 } else if (property.multiplex) {
65 overrideIntoMultiplex(property, by);
66 } else {
67 overrideSimple(property, by);
68 }
69}
70
71function overrideShorthand(property, by) {
72 by.unused = true;
73
74 for (var i = 0, l = property.components.length; i < l; i++) {
75 override(property.components[i], by.components[i]);
76 }
77}
78
79function turnIntoMultiplex(property, size) {
80 property.multiplex = true;
81
82 if (configuration[property.name].shorthand) {
83 turnShorthandValueIntoMultiplex(property, size);
84 } else {
85 turnLonghandValueIntoMultiplex(property, size);
86 }
87}
88
89function turnShorthandValueIntoMultiplex(property, size) {
90 var component;
91 var i, l;
92
93 for (i = 0, l = property.components.length; i < l; i++) {
94 component = property.components[i];
95
96 if (!component.multiplex) {
97 turnLonghandValueIntoMultiplex(component, size);
98 }
99 }
100}
101
102function turnLonghandValueIntoMultiplex(property, size) {
103 var descriptor = configuration[property.name];
104 var withRealValue = descriptor.intoMultiplexMode == 'real';
105 var withValue = descriptor.intoMultiplexMode == 'real'
106 ? property.value.slice(0)
107 : (descriptor.intoMultiplexMode == 'placeholder' ? descriptor.placeholderValue : descriptor.defaultValue);
108 var i = multiplexSize(property);
109 var j;
110 var m = withValue.length;
111
112 for (; i < size; i++) {
113 property.value.push([Token.PROPERTY_VALUE, Marker.COMMA]);
114
115 if (Array.isArray(withValue)) {
116 for (j = 0; j < m; j++) {
117 property.value.push(withRealValue ? withValue[j] : [Token.PROPERTY_VALUE, withValue[j]]);
118 }
119 } else {
120 property.value.push(withRealValue ? withValue : [Token.PROPERTY_VALUE, withValue]);
121 }
122 }
123}
124
125function multiplexSize(component) {
126 var size = 0;
127
128 for (var i = 0, l = component.value.length; i < l; i++) {
129 if (component.value[i][1] == Marker.COMMA) { size++; }
130 }
131
132 return size + 1;
133}
134
135function lengthOf(property) {
136 var fakeAsArray = [
137 Token.PROPERTY,
138 [Token.PROPERTY_NAME, property.name]
139 ].concat(property.value);
140 return serializeProperty([fakeAsArray], 0).length;
141}
142
143function moreSameShorthands(properties, startAt, name) {
144 // Since we run the main loop in `compactOverrides` backwards, at this point some
145 // properties may not be marked as unused.
146 // We should consider reverting the order if possible
147 var count = 0;
148
149 for (var i = startAt; i >= 0; i--) {
150 if (properties[i].name == name && !properties[i].unused) { count++; }
151 if (count > 1) { break; }
152 }
153
154 return count > 1;
155}
156
157function overridingFunction(shorthand, validator) {
158 for (var i = 0, l = shorthand.components.length; i < l; i++) {
159 if (!anyValue(validator.isUrl, shorthand.components[i])
160 && anyValue(validator.isFunction, shorthand.components[i])) { return true; }
161 }
162
163 return false;
164}
165
166function anyValue(fn, property) {
167 for (var i = 0, l = property.value.length; i < l; i++) {
168 if (property.value[i][1] == Marker.COMMA) { continue; }
169
170 if (fn(property.value[i][1])) { return true; }
171 }
172
173 return false;
174}
175
176function wouldResultInLongerValue(left, right) {
177 if (!left.multiplex && !right.multiplex || left.multiplex && right.multiplex) { return false; }
178
179 var multiplex = left.multiplex ? left : right;
180 var simple = left.multiplex ? right : left;
181 var component;
182
183 var multiplexClone = deepClone(multiplex);
184 restoreFromOptimizing([multiplexClone], restoreWithComponents);
185
186 var simpleClone = deepClone(simple);
187 restoreFromOptimizing([simpleClone], restoreWithComponents);
188
189 var lengthBefore = lengthOf(multiplexClone) + 1 + lengthOf(simpleClone);
190
191 if (left.multiplex) {
192 component = findComponentIn(multiplexClone, simpleClone);
193 overrideIntoMultiplex(component, simpleClone);
194 } else {
195 component = findComponentIn(simpleClone, multiplexClone);
196 turnIntoMultiplex(simpleClone, multiplexSize(multiplexClone));
197 overrideByMultiplex(component, multiplexClone);
198 }
199
200 restoreFromOptimizing([simpleClone], restoreWithComponents);
201
202 var lengthAfter = lengthOf(simpleClone);
203
204 return lengthBefore <= lengthAfter;
205}
206
207function isCompactable(property) {
208 return property.name in configuration;
209}
210
211function noneOverrideHack(left, right) {
212 return !left.multiplex
213 && (left.name == 'background' || left.name == 'background-image')
214 && right.multiplex
215 && (right.name == 'background' || right.name == 'background-image')
216 && anyLayerIsNone(right.value);
217}
218
219function anyLayerIsNone(values) {
220 var layers = intoLayers(values);
221
222 for (var i = 0, l = layers.length; i < l; i++) {
223 if (layers[i].length == 1 && layers[i][0][1] == 'none') { return true; }
224 }
225
226 return false;
227}
228
229function intoLayers(values) {
230 var layers = [];
231
232 for (var i = 0, layer = [], l = values.length; i < l; i++) {
233 var value = values[i];
234 if (value[1] == Marker.COMMA) {
235 layers.push(layer);
236 layer = [];
237 } else {
238 layer.push(value);
239 }
240 }
241
242 layers.push(layer);
243 return layers;
244}
245
246function overrideProperties(properties, withMerging, compatibility, validator) {
247 var mayOverride, right, left, component;
248 var overriddenComponents;
249 var overriddenComponent;
250 var overridingComponent;
251 var overridable;
252 var i, j, k;
253
254 propertyLoop:
255 for (i = properties.length - 1; i >= 0; i--) {
256 right = properties[i];
257
258 if (!isCompactable(right)) { continue; }
259
260 if (right.block) { continue; }
261
262 mayOverride = configuration[right.name].canOverride || sameValue;
263
264 traverseLoop:
265 for (j = i - 1; j >= 0; j--) {
266 left = properties[j];
267
268 if (!isCompactable(left)) { continue; }
269
270 if (left.block) { continue; }
271
272 if (left.dynamic || right.dynamic) { continue; }
273
274 if (left.unused || right.unused) { continue; }
275
276 if (left.hack && !right.hack && !right.important || !left.hack && !left.important && right.hack) { continue; }
277
278 if (left.important == right.important && left.hack[0] != right.hack[0]) { continue; }
279
280 if (left.important == right.important
281 && (left.hack[0] != right.hack[0] || (left.hack[1] && left.hack[1] != right.hack[1]))) { continue; }
282
283 if (hasInherit(right)) { continue; }
284
285 if (noneOverrideHack(left, right)) { continue; }
286
287 if (right.shorthand && isComponentOf(right, left)) {
288 // maybe `left` can be overridden by `right` which is a shorthand?
289 if (!right.important && left.important) { continue; }
290
291 if (!sameVendorPrefixesIn([left], right.components)) { continue; }
292
293 if (!anyValue(validator.isFunction, left) && overridingFunction(right, validator)) { continue; }
294
295 if (!isMergeableShorthand(right)) {
296 left.unused = true;
297 continue;
298 }
299
300 component = findComponentIn(right, left);
301 mayOverride = configuration[left.name].canOverride || sameValue;
302 if (everyValuesPair(mayOverride.bind(null, validator), left, component)) {
303 left.unused = true;
304 }
305 } else if (right.shorthand && overridesNonComponentShorthand(right, left)) {
306 // `right` is a shorthand while `left` can be overriden by it, think `border` and `border-top`
307 if (!right.important && left.important) {
308 continue;
309 }
310
311 if (!sameVendorPrefixesIn([left], right.components)) {
312 continue;
313 }
314
315 if (!anyValue(validator.isFunction, left) && overridingFunction(right, validator)) {
316 continue;
317 }
318
319 overriddenComponents = left.shorthand
320 ? left.components
321 : [left];
322
323 for (k = overriddenComponents.length - 1; k >= 0; k--) {
324 overriddenComponent = overriddenComponents[k];
325 overridingComponent = findComponentIn(right, overriddenComponent);
326 mayOverride = configuration[overriddenComponent.name].canOverride || sameValue;
327
328 if (!everyValuesPair(mayOverride.bind(null, validator), left, overridingComponent)) {
329 continue traverseLoop;
330 }
331 }
332
333 left.unused = true;
334 } else if (withMerging && left.shorthand && !right.shorthand && isComponentOf(left, right, true)) {
335 // maybe `right` can be pulled into `left` which is a shorthand?
336 if (right.important && !left.important) { continue; }
337
338 if (!right.important && left.important) {
339 right.unused = true;
340 continue;
341 }
342
343 // Pending more clever algorithm in #527
344 if (moreSameShorthands(properties, i - 1, left.name)) { continue; }
345
346 if (overridingFunction(left, validator)) { continue; }
347
348 if (!isMergeableShorthand(left)) { continue; }
349
350 if (hasUnset(left) || hasUnset(right)) { continue; }
351
352 component = findComponentIn(left, right);
353 if (everyValuesPair(mayOverride.bind(null, validator), component, right)) {
354 var disabledBackgroundMerging = !compatibility.properties.backgroundClipMerging && component.name.indexOf('background-clip') > -1
355 || !compatibility.properties.backgroundOriginMerging && component.name.indexOf('background-origin') > -1
356 || !compatibility.properties.backgroundSizeMerging && component.name.indexOf('background-size') > -1;
357 var nonMergeableValue = configuration[right.name].nonMergeableValue === right.value[0][1];
358
359 if (disabledBackgroundMerging || nonMergeableValue) { continue; }
360
361 if (!compatibility.properties.merging && wouldBreakCompatibility(left, validator)) { continue; }
362
363 if (component.value[0][1] != right.value[0][1] && (hasInherit(left) || hasInherit(right))) { continue; }
364
365 if (wouldResultInLongerValue(left, right)) { continue; }
366
367 if (!left.multiplex && right.multiplex) { turnIntoMultiplex(left, multiplexSize(right)); }
368
369 override(component, right);
370 left.dirty = true;
371 }
372 } else if (withMerging && left.shorthand && right.shorthand && left.name == right.name) {
373 // merge if all components can be merged
374
375 if (!left.multiplex && right.multiplex) { continue; }
376
377 if (!right.important && left.important) {
378 right.unused = true;
379 continue propertyLoop;
380 }
381
382 if (right.important && !left.important) {
383 left.unused = true;
384 continue;
385 }
386
387 if (!isMergeableShorthand(right)) {
388 left.unused = true;
389 continue;
390 }
391
392 for (k = left.components.length - 1; k >= 0; k--) {
393 var leftComponent = left.components[k];
394 var rightComponent = right.components[k];
395
396 mayOverride = configuration[leftComponent.name].canOverride || sameValue;
397 if (!everyValuesPair(mayOverride.bind(null, validator), leftComponent, rightComponent)) {
398 continue propertyLoop;
399 }
400 }
401
402 overrideShorthand(left, right);
403 left.dirty = true;
404 } else if (withMerging && left.shorthand && right.shorthand && isComponentOf(left, right)) {
405 // border is a shorthand but any of its components is a shorthand too
406
407 if (!left.important && right.important) { continue; }
408
409 component = findComponentIn(left, right);
410 mayOverride = configuration[right.name].canOverride || sameValue;
411 if (!everyValuesPair(mayOverride.bind(null, validator), component, right)) { continue; }
412
413 if (left.important && !right.important) {
414 right.unused = true;
415 continue;
416 }
417
418 var rightRestored = configuration[right.name].restore(right, configuration);
419 if (rightRestored.length > 1) { continue; }
420
421 component = findComponentIn(left, right);
422 override(component, right);
423 right.dirty = true;
424 } else if (left.name == right.name) {
425 // two non-shorthands should be merged based on understandability
426 overridable = true;
427
428 if (right.shorthand) {
429 for (k = right.components.length - 1; k >= 0 && overridable; k--) {
430 overriddenComponent = left.components[k];
431 overridingComponent = right.components[k];
432 mayOverride = configuration[overridingComponent.name].canOverride || sameValue;
433
434 overridable = everyValuesPair(mayOverride.bind(null, validator), overriddenComponent, overridingComponent);
435 }
436 } else {
437 mayOverride = configuration[right.name].canOverride || sameValue;
438 overridable = everyValuesPair(mayOverride.bind(null, validator), left, right);
439 }
440
441 if (left.important && !right.important && overridable) {
442 right.unused = true;
443 continue;
444 }
445
446 if (!left.important && right.important && overridable) {
447 left.unused = true;
448 continue;
449 }
450
451 if (!overridable) {
452 continue;
453 }
454
455 left.unused = true;
456 }
457 }
458 }
459}
460
461module.exports = overrideProperties;
Note: See TracBrowser for help on using the repository browser.