Skip to content

Commit 185f0fb

Browse files
fix: do not break calc with single var (#69)
1 parent 34fe682 commit 185f0fb

File tree

3 files changed

+96
-70
lines changed

3 files changed

+96
-70
lines changed

src/__tests__/index.js

+21
Original file line numberDiff line numberDiff line change
@@ -583,3 +583,24 @@ test(
583583
'calc(unknown(#fff) * other-unknown(200px))',
584584
'calc(unknown(#fff)*other-unknown(200px))',
585585
);
586+
587+
test(
588+
'should not strip calc with single CSS custom variable',
589+
testValue,
590+
'calc(var(--foo))',
591+
'calc(var(--foo))',
592+
);
593+
594+
test(
595+
'should strip unnecessary calc with single CSS custom variable',
596+
testValue,
597+
'calc(calc(var(--foo)))',
598+
'calc(var(--foo))',
599+
);
600+
601+
test(
602+
'should not strip calc with single CSS custom variables and value',
603+
testValue,
604+
'calc(var(--foo) + 10px)',
605+
'calc(var(--foo) + 10px)',
606+
);

src/lib/stringifier.js

+73-69
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,73 @@
1-
const order = {
2-
"*": 0,
3-
"/": 0,
4-
"+": 1,
5-
"-": 1,
6-
};
7-
8-
function round(value, prec) {
9-
if (prec !== false) {
10-
const precision = Math.pow(10, prec);
11-
return Math.round(value * precision) / precision;
12-
}
13-
return value;
14-
}
15-
16-
function stringify(node, prec) {
17-
switch (node.type) {
18-
case "MathExpression": {
19-
const {left, right, operator: op} = node;
20-
let str = "";
21-
22-
if (left.type === 'MathExpression' && order[op] < order[left.operator])
23-
str += `(${stringify(left, prec)})`;
24-
else
25-
str += stringify(left, prec);
26-
27-
str += order[op] ? ` ${node.operator} ` : node.operator;
28-
29-
if (right.type === 'MathExpression' && order[op] < order[right.operator])
30-
str += `(${stringify(right, prec)})`;
31-
else
32-
str += stringify(right, prec);
33-
34-
return str;
35-
}
36-
case "Value":
37-
return round(node.value, prec);
38-
case 'Function':
39-
return node.value;
40-
default:
41-
return round(node.value, prec) + node.unit;
42-
}
43-
}
44-
45-
export default function (
46-
calc,
47-
node,
48-
originalValue,
49-
options,
50-
result,
51-
item
52-
) {
53-
let str = stringify(node, options.precision);
54-
55-
if (node.type === "MathExpression") {
56-
// if calc expression couldn't be resolved to a single value, re-wrap it as
57-
// a calc()
58-
str = `${calc}(${str})`;
59-
60-
// if the warnWhenCannotResolve option is on, inform the user that the calc
61-
// expression could not be resolved to a single value
62-
if (options.warnWhenCannotResolve) {
63-
result.warn(
64-
"Could not reduce expression: " + originalValue,
65-
{ plugin: 'postcss-calc', node: item });
66-
}
67-
}
68-
return str;
69-
}
1+
const order = {
2+
"*": 0,
3+
"/": 0,
4+
"+": 1,
5+
"-": 1,
6+
};
7+
8+
function round(value, prec) {
9+
if (prec !== false) {
10+
const precision = Math.pow(10, prec);
11+
return Math.round(value * precision) / precision;
12+
}
13+
return value;
14+
}
15+
16+
function stringify(node, prec) {
17+
switch (node.type) {
18+
case "MathExpression": {
19+
const {left, right, operator: op} = node;
20+
let str = "";
21+
22+
if (left.type === 'MathExpression' && order[op] < order[left.operator])
23+
str += `(${stringify(left, prec)})`;
24+
else
25+
str += stringify(left, prec);
26+
27+
str += order[op] ? ` ${node.operator} ` : node.operator;
28+
29+
if (right.type === 'MathExpression' && order[op] < order[right.operator])
30+
str += `(${stringify(right, prec)})`;
31+
else
32+
str += stringify(right, prec);
33+
34+
return str;
35+
}
36+
case "Value":
37+
return round(node.value, prec);
38+
case 'Function':
39+
return node.value;
40+
default:
41+
return round(node.value, prec) + node.unit;
42+
}
43+
}
44+
45+
export default function (
46+
calc,
47+
node,
48+
originalValue,
49+
options,
50+
result,
51+
item
52+
) {
53+
let str = stringify(node, options.precision);
54+
55+
const shouldPrintCalc =
56+
node.type === "MathExpression" ||
57+
(node.type === "Function" && node.value.toLowerCase().slice(0, 4) === "var(");
58+
59+
if (shouldPrintCalc) {
60+
// if calc expression couldn't be resolved to a single value, re-wrap it as
61+
// a calc()
62+
str = `${calc}(${str})`;
63+
64+
// if the warnWhenCannotResolve option is on, inform the user that the calc
65+
// expression could not be resolved to a single value
66+
if (options.warnWhenCannotResolve) {
67+
result.warn(
68+
"Could not reduce expression: " + originalValue,
69+
{ plugin: 'postcss-calc', node: item });
70+
}
71+
}
72+
return str;
73+
}

src/lib/transform.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@ const MATCH_CALC = /((?:-(moz|webkit)-)?calc)/i;
1212
function transformValue(value, options, result, item) {
1313
return valueParser(value).walk(node => {
1414
// skip anything which isn't a calc() function
15-
if (node.type !== 'function' || !MATCH_CALC.test(node.value))
15+
if (node.type !== 'function' || !MATCH_CALC.test(node.value)) {
1616
return node;
17+
}
1718

1819
// stringify calc expression and produce an AST
1920
const contents = valueParser.stringify(node.nodes);

0 commit comments

Comments
 (0)