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");
12 const ruleName = "block-closing-brace-newline-before";
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'
21 const rule = function(expectation) {
22 return (root, result) => {
23 const validOptions = validateOptions(result, ruleName, {
25 possible: ["always", "always-multi-line", "never-multi-line"]
31 // Check both kinds of statements: rules and at-rules
32 root.walkRules(check);
33 root.walkAtRules(check);
35 function check(statement) {
36 // Return early if blockless or has empty block
37 if (!hasBlock(statement) || hasEmptyBlock(statement)) {
41 // Ignore extra semicolon
42 const after = (statement.raws.after || "").replace(/;+/, "");
43 if (after === undefined) {
47 const blockIsMultiLine = !isSingleLineString(blockString(statement));
48 const statementString = statement.toString();
50 let index = statementString.length - 2;
51 if (statementString[index - 1] === "\r") {
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);
71 expectation === "never-multi-line"
73 complain(messages.rejectedBeforeMultiLine);
76 function complain(message) {
89 rule.ruleName = ruleName;
90 rule.messages = messages;
91 module.exports = rule;