UNPKG

2.5 kBJavaScriptView Raw
1'use strict';
2
3const blockString = require('../../utils/blockString');
4const hasBlock = require('../../utils/hasBlock');
5const hasEmptyBlock = require('../../utils/hasEmptyBlock');
6const report = require('../../utils/report');
7const ruleMessages = require('../../utils/ruleMessages');
8const validateOptions = require('../../utils/validateOptions');
9const whitespaceChecker = require('../../utils/whitespaceChecker');
10
11const ruleName = 'block-closing-brace-space-before';
12
13const messages = ruleMessages(ruleName, {
14 expectedBefore: () => 'Expected single space before "}"',
15 rejectedBefore: () => 'Unexpected whitespace before "}"',
16 expectedBeforeSingleLine: () => 'Expected single space before "}" of a single-line block',
17 rejectedBeforeSingleLine: () => 'Unexpected whitespace before "}" of a single-line block',
18 expectedBeforeMultiLine: () => 'Expected single space before "}" of a multi-line block',
19 rejectedBeforeMultiLine: () => 'Unexpected whitespace before "}" of a multi-line block',
20});
21
22function rule(expectation, options, context) {
23 const checker = whitespaceChecker('space', expectation, messages);
24
25 return (root, result) => {
26 const validOptions = validateOptions(result, ruleName, {
27 actual: expectation,
28 possible: [
29 'always',
30 'never',
31 'always-single-line',
32 'never-single-line',
33 'always-multi-line',
34 'never-multi-line',
35 ],
36 });
37
38 if (!validOptions) {
39 return;
40 }
41
42 // Check both kinds of statement: rules and at-rules
43 root.walkRules(check);
44 root.walkAtRules(check);
45
46 function check(statement) {
47 // Return early if blockless or has empty block
48 if (!hasBlock(statement) || hasEmptyBlock(statement)) {
49 return;
50 }
51
52 const source = blockString(statement);
53 const statementString = statement.toString();
54
55 let index = statementString.length - 2;
56
57 if (statementString[index - 1] === '\r') {
58 index -= 1;
59 }
60
61 checker.before({
62 source,
63 index: source.length - 1,
64 err: (msg) => {
65 if (context.fix) {
66 if (expectation.startsWith('always')) {
67 statement.raws.after = statement.raws.after.replace(/\s*$/, ' ');
68
69 return;
70 }
71
72 if (expectation.startsWith('never')) {
73 statement.raws.after = statement.raws.after.replace(/\s*$/, '');
74
75 return;
76 }
77 }
78
79 report({
80 message: msg,
81 node: statement,
82 index,
83 result,
84 ruleName,
85 });
86 },
87 });
88 }
89 };
90}
91
92rule.ruleName = ruleName;
93rule.messages = messages;
94module.exports = rule;