postcss-calc 10.1.0 → 11.0.0-rc.0

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.
Files changed (67) hide show
  1. package/README.md +56 -1
  2. package/package.json +19 -13
  3. package/src/index.js +122 -27
  4. package/src/lib/convertUnits.js +105 -0
  5. package/src/lib/node.js +189 -0
  6. package/src/lib/parser.js +314 -0
  7. package/src/lib/serialize.js +226 -0
  8. package/src/lib/simplify/abs.js +21 -0
  9. package/src/lib/simplify/atan2.js +25 -0
  10. package/src/lib/simplify/bucket.js +48 -0
  11. package/src/lib/simplify/call.js +59 -0
  12. package/src/lib/simplify/cancel.js +39 -0
  13. package/src/lib/simplify/clamp.js +26 -0
  14. package/src/lib/simplify/exp.js +18 -0
  15. package/src/lib/simplify/fold.js +63 -0
  16. package/src/lib/simplify/hypot.js +22 -0
  17. package/src/lib/simplify/inverse-trig.js +29 -0
  18. package/src/lib/simplify/log.js +25 -0
  19. package/src/lib/simplify/min-max.js +23 -0
  20. package/src/lib/simplify/mod-rem.js +47 -0
  21. package/src/lib/simplify/pow.js +20 -0
  22. package/src/lib/simplify/product.js +133 -0
  23. package/src/lib/simplify/round.js +113 -0
  24. package/src/lib/simplify/sign.js +22 -0
  25. package/src/lib/simplify/sqrt.js +18 -0
  26. package/src/lib/simplify/sum.js +83 -0
  27. package/src/lib/simplify/trig.js +40 -0
  28. package/src/lib/simplify.js +40 -0
  29. package/src/lib/tokenizer.js +115 -0
  30. package/types/index.d.ts +15 -17
  31. package/types/lib/convertUnits.d.ts +16 -0
  32. package/types/lib/node.d.ts +90 -0
  33. package/types/lib/parser.d.ts +39 -0
  34. package/types/lib/serialize.d.ts +20 -0
  35. package/types/lib/simplify/abs.d.ts +7 -0
  36. package/types/lib/simplify/atan2.d.ts +7 -0
  37. package/types/lib/simplify/bucket.d.ts +19 -0
  38. package/types/lib/simplify/call.d.ts +12 -0
  39. package/types/lib/simplify/cancel.d.ts +19 -0
  40. package/types/lib/simplify/clamp.d.ts +7 -0
  41. package/types/lib/simplify/exp.d.ts +7 -0
  42. package/types/lib/simplify/fold.d.ts +12 -0
  43. package/types/lib/simplify/hypot.d.ts +7 -0
  44. package/types/lib/simplify/inverse-trig.d.ts +7 -0
  45. package/types/lib/simplify/log.d.ts +7 -0
  46. package/types/lib/simplify/min-max.d.ts +8 -0
  47. package/types/lib/simplify/mod-rem.d.ts +8 -0
  48. package/types/lib/simplify/pow.d.ts +7 -0
  49. package/types/lib/simplify/product.d.ts +16 -0
  50. package/types/lib/simplify/round.d.ts +8 -0
  51. package/types/lib/simplify/sign.d.ts +7 -0
  52. package/types/lib/simplify/sqrt.d.ts +7 -0
  53. package/types/lib/simplify/sum.d.ts +18 -0
  54. package/types/lib/simplify/trig.d.ts +7 -0
  55. package/types/lib/simplify.d.ts +18 -0
  56. package/types/lib/tokenizer.d.ts +19 -0
  57. package/types/lib/type.d.ts +16 -0
  58. package/src/lib/convertUnit.js +0 -160
  59. package/src/lib/reducer.js +0 -390
  60. package/src/lib/stringifier.js +0 -98
  61. package/src/lib/transform.js +0 -109
  62. package/src/parser.d.ts +0 -79
  63. package/src/parser.js +0 -4200
  64. package/types/lib/convertUnit.d.ts +0 -8
  65. package/types/lib/reducer.d.ts +0 -14
  66. package/types/lib/stringifier.d.ts +0 -5
  67. package/types/lib/transform.d.ts +0 -6
