Skip to content

Commit 99d9fa5

Browse files
committed
fix: respect CSS var when reducing
Fix cssnano/cssnano#1235 Preserve the parentheses around a math expression that contains a var() function call, to guarantee that the expression value stays the same. The CSS custom properties might contain an addition or subtraction, so even distributing multiplication or division is not safe.
1 parent 3f2c424 commit 99d9fa5

File tree

2 files changed

+30
-7
lines changed

2 files changed

+30
-7
lines changed

Diff for: src/__tests__/index.js

+19-6
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ test(
106106
'should reduce additions and subtractions (7)',
107107
testValue(
108108
'calc(0px - (24px - (var(--a) - var(--b)) / 2 + var(--c)))',
109-
'calc(-24px + var(--a)/2 - var(--b)/2 - var(--c))'
109+
'calc(-24px + (var(--a) - var(--b))/2 - var(--c))'
110110
)
111111
);
112112

@@ -122,27 +122,27 @@ test(
122122

123123
test(
124124
'should reduce multiplication',
125-
testValue('calc(((var(--a) + 4px) * 2) * 2)', 'calc(var(--a)*2*2 + 16px)')
125+
testValue('calc(((var(--a) + 4px) * 2) * 2)', 'calc((var(--a) + 4px)*2*2)')
126126
);
127127

128128
test(
129129
'should reduce multiplication before reducing additions',
130130
testValue(
131131
'calc(((var(--a) + 4px) * 2) * 2 + 4px)',
132-
'calc(var(--a)*2*2 + 20px)'
132+
'calc((var(--a) + 4px)*2*2 + 4px)'
133133
)
134134
);
135135

136136
test(
137137
'should reduce division',
138-
testValue('calc(((var(--a) + 4px) / 2) / 2)', 'calc(var(--a)/2/2 + 1px)')
138+
testValue('calc(((var(--a) + 4px) / 2) / 2)', 'calc((var(--a) + 4px)/2/2)')
139139
);
140140

141141
test(
142142
'should reduce division before reducing additions',
143143
testValue(
144144
'calc(((var(--a) + 4px) / 2) / 2 + 4px)',
145-
'calc(var(--a)/2/2 + 5px)'
145+
'calc((var(--a) + 4px)/2/2 + 4px)'
146146
)
147147
);
148148

@@ -750,7 +750,20 @@ test(
750750
(var(--fluid-screen) - ((var(--fluid-min-width) / 16) * 1rem)) /
751751
((var(--fluid-max-width) / 16) - (var(--fluid-min-width) / 16))
752752
)`,
753-
'calc((var(--fluid-screen) - var(--fluid-min-width)/16*1rem)/(var(--fluid-max-width)/16 - var(--fluid-min-width)/16))'
753+
'calc((var(--fluid-screen) - ((var(--fluid-min-width)/16)*1rem))/(var(--fluid-max-width)/16 - var(--fluid-min-width)/16))'
754+
)
755+
);
756+
757+
test(
758+
'should preserve division precedence (3)',
759+
testValue('calc(1/(10/var(--dot-size)))', 'calc(1/(10/var(--dot-size)))')
760+
);
761+
762+
test(
763+
'should correctly preserve parentheses',
764+
testValue(
765+
'calc(1/((var(--a) - var(--b))/16))',
766+
'calc(1/(var(--a) - var(--b))/16)'
754767
)
755768
);
756769

Diff for: src/lib/reducer.js

+11-1
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,16 @@ function convertNodesUnits(left, right, precision) {
285285
}
286286
}
287287

288+
/**
289+
* @param {import('../parser').ParenthesizedExpression} node
290+
*/
291+
function includesNoCssProperties(node) {
292+
return node.content.type !== 'Function' &&
293+
(node.content.type !== 'MathExpression' ||
294+
(node.content.right.type !== 'Function' &&
295+
node.content.left.type !== 'Function')
296+
);
297+
}
288298
/**
289299
* @param {import('../parser').CalcNode} node
290300
* @param {number} precision
@@ -309,7 +319,7 @@ function reduce(node, precision) {
309319
}
310320

311321
if (node.type === 'ParenthesizedExpression') {
312-
if (node.content.type !== 'Function') {
322+
if (includesNoCssProperties(node)) {
313323
return reduce(node.content, precision);
314324
}
315325
}

0 commit comments

Comments
 (0)