.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / stylelint / lib / rules / selector-max-compound-selectors / index.js
1 "use strict";
2
3 const isStandardSyntaxRule = require("../../utils/isStandardSyntaxRule");
4 const isStandardSyntaxSelector = require("../../utils/isStandardSyntaxSelector");
5 const parseSelector = require("../../utils/parseSelector");
6 const report = require("../../utils/report");
7 const resolvedNestedSelector = require("postcss-resolve-nested-selector");
8 const ruleMessages = require("../../utils/ruleMessages");
9 const validateOptions = require("../../utils/validateOptions");
10
11 const ruleName = "selector-max-compound-selectors";
12
13 const messages = ruleMessages(ruleName, {
14   expected: (selector, max) =>
15     `Expected "${selector}" to have no more than ${max} compound ${
16       max === 1 ? "selector" : "selectors"
17     }`
18 });
19
20 const rule = function(max) {
21   return (root, result) => {
22     const validOptions = validateOptions(result, ruleName, {
23       actual: max,
24       possible: [
25         function(max) {
26           return typeof max === "number" && max > 0;
27         }
28       ]
29     });
30     if (!validOptions) {
31       return;
32     }
33
34     // Finds actual selectors in selectorNode object and checks them
35     function checkSelector(selectorNode, rule) {
36       let compoundCount = 1;
37
38       selectorNode.each(childNode => {
39         // Only traverse inside actual selectors and :not()
40         if (childNode.type === "selector" || childNode.value === ":not") {
41           checkSelector(childNode, rule);
42         }
43
44         // Compound selectors are separated by combinators, so increase count when meeting one
45         if (childNode.type === "combinator") {
46           compoundCount++;
47         }
48       });
49
50       if (
51         selectorNode.type !== "root" &&
52         selectorNode.type !== "pseudo" &&
53         compoundCount > max
54       ) {
55         report({
56           ruleName,
57           result,
58           node: rule,
59           message: messages.expected(selectorNode, max),
60           word: selectorNode
61         });
62       }
63     }
64
65     root.walkRules(rule => {
66       if (!isStandardSyntaxRule(rule)) {
67         return;
68       }
69       if (!isStandardSyntaxSelector(rule.selector)) {
70         return;
71       }
72
73       // Using `rule.selectors` gets us each selector if there is a comma separated set
74       rule.selectors.forEach(selector => {
75         resolvedNestedSelector(selector, rule).forEach(resolvedSelector => {
76           // Process each resolved selector with `checkSelector` via postcss-selector-parser
77           parseSelector(resolvedSelector, result, rule, s =>
78             checkSelector(s, rule)
79           );
80         });
81       });
82     });
83   };
84 };
85
86 rule.ruleName = ruleName;
87 rule.messages = messages;
88 module.exports = rule;