From 80bfade3f302118ca1c1ab934df3aa4154437675 Mon Sep 17 00:00:00 2001 From: Estevan Maito Date: Fri, 12 Jun 2020 17:00:15 -0300 Subject: [PATCH] fix(plugin): improve classes generation when a pseudo class is present Uses the same approach as Tailwind CSS for variants generation. fix #2 --- src/index.js | 108 ++++++++++++++++++--------------------------------- 1 file changed, 37 insertions(+), 71 deletions(-) diff --git a/src/index.js b/src/index.js index 1bcfd31..a31ab02 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,6 @@ const selectorParser = require('postcss-selector-parser') -module.exports = ({ addVariant, theme, e }) => { +module.exports = ({ addVariant, theme }) => { const themeVariants = theme('themeVariants') if (!themeVariants) { throw new Error('tailwindcss-multi-theme expects a themeVariants property in theme.') @@ -16,96 +16,62 @@ module.exports = ({ addVariant, theme, e }) => { ) } - themeVariants.forEach((tv) => { - const root = `.theme-${tv} ` - - addVariant(`${tv}`, ({ modifySelectors, separator }) => { + function generatePseudoClassVariant(themeVariant, pseudoClass, selectorPrefix = pseudoClass) { + const root = `.theme-${themeVariant} ` + addVariant(`${themeVariant}:${selectorPrefix}`, ({ modifySelectors, separator }) => { modifySelectors(({ selector }) => { return selectorParser((selectors) => { selectors.walkClasses((sel) => { - sel.value = `${tv}${separator}${sel.value}` + sel.value = `${themeVariant}${separator}${selectorPrefix}${separator}${sel.value}` sel.parent.insertBefore(sel, selectorParser().astSync(root)) + sel.parent.insertAfter(sel, selectorParser.pseudo({ value: `:${pseudoClass}` })) }) }).processSync(selector) }) }) + } - addVariant(`${tv}:group-hover`, ({ modifySelectors, separator }) => { - modifySelectors(({ className }) => { - return `${root} .group:hover .${e(`${tv}${separator}group-hover${separator}${className}`)}` - }) - }) - - addVariant(`${tv}:group-focus`, ({ modifySelectors, separator }) => { - modifySelectors(({ className }) => { - return `${root} .group:focus .${e(`${tv}${separator}group-focus${separator}${className}`)}` - }) - }) - - addVariant(`${tv}:focus-within`, ({ modifySelectors, separator }) => { - modifySelectors(({ className }) => { - return `${root}.${e(`${tv}${separator}focus-within${separator}${className}`)}:focus-within` - }) - }) - - addVariant(`${tv}:first`, ({ modifySelectors, separator }) => { - modifySelectors(({ className }) => { - return `${root}.${e(`${tv}${separator}first${separator}${className}`)}:first-child` - }) - }) - - addVariant(`${tv}:last`, ({ modifySelectors, separator }) => { - modifySelectors(({ className }) => { - return `${root}.${e(`${tv}${separator}last${separator}${className}`)}:last-child` - }) - }) - - addVariant(`${tv}:odd`, ({ modifySelectors, separator }) => { - modifySelectors(({ className }) => { - return `${root}.${e(`${tv}${separator}odd${separator}${className}`)}:nth-child(odd)` - }) - }) - - addVariant(`${tv}:even`, ({ modifySelectors, separator }) => { - modifySelectors(({ className }) => { - return `${root}.${e(`${tv}${separator}even${separator}${className}`)}:nth-child(even)` - }) - }) - - addVariant(`${tv}:hover`, ({ modifySelectors, separator }) => { - modifySelectors(({ className }) => { - return `${root}.${e(`${tv}${separator}hover${separator}${className}`)}:hover` + function generateGroupVariant(themeVariant, pseudoClass, selectorPrefix) { + const root = `.theme-${themeVariant} ` + addVariant(`${themeVariant}:${selectorPrefix}`, ({ modifySelectors, separator }) => { + modifySelectors(({ selector }) => { + return selectorParser((selectors) => { + selectors.walkClasses((sel) => { + sel.value = `${themeVariant}${separator}${selectorPrefix}${separator}${sel.value}` + sel.parent.insertBefore(sel, selectorParser().astSync(`${root}.${pseudoClass} `)) + }) + }).processSync(selector) }) }) + } - addVariant(`${tv}:focus`, ({ modifySelectors, separator }) => { + function generateDefaultVariant(themeVariant) { + const root = `.theme-${themeVariant} ` + addVariant(`${themeVariant}`, ({ modifySelectors, separator }) => { modifySelectors(({ selector }) => { return selectorParser((selectors) => { selectors.walkClasses((sel) => { - sel.value = `${tv}${separator}focus${separator}${sel.value}` + sel.value = `${themeVariant}${separator}${sel.value}` sel.parent.insertBefore(sel, selectorParser().astSync(root)) - sel.parent.insertAfter(sel, selectorParser.pseudo({ value: ':focus' })) }) }).processSync(selector) }) }) + } - addVariant(`${tv}:active`, ({ modifySelectors, separator }) => { - modifySelectors(({ className }) => { - return `${root}.${e(`${tv}${separator}active${separator}${className}`)}:active` - }) - }) - - addVariant(`${tv}:visited`, ({ modifySelectors, separator }) => { - modifySelectors(({ className }) => { - return `${root}.${e(`${tv}${separator}visited${separator}${className}`)}:visited` - }) - }) - - addVariant(`${tv}:disabled`, ({ modifySelectors, separator }) => { - modifySelectors(({ className }) => { - return `${root}.${e(`${tv}${separator}disabled${separator}${className}`)}:disabled` - }) - }) + themeVariants.forEach((tv) => { + generateDefaultVariant(tv) + generateGroupVariant(tv, 'group:hover', 'group-hover') + generateGroupVariant(tv, 'group:focus', 'group-focus') + generatePseudoClassVariant(tv, 'focus') + generatePseudoClassVariant(tv, 'hover') + generatePseudoClassVariant(tv, 'active') + generatePseudoClassVariant(tv, 'visited') + generatePseudoClassVariant(tv, 'disabled') + generatePseudoClassVariant(tv, 'focus-within') + generatePseudoClassVariant(tv, 'first-child', 'first') + generatePseudoClassVariant(tv, 'last-child', 'last') + generatePseudoClassVariant(tv, 'nth-child(even)', 'even') + generatePseudoClassVariant(tv, 'nth-child(odd)', 'odd') }) }