postcss-calc 7.0.0 → 7.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,15 +5,10 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = void 0;
7
7
 
8
- var _convert = _interopRequireDefault(require("./convert"));
8
+ var _convertUnit = _interopRequireDefault(require("./convertUnit"));
9
9
 
10
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
11
 
12
- function reduce(node, precision) {
13
- if (node.type === "MathExpression") return reduceMathExpression(node, precision);
14
- return node;
15
- }
16
-
17
12
  function isEqual(left, right) {
18
13
  return left.type === right.type && left.value === right.value;
19
14
  }
@@ -34,167 +29,230 @@ function isValueType(type) {
34
29
  case 'VminValue':
35
30
  case 'VmaxValue':
36
31
  case 'PercentageValue':
37
- case 'Value':
32
+ case 'Number':
38
33
  return true;
39
34
  }
40
35
 
41
36
  return false;
42
37
  }
43
38
 
44
- function convertMathExpression(node, precision) {
45
- var nodes = (0, _convert.default)(node.left, node.right, precision);
46
- var left = reduce(nodes.left, precision);
47
- var right = reduce(nodes.right, precision);
48
-
49
- if (left.type === "MathExpression" && right.type === "MathExpression") {
50
- if (left.operator === '/' && right.operator === '*' || left.operator === '-' && right.operator === '+' || left.operator === '*' && right.operator === '/' || left.operator === '+' && right.operator === '-') {
51
- if (isEqual(left.right, right.right)) nodes = (0, _convert.default)(left.left, right.left, precision);else if (isEqual(left.right, right.left)) nodes = (0, _convert.default)(left.left, right.right, precision);
52
- left = reduce(nodes.left, precision);
53
- right = reduce(nodes.right, precision);
54
- }
55
- }
56
-
57
- node.left = left;
58
- node.right = right;
59
- return node;
60
- }
61
-
62
39
  function flip(operator) {
63
40
  return operator === '+' ? '-' : '+';
64
41
  }
65
42
 
