From a6d42575bc588f39cb3b7b6304080d1e343c617e Mon Sep 17 00:00:00 2001 From: Pixel Date: Sun, 27 Sep 2026 15:18:45 +0300 Subject: [PATCH] fix: report each disallowed attribute location in `selector-complexity` --- src/rules/selector-complexity.js | 13 ++-- tests/rules/selector-complexity.test.js | 84 +++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 9 deletions(-) diff --git a/src/rules/selector-complexity.js b/src/rules/selector-complexity.js index 8b7773b7..b29fdb09 100644 --- a/src/rules/selector-complexity.js +++ b/src/rules/selector-complexity.js @@ -310,7 +310,6 @@ export default /** @satisfies {SelectorComplexityRuleDefinition} */ ({ selectors, "PseudoElementSelector", ); - const attributeNames = attributeSelectors.map(s => s.name.name); const attributeMatchers = attributeSelectors .map(child => child.matcher) .filter(Boolean); @@ -434,16 +433,12 @@ export default /** @satisfies {SelectorComplexityRuleDefinition} */ ({ } if (disallowAttributes.length > 0) { - let disallowAttributesLocation; - for (const attributeName of attributeNames) { + for (const selectorNode of attributeSelectors) { + const attributeName = selectorNode.name.name; + if (disallowAttributes.includes(attributeName)) { - disallowAttributesLocation = - attributeSelectors.find( - selector => - selector.name.name === attributeName, - ).name.loc; context.report({ - loc: disallowAttributesLocation, + loc: selectorNode.name.loc, messageId: "disallowedSelectors", data: { selectorName: attributeName, diff --git a/tests/rules/selector-complexity.test.js b/tests/rules/selector-complexity.test.js index e0bb33a2..74724f12 100644 --- a/tests/rules/selector-complexity.test.js +++ b/tests/rules/selector-complexity.test.js @@ -796,6 +796,90 @@ ruleTester.run("selector-complexity", rule, { }, ], }, + { + code: "[data-foo][data-bar][data-foo] {}", + options: [{ disallowAttributes: ["data-foo"] }], + errors: [ + { + messageId: "disallowedSelectors", + data: { + selectorName: "data-foo", + selector: "attribute", + }, + line: 1, + column: 2, + endLine: 1, + endColumn: 10, + }, + { + messageId: "disallowedSelectors", + data: { + selectorName: "data-foo", + selector: "attribute", + }, + line: 1, + column: 22, + endLine: 1, + endColumn: 30, + }, + ], + }, + { + code: "[alt] img[alt] {}", + options: [{ disallowAttributes: ["alt"] }], + errors: [ + { + messageId: "disallowedSelectors", + data: { + selectorName: "alt", + selector: "attribute", + }, + line: 1, + column: 2, + endLine: 1, + endColumn: 5, + }, + { + messageId: "disallowedSelectors", + data: { + selectorName: "alt", + selector: "attribute", + }, + line: 1, + column: 11, + endLine: 1, + endColumn: 14, + }, + ], + }, + { + code: "a[href][href*='x'] {}", + options: [{ disallowAttributes: ["href"] }], + errors: [ + { + messageId: "disallowedSelectors", + data: { + selectorName: "href", + selector: "attribute", + }, + line: 1, + column: 3, + endLine: 1, + endColumn: 7, + }, + { + messageId: "disallowedSelectors", + data: { + selectorName: "href", + selector: "attribute", + }, + line: 1, + column: 9, + endLine: 1, + endColumn: 13, + }, + ], + }, { code: "[class*='foo'] {}", options: [{ disallowAttributeMatchers: ["*="] }],