.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / stylelint / lib / rules / declaration-empty-line-before / index.js
1 "use strict";
2
3 const addEmptyLineBefore = require("../../utils/addEmptyLineBefore");
4 const blockString = require("../../utils/blockString");
5 const hasEmptyLine = require("../../utils/hasEmptyLine");
6 const isAfterComment = require("../../utils/isAfterComment");
7 const isAfterStandardPropertyDeclaration = require("../../utils/isAfterStandardPropertyDeclaration");
8 const isCustomProperty = require("../../utils/isCustomProperty");
9 const isFirstNested = require("../../utils/isFirstNested");
10 const isSingleLineString = require("../../utils/isSingleLineString");
11 const isStandardSyntaxDeclaration = require("../../utils/isStandardSyntaxDeclaration");
12 const optionsMatches = require("../../utils/optionsMatches");
13 const removeEmptyLinesBefore = require("../../utils/removeEmptyLinesBefore");
14 const report = require("../../utils/report");
15 const ruleMessages = require("../../utils/ruleMessages");
16 const validateOptions = require("../../utils/validateOptions");
17
18 const ruleName = "declaration-empty-line-before";
19
20 const messages = ruleMessages(ruleName, {
21   expected: "Expected empty line before declaration",
22   rejected: "Unexpected empty line before declaration"
23 });
24
25 const rule = function(expectation, options, context) {
26   return (root, result) => {
27     const validOptions = validateOptions(
28       result,
29       ruleName,
30       {
31         actual: expectation,
32         possible: ["always", "never"]
33       },
34       {
35         actual: options,
36         possible: {
37           except: ["first-nested", "after-comment", "after-declaration"],
38           ignore: [
39             "after-comment",
40             "after-declaration",
41             "inside-single-line-block"
42           ]
43         },
44         optional: true
45       }
46     );
47     if (!validOptions) {
48       return;
49     }
50
51     root.walkDecls(decl => {
52       const prop = decl.prop,
53         parent = decl.parent;
54
55       if (!isStandardSyntaxDeclaration(decl)) {
56         return;
57       }
58       if (isCustomProperty(prop)) {
59         return;
60       }
61
62       // Optionally ignore the node if a comment precedes it
63       if (
64         optionsMatches(options, "ignore", "after-comment") &&
65         isAfterComment(decl)
66       ) {
67         return;
68       }
69
70       // Optionally ignore the node if a declaration precedes it
71       if (
72         optionsMatches(options, "ignore", "after-declaration") &&
73         isAfterStandardPropertyDeclaration(decl)
74       ) {
75         return;
76       }
77
78       // Optionally ignore nodes inside single-line blocks
79       if (
80         optionsMatches(options, "ignore", "inside-single-line-block") &&
81         isSingleLineString(blockString(parent))
82       ) {
83         return;
84       }
85
86       let expectEmptyLineBefore = expectation === "always" ? true : false;
87
88       // Optionally reverse the expectation if any exceptions apply
89       if (
90         (optionsMatches(options, "except", "first-nested") &&
91           isFirstNested(decl)) ||
92         (optionsMatches(options, "except", "after-comment") &&
93           isAfterComment(decl)) ||
94         (optionsMatches(options, "except", "after-declaration") &&
95           isAfterStandardPropertyDeclaration(decl))
96       ) {
97         expectEmptyLineBefore = !expectEmptyLineBefore;
98       }
99
100       // Check for at least one empty line
101       const hasEmptyLineBefore = hasEmptyLine(decl.raws.before);
102
103       // Return if the expectation is met
104       if (expectEmptyLineBefore === hasEmptyLineBefore) {
105         return;
106       }
107
108       // Fix
109       if (context.fix) {
110         if (expectEmptyLineBefore) {
111           addEmptyLineBefore(decl, context.newline);
112         } else {
113           removeEmptyLinesBefore(decl, context.newline);
114         }
115
116         return;
117       }
118
119       const message = expectEmptyLineBefore
120         ? messages.expected
121         : messages.rejected;
122       report({ message, node: decl, result, ruleName });
123     });
124   };
125 };
126
127 rule.ruleName = ruleName;
128 rule.messages = messages;
129 module.exports = rule;