1 | 'use strict';
|
2 |
|
3 | function rule(analyzer) {
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 | var redundantChildSelectors = {
|
10 | 'ul': ['li'],
|
11 | 'ol': ['li'],
|
12 | 'select': ['option'],
|
13 | 'table': ['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 |
|
23 | if (noExpressions < 2) {
|
24 | return;
|
25 | }
|
26 |
|
27 |
|
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 |
|
41 | if (expressions[nodeIndex].combinator !== ' ') {
|
42 | return;
|
43 | }
|
44 |
|
45 |
|
46 |
|
47 | nextNode = selectorNodeNames[nodeIndex + 1];
|
48 |
|
49 | if (redundantNodes.indexOf(nextNode) > -1) {
|
50 |
|
51 |
|
52 |
|
53 | curExpression = expressions[nodeIndex];
|
54 |
|
55 | if (curExpression.pseudos || curExpression.attributes) {
|
56 | return;
|
57 | }
|
58 |
|
59 |
|
60 |
|
61 |
|
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 |
|
74 | rule.description = 'Reports redundant child nodes selectors';
|
75 | module.exports = rule;
|