.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / stylelint / lib / rules / block-closing-brace-newline-before / index.js
1 "use strict";
2
3 const _ = require("lodash");
4 const blockString = require("../../utils/blockString");
5 const hasBlock = require("../../utils/hasBlock");
6 const hasEmptyBlock = require("../../utils/hasEmptyBlock");
7 const isSingleLineString = require("../../utils/isSingleLineString");
8 const report = require("../../utils/report");
9 const ruleMessages = require("../../utils/ruleMessages");
10 const validateOptions = require("../../utils/validateOptions");
11
12 const ruleName = "block-closing-brace-newline-before";
13
14 const messages = ruleMessages(ruleName, {
15   expectedBefore: 'Expected newline before "}"',
16   expectedBeforeMultiLine: 'Expected newline before "}" of a multi-line block',
17   rejectedBeforeMultiLine:
18     'Unexpected whitespace before "}" of a multi-line block'
19 });
20
21 const rule = function(expectation) {
22   return (root, result) => {
23     const validOptions = validateOptions(result, ruleName, {
24       actual: expectation,
25       possible: ["always", "always-multi-line", "never-multi-line"]
26     });
27     if (!validOptions) {
28       return;
29     }
30
31     // Check both kinds of statements: rules and at-rules
32     root.walkRules(check);
33     root.walkAtRules(check);
34
35     function check(statement) {
36       // Return early if blockless or has empty block
37       if (!hasBlock(statement) || hasEmptyBlock(statement)) {
38         return;
39       }
40
41       // Ignore extra semicolon
42       const after = (statement.raws.after || "").replace(/;+/, "");
43       if (after === undefined) {
44         return;
45       }
46
47       const blockIsMultiLine = !isSingleLineString(blockString(statement));
48       const statementString = statement.toString();
49
50       let index = statementString.length - 2;
51       if (statementString[index - 1] === "\r") {
52         index -= 1;
53       }
54
55       // We're really just checking whether a
56       // newline *starts* the block's final space -- between
57       // the last declaration and the closing brace. We can
58       // ignore any other whitespace between them, because that
59       // will be checked by the indentation rule.
60       if (!_.startsWith(after, "\n") && !_.startsWith(after, "\r\n")) {
61         if (expectation === "always") {
62           complain(messages.expectedBefore);
63         } else if (blockIsMultiLine && expectation === "always-multi-line") {
64           complain(messages.expectedBeforeMultiLine);
65         }
66       }
67
68       if (
69         after !== "" &&
70         blockIsMultiLine &&
71         expectation === "never-multi-line"
72       ) {
73         complain(messages.rejectedBeforeMultiLine);
74       }
75
76       function complain(message) {
77         report({
78           message,
79           result,
80           ruleName,
81           node: statement,
82           index
83         });
84       }
85     }
86   };
87 };
88
89 rule.ruleName = ruleName;
90 rule.messages = messages;
91 module.exports = rule;