@mrhenry/stylelint-mrhenry-nesting 3.0.1 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.mjs +37 -0
  2. package/package.json +4 -3
package/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import stylelint from 'stylelint';
2
2
  import selectorParser from 'postcss-selector-parser';
3
+ import { compare, selectorSpecificity } from '@csstools/selector-specificity';
3
4
 
4
5
  const ruleName = "@mrhenry/stylelint-mrhenry-nesting";
5
6
  const messages = stylelint.utils.ruleMessages(ruleName, {
@@ -18,6 +19,9 @@ const messages = stylelint.utils.ruleMessages(ruleName, {
18
19
  rejectedNestingSelectorIncorrectShape: () => {
19
20
  return `Nested selectors must be compound selectors, starting with "&" and followed by a single pseudo selector.`;
20
21
  },
22
+ rejectedMixedSpecificity: () => {
23
+ return `Each selector of a list in a nested context take the specificity of the most specific list item. This can lead to unexpected results.`;
24
+ },
21
25
  });
22
26
 
23
27
  const meta = {
@@ -101,6 +105,39 @@ const ruleFunction = (primaryOption, secondaryOption, context) => {
101
105
  });
102
106
  });
103
107
 
108
+ postcssRoot.walkRules((rule) => {
109
+ const containsBlocks = rule.nodes && rule.nodes.some((node) => node.type === 'rule' || node.type === 'atrule');
110
+ if (!containsBlocks) {
111
+ return;
112
+ }
113
+
114
+ const selectorAST = selectorParser().astSync(rule.selector);
115
+ if (selectorAST.nodes?.length < 2) {
116
+ return;
117
+ }
118
+
119
+ const specificities = selectorAST.nodes.map((node) => {
120
+ return selectorSpecificity(node);
121
+ });
122
+
123
+ const specificitiesAreEqual = specificities.every((specificity) => {
124
+ return compare(specificity, specificities[0]) === 0;
125
+ });
126
+
127
+ if (specificitiesAreEqual) {
128
+ return;
129
+ }
130
+
131
+ stylelint.utils.report({
132
+ message: messages.rejectedMixedSpecificity(),
133
+ node: rule,
134
+ index: 0,
135
+ endIndex: rule.selector.length,
136
+ result: postcssResult,
137
+ ruleName,
138
+ });
139
+ });
140
+
104
141
  postcssRoot.walkRules((rule) => {
105
142
  {
106
143
  let rulesDepth = 1;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrhenry/stylelint-mrhenry-nesting",
3
- "version": "3.0.1",
3
+ "version": "3.1.1",
4
4
  "description": "Mr. Henry's preferred way of writing nested CSS",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -28,12 +28,13 @@
28
28
  "stylelint-plugin"
29
29
  ],
30
30
  "dependencies": {
31
- "postcss-selector-parser": "^6.0.11"
31
+ "@csstools/selector-specificity": "^4.0.0",
32
+ "postcss-selector-parser": "^6.1.1"
32
33
  },
33
34
  "peerDependencies": {
34
35
  "stylelint": "^16.0.0"
35
36
  },
36
37
  "devDependencies": {
37
- "stylelint": "^16.0.2"
38
+ "stylelint": "^16.7.0"
38
39
  }
39
40
  }