UNPKG

1.64 kBJavaScriptView Raw
1'use strict';
2
3function rule(analyzer) {
4 analyzer.setMetric('redundantBodySelectors');
5
6 analyzer.on('selector', function(rule, selector, expressions) {
7 var noExpressions = expressions.length;
8
9 // check more complex selectors only
10 if (noExpressions < 2) {
11 return;
12 }
13
14 var firstTag = expressions[0].tag,
15 firstHasClass = !!expressions[0].classList,
16 isDescendantCombinator = (expressions[1].combinator === '>'),
17 isShortExpression = (noExpressions === 2),
18 isRedundant = true; // always expect the worst ;)
19
20 // first, let's find the body tag selector in the expression
21 var bodyIndex = expressions.
22 map(function(item) {
23 return item.tag;
24 }).
25 indexOf('body');
26
27 // body selector not found - skip the rules that follow
28 if (bodyIndex < 0) {
29 return;
30 }
31
32 // matches "html > body"
33 // matches "html.modal-popup-mode body" (issue #44)
34 if ((firstTag === 'html') && (bodyIndex === 1) && (isDescendantCombinator || isShortExpression)) {
35 isRedundant = false;
36 }
37 // matches "body > .bar" (issue #82)
38 else if ((bodyIndex === 0) && isDescendantCombinator) {
39 isRedundant = false;
40 }
41 // matches "body.foo ul li a"
42 else if ((bodyIndex === 0) && firstHasClass) {
43 isRedundant = false;
44 }
45 // matches ".has-modal > body" (issue #49)
46 else if (firstHasClass && (bodyIndex === 1) && isDescendantCombinator) {
47 isRedundant = false;
48 }
49
50 // report he redundant body selector
51 if (isRedundant) {
52 analyzer.incrMetric('redundantBodySelectors');
53 analyzer.addOffender('redundantBodySelectors', selector);
54 }
55 });
56}
57
58rule.description = 'Reports redundant body selectors';
59module.exports = rule;