-
Notifications
You must be signed in to change notification settings - Fork 324
/
optimize.js
138 lines (109 loc) · 4.87 KB
/
optimize.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
var populateComponents = require('./populate-components');
var compactOverrides = require('./override-compactor');
var compactShorthands = require('./shorthand-compactor');
var compactable = require('../compactable');
var restoreWithComponents = require('../restore-with-components');
var wrapForOptimizing = require('../../wrap-for-optimizing').all;
var removeUnused = require('../../remove-unused');
var restoreFromOptimizing = require('../../restore-from-optimizing');
var OptimizationLevel = require('../../../options/optimization-level').OptimizationLevel;
var serializeProperty = require('../../../writer/one-time').property;
function _optimize(properties, mergeAdjacent, aggressiveMerging, validator) {
var overrideMapping = {};
var lastName = null;
var lastProperty;
var j;
function mergeablePosition(position) {
if (mergeAdjacent === false || mergeAdjacent === true)
return mergeAdjacent;
return mergeAdjacent.indexOf(position) > -1;
}
function sameValue(position) {
var left = properties[position - 1];
var right = properties[position];
return serializeProperty(left.all, left.position) == serializeProperty(right.all, right.position);
}
propertyLoop:
for (var position = 0, total = properties.length; position < total; position++) {
var property = properties[position];
var _name = (property.name == '-ms-filter' || property.name == 'filter') ?
(lastName == 'background' || lastName == 'background-image' ? lastName : property.name) :
property.name;
var isImportant = property.important;
var isHack = property.hack;
if (property.unused)
continue;
if (position > 0 && lastProperty && _name == lastName && isImportant == lastProperty.important && isHack == lastProperty.hack && sameValue(position) && !lastProperty.unused) {
property.unused = true;
continue;
}
// comment is necessary - we assume that if two properties are one after another
// then it is intentional way of redefining property which may not be widely supported
// e.g. a{display:inline-block;display:-moz-inline-box}
// however if `mergeablePosition` yields true then the rule does not apply
// (e.g merging two adjacent selectors: `a{display:block}a{display:block}`)
if (_name in overrideMapping && (aggressiveMerging && _name != lastName || mergeablePosition(position))) {
var toOverridePositions = overrideMapping[_name];
var canOverride = compactable[_name] && compactable[_name].canOverride;
var anyRemoved = false;
for (j = toOverridePositions.length - 1; j >= 0; j--) {
var toRemove = properties[toOverridePositions[j]];
var longhandToShorthand = toRemove.name != _name;
var wasImportant = toRemove.important;
var wasHack = toRemove.hack;
if (toRemove.unused)
continue;
if (longhandToShorthand && wasImportant)
continue;
if (!wasImportant && (wasHack && !isHack || !wasHack && isHack))
continue;
if (wasImportant && (isHack == 'star' || isHack == 'underscore'))
continue;
if (!wasHack && !isHack && !longhandToShorthand && canOverride && !canOverride(toRemove, property, validator))
continue;
if (wasImportant && !isImportant || wasImportant && isHack) {
property.unused = true;
lastProperty = property;
continue propertyLoop;
} else {
anyRemoved = true;
toRemove.unused = true;
}
}
if (anyRemoved) {
position = -1;
lastProperty = null;
lastName = null;
overrideMapping = {};
continue;
}
} else {
overrideMapping[_name] = overrideMapping[_name] || [];
overrideMapping[_name].push(position);
}
lastName = _name;
lastProperty = property;
}
}
function compactorOptimize(selector, properties, mergeAdjacent, withCompacting, overrideOptions, context) {
var validator = context.validator;
var warnings = context.warnings;
var _properties = wrapForOptimizing(properties, false);
populateComponents(_properties, validator, warnings);
_optimize(_properties, mergeAdjacent, context.options.aggressiveMerging, validator);
for (var i = 0, l = _properties.length; i < l; i++) {
var _property = _properties[i];
if (_property.block) {
compactorOptimize(selector, _property.value[0][1], mergeAdjacent, withCompacting, overrideOptions, context);
}
}
if (overrideOptions.enabled && context.options.level[OptimizationLevel.Two].compactShorthands) {
compactOverrides(_properties, context.options.compatibility, overrideOptions.merging, validator);
}
if (withCompacting && context.options.level[OptimizationLevel.Two].compactShorthands) {
compactShorthands(_properties, validator);
}
restoreFromOptimizing(_properties, restoreWithComponents);
removeUnused(_properties);
}
module.exports = compactorOptimize;