1 | "use strict";
|
2 |
|
3 | var list = require("postcss/lib/list");
|
4 | var pkg = require("./package.json");
|
5 | var postcss = require("postcss");
|
6 |
|
7 | var 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 |
|
23 | var 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 |
|
58 | var 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 |
|
96 | var 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 |
|
115 | var 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 |
|
142 | module.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 |
|
189 | module.exports.pack = function (css, opts) {
|
190 | return postcss([
|
191 | this(opts)
|
192 | ]).process(css, opts);
|
193 | };
|