This repository has been archived by the owner on Oct 21, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2
/
media-query-optimizer.js
116 lines (97 loc) · 3.03 KB
/
media-query-optimizer.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
const postcss = require("postcss");
const matchAll = require("string.prototype.matchall");
const regex = {
minWidth: /\(\s*min\-width\s*:\s*(\s*[0-9\.]+)([\w]*)\s*\)/g,
maxWidth: /\(\s*max\-width\s*:\s*(\s*[0-9\.]+)([\w]*)\s*\)/g
};
function getValue(pxValue, units) {
if( pxValue === 0 ) {
return `0`;
}
if( units === "em" ) {
return `${pxValue / 16}em`;
}
if( units === "px" ) {
return `${pxValue}px`;
}
throw Error("media-query-optimizer only supports px and em units (for now).")
}
module.exports = postcss.plugin("postcss-media-query-optimizer", function () {
return function(css) {
css.walkAtRules("media", function(rule) {
let finalSelector = [];
rule.params.split(",").forEach(function(expression) {
let usingEms = false;
let minPx = undefined;
let maxPx = undefined;
let needsCorrection = false;
expression = expression.trim();
[...matchAll( expression, regex.minWidth )].forEach(function(minMatch, i) {
let minValue = parseFloat(minMatch[1]);
if( minMatch[2] === "em" ) {
usingEms = true;
minValue *= 16;
}
if( minPx === undefined ) {
minPx = minValue;
} else {
minPx = Math.max(minPx, minValue);
}
if(i > 0) {
needsCorrection = true;
}
});
[...matchAll( expression, regex.maxWidth )].forEach(function(maxMatch, i) {
let maxValue = parseFloat(maxMatch[1]);
if( maxMatch[2] === "em" ) {
usingEms = true;
maxValue *= 16;
}
if( maxPx === undefined ) {
maxPx = maxValue;
} else {
maxPx = Math.min(maxPx, maxValue);
}
if(i > 0) {
needsCorrection = true;
}
});
if( maxPx !== undefined && maxPx === 0 ) {
return;
}
if(minPx !== undefined && maxPx !== undefined && minPx > maxPx) {
return;
}
// console.log( expression, needsCorrection, minPx, maxPx );
if(minPx !== undefined && minPx === 0) {
if( maxPx === undefined ) {
finalSelector.push("all");
return;
} else {
finalSelector.push(`(max-width: ${getValue(maxPx, usingEms ? "em" : "px")})`);
return;
}
} else if(needsCorrection) {
let results = [];
if(minPx !== undefined) {
results.push(`(min-width: ${getValue(minPx, usingEms ? "em" : "px")})`);
}
if(maxPx !== undefined) {
results.push(`(max-width: ${getValue(maxPx, usingEms ? "em" : "px")})`);
}
if( results.length ) {
finalSelector.push(results.join(" and "));
return;
}
}
// passthrough
finalSelector.push(expression);
});
if( finalSelector.length === 0 ) {
rule.remove();
} else {
rule.params = finalSelector.join(", ");
}
});
};
});