UNPKG

2 kBJavaScriptView Raw
1'use strict';
2
3const isLogicalCombination = require('../../utils/isLogicalCombination');
4const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule');
5const parseSelector = require('../../utils/parseSelector');
6const report = require('../../utils/report');
7const resolvedNestedSelector = require('postcss-resolve-nested-selector');
8const ruleMessages = require('../../utils/ruleMessages');
9const validateOptions = require('../../utils/validateOptions');
10
11const ruleName = 'selector-max-class';
12
13const messages = ruleMessages(ruleName, {
14 expected: (selector, max) =>
15 `Expected "${selector}" to have no more than ${max} ${max === 1 ? 'class' : 'classes'}`,
16});
17
18function rule(max) {
19 return (root, result) => {
20 const validOptions = validateOptions(result, ruleName, {
21 actual: max,
22 possible: [
23 function (max) {
24 return typeof max === 'number' && max >= 0;
25 },
26 ],
27 });
28
29 if (!validOptions) {
30 return;
31 }
32
33 function checkSelector(selectorNode, ruleNode) {
34 const count = selectorNode.reduce((total, childNode) => {
35 // Only traverse inside actual selectors and logical combinations
36 if (childNode.type === 'selector' || isLogicalCombination(childNode)) {
37 checkSelector(childNode, ruleNode);
38 }
39
40 return (total += childNode.type === 'class' ? 1 : 0);
41 }, 0);
42
43 if (selectorNode.type !== 'root' && selectorNode.type !== 'pseudo' && count > max) {
44 report({
45 ruleName,
46 result,
47 node: ruleNode,
48 message: messages.expected(selectorNode, max),
49 word: selectorNode,
50 });
51 }
52 }
53
54 root.walkRules((ruleNode) => {
55 if (!isStandardSyntaxRule(ruleNode)) {
56 return;
57 }
58
59 ruleNode.selectors.forEach((selector) => {
60 resolvedNestedSelector(selector, ruleNode).forEach((resolvedSelector) => {
61 parseSelector(resolvedSelector, result, ruleNode, (container) =>
62 checkSelector(container, ruleNode),
63 );
64 });
65 });
66 });
67 };
68}
69
70rule.ruleName = ruleName;
71rule.messages = messages;
72module.exports = rule;