UNPKG

2.18 kBJavaScriptView Raw
1'use strict';
2
3const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule');
4const parseSelector = require('../../utils/parseSelector');
5const report = require('../../utils/report');
6const ruleMessages = require('../../utils/ruleMessages');
7const validateOptions = require('../../utils/validateOptions');
8
9const ruleName = 'selector-descendant-combinator-no-non-space';
10
11const messages = ruleMessages(ruleName, {
12 rejected: (nonSpaceCharacter) => `Unexpected "${nonSpaceCharacter}"`,
13});
14
15function rule(expectation, options, context) {
16 return (root, result) => {
17 const validOptions = validateOptions(result, ruleName, {
18 actual: expectation,
19 });
20
21 if (!validOptions) {
22 return;
23 }
24
25 root.walkRules((rule) => {
26 if (!isStandardSyntaxRule(rule)) {
27 return;
28 }
29
30 let hasFixed = false;
31 const selector = rule.raws.selector ? rule.raws.selector.raw : rule.selector;
32
33 // Return early for selectors containing comments
34 // TODO: renable when parser and stylelint are compatible
35 if (selector.includes('/*')) return;
36
37 const fixedSelector = parseSelector(selector, result, rule, (fullSelector) => {
38 fullSelector.walkCombinators((combinatorNode) => {
39 if (combinatorNode.value !== ' ') {
40 return;
41 }
42
43 const value = combinatorNode.toString();
44
45 if (
46 value.includes(' ') ||
47 value.includes('\t') ||
48 value.includes('\n') ||
49 value.includes('\r')
50 ) {
51 if (context.fix && /^\s+$/.test(value)) {
52 hasFixed = true;
53 combinatorNode.raws.value = ' ';
54 combinatorNode.rawSpaceBefore = combinatorNode.rawSpaceBefore.replace(/^\s+/, '');
55 combinatorNode.rawSpaceAfter = combinatorNode.rawSpaceAfter.replace(/\s+$/, '');
56
57 return;
58 }
59
60 report({
61 result,
62 ruleName,
63 message: messages.rejected(value),
64 node: rule,
65 index: combinatorNode.sourceIndex,
66 });
67 }
68 });
69 });
70
71 if (hasFixed) {
72 if (!rule.raws.selector) {
73 rule.selector = fixedSelector;
74 } else {
75 rule.raws.selector.raw = fixedSelector;
76 }
77 }
78 });
79 };
80}
81
82rule.ruleName = ruleName;
83rule.messages = messages;
84module.exports = rule;