Uname: Linux webm016.cluster127.gra.hosting.ovh.net 5.15.167-ovh-vps-grsec-zfs-classid #1 SMP Tue Sep 17 08:14:20 UTC 2024 x86_64
Software: Apache
PHP version: 7.4.33 [ PHP INFO ] PHP os: Linux
Server Ip: 54.36.31.145
Your Ip: 216.73.216.182
User: homesquasz (91404) | Group: users (100)
Safe Mode: OFF
Disable Function:
_dyuweyrj4,_dyuweyrj4r,dl

name : index.js
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports["default"] = findOperators;
exports.mathOperatorCharType = mathOperatorCharType;

/**
 * Processes a string and finds Sass operators in it
 *
 * @param {Object} args - Named arguments object
 * @param {String} args.string - the input string
 * @param {Number} args.globalIndex - the position of args.string from the start of the line
 * @param {Boolean} args.isAfterColon - pass "true" if the string is
 *    a variable value, a mixin/function parameter default.
 *    In such cases + and / tend to be operations more often
 * @param {Function} args.callback - will be called on every instance of
 *    an operator. Accepts parameters:
 *    • string - the default source string
 *    • globalIndex - the string's position in the outer input
 *    • startIndex - index in string, where the operator starts
 *    • endIndex - index in string, where the operator ends (for `==`, etc.)
 *
 * @return {Array} array of { symbol, globalIndex, startIndex, endIndex }
 *    for each operator found within a string
 */
function findOperators(_ref) {
  var string = _ref.string,
      globalIndex = _ref.globalIndex,
      isAfterColon = _ref.isAfterColon,
      callback = _ref.callback;
  var mathOperators = ["+", "/", "-", "*", "%"]; // A stack of modes activated for the current char: string, interpolation
  // Calculations inside strings are not processed, so spaces are not linted

  var modesEntered = [{
    mode: "normal",
    isCalculationEnabled: true,
    character: null
  }];
  var result = [];
  var lastModeIndex = 0;

  for (var i = 0; i < string.length; i++) {
    var character = string[i];
    var substringStartingWithIndex = string.substring(i);
    var lastMode = modesEntered[lastModeIndex]; // If entering/exiting a string

    if (character === '"' || character === "'") {
      if (lastMode && lastMode.isCalculationEnabled === true) {
        modesEntered.push({
          mode: "string",
          isCalculationEnabled: false,
          character: character
        });
        lastModeIndex++;
      } else if (lastMode && lastMode.mode === "string" && lastMode.character === character && string[i - 1] !== "\\") {
        modesEntered.pop();
        lastModeIndex--;
      }
    } // If entering/exiting interpolation (may be inside a string)
    // Comparing with length-2 because `#{` at the very end doesnt matter


    if (character === "#" && i + 1 < string.length - 2 && string[i + 1] === "{") {
      modesEntered.push({
        mode: "interpolation",
        isCalculationEnabled: true
      });
      lastModeIndex++;
    } else if (character === "}") {
      modesEntered.pop();
      lastModeIndex--;
    } // Don't lint if inside a string


    if (lastMode && lastMode.isCalculationEnabled === false) {
      continue;
    } // If it's a math operator


    if (mathOperators.includes(character) && mathOperatorCharType(string, i, isAfterColon) === "op" || // or is "<" or ">"
    substringStartingWithIndex.search(/^[<>]([^=]|$)/) !== -1) {
      result.push({
        symbol: string[i],
        globalIndex: globalIndex,
        startIndex: i,
        endIndex: i
      });

      if (callback) {
        callback(string, globalIndex, i, i);
      }
    } // "<=", ">=", "!=", "=="


    if (substringStartingWithIndex.search(/^[><=!]=/) !== -1) {
      result.push({
        symbol: string[i],
        globalIndex: globalIndex,
        startIndex: i,
        endIndex: i + 1
      });

      if (callback) {
        callback(string, globalIndex, i, i + 1);
      }
    }
  } // result.length > 0 && console.log(string, result)


  return result;
}
/**
 * Checks if a character is an operator, a sign (+ or -), or part of a string
 *
 * @param {String} string - the source string
 * @param {Number} index - the index of the character in string to check
 * @param {Boolean} isAfterColon - if the value string a variable
 *    value, a mixin/function parameter default. In such cases + and / tend
 *    to be operations more often
 * @return {String|false}
 *    • "op", if the character is a operator in a math/string operation
 *    • "sign" if it is a + or - before a numeric,
 *    • "char" if it is a part of a string,
 *    • false - if it is none from above (most likely an error)
 */


