UNPKG

2.42 kBJavaScriptView Raw
1'use strict';
2
3const atRuleParamIndex = require('../../utils/atRuleParamIndex');
4const findMediaOperator = require('../findMediaOperator');
5const report = require('../../utils/report');
6const ruleMessages = require('../../utils/ruleMessages');
7const validateOptions = require('../../utils/validateOptions');
8const whitespaceChecker = require('../../utils/whitespaceChecker');
9
10const ruleName = 'media-feature-range-operator-space-before';
11
12const messages = ruleMessages(ruleName, {
13 expectedBefore: () => 'Expected single space before range operator',
14 rejectedBefore: () => 'Unexpected whitespace before range operator',
15});
16
17function rule(expectation, options, context) {
18 const checker = whitespaceChecker('space', expectation, messages);
19
20 return (root, result) => {
21 const validOptions = validateOptions(result, ruleName, {
22 actual: expectation,
23 possible: ['always', 'never'],
24 });
25
26 if (!validOptions) {
27 return;
28 }
29
30 root.walkAtRules(/^media$/i, (atRule) => {
31 const fixOperatorIndices = [];
32 const fix = context.fix ? (index) => fixOperatorIndices.push(index) : null;
33
34 findMediaOperator(atRule, (match, params, node) => {
35 checkBeforeOperator(match, params, node, fix);
36 });
37
38 if (fixOperatorIndices.length) {
39 let params = atRule.raws.params ? atRule.raws.params.raw : atRule.params;
40
41 fixOperatorIndices
42 .sort((a, b) => b - a)
43 .forEach((index) => {
44 const beforeOperator = params.slice(0, index);
45 const afterOperator = params.slice(index);
46
47 if (expectation === 'always') {
48 params = beforeOperator.replace(/\s*$/, ' ') + afterOperator;
49 } else if (expectation === 'never') {
50 params = beforeOperator.replace(/\s*$/, '') + afterOperator;
51 }
52 });
53
54 if (atRule.raws.params) {
55 atRule.raws.params.raw = params;
56 } else {
57 atRule.params = params;
58 }
59 }
60 });
61
62 function checkBeforeOperator(match, params, node, fix) {
63 // The extra `+ 1` is because the match itself contains
64 // the character before the operator
65 checker.before({
66 source: params,
67 index: match.startIndex,
68 err: (m) => {
69 if (fix) {
70 fix(match.startIndex);
71
72 return;
73 }
74
75 report({
76 message: m,
77 node,
78 index: match.startIndex - 1 + atRuleParamIndex(node),
79 result,
80 ruleName,
81 });
82 },
83 });
84 }
85 };
86}
87
88rule.ruleName = ruleName;
89rule.messages = messages;
90module.exports = rule;