From 124e835bd51d3d641898d4831c8367648fd260ae Mon Sep 17 00:00:00 2001 From: krister Date: Wed, 17 Jul 2019 19:12:23 +0300 Subject: [PATCH 1/2] Fix selector-no-union-class-name throwing when parent.selector is undefined --- .../__tests__/index.js | 14 ++++++++++++++ src/rules/selector-no-union-class-name/index.js | 10 +++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/rules/selector-no-union-class-name/__tests__/index.js b/src/rules/selector-no-union-class-name/__tests__/index.js index 5a644f3f..97e81039 100644 --- a/src/rules/selector-no-union-class-name/__tests__/index.js +++ b/src/rules/selector-no-union-class-name/__tests__/index.js @@ -95,6 +95,20 @@ testRule(rule, { } `, description: "ignores an ampersand chained with an attribute" + }, + { + code: ` + @mixin demo() { + @content; + } + .a-selector { + @include demo() { + button:hover & { + background:purple + } + } + }`, + description: "should not throw an error when using nesting (issue #345)" } ], diff --git a/src/rules/selector-no-union-class-name/index.js b/src/rules/selector-no-union-class-name/index.js index c59981b1..981dc7a0 100644 --- a/src/rules/selector-no-union-class-name/index.js +++ b/src/rules/selector-no-union-class-name/index.js @@ -35,9 +35,13 @@ export default function(actual) { root.walkRules(/&/, rule => { const parentNodes = []; - parseSelector(rule.parent.selector, result, rule, fullSelector => { - fullSelector.walk(node => parentNodes.push(node)); - }); + if (rule.parent && rule.parent.selector) { + parseSelector(rule.parent.selector, result, rule, fullSelector => { + fullSelector.walk(node => parentNodes.push(node)); + }); + } + + if (parentNodes.length === 0) return; const lastParentNode = parentNodes[parentNodes.length - 1]; From c765d13722e3d0f077a55b61d73b6cf08eab7c15 Mon Sep 17 00:00:00 2001 From: Jan Nicklas Date: Thu, 18 Jul 2019 09:54:11 +0200 Subject: [PATCH 2/2] Use closest selector --- .../selector-no-union-class-name/index.js | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/rules/selector-no-union-class-name/index.js b/src/rules/selector-no-union-class-name/index.js index 981dc7a0..4555c71b 100644 --- a/src/rules/selector-no-union-class-name/index.js +++ b/src/rules/selector-no-union-class-name/index.js @@ -35,8 +35,10 @@ export default function(actual) { root.walkRules(/&/, rule => { const parentNodes = []; - if (rule.parent && rule.parent.selector) { - parseSelector(rule.parent.selector, result, rule, fullSelector => { + const selector = getSelectorFromRule(rule.parent); + + if (selector) { + parseSelector(selector, result, rule, fullSelector => { fullSelector.walk(node => parentNodes.push(node)); }); } @@ -67,3 +69,21 @@ export default function(actual) { }); }; } + +/** + * Searches for the closest rule which + * has a selector and returns the selector + * @returns {string|undefined} + */ +function getSelectorFromRule(rule) { + // All non at-rules have their own selector + if (rule.selector !== undefined) { + return rule.selector; + } + + // At-rules like @mixin don't have a selector themself + // but their parents might have one + if (rule.parent) { + return getSelectorFromRule(rule.parent); + } +}