Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 87d57ef

Browse files
authoredJan 30, 2025··
fix: handle calc keywords correctly (#234)
Fix #210
1 parent b1f5339 commit 87d57ef

File tree

5 files changed

+50
-2
lines changed

5 files changed

+50
-2
lines changed
 

‎parser.jison

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@
7373
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)dppx\b return 'RES';
7474
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)\% return 'PERCENTAGE';
7575
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)\b return 'NUMBER';
76+
("infinity"|"pi"|"e")\b return 'CALC_KEYWORD';
77+
7678

7779
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)-?([a-zA-Z_]|[\240-\377]|(\\[0-9a-fA-F]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-fA-F]))([a-zA-Z0-9_-]|[\240-\377]|(\\[0-9a-fA-F]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-fA-F]))*\b return 'UNKNOWN_DIMENSION';
7880

@@ -106,6 +108,7 @@ expression
106108
| function { $$ = $1; }
107109
| dimension { $$ = $1; }
108110
| number { $$ = $1; }
111+
| calc_keyword { $$ = $1; }
109112
;
110113

111114
function
@@ -160,6 +163,10 @@ expression
160163
| SUB dimension { var prev = $2; prev.value *= -1; $$ = prev; }
161164
;
162165

166+
calc_keyword
167+
: CALC_KEYWORD { $$ = { type: 'CalcKeyword', value: $1 }; }
168+
;
169+
163170
number
164171
: NUMBER { $$ = { type: 'Number', value: parseFloat($1) }; }
165172
| ADD NUMBER { $$ = { type: 'Number', value: parseFloat($2) }; }

‎src/lib/reducer.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -361,6 +361,9 @@ function includesNoCssProperties(node) {
361361
* @return {import('../parser').CalcNode}
362362
*/
363363
function reduce(node, precision) {
364+
if (node.type === 'MathExpression' && (node.left.type === 'CalcKeyword' || node.right.type === 'CalcKeyword')) {
365+
return node;
366+
}
364367
if (node.type === 'MathExpression') {
365368
if (isAddSubOperator(node.operator)) {
366369
// reduceAddSubExpression will call reduce recursively

‎src/lib/stringifier.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ function stringify(node, prec) {
3131
let str = '';
3232
if (left.type === 'MathExpression' && order[op] < order[left.operator]) {
3333
str += `(${stringify(left, prec)})`;
34+
} else if (left.type === 'CalcKeyword') {
35+
str += left.value;
3436
} else {
3537
str += stringify(left, prec);
3638
}
@@ -42,6 +44,8 @@ function stringify(node, prec) {
4244
order[op] < order[right.operator]
4345
) {
4446
str += `(${stringify(right, prec)})`;
47+
} else if (right.type === 'CalcKeyword') {
48+
str += right.value;
4549
} else {
4650
str += stringify(right, prec);
4751
}
@@ -54,6 +58,8 @@ function stringify(node, prec) {
5458
return node.value.toString();
5559
case 'ParenthesizedExpression':
5660
return `(${stringify(node.content, prec)})`;
61+
case 'CalcKeyword':
62+
return node.value;
5763
default:
5864
return round(node.value, prec) + node.unit;
5965
}
@@ -74,7 +80,7 @@ module.exports = function (calc, node, originalValue, options, result, item) {
7480

7581
const shouldPrintCalc =
7682
node.type === 'MathExpression' || node.type === 'Function' ||
77-
node.type === 'ParenthesizedExpression';
83+
node.type === 'ParenthesizedExpression' || node.type === 'CalcKeyword';
7884

7985
if (shouldPrintCalc) {
8086
// if calc expression couldn't be resolved to a single value, re-wrap it as

‎src/parser.d.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,14 @@ export interface FunctionExpression {
6868
value: string;
6969
}
7070

71+
export interface CalcKeywordExpression {
72+
type: 'CalcKeyword';
73+
value: string;
74+
}
75+
7176
export type ValueExpression = DimensionExpression | NumberExpression;
7277

73-
export type CalcNode = MathExpression | ValueExpression | FunctionExpression | ParenthesizedExpression;
78+
export type CalcNode = MathExpression | ValueExpression | FunctionExpression | ParenthesizedExpression | CalcKeywordExpression;
7479

7580
export interface Parser {
7681
parse: (arg: string) => CalcNode;

‎test/index.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,33 @@ test(
259259
)
260260
);
261261

262+
263+
test(
264+
'should ignore multiplication with infinity',
265+
testValue('calc(infinity * 1px)', 'calc(infinity*1px)')
266+
);
267+
268+
test(
269+
'should ignore addition with infinity',
270+
testValue('calc(infinity + 1px)', 'calc(infinity + 1px)')
271+
);
272+
273+
test(
274+
'should ignore multiplication with pi',
275+
testValue('calc(1px * pi)', 'calc(1px*pi)')
276+
);
277+
278+
test(
279+
'should ignore addition with pi',
280+
testValue('calc(43 + pi)', 'calc(43 + pi)')
281+
);
282+
283+
test(
284+
'should preserve e',
285+
testValue('calc(e)', 'calc(e)')
286+
);
287+
288+
262289
test(
263290
'should reduce calc with newline characters',
264291
testValue('calc(\n1rem \n* 2 \n* 1.5)', '3rem')

0 commit comments

Comments
 (0)
Please sign in to comment.