UNPKG

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