1- /*
1+ /**
22 * Module dependencies
33 */
44var balanced = require ( "balanced-match" )
5+ var reduceFunctionCall = require ( "reduce-function-call" )
56
67/**
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
189 *
19- * @param {Array } expressions
20- * @param {Object } declaration
10+ * @type {Function }
2111 */
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
3713
3814/**
39- * Parses expressions in a value
15+ * Reduce CSS calc() in a string, whenever it's possible
4016 *
41- * @param {String } value
42- * @returns {Array }
43- * @api private
17+ * @param {String } value css input
4418 */
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 )
6821}
6922
7023/**
@@ -75,24 +28,34 @@ function getExpressions(value) {
7528 * @api private
7629 */
7730
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+ }
8135
8236 var balancedExpr = balanced ( "(" , ")" , expression )
83- if ( balancedExpr ) {
37+ while ( balancedExpr ) {
8438 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")
8640 }
8741
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+ }
8952 }
9053
9154 var units = getUnitsInExpression ( expression )
9255
9356 // If multiple units let the expression be (i.e. browser calc())
9457 if ( units . length > 1 ) {
95- return { resolved : false , value : expression }
58+ return functionIdentifier + "(" + expression + ")"
9659 }
9760
9861 var unit = units [ 0 ] || ""
@@ -112,7 +75,7 @@ function evaluateExpression (expression) {
11275 result = eval ( toEvaluate )
11376 }
11477 catch ( e ) {
115- return { resolved : false , value : expression }
78+ return functionIdentifier + "(" + expression + ")"
11679 }
11780
11881 // Transform back to a percentage result:
@@ -125,7 +88,7 @@ function evaluateExpression (expression) {
12588 result += unit
12689 }
12790
128- return { resolved : true , value : result }
91+ return result
12992}
13093
13194/**
0 commit comments