function mathOperatorCharType(string, index, isAfterColon) {
  // !Checking here to prevent unnecessary calculations and deep recursion
  // when calling isPrecedingOperator()
  if (!["+", "/", "-", "*", "%"].includes(string[index])) {
    return "char";
  }

  var character = string[index];
  var prevCharacter = string[index - 1];

  if (prevCharacter !== "\\") {
    // ---- Processing + characters
    if (character === "+") {
      return checkPlus(string, index, isAfterColon);
    } // ---- Processing - characters


    if (character === "-") {
      return checkMinus(string, index);
    } // ---- Processing * character


    if (character === "*") {
      return "op";
    } // ---- Processing % character


    if (character === "%") {
      return checkPercent(string, index);
    } // ---- Processing / character
    // https://sass-lang.com/documentation/operators/numeric#slash-separated-values


    if (character === "/") {
      return checkSlash(string, index, isAfterColon);
    }
  }

  return "char";
} // --------------------------------------------------------------------------
// Functions for checking particular characters (+, -, /)
// --------------------------------------------------------------------------

/**
 * Checks the specified `+` char type: operator, sign (+ or -), part of string
 *
 * @param {String} string - the source string
 * @param {Number} index - the index of the character in string to check
 * @param {Boolean} isAftercolon - if the value string a variable
 *    value, a mixin/function parameter default. In such cases + is always an
 *    operator if surrounded by numbers/values with units
 * @return {String|false}
 *    • "op", if the character is a operator in a math/string operation
 *    • "sign" if it is a sign before a positive number,
 *    • false - if it is none from above (most likely an error)
 */


function checkPlus(string, index, isAftercolon) {
  var before = string.substring(0, index);
  var after = string.substring(index + 1); // If the character is at the beginning of the input

  var isAtStart_ = isAtStart(string, index); // If the character is at the end of the input

  var isAtEnd_ = isAtEnd(string, index);
  var isWhitespaceBefore = before.search(/\s$/) !== -1;
  var isWhitespaceAfter = after.search(/^\s/) !== -1;
  var isValueWithUnitAfter_ = isValueWithUnitAfter(after);
  var isNumberAfter_ = isNumberAfter(after);
  var isInterpolationAfter_ = isInterpolationAfter(after); // The early check above helps prevent deep recursion here

  var isPrecedingOperator_ = isPrecedingOperator(string, index);

  if (isAtStart_) {
    // console.log("+, `+<sth>` or `+ <sth>`")
    return "sign";
  } // E.g. `1+1`, `string+#fff`


  if (!isAtStart_ && !isWhitespaceBefore && !isAtEnd_ && !isWhitespaceAfter) {
    // E.g. `1-+1`
    if (isPrecedingOperator_) {
      // console.log('1+1')
      return "sign";
    } // console.log("+, no spaces")


    return "op";
  } // e.g. `something +something`


  if (!isAtEnd_ && !isWhitespaceAfter) {
    // e.g. `+something`, ` ... , +something`, etc.
    if (isNoOperandBefore(string, index)) {
      // console.log("+, nothing before")
      return "sign";
    } // e.g. `sth +10px`, `sth +1`


    if (isValueWithUnitAfter_.is && !isValueWithUnitAfter_.opsBetween || isNumberAfter_.is && !isNumberAfter_.opsBetween) {
      if (isAftercolon === true) {
        // console.log(": 10px +1")
        return "op";
      } // e.g. `(sth +10px)`, `fun(sth +1)`


      if (isInsideParens(string, index) || isInsideFunctionCall(string, index).is) {
        // console.log("+10px or +1, inside function or parens")
        return "op";
      } // e.g. `#{10px +1}`


      if (isInsideInterpolation(string, index)) {
        // console.log('+, #{10px +1}')
        return "op";
      } // console.log('+, default')


      return "sign";
    } // e.g. `sth +#fff`, `sth +string`, `sth +#{...}`, `sth +$var`


    if (isStringAfter(after) || isHexColorAfter(after) || after[0] === "$" || isInterpolationAfter_.is && !isInterpolationAfter_.opsBefore) {
      // e.g. `sth+ +string`
      if (isPrecedingOperator_) {
        // console.log("+10px or +1, before is an operator")
        return "sign";
      } // console.log("+#000, +string, +#{sth}, +$var")


      return "op";
    } // console.log('sth +sth, default')


    return "op";
  } // If the + is after a value, e.g. `$var+`


  if (!isAtStart_ && !isWhitespaceBefore) {
    // It is always an operator. Prior to Sass 4, `#{...}+` was differernt,
    // but that's not logical and had been fixed.
    // console.log('1+ sth')
    return "op";
  } // If it has whitespaces on both sides
  // console.log('sth + sth')


  return "op";
}
/**
 * Checks the specified `-` character: operator, sign (+ or -), part of string
 *
 * @param {String} string - the source string
 * @param {Number} index - the index of the character in string to check
 * @return {String|false}
 *    • "op", if the character is a operator in a math/string operation
 *    • "sign" if it is a sign before a negative number,
 *    • "char" if it is a part of a string or identifier,
 *    • false - if it is none from above (most likely an error)
 */