66
43
  function flipValue(node) {
67
- if (isValueType(node.type)) node.value = -node.value;else if (node.type == 'MathExpression') {
68
- node.left = flipValue(node.left);
69
- node.right = flipValue(node.right);
44
+ if (isValueType(node.type)) {
45
+ node.value = -node.value;
46
+ } else if (node.type === 'MathExpression') {
47
+ if (node.operator === '*' || node.operator === '/') {
48
+ node.left = flipValue(node.left);
49
+ } else {
50
+ node.left = flipValue(node.left);
51
+ node.right = flipValue(node.right);
52
+ }
70
53
  }
54
+
71
55
  return node;
72
56
  }
73
57
 
74
58
  function reduceAddSubExpression(node, precision) {
75
- var _node = node,
76
- left = _node.left,
77
- right = _node.right,
78
- op = _node.operator;
79
- if (left.type === 'Function' || right.type === 'Function') return node; // something + 0 => something
59
+ // something + 0 => something
80
60
  // something - 0 => something
61
+ if (isValueType(node.right.type) && node.right.value === 0) {
62
+ return node.left;
63
+ } // 0 + something => something
81
64
 
82
- if (right.value === 0) return left; // 0 + something => something
83
65
 
84
- if (left.value === 0 && op === "+") return right; // 0 - something => -something
66
+ if (isValueType(node.left.type) && node.left.value === 0 && node.operator === "+") {
67
+ return node.right;
68
+ } // 0 - something => -something
85
69
 
86
- if (left.value === 0 && op === "-") return flipValue(right); // value + value
70
+
71
+ if (isValueType(node.left.type) && node.left.value === 0 && node.operator === "-" && !isCSSFunction(node.right)) {
72
+ return flipValue(node.right);
73
+ } // value + value
87
74
  // value - value
88
75
 
89
- if (left.type === right.type && isValueType(left.type)) {
90
- node = Object.assign({}, left);
91
- if (op === "+") node.value = left.value + right.value;else node.value = left.value - right.value;
76
+
77
+ if (isValueType(node.left.type) && node.left.type === node.right.type) {
78
+ var operator = node.operator;
79
+
80
+ var _covertNodesUnits = covertNodesUnits(node.left, node.right, precision),
81
+ left = _covertNodesUnits.left,
82
+ right = _covertNodesUnits.right;
83
+
84
+ if (operator === "+") {
85
+ left.value += right.value;
86
+ } else {
87
+ left.value -= right.value;
88
+ }
89
+
90
+ return left;
92
91
  } // value <op> (expr)
93
92
 
94
93
 
95
- if (isValueType(left.type) && (right.operator === '+' || right.operator === '-') && right.type === 'MathExpression') {
96
- // value + (value + something) => (value + value) + something
97
- // value + (value - something) => (value + value) - something
98
- // value - (value + something) => (value - value) - something
99
- // value - (value - something) => (value - value) + something
100
- if (left.type === right.left.type) {
101
- node = Object.assign({}, node);
102
- node.left = reduce({
103
- type: 'MathExpression',
104
- operator: op,
105
- left: left,
106
- right: right.left
107
- }, precision);
108
- node.right = right.right;
109
- node.operator = op === '-' ? flip(right.operator) : right.operator;
110
- return reduce(node, precision);
111
- } // value + (something + value) => (value + value) + something
112
- // value + (something - value) => (value - value) + something
113
- // value - (something + value) => (value - value) - something
114
- // value - (something - value) => (value + value) - something
115
- else if (left.type === right.right.type) {
116
- node = Object.assign({}, node);
94
+ if (node.right.type === 'MathExpression' && (node.right.operator === '+' || node.right.operator === '-')) {
95
+ // something - (something + something) => something - something - something
96
+ // something - (something - something) => something - something + something
97
+ if ((node.right.operator === '+' || node.right.operator === '-') && node.operator === '-') {
98
+ node.right.operator = flip(node.right.operator);
99
+ }
100
+
101
+ if (isValueType(node.left.type)) {
102
+ // value + (value + something) => value + something
103
+ // value + (value - something) => value - something
104
+ // value - (value + something) => value - something
105
+ // value - (value - something) => value + something
106
+ if (node.left.type === node.right.left.type) {
107
+ var _left = node.left,
108
+ _operator = node.operator,
109
+ _right = node.right;
117
110
  node.left = reduce({
118
111
  type: 'MathExpression',
119
- operator: op === '-' ? flip(right.operator) : right.operator,
120
- left: left,
121
- right: right.right
122
- }, precision);
123
- node.right = right.left;
112
+ operator: _operator,
113
+ left: _left,
114
+ right: _right.left
115
+ });
116
+ node.operator = _right.operator;
117
+ node.right = _right.right;
124
118
  return reduce(node, precision);
125
- } // value - (something + something) => value - something - something
126
- else if (op === '-' && right.operator === '+') {
127
- node = Object.assign({}, node);
128
- node.right.operator = '-';
129
- return reduce(node, precision);
130
- }
119
+ } // something + (something + value) => dimension + something
120
+ // something + (something - value) => dimension + something
121
+ // something - (something + value) => dimension - something
122
+ // something - (something - value) => dimension - something
123
+
124
+
125
+ if (node.left.type === node.right.right.type) {
126
+ var _left2 = node.left,
127
+ _right2 = node.right;
128
+ node.left = reduce({
129
+ type: 'MathExpression',
130
+ operator: _right2.operator,
131
+ left: _left2,
132
+ right: _right2.right
133
+ });
134
+ node.right = _right2.left;
135
+ return reduce(node, precision);
136
+ }
137
+ }
131
138
  } // (expr) <op> value
132
139
 
133
140
 
134
- if (left.type === 'MathExpression' && (left.operator === '+' || left.operator === '-') && isValueType(right.type)) {
135
- // (value + something) + value => (value + value) + something
136
- // (value - something) + value => (value + value) - something
137
- // (value + something) - value => (value - value) + something
138
- // (value - something) - value => (value - value) - something
139
- if (right.type === left.left.type) {
140
- node = Object.assign({}, left);
141
- node.left = reduce({
141
+ if (node.left.type === 'MathExpression' && (node.left.operator === '+' || node.left.operator === '-') && isValueType(node.right.type)) {
142
+ // (value + something) + value => value + something
143
+ // (value - something) + value => value - something
144
+ // (value + something) - value => value + something
145
+ // (value - something) - value => value - something
146
+ if (node.right.type === node.left.left.type) {
147
+ var _left3 = node.left,
148
+ _operator2 = node.operator,
149
+ _right3 = node.right;
150
+ _left3.left = reduce({
142
151
  type: 'MathExpression',
143
- operator: op,
144
- left: left.left,
145
- right: right
152
+ operator: _operator2,
153
+ left: _left3.left,
154
+ right: _right3
146
155
  }, precision);
147
- return reduce(node, precision);
148
- } // (something + value) + value => something + (value + value)
149
- // (something - value1) + value2 => something - (value2 - value1)
150
- // (something + value) - value => something + (value - value)
151
- // (something - value) - value => something - (value + value)
152
- else if (right.type === left.right.type) {
153
- node = Object.assign({}, left);
154
-
155
- if (left.operator === '-') {
156
- node.right = reduce({
157
- type: 'MathExpression',
158
- operator: flip(op),
159
- left: left.right,
160
- right: right
161
- }, precision);
162
-
163
- if (node.right.value && node.right.value < 0) {
164
- node.right.value = Math.abs(node.right.value);
165
- node.operator = '+';
166
- } else {
167
- node.operator = left.operator;
168
- }
169
- } else {
170
- node.right = reduce({
171
- type: 'MathExpression',
172
- operator: op,
173
- left: left.right,
174
- right: right
175
- }, precision);
176
- }
177
-
178
- if (node.right.value < 0) {
179
- node.right.value *= -1;
180
- node.operator = node.operator === '-' ? '+' : '-';
181
- }
156
+ return reduce(_left3, precision);
157
+ } // (something + dimension) + dimension => something + dimension
158
+ // (something - dimension) + dimension => something - dimension
159
+ // (something + dimension) - dimension => something + dimension
160
+ // (something - dimension) - dimension => something - dimension
182
161
 
183
- return reduce(node, precision);
162
+
163
+ if (node.right.type === node.left.right.type) {
164
+ var _left4 = node.left,
165
+ _operator3 = node.operator,
166
+ _right4 = node.right;
167
+
168
+ if (_left4.operator === '-') {
169
+ _left4.operator = _operator3 === '-' ? '-' : '+';
170
+ _left4.right = reduce({
171
+ type: 'MathExpression',
172
+ operator: _operator3 === '-' ? '+' : '-',
173
+ left: _right4,
174
+ right: _left4.right
175
+ }, precision);
176
+ } else {
177
+ _left4.right = reduce({
178
+ type: 'MathExpression',
179
+ operator: _operator3,
180
+ left: _left4.right,
181
+ right: _right4
182
+ }, precision);
183
+ }
184
+
185
+ if (_left4.right.value < 0) {
186
+ _left4.right.value *= -1;
187
+ _left4.operator = _left4.operator === '-' ? '+' : '-';
184
188
  }
185
- }
186
189
 
187
- if (left.type === 'MathExpression' && right.type === 'MathExpression' && op === '-' && right.operator === '-') {
188
- node.right.operator = flip(node.right.operator);
190
+ _left4.parenthesized = node.parenthesized;
191
+ return reduce(_left4, precision);
192
+ }
193
+ } // (expr) + (expr) => number
194
+ // (expr) - (expr) => number
195
+
196
+
197
+ if (node.right.type === 'MathExpression' && node.left.type === 'MathExpression') {
198
+ if (node.left.operator === "-" && node.right.operator === "+" || node.right.operator === "-" && node.left.operator === "+") {
199
+ // (expr1 - something) + (expr2 + something) => expr1 + expr2
200
+ // (expr1 + something) + (expr2 - something) => expr1 + expr2
201
+ // (expr1 - something) - (expr2 + something) => expr1 + expr2
202
+ // (expr1 + something) - (expr2 - something) => expr1 + expr2
203
+ if (isEqual(node.left.right, node.right.right)) {
204
+ var newNodes = covertNodesUnits(node.left.left, node.right.left, precision);
205
+ node.left = newNodes.left;
206
+ node.right = newNodes.right;
207
+ return reduce(node, precision);
208
+ } // (expr1 - something) + (something + expr2) => expr1 + expr2
209
+ // (expr1 + something) + (something - expr2) => expr1 + expr2
210
+ // (expr1 - something) - (something + expr2) => expr1 + expr2
211
+ // (expr1 + something) - (something - expr2) => expr1 + expr2
212
+
213
+
214
+ if (isEqual(node.left.right, node.right.left)) {
215
+ var _newNodes = covertNodesUnits(node.left.left, node.right.right, precision);
216
+
217
+ node.left = _newNodes.left;
218
+ node.right = _newNodes.right;
219
+ return reduce(node, precision);
220
+ } // (expr1 / something) + (expr2 / something) => (expr1 + expr2) / something
221
+ // (expr1 * something) + (expr2 * something) => (expr1 + expr2) * something
222
+ // (expr1 / something) - (expr2 / something) => (expr1 - expr2) / something
223
+ // (expr1 * something) - (expr2 * something) => (expr1 - expr2) * something
224
+
225
+ } else if ((node.left.operator === "/" || node.left.operator === "*") && node.left.operator === node.right.operator && isEqual(node.left.right, node.right.right)) {
226
+ return reduce({
227
+ type: "MathExpression",
228
+ operator: node.left.operator,
229
+ left: {
230
+ type: "MathExpression",
231
+ operator: node.operator,
232
+ left: node.left.left,
233
+ right: node.right.left
234
+ },
235
+ right: node.left.right
236
+ }, precision);
237
+ }
189
238
  }
190
239
 
191
240
  return node;
192
241
  }
193
242
 
194
243
  function reduceDivisionExpression(node) {
195
- if (!isValueType(node.right.type)) return node;
196
- if (node.right.type !== 'Value') throw new Error(`Cannot divide by "${node.right.unit}", number expected`);
197
- if (node.right.value === 0) throw new Error('Cannot divide by zero'); // something / value
244
+ if (!isValueType(node.right.type)) {
245
+ return node;
246
+ }
247
+
248
+ if (node.right.type !== 'Number') {
249
+ throw new Error(`Cannot divide by "${node.right.unit}", number expected`);
250
+ }
251
+
252
+ if (node.right.value === 0) {
253
+ throw new Error('Cannot divide by zero');
254
+ } // something / value
255
+
198
256
 
199
257
  if (isValueType(node.left.type)) {
200
258
  node.left.value /= node.right.value;
@@ -205,46 +263,86 @@ function reduceDivisionExpression(node) {
205
263
  }
206
264
 
207
265
  function reduceMultiplicationExpression(node) {
208
- // (expr) * value
209
- if (node.left.type === 'MathExpression' && node.right.type === 'Value') {
266
+ // (expr) * number
267
+ if (node.left.type === 'MathExpression' && node.right.type === 'Number') {
210
268
  if (isValueType(node.left.left.type) && isValueType(node.left.right.type)) {
211
269
  node.left.left.value *= node.right.value;
212
270
  node.left.right.value *= node.right.value;
213
271
  return node.left;
214
272
  }
215
- } // something * value
216
- else if (isValueType(node.left.type) && node.right.type === 'Value') {
217
- node.left.value *= node.right.value;
218
- return node.left;
219
- } // value * (expr)
220
- else if (node.left.type === 'Value' && node.right.type === 'MathExpression') {
221
- if (isValueType(node.right.left.type) && isValueType(node.right.right.type)) {
222
- node.right.left.value *= node.left.value;
223
- node.right.right.value *= node.left.value;
224
- return node.right;
225
- }
226
- } // value * something
227
- else if (node.left.type === 'Value' && isValueType(node.right.type)) {
228
- node.right.value *= node.left.value;
229
- return node.right;
230
- }
273
+ } // something * number
274
+
275
+
276
+ if (isValueType(node.left.type) && node.right.type === 'Number') {
277
+ node.left.value *= node.right.value;
278
+ return node.left;
279
+ } // number * (expr)
280
+
281
+
282
+ if (node.left.type === 'Number' && node.right.type === 'MathExpression') {
283
+ if (isValueType(node.right.left.type) && isValueType(node.right.right.type)) {
284
+ node.right.left.value *= node.left.value;
285
+ node.right.right.value *= node.left.value;
286
+ return node.right;
287
+ }
288
+ } // number * something
289
+
290
+
291
+ if (node.left.type === 'Number' && isValueType(node.right.type)) {
292
+ node.right.value *= node.left.value;
293
+ return node.right;
294
+ }
231
295
 
232
296
  return node;
233
297
  }
234
298
 
235
- function reduceMathExpression(node, precision) {
236
- node = convertMathExpression(node, precision);
299
+ function covertNodesUnits(left, right, precision) {
300
+ switch (left.type) {
301
+ case 'LengthValue':
302
+ case 'AngleValue':
303
+ case 'TimeValue':
304
+ case 'FrequencyValue':
305
+ case 'ResolutionValue':
306
+ if (right.type === left.type && right.unit && left.unit) {
307
+ var converted = (0, _convertUnit.default)(right.value, right.unit, left.unit, precision);
308
+ right = {
309
+ type: left.type,
310
+ value: converted,
311
+ unit: left.unit
312
+ };
313
+ }
314
+
315
+ return {
316
+ left,
317
+ right
318
+ };
319
+
320
+ default:
321
+ return {
322
+ left,
323
+ right
324
+ };
325
+ }
326
+ }
327
+
328
+ function reduce(node, precision) {
329
+ if (node.type === "MathExpression") {
330
+ node.left = reduce(node.left, precision);
331
+ node.right = reduce(node.right, precision);
237
332
 
238
- switch (node.operator) {
239
- case "+":
240
- case "-":
241
- return reduceAddSubExpression(node, precision);
333
+ switch (node.operator) {
334
+ case "+":
335
+ case "-":
336
+ return reduceAddSubExpression(node, precision);
242
337
 
243
- case "/":
244
- return reduceDivisionExpression(node, precision);
338
+ case "/":
339
+ return reduceDivisionExpression(node, precision);
245
340
 
246
- case "*":
247
- return reduceMultiplicationExpression(node);
341
+ case "*":
342
+ return reduceMultiplicationExpression(node, precision);
343
+ }
344
+
345
+ return node;
248
346
  }
249
347
 
250
348
  return node;
@@ -252,4 +350,17 @@ function reduceMathExpression(node, precision) {
252
350
 
253
351
  var _default = reduce;
254
352
  exports.default = _default;
353
+
354
+ function isCSSFunction(node) {
355
+ if (node.type === "Function") {
356
+ return true;
357
+ }
358
+
359
+ if (node.type === "MathExpression") {
360
+ return isCSSFunction(node.left) || isCSSFunction(node.right);
361
+ }
362
+
363
+ return false;
364
+ }
365
+
255
366
  module.exports = exports.default;
@@ -28,13 +28,25 @@ function stringify(node, prec) {
28
28
  right = node.right,
29
29
  op = node.operator;
30
30
  var str = "";
31
- if (left.type === 'MathExpression' && order[op] < order[left.operator]) str += `(${stringify(left, prec)})`;else str += stringify(left, prec);
31
+
32
+ if (left.type === 'MathExpression' && order[op] < order[left.operator]) {
33
+ str += `(${stringify(left, prec)})`;
34
+ } else {
35
+ str += stringify(left, prec);
36
+ }
37
+
32
38
  str += order[op] ? ` ${node.operator} ` : node.operator;
33
- if (right.type === 'MathExpression' && order[op] < order[right.operator]) str += `(${stringify(right, prec)})`;else str += stringify(right, prec);
39
+
40
+ if (right.type === 'MathExpression' && order[op] < order[right.operator]) {
41
+ str += `(${stringify(right, prec)})`;
42
+ } else {
43
+ str += stringify(right, prec);
44
+ }
45
+
34
46
  return str;
35
47
  }
36
48
 
37
- case "Value":
49
+ case 'Number':
38
50
  return round(node.value, prec);
39
51
 
40
52
  case 'Function':
@@ -47,8 +59,9 @@ function stringify(node, prec) {
47
59
 
48
60
  function _default(calc, node, originalValue, options, result, item) {
49
61
  var str = stringify(node, options.precision);
62
+ var shouldPrintCalc = node.type === "MathExpression" || node.type === "Function";
50
63
 
51
- if (node.type === "MathExpression") {
64
+ if (shouldPrintCalc) {
52
65
  // if calc expression couldn't be resolved to a single value, re-wrap it as
53
66
  // a calc()
54
67
  str = `${calc}(${str})`; // if the warnWhenCannotResolve option is on, inform the user that the calc
@@ -23,7 +23,10 @@ var MATCH_CALC = /((?:-(moz|webkit)-)?calc)/i;
23
23
  function transformValue(value, options, result, item) {
24
24
  return (0, _postcssValueParser.default)(value).walk(function (node) {
25
25
  // skip anything which isn't a calc() function
26
- if (node.type !== 'function' || !MATCH_CALC.test(node.value)) return node; // stringify calc expression and produce an AST
26
+ if (node.type !== 'function' || !MATCH_CALC.test(node.value)) {
27
+ return node;
28
+ } // stringify calc expression and produce an AST
29
+
27
30
 
28
31
  var contents = _postcssValueParser.default.stringify(node.nodes);
29
32
 
@@ -31,11 +34,12 @@ function transformValue(value, options, result, item) {
31
34
  // or a simplified calc expression
32
35
 
33
36
 
34
- var reducedAst = (0, _reducer.default)(ast, options.precision, item); // stringify AST and write it back
37
+ var reducedAst = (0, _reducer.default)(ast, options.precision); // stringify AST and write it back
35
38
 
36
39
  node.type = 'word';
37
40
  node.value = (0, _stringifier.default)(node.value, reducedAst, value, options, result, item);
38
- }, true).toString();
41
+ return false;
42
+ }).toString();
39
43
  }
40
44
 
41
45
  function transformSelector(value, options, result, item) {
@@ -49,7 +53,10 @@ function transformSelector(value, options, result, item) {
49
53
  // e.g. the "calc(3*3)" part of "div:nth-child(2n + calc(3*3))"
50
54
 
51
55
 
52
- if (node.type === 'tag') node.value = transformValue(node.value, options, result, item);
56
+ if (node.type === 'tag') {
57
+ node.value = transformValue(node.value, options, result, item);
58
+ }
59
+
53
60
  return;
54
61
  });
55
62
  }).processSync(value);
@@ -65,7 +72,9 @@ var _default = function _default(node, property, options, result) {
65
72
  var clone = node.clone();
66
73
  clone[property] = value;
67
74
  node.parent.insertBefore(node, clone);
68
- } else node[property] = value;
75
+ } else {
76
+ node[property] = value;
77
+ }
69
78
  };
70
79
 
71
80
  exports.default = _default;