.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / stylelint / lib / rules / selector-max-combinators / 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-combinators";
12
13 const messages = ruleMessages(ruleName, {
14   expected: (selector, max) =>
15     `Expected "${selector}" to have no more than ${max} ${
16       max === 1 ? "combinator" : "combinators"
17     }`
18 });
19
20 function rule(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     function checkSelector(selectorNode, ruleNode) {
35       const count = selectorNode.reduce((total, childNode) => {
36         // Only traverse inside actual selectors
37         if (childNode.type === "selector") {
38           checkSelector(childNode, ruleNode);
39         }
40
41         return (total += childNode.type === "combinator" ? 1 : 0);
42       }, 0);
43
44       if (
45         selectorNode.type !== "root" &&
46         selectorNode.type !== "pseudo" &&
47         count > max
48       ) {
49         report({
50           ruleName,
51           result,
52           node: ruleNode,
53           message: messages.expected(selectorNode, max),
54           word: selectorNode
55         });
56       }
57     }
58
59     root.walkRules(ruleNode => {
60       if (!isStandardSyntaxRule(ruleNode)) {
61         return;
62       }
63       if (!isStandardSyntaxSelector(ruleNode.selector)) {
64         return;
65       }
66       if (
67         ruleNode.nodes.some(
68           node => ["rule", "atrule"].indexOf(node.type) !== -1
69         )
70       ) {
71         // Skip unresolved nested selectors
72         return;
73       }
74
75       ruleNode.selectors.forEach(selector => {
76         resolvedNestedSelector(selector, ruleNode).forEach(resolvedSelector => {
77           parseSelector(resolvedSelector, result, ruleNode, container =>
78             checkSelector(container, ruleNode)
79           );
80         });
81       });
82     });
83   };
84 }
85
86 rule.ruleName = ruleName;
87 rule.messages = messages;
88 module.exports = rule;