@@ -8,7 +8,6 @@ var reduceFunctionCall = require("reduce-function-call")
8
8
* Constantes
9
9
*/
10
10
var MAX_STACK = 100 // should be enough for a single calc()...
11
- var DECIMAL_PRECISION = 100000 // 5 decimals
12
11
var NESTED_CALC_RE = / ( \+ | \- | \* | \\ | [ ^ a - z ] | ) ( \s * ) ( \( ) / g
13
12
14
13
/**
@@ -28,103 +27,104 @@ module.exports = reduceCSSCalc
28
27
*
29
28
* @param {String } value css input
30
29
*/
31
- function reduceCSSCalc ( value ) {
30
+ function reduceCSSCalc ( value , decimalPrecision ) {
32
31
stack = 0
33
- return reduceFunctionCall ( value , / ( (?: \- [ a - z ] + \- ) ? c a l c ) \( / , evaluateExpression )
34
- }
32
+ decimalPrecision = Math . pow ( 10 , decimalPrecision === undefined ? 5 : decimalPrecision )
33
+
34
+ /**
35
+ * Evaluates an expression
36
+ *
37
+ * @param {String } expression
38
+ * @returns {String }
39
+ */
40
+ function evaluateExpression ( expression , functionIdentifier , call ) {
41
+ if ( stack ++ > MAX_STACK ) {
42
+ stack = 0
43
+ throw new Error ( "Call stack overflow for " + call )
44
+ }
35
45
36
- /**
37
- * Evaluates an expression
38
- *
39
- * @param {String } expression
40
- * @returns {String }
41
- */
42
- function evaluateExpression ( expression , functionIdentifier , call ) {
43
- if ( stack ++ > MAX_STACK ) {
44
- stack = 0
45
- throw new Error ( "Call stack overflow for " + call )
46
- }
46
+ if ( expression === "" ) {
47
+ throw new Error ( functionIdentifier + "(): '" + call + "' must contain a non-whitespace string" )
48
+ }
47
49
48
- if ( expression === "" ) {
49
- throw new Error ( functionIdentifier + "(): '" + call + "' must contain a non-whitespace string" )
50
- }
50
+ expression = evaluateNestedExpression ( expression , call )
51
51
52
- expression = evaluateNestedExpression ( expression , call )
52
+ var units = getUnitsInExpression ( expression )
53
53
54
- var units = getUnitsInExpression ( expression )
54
+ // If multiple units let the expression be (i.e. browser calc())
55
+ if ( units . length > 1 ) {
56
+ return functionIdentifier + "(" + expression + ")"
57
+ }
55
58
56
- // If multiple units let the expression be (i.e. browser calc())
57
- if ( units . length > 1 ) {
58
- return functionIdentifier + "(" + expression + ")"
59
- }
59
+ var unit = units [ 0 ] || ""
60
60
61
- var unit = units [ 0 ] || ""
61
+ if ( unit === "%" ) {
62
+ // Convert percentages to numbers, to handle expressions like: 50% * 50% (will become: 25%):
63
+ expression = expression . replace ( / \b [ 0 - 9 \. ] + % / g, function ( percent ) {
64
+ return parseFloat ( percent . slice ( 0 , - 1 ) ) * 0.01
65
+ } )
66
+ }
62
67
63
- if ( unit === "%" ) {
64
- // Convert percentages to numbers, to handle expressions like: 50% * 50% (will become: 25%):
65
- expression = expression . replace ( / \b [ 0 - 9 \. ] + % / g, function ( percent ) {
66
- return parseFloat ( percent . slice ( 0 , - 1 ) ) * 0.01
67
- } )
68
- }
68
+ // Remove units in expression:
69
+ var toEvaluate = expression . replace ( new RegExp ( unit , "g" ) , "" )
70
+ var result
69
71
70
- // Remove units in expression:
71
- var toEvaluate = expression . replace ( new RegExp ( unit , "g" ) , "" )
72
- var result
72
+ try {
73
+ result = eval ( toEvaluate )
74
+ }
75
+ catch ( e ) {
76
+ return functionIdentifier + "(" + expression + ")"
77
+ }
73
78
74
- try {
75
- result = eval ( toEvaluate )
76
- }
77
- catch ( e ) {
78
- return functionIdentifier + "(" + expression + ")"
79
- }
79
+ // Transform back to a percentage result:
80
+ if ( unit === "%" ) {
81
+ result *= 100
82
+ }
80
83
81
- // Transform back to a percentage result:
82
- if ( unit === "%" ) {
83
- result *= 100
84
- }
84
+ // adjust rounding shit
85
+ // (0.1 * 0.2 === 0.020000000000000004)
86
+ result = Math . round ( result * decimalPrecision ) / decimalPrecision
85
87
86
- // adjust rounding shit
87
- // (0.1 * 0.2 === 0.020000000000000004)
88
- result = Math . round ( result * DECIMAL_PRECISION ) / DECIMAL_PRECISION
88
+ // We don't need units for zero values...
89
+ if ( result !== 0 ) {
90
+ result += unit
91
+ }
89
92
90
- // We don't need units for zero values...
91
- if ( result !== 0 ) {
92
- result += unit
93
+ return result
93
94
}
94
95
95
- return result
96
- }
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" )
96
+ /**
97
+ * Evaluates nested expressions
98
+ *
99
+ * @param {String } expression
100
+ * @returns {String }
101
+ */
102
+ function evaluateNestedExpression ( expression , call ) {
103
+ var evaluatedPart = ""
104
+ var nonEvaluatedPart = expression
105
+ var matches
106
+ while ( ( matches = NESTED_CALC_RE . exec ( nonEvaluatedPart ) ) ) {
107
+ if ( matches [ 0 ] . index > 0 ) {
108
+ evaluatedPart += nonEvaluatedPart . substring ( 0 , matches [ 0 ] . index )
109
+ }
110
+
111
+ var balancedExpr = balanced ( "(" , ")" , nonEvaluatedPart . substring ( [ 0 ] . index ) )
112
+ if ( balancedExpr . body === "" ) {
113
+ throw new Error ( "'" + expression + "' must contain a non-whitespace string" )
114
+ }
115
+
116
+ var evaluated = evaluateExpression ( balancedExpr . body , "" , call )
117
+
118
+ evaluatedPart += balancedExpr . pre + evaluated
119
+ nonEvaluatedPart = balancedExpr . post
116
120
}
117
121
118
- var evaluated = evaluateExpression ( balancedExpr . body , "" , call )
119
-
120
- evaluatedPart += balancedExpr . pre + evaluated
121
- nonEvaluatedPart = balancedExpr . post
122
+ return evaluatedPart + nonEvaluatedPart
122
123
}
123
124
124
- return evaluatedPart + nonEvaluatedPart
125
+ return reduceFunctionCall ( value , / ( (?: \- [ a - z ] + \- ) ? c a l c ) \( / , evaluateExpression )
125
126
}
126
127
127
-
128
128
/**
129
129
* Checks what units are used in an expression
130
130
*
0 commit comments