From 18d3da2dcfa4f4cc1318a7c8a717a51b2c6f4d4f Mon Sep 17 00:00:00 2001 From: Johnny Zabala Date: Sat, 20 Jun 2020 16:43:47 -0400 Subject: [PATCH] feat(variants): add independent rtl and ltr variants --- README.md | 6 +-- src/index.js | 47 ++++++++++++--------- tests/variantGenerator.test.js | 77 +++++++++++++++++++++++++++++++--- 3 files changed, 102 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index e64986c..4eb68a7 100644 --- a/README.md +++ b/README.md @@ -33,9 +33,9 @@ Finally, you can use the plugin and add it to modules you want to use it with. ```js variants: { - float: ['responsive', 'direction'], - margin: ['responsive', 'direction'], - padding: ['responsive', 'direction'], + float: ['responsive', 'direction'], // adds both rtl and ltr variants + margin: ['responsive', 'rtl'], // only adds rtl variant + padding: ['responsive', 'ltr'], // only adds ltr variant }, ``` diff --git a/src/index.js b/src/index.js index e4a5bef..ec92a46 100644 --- a/src/index.js +++ b/src/index.js @@ -1,33 +1,42 @@ function addSelectors(container, modifierFunction) { const rules = []; - container.walkRules(rule => { - const selectors = rule.selectors.map(selector => modifierFunction(selector.slice(1))); + container.walkRules((rule) => { + const selectors = rule.selectors.map((selector) => modifierFunction(selector.slice(1))); rules.push(rule.clone({ selectors })); }); return rules; } +const RTL_VARIANT = 'rtl'; +const LTR_VARIANT = 'ltr'; + function generator({ addVariant, e }) { - addVariant('direction', ({ container, separator }) => { - const result = container.clone({ nodes: [] }); - - ['ltr', 'rtl'].forEach(dir => { - result.nodes = result.nodes.concat( - addSelectors(container, className => { - return [ - `[dir='${dir}'] .${dir}${e(separator)}${className}`, - `[dir='${dir}'].${dir}${e(separator)}${className}`, - ]; - }) - ); - }); - - return result; - }); + addVariant('direction', variantGenerator([LTR_VARIANT, RTL_VARIANT])); + addVariant(LTR_VARIANT, variantGenerator([LTR_VARIANT])); + addVariant(RTL_VARIANT, variantGenerator([RTL_VARIANT])); + + function variantGenerator(variants) { + return ({ container, separator }) => { + const result = container.clone({ nodes: [] }); + + variants.forEach((dir) => { + result.nodes = result.nodes.concat( + addSelectors(container, (className) => { + return [ + `[dir='${dir}'] .${dir}${e(separator)}${className}`, + `[dir='${dir}'].${dir}${e(separator)}${className}`, + ]; + }) + ); + }); + + return result; + }; + } } -module.exports = function() { +module.exports = function () { return generator; }; diff --git a/tests/variantGenerator.test.js b/tests/variantGenerator.test.js index 5654fef..90d0be1 100644 --- a/tests/variantGenerator.test.js +++ b/tests/variantGenerator.test.js @@ -2,6 +2,14 @@ const postcss = require('postcss'); const tailwindcss = require('tailwindcss'); const config = require('./config'); +function expectMatch(input, output) { + return postcss([tailwindcss(config)]) + .process(input, { from: undefined }) + .then((result) => { + expect(result.css).toMatchCss(output); + expect(result.warnings().length).toBe(0); + }); +} test('it generates direction variants', () => { const input = ` @variants direction { @@ -40,10 +48,67 @@ test('it generates direction variants', () => { } `; - return postcss([tailwindcss(config)]) - .process(input, { from: undefined }) - .then(result => { - expect(result.css).toMatchCss(output); - expect(result.warnings().length).toBe(0); - }); + return expectMatch(input, output); +}); + +test('it generates rtl variant', () => { + const input = ` + @variants rtl { + .banana { color: yellow; } + .tomato { color: red; } + } + `; + + const output = ` + .banana { + color: yellow; + } + + .tomato { + color: red; + } + + [dir='rtl'] .rtl\\:banana, + [dir='rtl'].rtl\\:banana { + color: yellow; + } + + [dir='rtl'] .rtl\\:tomato, + [dir='rtl'].rtl\\:tomato { + color: red; + } + `; + + return expectMatch(input, output); +}); + +test('it generates ltr variant', () => { + const input = ` + @variants ltr { + .banana { color: yellow; } + .tomato { color: red; } + } + `; + + const output = ` + .banana { + color: yellow; + } + + .tomato { + color: red; + } + + [dir='ltr'] .ltr\\:banana, + [dir='ltr'].ltr\\:banana { + color: yellow; + } + + [dir='ltr'] .ltr\\:tomato, + [dir='ltr'].ltr\\:tomato { + color: red; + } + `; + + return expectMatch(input, output); });