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");
13 const ruleName = "block-closing-brace-newline-after";
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'
27 const rule = function(expectation, options) {
28 const checker = whitespaceChecker("newline", expectation, messages);
29 return (root, result) => {
30 const validOptions = validateOptions(
46 ignoreAtRules: [_.isString]
55 // Check both kinds of statements: rules and at-rules
56 root.walkRules(check);
57 root.walkAtRules(check);
59 function check(statement) {
60 if (!hasBlock(statement)) {
63 if (optionsMatches(options, "ignoreAtRules", statement.name)) {
67 const nextNode = statement.next();
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;
78 const nodeToCheck = nextNodeIsSingleLineComment
86 let reportIndex = statement.toString().length;
87 let source = rawNodeString(nodeToCheck);
89 // Skip a semicolon at the beginning, if any
90 if (source && source[0] === ";") {
91 source = source.slice(1);
95 // Only check one after, because there might be other
96 // spaces handled by the indentation rule
97 checker.afterOneOnly({
100 lineCheckStr: blockString(statement),
115 rule.ruleName = ruleName;
116 rule.messages = messages;
117 module.exports = rule;