Actualizacion maquina principal
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / stylelint / lib / rules / selector-max-specificity / index.js
diff --git a/.config/coc/extensions/node_modules/coc-prettier/node_modules/stylelint/lib/rules/selector-max-specificity/index.js b/.config/coc/extensions/node_modules/coc-prettier/node_modules/stylelint/lib/rules/selector-max-specificity/index.js
new file mode 100755 (executable)
index 0000000..02bd527
--- /dev/null
@@ -0,0 +1,158 @@
+"use strict";
+
+const _ = require("lodash");
+const isStandardSyntaxRule = require("../../utils/isStandardSyntaxRule");
+const isStandardSyntaxSelector = require("../../utils/isStandardSyntaxSelector");
+const optionsMatches = require("../../utils/optionsMatches");
+const parseSelector = require("../../utils/parseSelector");
+const report = require("../../utils/report");
+const resolvedNestedSelector = require("postcss-resolve-nested-selector");
+const ruleMessages = require("../../utils/ruleMessages");
+const specificity = require("specificity");
+const validateOptions = require("../../utils/validateOptions");
+
+const ruleName = "selector-max-specificity";
+
+const messages = ruleMessages(ruleName, {
+  expected: (selector, specificity) =>
+    `Expected "${selector}" to have a specificity no more than "${specificity}"`
+});
+
+// Return an array representation of zero specificity. We need a new array each time so that it can mutated
+const zeroSpecificity = () => [0, 0, 0, 0];
+
+// Calculate the sum of given array of specificity arrays
+const specificitySum = specificities => {
+  const sum = zeroSpecificity();
+  specificities.forEach(specificityArray => {
+    specificityArray.forEach((value, i) => {
+      sum[i] += value;
+    });
+  });
+  return sum;
+};
+
+const rule = function(max, options) {
+  return (root, result) => {
+    const validOptions = validateOptions(
+      result,
+      ruleName,
+      {
+        actual: max,
+        possible: [
+          function(max) {
+            // Check that the max specificity is in the form "a,b,c"
+            const pattern = new RegExp("^\\d+,\\d+,\\d+$");
+            return pattern.test(max);
+          }
+        ]
+      },
+      {
+        actual: options,
+        possible: {
+          ignoreSelectors: [_.isString]
+        },
+        optional: true
+      }
+    );
+    if (!validOptions) {
+      return;
+    }
+
+    // Calculate the specificity of a simple selector (type, attribute, class, id, or pseudos's own value)
+    const simpleSpecificity = selector => {
+      if (optionsMatches(options, "ignoreSelectors", selector)) {
+        return zeroSpecificity();
+      }
+      return specificity.calculate(selector)[0].specificityArray;
+    };
+
+    // Calculate the the specificity of the most specific direct child
+    const maxChildSpecificity = node =>
+      node.reduce((max, child) => {
+        const childSpecificity = nodeSpecificity(child); // eslint-disable-line no-use-before-define
+        return specificity.compare(childSpecificity, max) === 1
+          ? childSpecificity
+          : max;
+      }, zeroSpecificity());
+
+    // Calculate the specificity of a pseudo selector including own value and children
+    const pseudoSpecificity = node => {
+      // `node.toString()` includes children which should be processed separately,
+      // so use `node.value` instead
+      const ownValue = node.value;
+      const ownSpecificity =
+        ownValue === ":not" || ownValue === ":matches"
+          ? // :not and :matches don't add specificity themselves, but their children do
+            zeroSpecificity()
+          : simpleSpecificity(ownValue);
+
+      return specificitySum([ownSpecificity, maxChildSpecificity(node)]);
+    };
+
+    // Calculate the specificity of a node parsed by `postcss-selector-parser`
+    const nodeSpecificity = node => {
+      switch (node.type) {
+        case "attribute":
+        case "class":
+        case "id":
+        case "tag":
+          return simpleSpecificity(node.toString());
+        case "pseudo":
+          return pseudoSpecificity(node);
+        case "selector":
+          // Calculate the sum of all the direct children
+          return specificitySum(node.map(nodeSpecificity));
+        default:
+          return zeroSpecificity();
+      }
+    };
+
+    const maxSpecificityArray = ("0," + max).split(",").map(parseFloat);
+    root.walkRules(rule => {
+      if (!isStandardSyntaxRule(rule)) {
+        return;
+      }
+      if (!isStandardSyntaxSelector(rule.selector)) {
+        return;
+      }
+      // Using rule.selectors gets us each selector in the eventuality we have a comma separated set
+      rule.selectors.forEach(selector => {
+        resolvedNestedSelector(selector, rule).forEach(resolvedSelector => {
+          try {
+            // Skip non-standard syntax selectors
+            if (!isStandardSyntaxSelector(resolvedSelector)) {
+              return;
+            }
+            parseSelector(resolvedSelector, result, rule, selectorTree => {
+              // Check if the selector specificity exceeds the allowed maximum
+              if (
+                specificity.compare(
+                  maxChildSpecificity(selectorTree),
+                  maxSpecificityArray
+                ) === 1
+              ) {
+                report({
+                  ruleName,
+                  result,
+                  node: rule,
+                  message: messages.expected(resolvedSelector, max),
+                  word: selector
+                });
+              }
+            });
+          } catch (e) {
+            result.warn("Cannot parse selector", {
+              node: rule,
+              stylelintType: "parseError"
+            });
+          }
+        });
+      });
+    });
+  };
+};
+
+rule.ruleName = ruleName;
+rule.messages = messages;
+module.exports = rule;