Actualizacion maquina principal
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / stylelint / lib / rules / function-calc-no-unspaced-operator / index.js
diff --git a/.config/coc/extensions/node_modules/coc-prettier/node_modules/stylelint/lib/rules/function-calc-no-unspaced-operator/index.js b/.config/coc/extensions/node_modules/coc-prettier/node_modules/stylelint/lib/rules/function-calc-no-unspaced-operator/index.js
new file mode 100644 (file)
index 0000000..d6d65eb
--- /dev/null
@@ -0,0 +1,150 @@
+"use strict";
+
+const balancedMatch = require("balanced-match");
+const isWhitespace = require("../../utils/isWhitespace");
+const report = require("../../utils/report");
+const ruleMessages = require("../../utils/ruleMessages");
+const styleSearch = require("style-search");
+const validateOptions = require("../../utils/validateOptions");
+const valueParser = require("postcss-value-parser");
+
+const ruleName = "function-calc-no-unspaced-operator";
+
+const messages = ruleMessages(ruleName, {
+  expectedBefore: operator =>
+    `Expected single space before "${operator}" operator`,
+  expectedAfter: operator =>
+    `Expected single space after "${operator}" operator`,
+  expectedOperatorBeforeSign: operator =>
+    `Expected an operator before sign "${operator}"`
+});
+
+const rule = function(actual) {
+  return (root, result) => {
+    const validOptions = validateOptions(result, ruleName, { actual });
+    if (!validOptions) {
+      return;
+    }
+
+    function complain(message, node, index) {
+      report({ message, node, index, result, ruleName });
+    }
+
+    root.walkDecls(decl => {
+      valueParser(decl.value).walk(node => {
+        if (node.type !== "function" || node.value.toLowerCase() !== "calc") {
+          return;
+        }
+
+        const parensMatch = balancedMatch(
+          "(",
+          ")",
+          valueParser.stringify(node)
+        );
+        const rawExpression = parensMatch.body;
+        const expressionIndex =
+          decl.source.start.column +
+          decl.prop.length +
+          (decl.raws.between || "").length +
+          node.sourceIndex;
+        const expression = blurVariables(rawExpression);
+
+        checkSymbol("+");
+        checkSymbol("-");
+        checkSymbol("*");
+        checkSymbol("/");
+
+        function checkSymbol(symbol) {
+          const styleSearchOptions = {
+            source: expression,
+            target: symbol,
+            functionArguments: "skip"
+          };
+
+          styleSearch(styleSearchOptions, match => {
+            const index = match.startIndex;
+
+            // Deal with signs.
+            // (@ and $ are considered "digits" here to allow for variable syntaxes
+            // that permit signs in front of variables, e.g. `-$number`)
+            // As is "." to deal with fractional numbers without a leading zero
+            if (
+              (symbol === "+" || symbol === "-") &&
+              /[\d@$.]/.test(expression[index + 1])
+            ) {
+              const expressionBeforeSign = expression.substr(0, index);
+
+              // Ignore signs that directly follow a opening bracket
+              if (
+                expressionBeforeSign[expressionBeforeSign.length - 1] === "("
+              ) {
+                return;
+              }
+
+              // Ignore signs at the beginning of the expression
+              if (/^\s*$/.test(expressionBeforeSign)) {
+                return;
+              }
+
+              // Otherwise, ensure that there is a real operator preceeding them
+              if (/[*/+-]\s*$/.test(expressionBeforeSign)) {
+                return;
+              }
+
+              // And if not, complain
+              complain(
+                messages.expectedOperatorBeforeSign(symbol),
+                decl,
+                expressionIndex + index
+              );
+              return;
+            }
+
+            const beforeOk =
+              (expression[index - 1] === " " &&
+                !isWhitespace(expression[index - 2])) ||
+              newlineBefore(expression, index - 1);
+            if (!beforeOk) {
+              complain(
+                messages.expectedBefore(symbol),
+                decl,
+                expressionIndex + index
+              );
+            }
+
+            const afterOk =
+              (expression[index + 1] === " " &&
+                !isWhitespace(expression[index + 2])) ||
+              expression[index + 1] === "\n" ||
+              expression.substr(index + 1, 2) === "\r\n";
+
+            if (!afterOk) {
+              complain(
+                messages.expectedAfter(symbol),
+                decl,
+                expressionIndex + index
+              );
+            }
+          });
+        }
+      });
+    });
+  };
+};
+
+function blurVariables(source) {
+  return source.replace(/[$@][^)\s]+|#{.+?}/g, "0");
+}
+
+function newlineBefore(str, startIndex) {
+  let index = startIndex;
+  while (index && isWhitespace(str[index])) {
+    if (str[index] === "\n") return true;
+    index--;
+  }
+  return false;
+}
+
+rule.ruleName = ruleName;
+rule.messages = messages;
+module.exports = rule;