source: trip-planner-front/node_modules/postcss-calc/dist/lib/reducer.js@ eed0bf8

Last change on this file since eed0bf8 was 6a3a178, checked in by Ema <ema_spirova@…>, 3 years ago

initial commit

  • Property mode set to 100644
File size: 7.8 KB
RevLine 
[6a3a178]1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = void 0;
7
8var _convertUnit = _interopRequireDefault(require("./convertUnit"));
9
10function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
12function isValueType(type) {
13 switch (type) {
14 case 'LengthValue':
15 case 'AngleValue':
16 case 'TimeValue':
17 case 'FrequencyValue':
18 case 'ResolutionValue':
19 case 'EmValue':
20 case 'ExValue':
21 case 'ChValue':
22 case 'RemValue':
23 case 'VhValue':
24 case 'VwValue':
25 case 'VminValue':
26 case 'VmaxValue':
27 case 'PercentageValue':
28 case 'Number':
29 return true;
30 }
31
32 return false;
33}
34
35function flip(operator) {
36 return operator === '+' ? '-' : '+';
37}
38
39function isAddSubOperator(operator) {
40 return operator === '+' || operator === '-';
41}
42
43function collectAddSubItems(preOperator, node, collected, precision) {
44 if (!isAddSubOperator(preOperator)) {
45 throw new Error(`invalid operator ${preOperator}`);
46 }
47
48 const type = node.type;
49
50 if (isValueType(type)) {
51 const itemIndex = collected.findIndex(x => x.node.type === type);
52
53 if (itemIndex >= 0) {
54 if (node.value === 0) {
55 return;
56 }
57
58 const {
59 left: reducedNode,
60 right: current
61 } = covertNodesUnits(collected[itemIndex].node, node, precision);
62
63 if (collected[itemIndex].preOperator === '-') {
64 collected[itemIndex].preOperator = '+';
65 reducedNode.value *= -1;
66 }
67
68 if (preOperator === "+") {
69 reducedNode.value += current.value;
70 } else {
71 reducedNode.value -= current.value;
72 } // make sure reducedNode.value >= 0
73
74
75 if (reducedNode.value >= 0) {
76 collected[itemIndex] = {
77 node: reducedNode,
78 preOperator: '+'
79 };
80 } else {
81 reducedNode.value *= -1;
82 collected[itemIndex] = {
83 node: reducedNode,
84 preOperator: '-'
85 };
86 }
87 } else {
88 // make sure node.value >= 0
89 if (node.value >= 0) {
90 collected.push({
91 node,
92 preOperator
93 });
94 } else {
95 node.value *= -1;
96 collected.push({
97 node,
98 preOperator: flip(preOperator)
99 });
100 }
101 }
102 } else if (type === "MathExpression") {
103 if (isAddSubOperator(node.operator)) {
104 collectAddSubItems(preOperator, node.left, collected, precision);
105 const collectRightOperator = preOperator === '-' ? flip(node.operator) : node.operator;
106 collectAddSubItems(collectRightOperator, node.right, collected, precision);
107 } else {
108 // * or /
109 const reducedNode = reduce(node, precision); // prevent infinite recursive call
110
111 if (reducedNode.type !== "MathExpression" || isAddSubOperator(reducedNode.operator)) {
112 collectAddSubItems(preOperator, reducedNode, collected, precision);
113 } else {
114 collected.push({
115 node: reducedNode,
116 preOperator
117 });
118 }
119 }
120 } else {
121 collected.push({
122 node,
123 preOperator
124 });
125 }
126}
127
128function reduceAddSubExpression(node, precision) {
129 const collected = [];
130 collectAddSubItems('+', node, collected, precision);
131 const withoutZeroItem = collected.filter(item => !(isValueType(item.node.type) && item.node.value === 0));
132 const firstNonZeroItem = withoutZeroItem[0]; // could be undefined
133 // prevent producing "calc(-var(--a))" or "calc()"
134 // which is invalid css
135
136 if (!firstNonZeroItem || firstNonZeroItem.preOperator === '-' && !isValueType(firstNonZeroItem.node.type)) {
137 const firstZeroItem = collected.find(item => isValueType(item.node.type) && item.node.value === 0);
138 withoutZeroItem.unshift(firstZeroItem);
139 } // make sure the preOperator of the first item is +
140
141
142 if (withoutZeroItem[0].preOperator === '-' && isValueType(withoutZeroItem[0].node.type)) {
143 withoutZeroItem[0].node.value *= -1;
144 withoutZeroItem[0].preOperator = '+';
145 }
146
147 let root = withoutZeroItem[0].node;
148
149 for (let i = 1; i < withoutZeroItem.length; i++) {
150 root = {
151 type: 'MathExpression',
152 operator: withoutZeroItem[i].preOperator,
153 left: root,
154 right: withoutZeroItem[i].node
155 };
156 }
157
158 return root;
159}
160
161function reduceDivisionExpression(node) {
162 if (!isValueType(node.right.type)) {
163 return node;
164 }
165
166 if (node.right.type !== 'Number') {
167 throw new Error(`Cannot divide by "${node.right.unit}", number expected`);
168 }
169
170 return applyNumberDivision(node.left, node.right.value);
171} // apply (expr) / number
172
173
174function applyNumberDivision(node, divisor) {
175 if (divisor === 0) {
176 throw new Error('Cannot divide by zero');
177 }
178
179 if (isValueType(node.type)) {
180 node.value /= divisor;
181 return node;
182 }
183
184 if (node.type === "MathExpression" && isAddSubOperator(node.operator)) {
185 // turn (a + b) / num into a/num + b/num
186 // is good for further reduction
187 // checkout the test case
188 // "should reduce division before reducing additions"
189 return {
190 type: "MathExpression",
191 operator: node.operator,
192 left: applyNumberDivision(node.left, divisor),
193 right: applyNumberDivision(node.right, divisor)
194 };
195 } // it is impossible to reduce it into a single value
196 // .e.g the node contains css variable
197 // so we just preserve the division and let browser do it
198
199
200 return {
201 type: "MathExpression",
202 operator: '/',
203 left: node,
204 right: {
205 type: "Number",
206 value: divisor
207 }
208 };
209}
210
211function reduceMultiplicationExpression(node) {
212 // (expr) * number
213 if (node.right.type === 'Number') {
214 return applyNumberMultiplication(node.left, node.right.value);
215 } // number * (expr)
216
217
218 if (node.left.type === 'Number') {
219 return applyNumberMultiplication(node.right, node.left.value);
220 }
221
222 return node;
223} // apply (expr) / number
224
225
226function applyNumberMultiplication(node, multiplier) {
227 if (isValueType(node.type)) {
228 node.value *= multiplier;
229 return node;
230 }
231
232 if (node.type === "MathExpression" && isAddSubOperator(node.operator)) {
233 // turn (a + b) * num into a*num + b*num
234 // is good for further reduction
235 // checkout the test case
236 // "should reduce multiplication before reducing additions"
237 return {
238 type: "MathExpression",
239 operator: node.operator,
240 left: applyNumberMultiplication(node.left, multiplier),
241 right: applyNumberMultiplication(node.right, multiplier)
242 };
243 } // it is impossible to reduce it into a single value
244 // .e.g the node contains css variable
245 // so we just preserve the division and let browser do it
246
247
248 return {
249 type: "MathExpression",
250 operator: '*',
251 left: node,
252 right: {
253 type: "Number",
254 value: multiplier
255 }
256 };
257}
258
259function covertNodesUnits(left, right, precision) {
260 switch (left.type) {
261 case 'LengthValue':
262 case 'AngleValue':
263 case 'TimeValue':
264 case 'FrequencyValue':
265 case 'ResolutionValue':
266 if (right.type === left.type && right.unit && left.unit) {
267 const converted = (0, _convertUnit.default)(right.value, right.unit, left.unit, precision);
268 right = {
269 type: left.type,
270 value: converted,
271 unit: left.unit
272 };
273 }
274
275 return {
276 left,
277 right
278 };
279
280 default:
281 return {
282 left,
283 right
284 };
285 }
286}
287
288function reduce(node, precision) {
289 if (node.type === "MathExpression") {
290 if (isAddSubOperator(node.operator)) {
291 // reduceAddSubExpression will call reduce recursively
292 return reduceAddSubExpression(node, precision);
293 }
294
295 node.left = reduce(node.left, precision);
296 node.right = reduce(node.right, precision);
297
298 switch (node.operator) {
299 case "/":
300 return reduceDivisionExpression(node, precision);
301
302 case "*":
303 return reduceMultiplicationExpression(node, precision);
304 }
305
306 return node;
307 }
308
309 return node;
310}
311
312var _default = reduce;
313exports.default = _default;
314module.exports = exports.default;
Note: See TracBrowser for help on using the repository browser.