@@ -9,6 +9,7 @@ var reduceFunctionCall = require("reduce-function-call")
9
9
*/
10
10
var MAX_STACK = 100 // should be enough for a single calc()...
11
11
var DECIMAL_PRECISION = 10000 // 5 decimals
12
+ var NESTED_CALC_RE = / ( \+ | \- | \* | \\ | [ ^ a - z ] | ) ( \s * ) ( \( ) / g
12
13
13
14
/**
14
15
* Global variables
@@ -37,9 +38,7 @@ function reduceCSSCalc(value) {
37
38
*
38
39
* @param {String } expression
39
40
* @returns {String }
40
- * @api private
41
41
*/
42
-
43
42
function evaluateExpression ( expression , functionIdentifier , call ) {
44
43
if ( stack ++ > MAX_STACK ) {
45
44
stack = 0
@@ -50,23 +49,7 @@ function evaluateExpression (expression, functionIdentifier, call) {
50
49
throw new Error ( functionIdentifier + "(): '" + call + "' must contain a non-whitespace string" )
51
50
}
52
51
53
- var balancedExpr = balanced ( "(" , ")" , expression )
54
- while ( balancedExpr ) {
55
- if ( balancedExpr . body === "" ) {
56
- throw new Error ( functionIdentifier + "(): '" + expression + "' must contain a non-whitespace string" )
57
- }
58
-
59
- var evaluated = evaluateExpression ( balancedExpr . body , functionIdentifier , call )
60
-
61
- // if result didn't change since the last try, we consider it won't change anymore
62
- if ( evaluated === balancedExpr . body ) {
63
- balancedExpr = false
64
- }
65
- else {
66
- expression = balancedExpr . pre + evaluated + balancedExpr . post
67
- balancedExpr = balanced ( "(" , ")" , expression )
68
- }
69
- }
52
+ expression = evaluateNestedExpression ( expression , call )
70
53
71
54
var units = getUnitsInExpression ( expression )
72
55
@@ -112,12 +95,41 @@ function evaluateExpression (expression, functionIdentifier, call) {
112
95
return result
113
96
}
114
97
98
+ /**
99
+ * Evaluates nested expressions
100
+ *
101
+ * @param {String } expression
102
+ * @returns {String }
103
+ */
104
+ function evaluateNestedExpression ( expression , call ) {
105
+ var evaluatedPart = ""
106
+ var nonEvaluatedPart = expression
107
+ var matches
108
+ while ( ( matches = NESTED_CALC_RE . exec ( nonEvaluatedPart ) ) ) {
109
+ if ( matches [ 0 ] . index > 0 ) {
110
+ evaluatedPart += nonEvaluatedPart . substring ( 0 , matches [ 0 ] . index )
111
+ }
112
+
113
+ var balancedExpr = balanced ( "(" , ")" , nonEvaluatedPart . substring ( [ 0 ] . index ) )
114
+ if ( balancedExpr . body === "" ) {
115
+ throw new Error ( "'" + expression + "' must contain a non-whitespace string" )
116
+ }
117
+
118
+ var evaluated = evaluateExpression ( balancedExpr . body , "" , call )
119
+
120
+ evaluatedPart += balancedExpr . pre + evaluated
121
+ nonEvaluatedPart = balancedExpr . post
122
+ }
123
+
124
+ return evaluatedPart + nonEvaluatedPart
125
+ }
126
+
127
+
115
128
/**
116
129
* Checks what units are used in an expression
117
130
*
118
131
* @param {String } expression
119
132
* @returns {Array }
120
- * @api private
121
133
*/
122
134
123
135
function getUnitsInExpression ( expression ) {
0 commit comments