From 737f1ecde0f6879046469384718dd1fbd3fc1e15 Mon Sep 17 00:00:00 2001 From: Adam Wathan Date: Wed, 12 Jun 2019 08:57:47 -0400 Subject: [PATCH 1/3] Append variant pseudo-selectors after classes instead of replacing entire selector --- __tests__/variantsAtRule.test.js | 21 +++++++++++++++++++++ src/lib/substituteVariantsAtRules.js | 10 ++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/__tests__/variantsAtRule.test.js b/__tests__/variantsAtRule.test.js index af81375e5ca9..71831d240253 100644 --- a/__tests__/variantsAtRule.test.js +++ b/__tests__/variantsAtRule.test.js @@ -218,6 +218,27 @@ test('variants are generated in the order specified', () => { }) }) +test('the built-in variant pseudo-selectors are appended before any pseudo-elements', () => { + const input = ` + @variants hover, focus-within, focus, active { + .placeholder-yellow::placeholder { color: yellow; } + } + ` + + const output = ` + .placeholder-yellow::placeholder { color: yellow; } + .hover\\:placeholder-yellow:hover::placeholder { color: yellow; } + .focus-within\\:placeholder-yellow:focus-within::placeholder { color: yellow; } + .focus\\:placeholder-yellow:focus::placeholder { color: yellow; } + .active\\:placeholder-yellow:active::placeholder { color: yellow; } + ` + + return run(input).then(result => { + expect(result.css).toMatchCss(output) + expect(result.warnings().length).toBe(0) + }) +}) + test('the default variant can be generated in a specified position', () => { const input = ` @variants focus, active, default, hover { diff --git a/src/lib/substituteVariantsAtRules.js b/src/lib/substituteVariantsAtRules.js index 73981d6c3099..3de1cb70be1d 100644 --- a/src/lib/substituteVariantsAtRules.js +++ b/src/lib/substituteVariantsAtRules.js @@ -1,12 +1,18 @@ import _ from 'lodash' import postcss from 'postcss' +import selectorParser from 'postcss-selector-parser' import generateVariantFunction from '../util/generateVariantFunction' import e from '../util/escapeClassName' function generatePseudoClassVariant(pseudoClass) { return generateVariantFunction(({ modifySelectors, separator }) => { - return modifySelectors(({ className }) => { - return `.${e(`${pseudoClass}${separator}${className}`)}:${pseudoClass}` + return modifySelectors(({ selector }) => { + return selectorParser(selectors => { + selectors.walkClasses(sel => { + sel.value = `${pseudoClass}${separator}${sel.value}` + sel.parent.insertAfter(sel, selectorParser.pseudo({ value: `:${pseudoClass}` })) + }) + }).processSync(selector) }) }) } From eeb29472041175c97633addbc4219eae82ee7ecc Mon Sep 17 00:00:00 2001 From: Adam Wathan Date: Thu, 13 Jun 2019 07:52:37 -0400 Subject: [PATCH 2/3] Properly handle pseudo-elements with group-hover variant --- __tests__/variantsAtRule.test.js | 3 ++- src/lib/substituteVariantsAtRules.js | 9 +++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/__tests__/variantsAtRule.test.js b/__tests__/variantsAtRule.test.js index 71831d240253..88dd5c1dfcd2 100644 --- a/__tests__/variantsAtRule.test.js +++ b/__tests__/variantsAtRule.test.js @@ -220,7 +220,7 @@ test('variants are generated in the order specified', () => { test('the built-in variant pseudo-selectors are appended before any pseudo-elements', () => { const input = ` - @variants hover, focus-within, focus, active { + @variants hover, focus-within, focus, active, group-hover { .placeholder-yellow::placeholder { color: yellow; } } ` @@ -231,6 +231,7 @@ test('the built-in variant pseudo-selectors are appended before any pseudo-eleme .focus-within\\:placeholder-yellow:focus-within::placeholder { color: yellow; } .focus\\:placeholder-yellow:focus::placeholder { color: yellow; } .active\\:placeholder-yellow:active::placeholder { color: yellow; } + .group:hover .group-hover\\:placeholder-yellow::placeholder { color: yellow; } ` return run(input).then(result => { diff --git a/src/lib/substituteVariantsAtRules.js b/src/lib/substituteVariantsAtRules.js index 3de1cb70be1d..06d9f31d2306 100644 --- a/src/lib/substituteVariantsAtRules.js +++ b/src/lib/substituteVariantsAtRules.js @@ -24,8 +24,13 @@ function ensureIncludesDefault(variants) { const defaultVariantGenerators = { default: generateVariantFunction(() => {}), 'group-hover': generateVariantFunction(({ modifySelectors, separator }) => { - return modifySelectors(({ className }) => { - return `.group:hover .${e(`group-hover${separator}${className}`)}` + return modifySelectors(({ selector }) => { + return selectorParser(selectors => { + selectors.walkClasses(sel => { + sel.value = `group-hover${separator}${sel.value}` + sel.parent.insertBefore(sel, selectorParser().astSync('.group:hover ')) + }) + }).processSync(selector) }) }), hover: generatePseudoClassVariant('hover'), From a80720a8c67b9461e7d8395f693ed952750bbe32 Mon Sep 17 00:00:00 2001 From: Adam Wathan Date: Thu, 20 Jun 2019 11:24:54 -0400 Subject: [PATCH 3/3] Remove unused import --- src/lib/substituteVariantsAtRules.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lib/substituteVariantsAtRules.js b/src/lib/substituteVariantsAtRules.js index 06d9f31d2306..da0ce88e1d78 100644 --- a/src/lib/substituteVariantsAtRules.js +++ b/src/lib/substituteVariantsAtRules.js @@ -2,7 +2,6 @@ import _ from 'lodash' import postcss from 'postcss' import selectorParser from 'postcss-selector-parser' import generateVariantFunction from '../util/generateVariantFunction' -import e from '../util/escapeClassName' function generatePseudoClassVariant(pseudoClass) { return generateVariantFunction(({ modifySelectors, separator }) => {