1
- /*
1
+ /**
2
2
* Module dependencies
3
3
*/
4
4
var balanced = require ( "balanced-match" )
5
+ var reduceFunctionCall = require ( "reduce-function-call" )
5
6
6
7
/**
7
- * Constantes
8
- */
9
- var CALC_FUNC_IDENTIFIER = "calc"
10
- var EXPRESSION_OPT_VENDOR_PREFIX = "(\\-[a-z]+\\-)?"
11
- var EXPRESSION_METHOD_REGEXP = EXPRESSION_OPT_VENDOR_PREFIX + CALC_FUNC_IDENTIFIER
12
- var EXPRESSION_REGEXP = "\\b" + EXPRESSION_METHOD_REGEXP + "\\("
13
-
14
- module . exports = resolveValue
15
-
16
- /**
17
- * Walkthrough all expressions, evaluate them and insert them into the declaration
8
+ * Expose reduceCssCalc plugin
18
9
*
19
- * @param {Array } expressions
20
- * @param {Object } declaration
10
+ * @type {Function }
21
11
*/
22
-
23
- function resolveValue ( value ) {
24
- getExpressions ( value ) . forEach ( function ( expression ) {
25
- var result = evaluateExpression ( expression . body )
26
-
27
- value = value . replace (
28
- expression . fn + "(" + expression . body + ")" ,
29
- result . resolved ?
30
- result . value :
31
- expression . fn + "(" + result . value + ")"
32
- )
33
- } )
34
-
35
- return value
36
- }
12
+ module . exports = reduceCssCalc
37
13
38
14
/**
39
- * Parses expressions in a value
15
+ * Reduce CSS calc() in a string, whenever it's possible
40
16
*
41
- * @param {String } value
42
- * @returns {Array }
43
- * @api private
17
+ * @param {String } value css input
44
18
*/
45
-
46
- function getExpressions ( value ) {
47
- var expressions = [ ]
48
- var fnRE = new RegExp ( EXPRESSION_METHOD_REGEXP )
49
- do {
50
- var searchMatch = fnRE . exec ( value )
51
- var fn = searchMatch [ 0 ]
52
- var calcStartIndex = searchMatch . index
53
- var calcRef = balanced ( "(" , ")" , value . substring ( calcStartIndex ) )
54
-
55
- if ( ! calcRef ) {
56
- throw new SyntaxError ( "calc(): missing closing ')' in the value '" + value + "'" )
57
- }
58
- if ( calcRef . body === "" ) {
59
- throw new Error ( "calc(): calc() must contain a non-whitespace string" )
60
- }
61
-
62
- expressions . push ( { fn : fn , body : calcRef . body } )
63
- value = calcRef . post
64
- }
65
- while ( fnRE . test ( value ) )
66
-
67
- return expressions
19
+ function reduceCssCalc ( value ) {
20
+ return reduceFunctionCall ( value , / ( (?: \- [ a - z ] + \- ) ? c a l c ) \( / , evaluateExpression )
68
21
}
69
22
70
23
/**
@@ -75,24 +28,34 @@ function getExpressions(value) {
75
28
* @api private
76
29
*/
77
30
78
- function evaluateExpression ( expression ) {
79
- // Remove method names for possible nested expressions:
80
- expression = expression . replace ( new RegExp ( EXPRESSION_REGEXP , "g" ) , "(" )
31
+ function evaluateExpression ( expression , functionIdentifier , call ) {
32
+ if ( expression === "" ) {
33
+ throw new Error ( functionIdentifier + "(): '" + call + "' must contain a non-whitespace string" )
34
+ }
81
35
82
36
var balancedExpr = balanced ( "(" , ")" , expression )
83
- if ( balancedExpr ) {
37
+ while ( balancedExpr ) {
84
38
if ( balancedExpr . body === "" ) {
85
- throw new Error ( "calc (): () must contain a non-whitespace string")
39
+ throw new Error ( functionIdentifier + " (): '" + expression + "' must contain a non-whitespace string")
86
40
}
87
41
88
- expression = balancedExpr . pre + evaluateExpression ( balancedExpr . body ) . value + balancedExpr . post
42
+ var evaluated = evaluateExpression ( balancedExpr . body , functionIdentifier , call )
43
+
44
+ // if result didn't change since the last try, we consider it won't change anymore
45
+ if ( evaluated === balancedExpr . body ) {
46
+ balancedExpr = false
47
+ }
48
+ else {
49
+ expression = balancedExpr . pre + evaluated + balancedExpr . post
50
+ balancedExpr = balanced ( "(" , ")" , expression )
51
+ }
89
52
}
90
53
91
54
var units = getUnitsInExpression ( expression )
92
55
93
56
// If multiple units let the expression be (i.e. browser calc())
94
57
if ( units . length > 1 ) {
95
- return { resolved : false , value : expression }
58
+ return functionIdentifier + "(" + expression + ")"
96
59
}
97
60
98
61
var unit = units [ 0 ] || ""
@@ -112,7 +75,7 @@ function evaluateExpression (expression) {
112
75
result = eval ( toEvaluate )
113
76
}
114
77
catch ( e ) {
115
- return { resolved : false , value : expression }
78
+ return functionIdentifier + "(" + expression + ")"
116
79
}
117
80
118
81
// Transform back to a percentage result:
@@ -125,7 +88,7 @@ function evaluateExpression (expression) {
125
88
result += unit
126
89
}
127
90
128
- return { resolved : true , value : result }
91
+ return result
129
92
}
130
93
131
94
/**
0 commit comments