function checkMinus(string, index) {
  var before = string.substring(0, index);
  var after = string.substring(index + 1); // If the character is at the beginning of the input

  var isAtStart_ = isAtStart(string, index); // If the character is at the end of the input

  var isAtEnd_ = isAtEnd(string, index);
  var isWhitespaceBefore = before.search(/\s$/) !== -1;
  var isWhitespaceAfter = after.search(/^\s/) !== -1;
  var isValueWithUnitAfter_ = isValueWithUnitAfter(after);
  var isValueWithUnitBefore_ = isValueWithUnitBefore(before);
  var isNumberAfter_ = isNumberAfter(after);
  var isNumberBefore_ = isNumberBefore(before);
  var isInterpolationAfter_ = isInterpolationAfter(after);
  var isParensAfter_ = isParensAfter(after);
  var isParensBefore_ = isParensBefore(before); // The early check above helps prevent deep recursion here

  var isPrecedingOperator_ = isPrecedingOperator(string, index);
  var isInsideFunctionCall_ = isInsideFunctionCall(string, index);

  if (isAtStart_) {
    // console.log("-, -<sth> or - <sth>")
    return "sign";
  } // `10 -    11`


  if (!isAtEnd_ && !isAtStart_ && isWhitespaceBefore && isWhitespaceAfter) {
    // console.log("-, Op: 10px -  10px")
    return "op";
  } // e.g. `something -10px`


  if (!isAtEnd_ && !isAtStart_ && isWhitespaceBefore && !isWhitespaceAfter) {
    if (isParensAfter_.is && !isParensAfter_.opsBefore) {
      // console.log("-, Op: <sth> -(...)")
      return "op";
    } // e.g. `#{10px -1}`, `#{math.acos(-0.5)}`


    if (isInsideInterpolation(string, index)) {
      if (isInsideFunctionCall_.is && (isValueWithUnitAfter_.is && !isValueWithUnitAfter_.opsBetween || isNumberAfter_.is && !isNumberAfter_.opsBetween)) {
        return "sign";
      }

      return "op";
    } // e.g. `sth -1px`, `sth -1`.
    // Always a sign, even inside parens/function args


    if (isValueWithUnitAfter_.is && !isValueWithUnitAfter_.opsBetween || isNumberAfter_.is && !isNumberAfter_.opsBetween) {
      // console.log("-, sign: -1px or -1")
      return "sign";
    } // e.g. `sth --1`, `sth +-2px`


    if (isValueWithUnitAfter_.is && isValueWithUnitAfter_.opsBetween || isNumberAfter_.is && isNumberAfter_.opsBetween) {
      // console.log("-, op: --1px or --1")
      return "op";
    } // `<sth> -string`, `<sth> -#{...}`


    if (isStringAfter(after) || isInterpolationAfter_.is && !isInterpolationAfter_.opsBefore) {
      // console.log("-, char: -#{...}")
      return "char";
    } // e.g. `#0af -#f0a`, and edge-cases can take a hike


    if (isHexColorAfter(after) && isHexColorBefore(before.trim())) {
      // console.log("-, op: #fff-, -#fff")
      return "op";
    } // If the - is before a variable, than it's most likely an operator


    if (after[0] === "$") {
      if (isPrecedingOperator_) {
        // console.log("-, sign: -$var, another operator before")
        return "sign";
      } // console.log("-, op: -$var, NO other operator before")


      return "op";
    } // By default let's make it an sign for now
    // console.log('-, sign: default in <sth> -<sth>')


    return "sign";
  } // No whitespace before,
  // e.g. `10x- something`


  if (!isAtEnd_ && !isAtStart_ && !isWhitespaceBefore && isWhitespaceAfter) {
    if (isParensBefore_) {
      // console.log('-, op: `(...)- <sth>`')
      return "op";
    } // e.g. `#{10px- 1}`


    if (isInsideInterpolation(string, index)) {
      return "op";
    }

    if (isNumberBefore(before) || isHexColorBefore(before)) {
      // console.log('`-, op: 10- <sth>, #aff- <sth>`')
      return "op";
    } // console.log('-, char: default in <sth>- <sth>')


    return "char";
  } // NO Whitespace,
  // e.g. `10px-1`


  if (!isAtEnd_ && !isAtStart_ && !isWhitespaceBefore && !isWhitespaceAfter) {
    // console.log('no spaces')
    // `<something>-1`, `<something>-10px`
    if (isValueWithUnitAfter_.is && !isValueWithUnitAfter_.opsBetween || isNumberAfter_.is && !isNumberAfter_.opsBetween) {
      // `10px-1`, `1-10px`, `1-1`, `1x-1x`
      if (isValueWithUnitBefore_ || isNumberBefore_) {
        // console.log("-, op: 1-10px")
        return "op";
      } // The - could be a "sign" here, but for now "char" does the job

    } // `1-$var`


    if (isNumberBefore_ && after[0] === "$") {
      // console.log("-, op: 1-$var")
      return "op";
    } // `fn()-10px`


    if (isFunctionBefore(before) && (isNumberAfter_.is && !isNumberAfter_.opsBetween || isValueWithUnitAfter_.is && !isValueWithUnitAfter_.opsBetween)) {
      // console.log("-, op: fn()-10px")
      return "op";
    }
  } // And in all the other cases it's a characher inside a string
  // console.log("-, default: char")


  return "char";
}
/**
 * Checks the specified `/` character: operator, sign (+ or -), part of string
 *
 * @param {String} string - the source string
 * @param {Number} index - the index of the character in string to check
 * @param {Boolean} isAfterColon - if the value string a variable
 *    value, a mixin/function parameter default. In such cases / is always an
 *    operator if surrounded by numbers/values with units
 * @return {String|false}
 *    • "op", if the character is a operator in a math/string operation
 *    • "char" if it gets compiled as-is, e.g. `font: 10px/1.2;`,
 *    • false - if it is none from above (most likely an error)
 */


