UNPKG

2.48 kBJavaScriptView Raw
1'use strict';
2
3const ruleMessages = require('../../utils/ruleMessages');
4const selectorListCommaWhitespaceChecker = require('../selectorListCommaWhitespaceChecker');
5const validateOptions = require('../../utils/validateOptions');
6const whitespaceChecker = require('../../utils/whitespaceChecker');
7
8const ruleName = 'selector-list-comma-newline-before';
9
10const messages = ruleMessages(ruleName, {
11 expectedBefore: () => 'Expected newline before ","',
12 expectedBeforeMultiLine: () => 'Expected newline before "," in a multi-line list',
13 rejectedBeforeMultiLine: () => 'Unexpected whitespace before "," in a multi-line list',
14});
15
16function rule(expectation, options, context) {
17 const checker = whitespaceChecker('newline', expectation, messages);
18
19 return (root, result) => {
20 const validOptions = validateOptions(result, ruleName, {
21 actual: expectation,
22 possible: ['always', 'always-multi-line', 'never-multi-line'],
23 });
24
25 if (!validOptions) {
26 return;
27 }
28
29 let fixData;
30
31 selectorListCommaWhitespaceChecker({
32 root,
33 result,
34 locationChecker: checker.beforeAllowingIndentation,
35 checkedRuleName: ruleName,
36 fix: context.fix
37 ? (ruleNode, index) => {
38 fixData = fixData || new Map();
39 const commaIndices = fixData.get(ruleNode) || [];
40
41 commaIndices.push(index);
42 fixData.set(ruleNode, commaIndices);
43
44 return true;
45 }
46 : null,
47 });
48
49 if (fixData) {
50 fixData.forEach((commaIndices, ruleNode) => {
51 let selector = ruleNode.raws.selector ? ruleNode.raws.selector.raw : ruleNode.selector;
52
53 commaIndices
54 .sort((a, b) => b - a)
55 .forEach((index) => {
56 let beforeSelector = selector.slice(0, index);
57 const afterSelector = selector.slice(index);
58
59 if (expectation.startsWith('always')) {
60 const spaceIndex = beforeSelector.search(/\s+$/);
61
62 if (spaceIndex >= 0) {
63 beforeSelector =
64 beforeSelector.slice(0, spaceIndex) +
65 context.newline +
66 beforeSelector.slice(spaceIndex);
67 } else {
68 beforeSelector += context.newline;
69 }
70 } else if (expectation === 'never-multi-line') {
71 beforeSelector = beforeSelector.replace(/\s*$/, '');
72 }
73
74 selector = beforeSelector + afterSelector;
75 });
76
77 if (ruleNode.raws.selector) {
78 ruleNode.raws.selector.raw = selector;
79 } else {
80 ruleNode.selector = selector;
81 }
82 });
83 }
84 };
85}
86
87rule.ruleName = ruleName;
88rule.messages = messages;
89module.exports = rule;