reduce-css-calc
Advanced tools
Comparing version
@@ -0,1 +1,7 @@ | ||
# 1.1.2 - 2014-08-10 | ||
* Prevent infinite loop by adding a `Call stack overflow` | ||
* Correctly ignore unrecognized values (safer evaluation for nested expressions, see [postcss/postcss-calc#2](https://github.com/postcss/postcss-calc/issues/2)) | ||
* Handle rounding issues (eg: 10% * 20% now give 2%, not 2.0000000000000004%) | ||
# 1.1.1 - 2014-08-06 | ||
@@ -2,0 +8,0 @@ |
73
index.js
@@ -8,2 +8,14 @@ /** | ||
/** | ||
* Constantes | ||
*/ | ||
var MAX_STACK = 100 // should be enough for a single calc()... | ||
var DECIMAL_PRECISION = 10000 // 5 decimals | ||
var NESTED_CALC_RE = /(\+|\-|\*|\\|[^a-z]|)(\s*)(\()/g | ||
/** | ||
* Global variables | ||
*/ | ||
var stack | ||
/** | ||
* Expose reduceCSSCalc plugin | ||
@@ -21,2 +33,3 @@ * | ||
function reduceCSSCalc(value) { | ||
stack = 0 | ||
return reduceFunctionCall(value, /((?:\-[a-z]+\-)?calc)\(/, evaluateExpression) | ||
@@ -30,6 +43,9 @@ } | ||
* @returns {String} | ||
* @api private | ||
*/ | ||
function evaluateExpression (expression, functionIdentifier, call) { | ||
if (stack++ > MAX_STACK) { | ||
stack = 0 | ||
throw new Error("Call stack overflow for " + call) | ||
} | ||
function evaluateExpression (expression, functionIdentifier, call) { | ||
if (expression === "") { | ||
@@ -39,20 +55,4 @@ throw new Error(functionIdentifier + "(): '" + call + "' must contain a non-whitespace string") | ||
var balancedExpr = balanced("(", ")", expression) | ||
while (balancedExpr) { | ||
if (balancedExpr.body === "") { | ||
throw new Error(functionIdentifier + "(): '" + expression + "' must contain a non-whitespace string") | ||
} | ||
expression = evaluateNestedExpression(expression, call) | ||
var evaluated = evaluateExpression(balancedExpr.body, functionIdentifier, call) | ||
// if result didn't change since the last try, we consider it won't change anymore | ||
if (evaluated === balancedExpr.body) { | ||
balancedExpr = false | ||
} | ||
else { | ||
expression = balancedExpr.pre + evaluated + balancedExpr.post | ||
balancedExpr = balanced("(", ")", expression) | ||
} | ||
} | ||
var units = getUnitsInExpression(expression) | ||
@@ -88,2 +88,6 @@ | ||
result *= 100 | ||
// adjust rounding shit | ||
// (0.1 * 0.2 === 0.020000000000000004) | ||
result = Math.round(result * DECIMAL_PRECISION) / DECIMAL_PRECISION | ||
} | ||
@@ -100,2 +104,32 @@ | ||
/** | ||
* Evaluates nested expressions | ||
* | ||
* @param {String} expression | ||
* @returns {String} | ||
*/ | ||
function evaluateNestedExpression(expression, call) { | ||
var evaluatedPart = "" | ||
var nonEvaluatedPart = expression | ||
var matches | ||
while ((matches = NESTED_CALC_RE.exec(nonEvaluatedPart))) { | ||
if (matches[0].index > 0) { | ||
evaluatedPart += nonEvaluatedPart.substring(0, matches[0].index) | ||
} | ||
var balancedExpr = balanced("(", ")", nonEvaluatedPart.substring([0].index)) | ||
if (balancedExpr.body === "") { | ||
throw new Error("'" + expression + "' must contain a non-whitespace string") | ||
} | ||
var evaluated = evaluateExpression(balancedExpr.body, "", call) | ||
evaluatedPart += balancedExpr.pre + evaluated | ||
nonEvaluatedPart = balancedExpr.post | ||
} | ||
return evaluatedPart + nonEvaluatedPart | ||
} | ||
/** | ||
* Checks what units are used in an expression | ||
@@ -105,3 +139,2 @@ * | ||
* @returns {Array} | ||
* @api private | ||
*/ | ||
@@ -108,0 +141,0 @@ |
{ | ||
"name": "reduce-css-calc", | ||
"version": "1.1.1", | ||
"version": "1.1.2", | ||
"description": "Reduce CSS calc() function to the maximum", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
7562
15.68%124
26.53%