function checkSlash(string, index, isAfterColon) {
  // Trimming these, as spaces before/after a slash don't matter
  var before = string.substring(0, index).trim();
  var after = string.substring(index + 1).trim();
  var isValueWithUnitAfter_ = isValueWithUnitAfter(after);
  var isValueWithUnitBefore_ = isValueWithUnitBefore(before);
  var isNumberAfter_ = isNumberAfter(after);
  var isNumberBefore_ = isNumberBefore(before);
  var isParensAfter_ = isParensAfter(after);
  var isParensBefore_ = isParensBefore(before); // FIRST OFF. Interpolation on any of the sides is a NO-GO for division op

  if (isInterpolationBefore(before).is || isInterpolationAfter(after).is) {
    // console.log("/, interpolation")
    return "char";
  } // having a dot before propbably means a relative path.
  // e.g. url(../../image.png)


  if (isDotBefore(before)) {
    return "char";
  } // e.g. `(1px/1)`, `fn(7 / 15)`, but not `url(8/11)`


  var isInsideFn = isInsideFunctionCall(string, index);

  if (isInsideFn.is && isInsideFn.fn === "url" && isProtocolBefore(before)) {
    return "char";
  } // e.g. `10px/normal`


  if (isStringBefore(before).is || isStringAfter(after)) {
    // console.log("/, string")
    return "char";
  } // For all other value options (numbers, value+unit, hex color)
  // `$var/1`, `#fff/-$var`
  // Here we don't care if there is a sign before the var


  if (isVariableBefore(before) || isVariableAfter(after).is) {
    // console.log("/, variable")
    return "op";
  }

  if (isFunctionBefore(before) || isFunctionAfter(after).is) {
    // console.log("/, function as operand")
    return "op";
  }

  if (isParensBefore_ || isParensAfter_.is) {
    // console.log("/, function as operand")
    return "op";
  } // `$var: 10px/2; // 5px`


  if (isAfterColon === true && (isValueWithUnitAfter_.is || isNumberAfter_.is) && (isValueWithUnitBefore_ || isNumberBefore_)) {
    return "op";
  } // Quick check of the following operator symbol - if it is a math operator


  if ( // +, *, % count as operators unless after interpolation or at the start
  before.search(/[^{,(}\s]\s*[+*%]\s*[^(){},]+$/) !== -1 || // We consider minus as op only if surrounded by whitespaces (` - `);
  before.search(/[^{,(}\s]\s+-\s+[^(){},]+$/) !== -1 || // `10/2 * 3`, `10/2 % 3`, with or without spaces
  after.search(/^[^(){},]+[*%]/) !== -1 || // `10px/2px+1`, `10px/2px+ 1`
  after.search(/^[^(){},\s]+[+]/) !== -1 || // Anything but `10px/2px +1`, `10px/2px +1px`
  after.search(/^[^(){},\s]+\s+(\+\D)/) !== -1 || // Following ` -`: only if `$var` after (`10/10 -$var`)
  after.search(/^[^(){},\s]+\s+-(\$|\s)/) !== -1 || // Following `-`: only if number after (`10s/10s-10`, `10s/10s-.1`)
  after.search(/^[^(){},\s]+-(\.){0,1}\d/) !== -1 || // Or if there is a number before anything but string after (not `10s/1-str`,)
  after.search(/^(\d*\.){0,1}\d+-\s*[^#a-zA-Z_\s]/) !== -1) {
    // console.log("/, math op around")
    return "op";
  }

  if (isInsideParens(string, index) || isInsideFn.is && isInsideFn.fn !== "url") {
    // console.log("/, parens or function arg")
    return "op";
  } // console.log("/, default")


  return "char";
}
/**
 * Checks the specified `%` character: operator or part of value
 *
 * @param {String} string - the source string
 * @param {Number} index - the index of the character in string to check
 * @return {String|false}
 *    • "op", if the character is a operator in a math/string operation
 *    • "char" if it gets compiled as-is, e.g. `width: 10%`,
 *    • false - if it is none from above (most likely an error)
 */


function checkPercent(string, index) {
  // Trimming these, as spaces before/after a slash don't matter
  var before = string.substring(0, index);
  var after = string.substring(index + 1); // If the character is at the beginning of the input

  var isAtStart_ = isAtStart(string, index); // If the character is at the end of the input

  var isAtEnd_ = isAtEnd(string, index);
  var isWhitespaceBefore = before.search(/\s$/) !== -1;
  var isWhitespaceAfter = after.search(/^\s/) !== -1;
  var isParensBefore_ = isParensBefore(before); // FIRST OFF. Interpolation on any of the sides is a NO-GO

  if (isInterpolationBefore(before.trim()).is || isInterpolationAfter(after.trim()).is) {
    // console.log("%, interpolation")
    return "char";
  }

  if (isAtStart_ || isAtEnd_) {
    // console.log("%, start/end")
    return "char";
  } // In `<sth> %<sth>` it's most likely an operator (except for inteprolation
  // checked above)


  if (isWhitespaceBefore && !isWhitespaceAfter) {
    // console.log("%, `<sth> %<sth>`")
    return "op";
  } // `$var% 1`, `$var%1`, `$var%-1`


  if (isVariableBefore(before) || isParensBefore_) {
    // console.log("%, after a variable, function or parens")
    return "op";
  } // in all other cases in `<sth>% <sth>` it is most likely a unit


  if (!isWhitespaceBefore && isWhitespaceAfter) {
    // console.log("%, `<sth>% <sth>`")
    return "char";
  } // console.log("%, default")


  return "char";
} // --------------------------------------------------------------------------
// Lots of elementary helpers
// --------------------------------------------------------------------------


function isAtStart(string, index) {
  var before = string.substring(0, index).trim();
  return before.length === 0 || before.search(/[({,]$/) !== -1;
}

function isAtEnd(string, index) {
  var after = string.substring(index + 1).trim();
  return after.length === 0 || after.search(/^[,)}]/) !== -1;
}

function isInsideParens(string, index) {
  var before = string.substring(0, index).trim();
  var after = string.substring(index + 1).trim();

  if (before.search(/(?:^|[,{]|\s)\(\s*[^(){},]+$/) !== -1 && after.search(/^[^(){},\s]+\s*\)/) !== -1) {
    return true;
  }

  return false;
}

function isInsideInterpolation(string, index) {
  var before = string.substring(0, index).trim();

  if (before.search(/#{[^}]*$/) !== -1) {
    return true;
  }

  return false;
}
/**
 * Checks if the character is inside a function agruments
 *
 * @param {String} string - the input string
 * @param {Number} index - current character index
 * @return {Object} return
 *    {Boolean} return.is - if inside a function arguments
 *    {String} return.fn - function name
 */


function isInsideFunctionCall(string, index) {
  var result = {
    is: false,
    fn: null
  };
  var before = string.substring(0, index).trim();
  var after = string.substring(index + 1).trim();
  var beforeMatch = before.match(/([a-zA-Z_-][a-zA-Z0-9_-]*)\([^(){}]+$/);

  if (beforeMatch && beforeMatch[0] && after.search(/^[^(,]+\)/) !== -1) {
    result.is = true;
    result.fn = beforeMatch[1];
  }

  return result;
}
/**
 * Checks if there is a string before the character.
 * Also checks if there is a math operator in between
 *
 * @param {String} before - the input string that preceses the character
 * @return {Object} return
 *    {Boolean} return.is - if there is a string
 *    {String} return.opsBetween - if there are operators in between
 */


function isStringBefore(before) {
  var result = {
    is: false,
    opsBetween: false
  };
  var stringOpsClipped = before.replace(/(\s*[+/*%]|\s+-)+$/, "");

  if (stringOpsClipped !== before) {
    result.opsBetween = true;
  } // If it is quoted


  if (stringOpsClipped[stringOpsClipped.length - 1] === '"' || stringOpsClipped[stringOpsClipped.length - 1] === "'") {
    result.is = true;
  } else if (stringOpsClipped.search(/(?:^|[/(){},: ])([a-zA-Z_][a-zA-Z_0-9-]*|-+[a-zA-Z_]+[a-zA-Z_0-9-]*)$/) !== -1) {
    // First pattern: a1, a1a, a-1,
    result.is = true;
  }

  return result;
}

function isStringAfter(after) {
  var stringTrimmed = after.trim(); // If it is quoted

  if (stringTrimmed[0] === '"' || stringTrimmed[0] === "'") return true; // e.g. `a1`, `a1a`, `a-1`, and even `--s323`

  if (stringTrimmed.search(/^([a-zA-Z_][a-zA-Z_0-9-]*|-+[a-zA-Z_]+[a-zA-Z_0-9-]*)(?:$|[)}, ])/) !== -1) return true;
  return false;
}

function isInterpolationAfter(after) {
  var result = {
    is: false,
    opsBetween: false
  };
  var matches = after.match(/^\s*([+/*%-]\s*)*#{/);

  if (matches) {
    if (matches[0]) {
      result.is = true;
    }

    if (matches[1]) {
      result.opsBetween = true;
    }
  }

  return result;
}

function isParensAfter(after) {
  var result = {
    is: false,
    opsBetween: false
  };
  var matches = after.match(/^\s*([+/*%-]\s*)*\(/);

  if (matches) {
    if (matches[0]) {
      result.is = true;
    }

    if (matches[1]) {
      result.opsBetween = true;
    }
  }

  return result;
}

function isParensBefore(before) {
  return before.search(/\)\s*$/) !== -1;
}
/**
 * Checks if there is an interpolation before the character.
 * Also checks if there is a math operator in between
 *
 * @param {String} before - the input string that preceses the character
 * @return {Object} return
 *    {Boolean} return.is - if there is an interpolation
 *    {String} return.opsBetween - if there are operators in between
 */


function isInterpolationBefore(before) {
  var result = {
    is: false,
    opsBetween: false
  }; // Removing preceding operators if any

  var beforeOpsClipped = before.replace(/(\s*[+/*%-])+$/, "");

  if (beforeOpsClipped !== before) {
    result.opsBetween = true;
  }

  if (beforeOpsClipped[beforeOpsClipped.length - 1] === "}") {
    result.is = true;
  }

  return result;
}

function isValueWithUnitBefore(before) {
  // 1px, 0.1p-x, .2p-, 11.2pdf-df1df_
  // Surprisingly, ` d.10px` - .10px is separated from a sequence
  // and is considered a value with a unit
  if (before.trim().search(/(^|[/(, ]|\.)\d[a-zA-Z_0-9-]+$/) !== -1) {
    return true;
  }

  return false;
}

function isValueWithUnitAfter(after) {
  var result = {
    is: false,
    opsBetween: false
  }; // 1px, 0.1p-x, .2p-, 11.2pdf-dfd1f_
  // Again, ` d.10px` - .10px is separated from a sequence
  // and is considered a value with a unit

  var matches = after.match(/^\s*([+/*%-]\s*)*(\d+(\.\d+){0,1}|\.\d+)[a-zA-Z_0-9-%]+(?:$|[)}, ])/);

  if (matches) {
    if (matches[0]) {
      result.is = true;
    }

    if (matches[1]) {
      result.opsBetween = true;
    }
  }

  return result;
}

function isNumberAfter(after) {
  var result = {
    is: false,
    opsBetween: false
  };
  var matches = after.match(/^\s*([+/*%-]\s*)*(\d+(\.\d+){0,1}|\.\d+)(?:$|[)}, ])/);

  if (matches) {
    if (matches[0]) {
      result.is = true;
    }

    if (matches[1]) {
      result.opsBetween = true;
    }
  }

  return result;
}

function isNumberBefore(before) {
  if (before.trim().search(/(?:^|[/(){},\s])(\d+(\.\d+){0,1}|\.\d+)$/) !== -1) {
    return true;
  }

  return false;
}

function isVariableBefore(before) {
  return before.trim().search(/\$[a-zA-Z_0-9-]+$/) !== -1;
}

function isVariableAfter(after) {
  var result = {
    is: false,
    opsBetween: false
  };
  var matches = after.match(/^\s*([+/*%-]\s*)*\$/);

  if (matches) {
    if (matches[0]) {
      result.is = true;
    }

    if (matches[1]) {
      result.opsBetween = true;
    }
  }

  return result;
}

function isDotBefore(before) {
  return before.slice(-1) === ".";
}

function isProtocolBefore(before) {
  return before.search(/https?:/) !== -1;
}

function isFunctionBefore(before) {
  return before.trim().search(/[a-zA-Z0-9_-]\(.*?\)\s*$/) !== -1;
}

function isFunctionAfter(after) {
  var result = {
    is: false,
    opsBetween: false
  }; // `-fn()` is a valid function name, so if a - should be a sign/operator,
  // it must have a space after

  var matches = after.match(/^\s*(-\s+|[+/*%]\s*)*[a-zA-Z_-][a-zA-Z_0-9-]*\(/);

  if (matches) {
    if (matches[0]) {
      result.is = true;
    }

    if (matches[1]) {
      result.opsBetween = true;
    }
  }

  return result;
}
/**
 * Checks if the input string is a hex color value
 *
 * @param {String} string - the input
 * @return {Boolean} true, if the input is a hex color
 */


function isHexColor(string) {
  return string.trim().search(/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/) !== -1;
}

function isHexColorAfter(after) {
  var afterTrimmed = after.match(/(.*?)(?:[)},+/*%-]|\s|$)/)[1].trim();
  return isHexColor(afterTrimmed);
}

function isHexColorBefore(before) {
  if (before.search(/(?:[/(){},+*%-\s]|^)#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/) !== -1) {
    return true;
  }

  return false;
}
/**
 * Checks if there is no operand before the currenc char
 * In other words, the current char is at the start of a possible operation,
 * e.g. at the string start, after the opening paren or after a comma
 *
 * @param {String} string - the input string
 * @param {Number} index - current char's position in string
 * @return {Boolean}
 */


function isNoOperandBefore(string, index) {
  var before = string.substring(0, index).trim();
  return before.length === 0 || before.search(/[({,]&/) !== -1;
}

function isPrecedingOperator(string, index) {
  var prevCharIndex = -1;

  for (var i = index - 1; i >= 0; i--) {
    if (string[i].search(/\s/) === -1) {
      prevCharIndex = i;
      break;
    }
  }

  if (prevCharIndex === -1) {
    return false;
  }

  if (mathOperatorCharType(string, prevCharIndex) === "op") {
    return true;
  }

  return false;
}
© 2026 GrazzMean