can-override.js
5.37 KB
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
139
140
141
142
// Functions that decide what value can override what.
// The main purpose is to disallow removing CSS fallbacks.
// A separate implementation is needed for every different kind of CSS property.
// -----
// The generic idea is that properties that have wider browser support are 'more understandable'
// than others and that 'less understandable' values can't override more understandable ones.
// Use when two tokens of the same property can always be merged
function always() {
return true;
}
function alwaysButIntoFunction(property1, property2, validator) {
var value1 = property1.value[0][0];
var value2 = property2.value[0][0];
var validFunction1 = validator.isValidFunction(value1);
var validFunction2 = validator.isValidFunction(value2);
if (validFunction1 && validFunction2) {
return validator.areSameFunction(value1, value2);
} else if (!validFunction1 && validFunction2) {
return false;
} else {
return true;
}
}
function backgroundImage(property1, property2, validator) {
// The idea here is that 'more understandable' values override 'less understandable' values, but not vice versa
// Understandability: (none | url | inherit) > (same function) > (same value)
// (none | url)
var image1 = property1.value[0][0];
var image2 = property2.value[0][0];
if (image2 == 'none' || image2 == 'inherit' || validator.isValidUrl(image2))
return true;
if (image1 == 'none' || image1 == 'inherit' || validator.isValidUrl(image1))
return false;
// Functions with the same name can override each other; same values can override each other
return sameFunctionOrValue(property1, property2, validator);
}
function border(property1, property2, validator) {
return color(property1.components[2], property2.components[2], validator);
}
// Use for color properties (color, background-color, border-color, etc.)
function color(property1, property2, validator) {
// The idea here is that 'more understandable' values override 'less understandable' values, but not vice versa
// Understandability: (hex | named) > (rgba | hsla) > (same function name) > anything else
// NOTE: at this point rgb and hsl are replaced by hex values by clean-css
var color1 = property1.value[0][0];
var color2 = property2.value[0][0];
if (!validator.colorOpacity && (validator.isValidRgbaColor(color1) || validator.isValidHslaColor(color1)))
return false;
if (!validator.colorOpacity && (validator.isValidRgbaColor(color2) || validator.isValidHslaColor(color2)))
return false;
// (hex | named)
if (validator.isValidNamedColor(color2) || validator.isValidHexColor(color2))
return true;
if (validator.isValidNamedColor(color1) || validator.isValidHexColor(color1))
return false;
// (rgba|hsla)
if (validator.isValidRgbaColor(color2) || validator.isValidHslaColor(color2))
return true;
if (validator.isValidRgbaColor(color1) || validator.isValidHslaColor(color1))
return false;
// Functions with the same name can override each other; same values can override each other
return sameFunctionOrValue(property1, property2, validator);
}
function twoOptionalFunctions(property1, property2, validator) {
var value1 = property1.value[0][0];
var value2 = property2.value[0][0];
return !(validator.isValidFunction(value1) ^ validator.isValidFunction(value2));
}
function sameValue(property1, property2) {
var value1 = property1.value[0][0];
var value2 = property2.value[0][0];
return value1 === value2;
}
function sameFunctionOrValue(property1, property2, validator) {
var value1 = property1.value[0][0];
var value2 = property2.value[0][0];
// Functions with the same name can override each other
if (validator.areSameFunction(value1, value2))
return true;
return value1 === value2;
}
// Use for properties containing CSS units (margin-top, padding-left, etc.)
function unit(property1, property2, validator) {
// The idea here is that 'more understandable' values override 'less understandable' values, but not vice versa
// Understandability: (unit without functions) > (same functions | standard functions) > anything else
// NOTE: there is no point in having different vendor-specific functions override each other or standard functions,
// or having standard functions override vendor-specific functions, but standard functions can override each other
// NOTE: vendor-specific property values are not taken into consideration here at the moment
var value1 = property1.value[0][0];
var value2 = property2.value[0][0];
if (validator.isValidAndCompatibleUnitWithoutFunction(value1) && !validator.isValidAndCompatibleUnitWithoutFunction(value2))
return false;
if (validator.isValidUnitWithoutFunction(value2))
return true;
if (validator.isValidUnitWithoutFunction(value1))
return false;
// Standard non-vendor-prefixed functions can override each other
if (validator.isValidFunctionWithoutVendorPrefix(value2) && validator.isValidFunctionWithoutVendorPrefix(value1)) {
return true;
}
// Functions with the same name can override each other; same values can override each other
return sameFunctionOrValue(property1, property2, validator);
}
module.exports = {
always: always,
alwaysButIntoFunction: alwaysButIntoFunction,
backgroundImage: backgroundImage,
border: border,
color: color,
sameValue: sameValue,
sameFunctionOrValue: sameFunctionOrValue,
twoOptionalFunctions: twoOptionalFunctions,
unit: unit
};