.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / stylelint / lib / rules / block-closing-brace-newline-after / index.js
1 "use strict";
2
3 const _ = require("lodash");
4 const blockString = require("../../utils/blockString");
5 const hasBlock = require("../../utils/hasBlock");
6 const optionsMatches = require("../../utils/optionsMatches");
7 const rawNodeString = require("../../utils/rawNodeString");
8 const report = require("../../utils/report");
9 const ruleMessages = require("../../utils/ruleMessages");
10 const validateOptions = require("../../utils/validateOptions");
11 const whitespaceChecker = require("../../utils/whitespaceChecker");
12
13 const ruleName = "block-closing-brace-newline-after";
14
15 const messages = ruleMessages(ruleName, {
16   expectedAfter: () => 'Expected newline after "}"',
17   expectedAfterSingleLine: () =>
18     'Expected newline after "}" of a single-line block',
19   rejectedAfterSingleLine: () =>
20     'Unexpected whitespace after "}" of a single-line block',
21   expectedAfterMultiLine: () =>
22     'Expected newline after "}" of a multi-line block',
23   rejectedAfterMultiLine: () =>
24     'Unexpected whitespace after "}" of a multi-line block'
25 });
26
27 const rule = function(expectation, options) {
28   const checker = whitespaceChecker("newline", expectation, messages);
29   return (root, result) => {
30     const validOptions = validateOptions(
31       result,
32       ruleName,
33       {
34         actual: expectation,
35         possible: [
36           "always",
37           "always-single-line",
38           "never-single-line",
39           "always-multi-line",
40           "never-multi-line"
41         ]
42       },
43       {
44         actual: options,
45         possible: {
46           ignoreAtRules: [_.isString]
47         },
48         optional: true
49       }
50     );
51     if (!validOptions) {
52       return;
53     }
54
55     // Check both kinds of statements: rules and at-rules
56     root.walkRules(check);
57     root.walkAtRules(check);
58
59     function check(statement) {
60       if (!hasBlock(statement)) {
61         return;
62       }
63       if (optionsMatches(options, "ignoreAtRules", statement.name)) {
64         return;
65       }
66
67       const nextNode = statement.next();
68       if (!nextNode) {
69         return;
70       }
71
72       // Allow an end-of-line comment x spaces after the brace
73       const nextNodeIsSingleLineComment =
74         nextNode.type === "comment" &&
75         !/[^ ]/.test(nextNode.raws.before || "") &&
76         nextNode.toString().indexOf("\n") === -1;
77
78       const nodeToCheck = nextNodeIsSingleLineComment
79         ? nextNode.next()
80         : nextNode;
81
82       if (!nodeToCheck) {
83         return;
84       }
85
86       let reportIndex = statement.toString().length;
87       let source = rawNodeString(nodeToCheck);
88
89       // Skip a semicolon at the beginning, if any
90       if (source && source[0] === ";") {
91         source = source.slice(1);
92         reportIndex++;
93       }
94
95       // Only check one after, because there might be other
96       // spaces handled by the indentation rule
97       checker.afterOneOnly({
98         source,
99         index: -1,
100         lineCheckStr: blockString(statement),
101         err: msg => {
102           report({
103             message: msg,
104             node: statement,
105             index: reportIndex,
106             result,
107             ruleName
108           });
109         }
110       });
111     }
112   };
113 };
114
115 rule.ruleName = ruleName;
116 rule.messages = messages;
117 module.exports = rule;