UNPKG

2.11 kBJavaScriptView Raw
1'use strict';
2
3function rule(analyzer) {
4 // definition of redundant child nodes selectors (see #51 for the initial idea):
5 // ul li
6 // ol li
7 // table tr
8 // table th
9 var redundantChildSelectors = {
10 'ul': ['li'],
11 'ol': ['li'],
12 'select': ['option'],
13 'table': ['tr', 'th'], // e.g. table can not be followed by any of tr / th
14 'tr': ['td', 'th'],
15 };
16
17 analyzer.setMetric('redundantChildNodesSelectors');
18
19 analyzer.on('selector', function(rule, selector, expressions) {
20 var noExpressions = expressions.length;
21
22 // check more complex selectors only
23 if (noExpressions < 2) {
24 return;
25 }
26
27 // converts "ul#foo > li.test" selector into ['ul', 'li'] list
28 var selectorNodeNames = expressions.map(function(item) {
29 return item.tag;
30 });
31
32 Object.keys(redundantChildSelectors).forEach(function(nodeName) {
33 var nodeIndex = selectorNodeNames.indexOf(nodeName),
34 nextNode,
35 curExpression,
36 combinator,
37 redundantNodes = redundantChildSelectors[nodeName];
38
39 if ((nodeIndex > -1) && (nodeIndex < noExpressions - 1)) {
40 // skip cases like the following: "article > ul li"
41 if (expressions[nodeIndex].combinator !== ' ') {
42 return;
43 }
44
45 // we've found the possible offender, get the next node in the selector
46 // and compare it against rules in redundantChildSelectors
47 nextNode = selectorNodeNames[nodeIndex + 1];
48
49 if (redundantNodes.indexOf(nextNode) > -1) {
50 // skip selectors that match:
51 // - by attributes - foo[class*=bar]
52 // - by pseudo attributes - foo:lang(fo)
53 curExpression = expressions[nodeIndex];
54
55 if (curExpression.pseudos || curExpression.attributes) {
56 return;
57 }
58
59 // only the following combinator can match:
60 // ul li
61 // ul > li
62 combinator = expressions[nodeIndex + 1].combinator;
63
64 if ((combinator === ' ') || (combinator === '>')) {
65 analyzer.incrMetric('redundantChildNodesSelectors');
66 analyzer.addOffender('redundantChildNodesSelectors', selector);
67 }
68 }
69 }
70 });
71 });
72}
73
74rule.description = 'Reports redundant child nodes selectors';
75module.exports = rule;