.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / stylelint / lib / rules / max-nesting-depth / index.js
1 "use strict";
2
3 const _ = require("lodash");
4 const hasBlock = require("../../utils/hasBlock");
5 const optionsMatches = require("../../utils/optionsMatches");
6 const report = require("../../utils/report");
7 const ruleMessages = require("../../utils/ruleMessages");
8 const validateOptions = require("../../utils/validateOptions");
9
10 const ruleName = "max-nesting-depth";
11
12 const messages = ruleMessages(ruleName, {
13   expected: depth => `Expected nesting depth to be no more than ${depth}`
14 });
15
16 const rule = function(max, options) {
17   const isIgnoreAtRule = node =>
18     node.type === "atrule" &&
19     optionsMatches(options, "ignoreAtRules", node.name);
20
21   return (root, result) => {
22     validateOptions(
23       result,
24       ruleName,
25       {
26         actual: max,
27         possible: [_.isNumber]
28       },
29       {
30         optional: true,
31         actual: options,
32         possible: {
33           ignore: ["blockless-at-rules"],
34           ignoreAtRules: [_.isString]
35         }
36       }
37     );
38
39     root.walkRules(checkStatement);
40     root.walkAtRules(checkStatement);
41
42     function checkStatement(statement) {
43       if (isIgnoreAtRule(statement)) {
44         return;
45       }
46       if (!hasBlock(statement)) {
47         return;
48       }
49       const depth = nestingDepth(statement);
50       if (depth > max) {
51         report({
52           ruleName,
53           result,
54           node: statement,
55           message: messages.expected(max)
56         });
57       }
58     }
59   };
60
61   function nestingDepth(node, level) {
62     level = level || 0;
63     const parent = node.parent;
64
65     if (isIgnoreAtRule(parent)) {
66       return 0;
67     }
68
69     // The nesting depth level's computation has finished
70     // when this function, recursively called, receives
71     // a node that is not nested -- a direct child of the
72     // root node
73     if (
74       parent.type === "root" ||
75       (parent.type === "atrule" && parent.parent.type === "root")
76     ) {
77       return level;
78     }
79
80     if (
81       optionsMatches(options, "ignore", "blockless-at-rules") &&
82       node.type === "atrule" &&
83       node.every(child => child.type !== "decl")
84     ) {
85       return nestingDepth(parent, level);
86     }
87
88     // Unless any of the conditions above apply, we want to
89     // add 1 to the nesting depth level and then check the parent,
90     // continuing to add and move up the hierarchy
91     // until we hit the root node
92     return nestingDepth(parent, level + 1);
93   }
94 };
95
96 rule.ruleName = ruleName;
97 rule.messages = messages;
98 module.exports = rule;