File: //proc/1526/task/1922/cwd/zaklada/html/node_modules/reduce-css-calc/index.js
/**
 * Module dependencies
 */
var balanced = require("balanced-match")
var reduceFunctionCall = require("reduce-function-call")
var mexp = require("math-expression-evaluator")
/**
 * Constantes
 */
var MAX_STACK = 100 // should be enough for a single calc()...
var NESTED_CALC_RE = /(\+|\-|\*|\\|[^a-z]|)(\s*)(\()/g
/**
 * Global variables
 */
var stack
/**
 * Expose reduceCSSCalc plugin
 *
 * @type {Function}
 */
module.exports = reduceCSSCalc
/**
 * Reduce CSS calc() in a string, whenever it's possible
 *
 * @param {String} value css input
 */
function reduceCSSCalc(value, decimalPrecision) {
  stack = 0
  decimalPrecision = Math.pow(10, decimalPrecision === undefined ? 5 : decimalPrecision)
  // Allow calc() on multiple lines
  value = value.replace(/\n+/g, " ")
  /**
   * 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")
    }
    expression = evaluateNestedExpression(expression, call)
    var units = getUnitsInExpression(expression)
    // If the expression contains multiple units or CSS variables,
    // then let the expression be (i.e. browser calc())
    if (units.length > 1 || expression.indexOf("var(") > -1) {
      return functionIdentifier + "(" + expression + ")"
    }
    var unit = units[0] || ""
    if (unit === "%") {
      // Convert percentages to numbers, to handle expressions like: 50% * 50% (will become: 25%):
      // console.log(expression)
      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, "gi"), "")
    var result
    try {
      result = mexp.eval(toEvaluate)
    }
    catch (e) {
      return functionIdentifier + "(" + expression + ")"
    }
    // Transform back to a percentage result:
    if (unit === "%") {
      result *= 100
    }
    // adjust rounding shit
    // (0.1 * 0.2 === 0.020000000000000004)
    if (functionIdentifier.length || unit === "%") {
      result = Math.round(result * decimalPrecision) / decimalPrecision
    }
    // Add unit
    result += unit
    return result
  }
  /**
   * Evaluates nested expressions
   *
   * @param {String} expression
   * @returns {String}
   */
  function evaluateNestedExpression(expression, call) {
    // Remove the calc part from nested expressions to ensure
    // better browser compatibility
    expression = expression.replace(/((?:\-[a-z]+\-)?calc)/g, "")
    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
  }
  return reduceFunctionCall(value, /((?:\-[a-z]+\-)?calc)\(/, evaluateExpression)
}
/**
 * Checks what units are used in an expression
 *
 * @param {String} expression
 * @returns {Array}
 */
function getUnitsInExpression(expression) {
  var uniqueUnits = []
  var uniqueLowerCaseUnits = []
  var unitRegEx = /[\.0-9]([%a-z]+)/gi
  var matches = unitRegEx.exec(expression)
  while (matches) {
    if (!matches || !matches[1]) {
      continue
    }
    if (uniqueLowerCaseUnits.indexOf(matches[1].toLowerCase()) === -1) {
      uniqueUnits.push(matches[1])
      uniqueLowerCaseUnits.push(matches[1].toLowerCase())
    }
    matches = unitRegEx.exec(expression)
  }
  return uniqueUnits
}