@@ -0,0 +1,19 @@
1
+ export type TokenType = "number" | "dimension" | "ident" | "punct" | "eof";
2
+ export type Token = {
3
+ type: TokenType;
4
+ value: string;
5
+ /**
6
+ * Present on `dimension` tokens; `%` for percentages.
7
+ */
8
+ unit?: string | undefined;
9
+ pos: number;
10
+ /**
11
+ * Whitespace immediately before — drives the §10.1 `+`/`-` rule.
12
+ */
13
+ ws: boolean;
14
+ };
15
+ /**
16
+ * @param {string} input
17
+ * @return {Token[]}
18
+ */
19
+ export function tokenize(input: string): Token[];
@@ -0,0 +1,16 @@
1
+ export type BaseType = "length" | "angle" | "time" | "frequency" | "resolution" | "flex" | "percentage";
2
+ /**
3
+ * @param {string} unit
4
+ * @return {BaseType | null}
5
+ */
6
+ export function baseOf(unit: string): BaseType | null;
7
+ /**
8
+ * Convert a value within a single conversion family. Returns null when
9
+ * either unit is missing from the table (em/rem/vw need runtime context)
10
+ * or when the units belong to different base types.
11
+ * @param {number} value
12
+ * @param {string} from
13
+ * @param {string} to
14
+ * @return {number | null}
15
+ */
16
+ export function convert(value: number, from: string, to: string): number | null;
@@ -1,160 +0,0 @@
1
- 'use strict';
2
- /**
3
- * @type {{[key:string]: {[key:string]: number}}}
4
- */
5
- const conversions = {
6
- // Absolute length units
7
- px: {
8
- px: 1,
9
- cm: 96 / 2.54,
10
- mm: 96 / 25.4,
11
- q: 96 / 101.6,
12
- in: 96,
13
- pt: 96 / 72,
14
- pc: 16,
15
- },
16
- cm: {
17
- px: 2.54 / 96,
18
- cm: 1,
19
- mm: 0.1,
20
- q: 0.025,
21
- in: 2.54,
22
- pt: 2.54 / 72,
23
- pc: 2.54 / 6,
24
- },
25
- mm: {
26
- px: 25.4 / 96,
27
- cm: 10,
28
- mm: 1,
29
- q: 0.25,
30
- in: 25.4,
31
- pt: 25.4 / 72,
32
- pc: 25.4 / 6,
33
- },
34
- q: {
35
- px: 101.6 / 96,
36
- cm: 40,
37
- mm: 4,
38
- q: 1,
39
- in: 101.6,
40
- pt: 101.6 / 72,
41
- pc: 101.6 / 6,
42
- },
43
- in: {
44
- px: 1 / 96,
45
- cm: 1 / 2.54,
46
- mm: 1 / 25.4,
47
- q: 1 / 101.6,
48
- in: 1,
49
- pt: 1 / 72,
50
- pc: 1 / 6,
51
- },
52
- pt: {
53
- px: 0.75,
54
- cm: 72 / 2.54,
55
- mm: 72 / 25.4,
56
- q: 72 / 101.6,
57
- in: 72,
58
- pt: 1,
59
- pc: 12,
60
- },
61
- pc: {
62
- px: 0.0625,
63
- cm: 6 / 2.54,
64
- mm: 6 / 25.4,
65
- q: 6 / 101.6,
66
- in: 6,
67
- pt: 6 / 72,
68
- pc: 1,
69
- },
70
- // Angle units
71
- deg: {
72
- deg: 1,
73
- grad: 0.9,
74
- rad: 180 / Math.PI,
75
- turn: 360,
76
- },
77
- grad: {
78
- deg: 400 / 360,
79
- grad: 1,
80
- rad: 200 / Math.PI,
81
- turn: 400,
82
- },
83
- rad: {
84
- deg: Math.PI / 180,
85
- grad: Math.PI / 200,
86
- rad: 1,
87
- turn: Math.PI * 2,
88
- },
89
- turn: {
90
- deg: 1 / 360,
91
- grad: 0.0025,
92
- rad: 0.5 / Math.PI,
93
- turn: 1,
94
- },
95
- // Duration units
96
- s: {
97
- s: 1,
98
- ms: 0.001,
99
- },
100
- ms: {
101
- s: 1000,
102
- ms: 1,
103
- },
104
- // Frequency units
105
- hz: {
106
- hz: 1,
107
- khz: 1000,
108
- },
109
- khz: {
110
- hz: 0.001,
111
- khz: 1,
112
- },
113
- // Resolution units
114
- dpi: {
115
- dpi: 1,
116
- dpcm: 1 / 2.54,
117
- dppx: 1 / 96,
118
- },
119
- dpcm: {
120
- dpi: 2.54,
121
- dpcm: 1,
122
- dppx: 2.54 / 96,
123
- },
124
- dppx: {
125
- dpi: 96,
126
- dpcm: 96 / 2.54,
127
- dppx: 1,
128
- },
129
- };
130
- /**
131
- * @param {number} value
132
- * @param {string} sourceUnit
133
- * @param {string} targetUnit
134
- * @param {number|false} precision
135
- */
136
- function convertUnit(value, sourceUnit, targetUnit, precision) {
137
- const sourceUnitNormalized = sourceUnit.toLowerCase();
138
- const targetUnitNormalized = targetUnit.toLowerCase();
139
-
140
- if (!conversions[targetUnitNormalized]) {
141
- throw new Error('Cannot convert to ' + targetUnit);
142
- }
143
-
144
- if (!conversions[targetUnitNormalized][sourceUnitNormalized]) {
145
- throw new Error('Cannot convert from ' + sourceUnit + ' to ' + targetUnit);
146
- }
147
-
148
- const converted =
149
- conversions[targetUnitNormalized][sourceUnitNormalized] * value;
150
-
151
- if (precision !== false) {
152
- precision = Math.pow(10, Math.ceil(precision) || 5);
153
-
154
- return Math.round(converted * precision) / precision;
155
- }
156
-
157
- return converted;
158
- }
159
-
160
- module.exports = convertUnit;
@@ -1,390 +0,0 @@
1
- 'use strict';
2
- const convertUnit = require('./convertUnit.js');
3
-
4
- /**
5
- * @param {import('../parser').CalcNode} node
6
- * @return {node is import('../parser').ValueExpression}
7
- */
8
- function isValueType(node) {
9
- switch (node.type) {
10
- case 'LengthValue':
11
- case 'AngleValue':
12
- case 'TimeValue':
13
- case 'FrequencyValue':
14
- case 'ResolutionValue':
15
- case 'EmValue':
16
- case 'ExValue':
17
- case 'ChValue':
18
- case 'RemValue':
19
- case 'VhValue':
20
- case 'SvhValue':
21
- case 'LvhValue':
22
- case 'DvhValue':
23
- case 'VwValue':
24
- case 'SvwValue':
25
- case 'LvwValue':
26
- case 'DvwValue':
27
- case 'VminValue':
28
- case 'SvminValue':
29
- case 'LvminValue':
30
- case 'DvminValue':
31
- case 'VmaxValue':
32
- case 'SvmaxValue':
33
- case 'LvmaxValue':
34
- case 'DvmaxValue':
35
- case 'VbValue':
36
- case 'SvbValue':
37
- case 'LvbValue':
38
- case 'DvbValue':
39
- case 'ViValue':
40
- case 'SviValue':
41
- case 'LviValue':
42
- case 'DviValue':
43
- case 'CqwValue':
44
- case 'CqhValue':
45
- case 'CqiValue':
46
- case 'CqbValue':
47
- case 'CqminValue':
48
- case 'CqmaxValue':
49
- case 'PercentageValue':
50
- case 'LhValue':
51
- case 'RlhValue':
52
- case 'Number':
53
- return true;
54
- }
55
- return false;
56
- }
57
-
58
- /** @param {'-'|'+'} operator */
59
- function flip(operator) {
60
- return operator === '+' ? '-' : '+';
61
- }
62
-
63
- /**
64
- * @param {string} operator
65
- * @returns {operator is '+'|'-'}
66
- */
67
- function isAddSubOperator(operator) {
68
- return operator === '+' || operator === '-';
69
- }
70
-
71
- /**
72
- * @typedef {{preOperator: '+'|'-', node: import('../parser').CalcNode}} Collectible
73
- */
74
-
75
- /**
76
- * @param {'+'|'-'} preOperator
77
- * @param {import('../parser').CalcNode} node
78
- * @param {Collectible[]} collected
79
- * @param {number} precision
80
- */
81
- function collectAddSubItems(preOperator, node, collected, precision) {
82
- if (!isAddSubOperator(preOperator)) {
83
- throw new Error(`invalid operator ${preOperator}`);
84
- }
85
- if (isValueType(node)) {
86
- const itemIndex = collected.findIndex((x) => x.node.type === node.type);
87
- if (itemIndex >= 0) {
88
- if (node.value === 0) {
89
- return;
90
- }
91
- // can cast because of the criterion used to find itemIndex
92
- const otherValueNode = /** @type import('../parser').ValueExpression*/ (
93
- collected[itemIndex].node
94
- );
95
- const { left: reducedNode, right: current } = convertNodesUnits(
96
- otherValueNode,
97
- node,
98
- precision
99
- );
100
-
101
- if (collected[itemIndex].preOperator === '-') {
102
- collected[itemIndex].preOperator = '+';
103
- reducedNode.value *= -1;
104
- }
105
- if (preOperator === '+') {
106
- reducedNode.value += current.value;
107
- } else {
108
- reducedNode.value -= current.value;
109
- }
110
- // make sure reducedNode.value >= 0
111
- if (reducedNode.value >= 0) {
112
- collected[itemIndex] = { node: reducedNode, preOperator: '+' };
113
- } else {
114
- reducedNode.value *= -1;
115
- collected[itemIndex] = { node: reducedNode, preOperator: '-' };
116
- }
117
- } else {
118
- // make sure node.value >= 0
119
- if (node.value >= 0) {
120
- collected.push({ node, preOperator });
121
- } else {
122
- node.value *= -1;
123
- collected.push({ node, preOperator: flip(preOperator) });
124
- }
125
- }
126
- } else if (node.type === 'MathExpression') {
127
- if (isAddSubOperator(node.operator)) {
128
- collectAddSubItems(preOperator, node.left, collected, precision);
129
- const collectRightOperator =
130
- preOperator === '-' ? flip(node.operator) : node.operator;
131
- collectAddSubItems(
132
- collectRightOperator,
133
- node.right,
134
- collected,
135
- precision
136
- );
137
- } else {
138
- // * or /
139
- const reducedNode = reduce(node, precision);
140
- // prevent infinite recursive call
141
- if (
142
- reducedNode.type !== 'MathExpression' ||
143
- isAddSubOperator(reducedNode.operator)
144
- ) {
145
- collectAddSubItems(preOperator, reducedNode, collected, precision);
146
- } else {
147
- collected.push({ node: reducedNode, preOperator });
148
- }
149
- }
150
- } else if (node.type === 'ParenthesizedExpression') {
151
- collectAddSubItems(preOperator, node.content, collected, precision);
152
- } else {
153
- collected.push({ node, preOperator });
154
- }
155
- }
156
-
157
- /**
158
- * @param {import('../parser').CalcNode} node
159
- * @param {number} precision
160
- */
161
- function reduceAddSubExpression(node, precision) {
162
- /** @type Collectible[] */
163
- const collected = [];
164
- collectAddSubItems('+', node, collected, precision);
165
-
166
- const withoutZeroItem = collected.filter(
167
- (item) => !(isValueType(item.node) && item.node.value === 0)
168
- );
169
- const firstNonZeroItem = withoutZeroItem[0]; // could be undefined
170
-
171
- // prevent producing "calc(-var(--a))" or "calc()"
172
- // which is invalid css
173
- if (
174
- !firstNonZeroItem ||
175
- (firstNonZeroItem.preOperator === '-' &&
176
- !isValueType(firstNonZeroItem.node))
177
- ) {
178
- const firstZeroItem = collected.find(
179
- (item) => isValueType(item.node) && item.node.value === 0
180
- );
181
- if (firstZeroItem) {
182
- withoutZeroItem.unshift(firstZeroItem);
183
- }
184
- }
185
-
186
- // make sure the preOperator of the first item is +
187
- if (
188
- withoutZeroItem[0].preOperator === '-' &&
189
- isValueType(withoutZeroItem[0].node)
190
- ) {
191
- withoutZeroItem[0].node.value *= -1;
192
- withoutZeroItem[0].preOperator = '+';
193
- }
194
-
195
- let root = withoutZeroItem[0].node;
196
- for (let i = 1; i < withoutZeroItem.length; i++) {
197
- root = {
198
- type: 'MathExpression',
199
- operator: withoutZeroItem[i].preOperator,
200
- left: root,
201
- right: withoutZeroItem[i].node,
202
- };
203
- }
204
-
205
- return root;
206
- }
207
- /**
208
- * @param {import('../parser').MathExpression} node
209
- */
210
- function reduceDivisionExpression(node) {
211
- if (!isValueType(node.right)) {
212
- return node;
213
- }
214
-
215
- if (node.right.type !== 'Number') {
216
- throw new Error(`Cannot divide by "${node.right.unit}", number expected`);
217
- }
218
-
219
- return applyNumberDivision(node.left, node.right.value);
220
- }
221
-
222
- /**
223
- * apply (expr) / number
224
- *
225
- * @param {import('../parser').CalcNode} node
226
- * @param {number} divisor
227
- * @return {import('../parser').CalcNode}
228
- */
229
- function applyNumberDivision(node, divisor) {
230
- if (divisor === 0) {
231
- throw new Error('Cannot divide by zero');
232
- }
233
- if (isValueType(node)) {
234
- node.value /= divisor;
235
- return node;
236
- }
237
- if (node.type === 'MathExpression' && isAddSubOperator(node.operator)) {
238
- // turn (a + b) / num into a/num + b/num
239
- // is good for further reduction
240
- // checkout the test case
241
- // "should reduce division before reducing additions"
242
- return {
243
- type: 'MathExpression',
244
- operator: node.operator,
245
- left: applyNumberDivision(node.left, divisor),
246
- right: applyNumberDivision(node.right, divisor),
247
- };
248
- }
249
- // it is impossible to reduce it into a single value
250
- // .e.g the node contains css variable
251
- // so we just preserve the division and let browser do it
252
- return {
253
- type: 'MathExpression',
254
- operator: '/',
255
- left: node,
256
- right: {
257
- type: 'Number',
258
- value: divisor,
259
- },
260
- };
261
- }
262
- /**
263
- * @param {import('../parser').MathExpression} node
264
- */
265
- function reduceMultiplicationExpression(node) {
266
- // (expr) * number
267
- if (node.right.type === 'Number') {
268
- return applyNumberMultiplication(node.left, node.right.value);
269
- }
270
- // number * (expr)
271
- if (node.left.type === 'Number') {
272
- return applyNumberMultiplication(node.right, node.left.value);
273
- }
274
- return node;
275
- }
276
-
277
- /**
278
- * apply (expr) * number
279
- * @param {number} multiplier
280
- * @param {import('../parser').CalcNode} node
281
- * @return {import('../parser').CalcNode}
282
- */
283
- function applyNumberMultiplication(node, multiplier) {
284
- if (isValueType(node)) {
285
- node.value *= multiplier;
286
- return node;
287
- }
288
- if (node.type === 'MathExpression' && isAddSubOperator(node.operator)) {
289
- // turn (a + b) * num into a*num + b*num
290
- // is good for further reduction
291
- // checkout the test case
292
- // "should reduce multiplication before reducing additions"
293
- return {
294
- type: 'MathExpression',
295
- operator: node.operator,
296
- left: applyNumberMultiplication(node.left, multiplier),
297
- right: applyNumberMultiplication(node.right, multiplier),
298
- };
299
- }
300
- // it is impossible to reduce it into a single value
301
- // .e.g the node contains css variable
302
- // so we just preserve the division and let browser do it
303
- return {
304
- type: 'MathExpression',
305
- operator: '*',
306
- left: node,
307
- right: {
308
- type: 'Number',
309
- value: multiplier,
310
- },
311
- };
312
- }
313
-
314
- /**
315
- * @param {import('../parser').ValueExpression} left
316
- * @param {import('../parser').ValueExpression} right
317
- * @param {number} precision
318
- */
319
- function convertNodesUnits(left, right, precision) {
320
- switch (left.type) {
321
- case 'LengthValue':
322
- case 'AngleValue':
323
- case 'TimeValue':
324
- case 'FrequencyValue':
325
- case 'ResolutionValue':
326
- if (right.type === left.type && right.unit && left.unit) {
327
- const converted = convertUnit(
328
- right.value,
329
- right.unit,
330
- left.unit,
331
- precision
332
- );
333
-
334
- right = {
335
- type: left.type,
336
- value: converted,
337
- unit: left.unit,
338
- };
339
- }
340
-
341
- return { left, right };
342
- default:
343
- return { left, right };
344
- }
345
- }
346
-
347
- /**
348
- * @param {import('../parser').ParenthesizedExpression} node
349
- */
350
- function includesNoCssProperties(node) {
351
- return (
352
- node.content.type !== 'Function' &&
353
- (node.content.type !== 'MathExpression' ||
354
- (node.content.right.type !== 'Function' &&
355
- node.content.left.type !== 'Function'))
356
- );
357
- }
358
- /**
359
- * @param {import('../parser').CalcNode} node
360
- * @param {number} precision
361
- * @return {import('../parser').CalcNode}
362
- */
363
- function reduce(node, precision) {
364
- if (node.type === 'MathExpression') {
365
- if (isAddSubOperator(node.operator)) {
366
- // reduceAddSubExpression will call reduce recursively
367
- return reduceAddSubExpression(node, precision);
368
- }
369
- node.left = reduce(node.left, precision);
370
- node.right = reduce(node.right, precision);
371
- switch (node.operator) {
372
- case '/':
373
- return reduceDivisionExpression(node);
374
- case '*':
375
- return reduceMultiplicationExpression(node);
376
- }
377
-
378
- return node;
379
- }
380
-
381
- if (node.type === 'ParenthesizedExpression') {
382
- if (includesNoCssProperties(node)) {
383
- return reduce(node.content, precision);
384
- }
385
- }
386
-
387
- return node;
388
- }
389
-
390
- module.exports = reduce;
@@ -1,98 +0,0 @@
1
- 'use strict';
2
- const order = {
3
- '*': 0,
4
- '/': 0,
5
- '+': 1,
6
- '-': 1,
7
- };
8
-
9
- /**
10
- * @param {number} value
11
- * @param {number | false} prec
12
- */
13
- function round(value, prec) {
14
- if (prec !== false) {
15
- const precision = Math.pow(10, prec);
16
- return Math.round(value * precision) / precision;
17
- }
18
- return value;
19
- }
20
-
21
- /**
22
- * @param {number | false} prec
23
- * @param {import('../parser').CalcNode} node
24
- *
25
- * @return {string}
26
- */
27
- function stringify(node, prec) {
28
- switch (node.type) {
29
- case 'MathExpression': {
30
- const { left, right, operator: op } = node;
31
- let str = '';
32
- if (left.type === 'MathExpression' && order[op] < order[left.operator]) {
33
- str += `(${stringify(left, prec)})`;
34
- } else {
35
- str += stringify(left, prec);
36
- }
37
-
38
- str += order[op] ? ` ${node.operator} ` : node.operator;
39
-
40
- if (
41
- right.type === 'MathExpression' &&
42
- order[op] < order[right.operator]
43
- ) {
44
- str += `(${stringify(right, prec)})`;
45
- } else {
46
- str += stringify(right, prec);
47
- }
48
-
49
- return str;
50
- }
51
- case 'Number':
52
- return round(node.value, prec).toString();
53
- case 'Function':
54
- return node.value.toString();
55
- case 'ParenthesizedExpression':
56
- return `(${stringify(node.content, prec)})`;
57
- default:
58
- return round(node.value, prec) + node.unit;
59
- }
60
- }
61
-
62
- /**
63
- * @param {string} calc
64
- * @param {import('../parser').CalcNode} node
65
- * @param {string} originalValue
66
- * @param {{precision: number | false, warnWhenCannotResolve: boolean}} options
67
- * @param {import("postcss").Result} result
68
- * @param {import("postcss").ChildNode} item
69
- *
70
- * @returns {string}
71
- */
72
- module.exports = function (calc, node, originalValue, options, result, item) {
73
- let str = stringify(node, options.precision);
74
-
75
- const shouldPrintCalc =
76
- node.type === 'MathExpression' || node.type === 'Function' ||
77
- node.type === 'ParenthesizedExpression';
78
-
79
- if (shouldPrintCalc) {
80
- // if calc expression couldn't be resolved to a single value, re-wrap it as
81
- // a calc()
82
- if (node.type === 'ParenthesizedExpression') {
83
- str = `${calc}${str}`;
84
- } else {
85
- str = `${calc}(${str})`;
86
- }
87
-
88
- // if the warnWhenCannotResolve option is on, inform the user that the calc
89
- // expression could not be resolved to a single value
90
- if (options.warnWhenCannotResolve) {
91
- result.warn('Could not reduce expression: ' + originalValue, {
92
- plugin: 'postcss-calc',
93
- node: item,
94
- });
95
- }
96
- }
97
- return str;
98
- };