UNPKG

3.64 kBJavaScriptView Raw
1"use strict";
2
3var list = require("postcss/lib/list");
4var pkg = require("./package.json");
5var postcss = require("postcss");
6
7var isSourceMapAnnotation = function (rule) {
8 if (!rule) {
9 return false;
10 }
11
12 if (rule.type !== "comment") {
13 return false;
14 }
15
16 if (rule.text.toLowerCase().indexOf("# sourcemappingurl=") !== 0) {
17 return false;
18 }
19
20 return true;
21};
22
23var parseQueryList = function (queryList) {
24 var queries = [];
25 list.comma(queryList).forEach(function (query) {
26 var expressions = {};
27 list.space(query).forEach(function (expression) {
28 var feature;
29 var value;
30 expression = expression.toLowerCase();
31
32 if (expression === "and") {
33 return;
34 }
35
36 if (/^\w+$/.test(expression)) {
37 expressions[expression] = true;
38
39 return;
40 }
41
42 expression = list.split(expression.replace(/^\(|\)$/g, ""), [":"]);
43 feature = expression[0];
44 value = expression[1];
45
46 if (!expressions[feature]) {
47 expressions[feature] = [];
48 }
49
50 expressions[feature].push(value);
51 });
52 queries.push(expressions);
53 });
54
55 return queries;
56};
57
58var inspectLength = function (length) {
59 var num;
60 var unit;
61 length = /(-?\d*\.?\d+)(ch|em|ex|px|rem)/.exec(length);
62
63 if (!length) {
64 return Number.MAX_VALUE;
65 }
66
67 num = length[1];
68 unit = length[2];
69
70 switch (unit) {
71 case "ch":
72 num = parseFloat(num) * 8.8984375;
73
74 break;
75
76 case "em":
77 case "rem":
78 num = parseFloat(num) * 16;
79
80 break;
81
82 case "ex":
83 num = parseFloat(num) * 8.296875;
84
85 break;
86
87 case "px":
88 num = parseFloat(num);
89
90 break;
91 }
92
93 return num;
94};
95
96var pickMinimumMinWidth = function (expressions) {
97 var minWidths = [];
98 expressions.forEach(function (feature) {
99 var minWidth = feature["min-width"];
100
101 if (!minWidth || feature.not || feature.print) {
102 minWidth = [null];
103 }
104
105 minWidths.push(minWidth.map(inspectLength).sort(function (a, b) {
106 return b - a;
107 })[0]);
108 });
109
110 return minWidths.sort(function (a, b) {
111 return a - b;
112 })[0];
113};
114
115var sortQueryLists = function (queryLists, sort) {
116 var mapQueryLists = [];
117
118 if (!sort) {
119 return queryLists;
120 }
121
122 if (typeof sort === "function") {
123 return queryLists.sort(sort);
124 }
125
126 queryLists.forEach(function (queryList) {
127 mapQueryLists.push(parseQueryList(queryList));
128 });
129
130 return mapQueryLists.map(function (e, i) {
131 return {
132 index: i,
133 value: pickMinimumMinWidth(e)
134 };
135 }).sort(function (a, b) {
136 return a.value - b.value;
137 }).map(function (e) {
138 return queryLists[e.index];
139 });
140};
141
142module.exports = postcss.plugin(pkg.name, function (opts) {
143 if (!opts) {
144 opts = {};
145 }
146
147 if (!opts.sort) {
148 opts.sort = false;
149 }
150
151 return function (css) {
152 var queries = {};
153 var queryLists = [];
154 var sourceMap = css.last;
155
156 if (!isSourceMapAnnotation(sourceMap)) {
157 sourceMap = null;
158 }
159
160 css.walkAtRules("media", function (atRule) {
161 var past;
162 var queryList = atRule.params;
163 past = queries[queryList];
164
165 if (typeof past === "object") {
166 atRule.each(function (rule) {
167 past.append(rule.clone());
168 });
169 } else {
170 queries[queryList] = atRule.clone();
171 queryLists.push(queryList);
172 }
173
174 atRule.remove();
175 });
176
177 sortQueryLists(queryLists, opts.sort).forEach(function (queryList) {
178 css.append(queries[queryList]);
179 });
180
181 if (sourceMap) {
182 sourceMap.moveTo(css);
183 }
184
185 return css;
186 };
187});
188
189module.exports.pack = function (css, opts) {
190 return postcss([
191 this(opts)
192 ]).process(css, opts);
193};