reduce-css-calc
Advanced tools
Comparing version
@@ -0,1 +1,5 @@ | ||
# 1.2.0 - 2014-11-24 | ||
* Decimal precision is now customisable as the `precision` option | ||
# 1.1.4 - 2014-11-12 | ||
@@ -2,0 +6,0 @@ |
150
index.js
@@ -11,3 +11,2 @@ /** | ||
var MAX_STACK = 100 // should be enough for a single calc()... | ||
var DECIMAL_PRECISION = 100000 // 5 decimals | ||
var NESTED_CALC_RE = /(\+|\-|\*|\\|[^a-z]|)(\s*)(\()/g | ||
@@ -32,99 +31,100 @@ | ||
*/ | ||
function reduceCSSCalc(value) { | ||
function reduceCSSCalc(value, decimalPrecision) { | ||
stack = 0 | ||
return reduceFunctionCall(value, /((?:\-[a-z]+\-)?calc)\(/, evaluateExpression) | ||
} | ||
decimalPrecision = Math.pow(10, decimalPrecision === undefined ? 5 : decimalPrecision) | ||
/** | ||
* Evaluates an expression | ||
* | ||
* @param {String} expression | ||
* @returns {String} | ||
*/ | ||
function evaluateExpression (expression, functionIdentifier, call) { | ||
if (stack++ > MAX_STACK) { | ||
stack = 0 | ||
throw new Error("Call stack overflow for " + call) | ||
} | ||
/** | ||
* Evaluates an expression | ||
* | ||
* @param {String} expression | ||
* @returns {String} | ||
*/ | ||
function evaluateExpression (expression, functionIdentifier, call) { | ||
if (stack++ > MAX_STACK) { | ||
stack = 0 | ||
throw new Error("Call stack overflow for " + call) | ||
} | ||
if (expression === "") { | ||
throw new Error(functionIdentifier + "(): '" + call + "' must contain a non-whitespace string") | ||
} | ||
if (expression === "") { | ||
throw new Error(functionIdentifier + "(): '" + call + "' must contain a non-whitespace string") | ||
} | ||
expression = evaluateNestedExpression(expression, call) | ||
expression = evaluateNestedExpression(expression, call) | ||
var units = getUnitsInExpression(expression) | ||
var units = getUnitsInExpression(expression) | ||
// If multiple units let the expression be (i.e. browser calc()) | ||
if (units.length > 1) { | ||
return functionIdentifier + "(" + expression + ")" | ||
} | ||
// If multiple units let the expression be (i.e. browser calc()) | ||
if (units.length > 1) { | ||
return functionIdentifier + "(" + expression + ")" | ||
} | ||
var unit = units[0] || "" | ||
var unit = units[0] || "" | ||
if (unit === "%") { | ||
// Convert percentages to numbers, to handle expressions like: 50% * 50% (will become: 25%): | ||
expression = expression.replace(/\b[0-9\.]+%/g, function(percent) { | ||
return parseFloat(percent.slice(0, -1)) * 0.01 | ||
}) | ||
} | ||
if (unit === "%") { | ||
// Convert percentages to numbers, to handle expressions like: 50% * 50% (will become: 25%): | ||
expression = expression.replace(/\b[0-9\.]+%/g, function(percent) { | ||
return parseFloat(percent.slice(0, -1)) * 0.01 | ||
}) | ||
} | ||
// Remove units in expression: | ||
var toEvaluate = expression.replace(new RegExp(unit, "g"), "") | ||
var result | ||
// Remove units in expression: | ||
var toEvaluate = expression.replace(new RegExp(unit, "g"), "") | ||
var result | ||
try { | ||
result = eval(toEvaluate) | ||
} | ||
catch (e) { | ||
return functionIdentifier + "(" + expression + ")" | ||
} | ||
try { | ||
result = eval(toEvaluate) | ||
} | ||
catch (e) { | ||
return functionIdentifier + "(" + expression + ")" | ||
} | ||
// Transform back to a percentage result: | ||
if (unit === "%") { | ||
result *= 100 | ||
} | ||
// Transform back to a percentage result: | ||
if (unit === "%") { | ||
result *= 100 | ||
} | ||
// adjust rounding shit | ||
// (0.1 * 0.2 === 0.020000000000000004) | ||
result = Math.round(result * DECIMAL_PRECISION) / DECIMAL_PRECISION | ||
// adjust rounding shit | ||
// (0.1 * 0.2 === 0.020000000000000004) | ||
result = Math.round(result * decimalPrecision) / decimalPrecision | ||
// We don't need units for zero values... | ||
if (result !== 0) { | ||
result += unit | ||
// We don't need units for zero values... | ||
if (result !== 0) { | ||
result += unit | ||
} | ||
return result | ||
} | ||
return result | ||
} | ||
/** | ||
* 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) | ||
} | ||
/** | ||
* 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 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 | ||
} | ||
var evaluated = evaluateExpression(balancedExpr.body, "", call) | ||
evaluatedPart += balancedExpr.pre + evaluated | ||
nonEvaluatedPart = balancedExpr.post | ||
return evaluatedPart + nonEvaluatedPart | ||
} | ||
return evaluatedPart + nonEvaluatedPart | ||
return reduceFunctionCall(value, /((?:\-[a-z]+\-)?calc)\(/, evaluateExpression) | ||
} | ||
/** | ||
@@ -131,0 +131,0 @@ * Checks what units are used in an expression |
{ | ||
"name": "reduce-css-calc", | ||
"version": "1.1.4", | ||
"version": "1.2.0", | ||
"description": "Reduce CSS calc() function to the maximum", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
# reduce-css-calc [](https://travis-ci.org/MoOx/reduce-css-calc) | ||
Reduce CSS calc() function to the maximum. | ||
> Reduce CSS calc() function to the maximum. | ||
@@ -9,4 +9,4 @@ Particularly useful for packages like [rework-calc](https://github.com/reworkcss/rework-calc) or [postcss-calc](https://github.com/postcss/postcss-calc). | ||
```bash | ||
npm install reduce-css-calc | ||
```console | ||
$ npm install reduce-css-calc | ||
``` | ||
@@ -16,2 +16,4 @@ | ||
### `var reducedString = reduceCSSCalc(string, precision)` | ||
```javascript | ||
@@ -26,2 +28,8 @@ var reduceCSSCalc = require('reduce-css-calc') | ||
reduceCSSCalc("calc(1/3)") | ||
// 0.33333 | ||
reduceCSSCalc("calc(1/3)", 10) | ||
// 0.3333333333 | ||
reduceCSSCalc("calc(3rem * 2 - 1rem)") | ||
@@ -58,7 +66,7 @@ // 5rem | ||
```bash | ||
git clone https://github.com/MoOx/reduce-css-calc.git | ||
git checkout -b patch-1 | ||
npm install | ||
npm test | ||
```console | ||
$ git clone https://github.com/MoOx/reduce-css-calc.git | ||
$ git checkout -b patch-1 | ||
$ npm install | ||
$ npm test | ||
``` | ||
@@ -65,0 +73,0 @@ |
8015
6.09%73
12.31%