Skip to content

Commit

Permalink
fix: do not break calc with single var (#69)
Browse files Browse the repository at this point in the history
  • Loading branch information
evilebottnawi authored Mar 29, 2019
1 parent 34fe682 commit 185f0fb
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 70 deletions.
21 changes: 21 additions & 0 deletions src/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -583,3 +583,24 @@ test(
'calc(unknown(#fff) * other-unknown(200px))',
'calc(unknown(#fff)*other-unknown(200px))',
);

test(
'should not strip calc with single CSS custom variable',
testValue,
'calc(var(--foo))',
'calc(var(--foo))',
);

test(
'should strip unnecessary calc with single CSS custom variable',
testValue,
'calc(calc(var(--foo)))',
'calc(var(--foo))',
);

test(
'should not strip calc with single CSS custom variables and value',
testValue,
'calc(var(--foo) + 10px)',
'calc(var(--foo) + 10px)',
);
142 changes: 73 additions & 69 deletions src/lib/stringifier.js
Original file line number Diff line number Diff line change
@@ -1,69 +1,73 @@
const order = {
"*": 0,
"/": 0,
"+": 1,
"-": 1,
};

function round(value, prec) {
if (prec !== false) {
const precision = Math.pow(10, prec);
return Math.round(value * precision) / precision;
}
return value;
}

function stringify(node, prec) {
switch (node.type) {
case "MathExpression": {
const {left, right, operator: op} = node;
let str = "";

if (left.type === 'MathExpression' && order[op] < order[left.operator])
str += `(${stringify(left, prec)})`;
else
str += stringify(left, prec);

str += order[op] ? ` ${node.operator} ` : node.operator;

if (right.type === 'MathExpression' && order[op] < order[right.operator])
str += `(${stringify(right, prec)})`;
else
str += stringify(right, prec);

return str;
}
case "Value":
return round(node.value, prec);
case 'Function':
return node.value;
default:
return round(node.value, prec) + node.unit;
}
}

export default function (
calc,
node,
originalValue,
options,
result,
item
) {
let str = stringify(node, options.precision);

if (node.type === "MathExpression") {
// if calc expression couldn't be resolved to a single value, re-wrap it as
// a calc()
str = `${calc}(${str})`;

// if the warnWhenCannotResolve option is on, inform the user that the calc
// expression could not be resolved to a single value
if (options.warnWhenCannotResolve) {
result.warn(
"Could not reduce expression: " + originalValue,
{ plugin: 'postcss-calc', node: item });
}
}
return str;
}
const order = {
"*": 0,
"/": 0,
"+": 1,
"-": 1,
};

function round(value, prec) {
if (prec !== false) {
const precision = Math.pow(10, prec);
return Math.round(value * precision) / precision;
}
return value;
}

function stringify(node, prec) {
switch (node.type) {
case "MathExpression": {
const {left, right, operator: op} = node;
let str = "";

if (left.type === 'MathExpression' && order[op] < order[left.operator])
str += `(${stringify(left, prec)})`;
else
str += stringify(left, prec);

str += order[op] ? ` ${node.operator} ` : node.operator;

if (right.type === 'MathExpression' && order[op] < order[right.operator])
str += `(${stringify(right, prec)})`;
else
str += stringify(right, prec);

return str;
}
case "Value":
return round(node.value, prec);
case 'Function':
return node.value;
default:
return round(node.value, prec) + node.unit;
}
}

export default function (
calc,
node,
originalValue,
options,
result,
item
) {
let str = stringify(node, options.precision);

const shouldPrintCalc =
node.type === "MathExpression" ||
(node.type === "Function" && node.value.toLowerCase().slice(0, 4) === "var(");

if (shouldPrintCalc) {
// if calc expression couldn't be resolved to a single value, re-wrap it as
// a calc()
str = `${calc}(${str})`;

// if the warnWhenCannotResolve option is on, inform the user that the calc
// expression could not be resolved to a single value
if (options.warnWhenCannotResolve) {
result.warn(
"Could not reduce expression: " + originalValue,
{ plugin: 'postcss-calc', node: item });
}
}
return str;
}
3 changes: 2 additions & 1 deletion src/lib/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ const MATCH_CALC = /((?:-(moz|webkit)-)?calc)/i;
function transformValue(value, options, result, item) {
return valueParser(value).walk(node => {
// skip anything which isn't a calc() function
if (node.type !== 'function' || !MATCH_CALC.test(node.value))
if (node.type !== 'function' || !MATCH_CALC.test(node.value)) {
return node;
}

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

0 comments on commit 185f0fb

Please sign in to comment.