From 013f845281ab2bdafcb5afa7fdcf2918ede08f3a Mon Sep 17 00:00:00 2001 From: dumconstantin Date: Fri, 24 Nov 2017 16:26:40 +0200 Subject: [PATCH] Make the hoverable, focusable and responsive separator (default '\:') configurable. --- __tests__/focusableAtRule.test.js | 9 +++++--- __tests__/hoverableAtRule.test.js | 9 +++++--- __tests__/variantsAtRule.test.js | 29 ++++++++++++++------------ defaultConfig.stub.js | 1 + src/lib/substituteFocusableAtRules.js | 5 +++-- src/lib/substituteHoverableAtRules.js | 5 +++-- src/lib/substituteResponsiveAtRules.js | 6 +++++- src/lib/substituteVariantsAtRules.js | 14 +++++++------ 8 files changed, 48 insertions(+), 30 deletions(-) diff --git a/__tests__/focusableAtRule.test.js b/__tests__/focusableAtRule.test.js index ea8749f5e..3fc66a69b 100644 --- a/__tests__/focusableAtRule.test.js +++ b/__tests__/focusableAtRule.test.js @@ -1,7 +1,10 @@ import postcss from 'postcss' import plugin from '../src/lib/substituteFocusableAtRules' +import config from '../defaultConfig.stub.js' -function run(input, opts = () => {}) { +const separator = config.options.separator + +function run(input, opts = () => config) { return postcss([plugin(opts)]).process(input) } @@ -16,8 +19,8 @@ test('it adds a focusable variant to each nested class definition', () => { const output = ` .banana { color: yellow; } .chocolate { color: brown; } - .focus\\:banana:focus { color: yellow; } - .focus\\:chocolate:focus { color: brown; } + .focus${separator}banana:focus { color: yellow; } + .focus${separator}chocolate:focus { color: brown; } ` return run(input).then(result => { diff --git a/__tests__/hoverableAtRule.test.js b/__tests__/hoverableAtRule.test.js index e47c1bda2..2aeb5ccfa 100644 --- a/__tests__/hoverableAtRule.test.js +++ b/__tests__/hoverableAtRule.test.js @@ -1,7 +1,10 @@ import postcss from 'postcss' import plugin from '../src/lib/substituteHoverableAtRules' +import config from '../defaultConfig.stub.js' -function run(input, opts = () => {}) { +const separator = config.options.separator + +function run(input, opts = () => config) { return postcss([plugin(opts)]).process(input) } @@ -16,8 +19,8 @@ test('it adds a hoverable variant to each nested class definition', () => { const output = ` .banana { color: yellow; } .chocolate { color: brown; } - .hover\\:banana:hover { color: yellow; } - .hover\\:chocolate:hover { color: brown; } + .hover${separator}banana:hover { color: yellow; } + .hover${separator}chocolate:hover { color: brown; } ` return run(input).then(result => { diff --git a/__tests__/variantsAtRule.test.js b/__tests__/variantsAtRule.test.js index 3dc19ec86..73aeaff19 100644 --- a/__tests__/variantsAtRule.test.js +++ b/__tests__/variantsAtRule.test.js @@ -1,7 +1,10 @@ import postcss from 'postcss' import plugin from '../src/lib/substituteVariantsAtRules' +import config from '../defaultConfig.stub.js' -function run(input, opts = () => {}) { +const separator = config.options.separator + +function run(input, opts = () => config) { return postcss([plugin(opts)]).process(input) } @@ -16,8 +19,8 @@ test('it can generate hover variants', () => { const output = ` .banana { color: yellow; } .chocolate { color: brown; } - .hover\\:banana:hover { color: yellow; } - .hover\\:chocolate:hover { color: brown; } + .hover${separator}banana:hover { color: yellow; } + .hover${separator}chocolate:hover { color: brown; } ` return run(input).then(result => { @@ -37,8 +40,8 @@ test('it can generate focus variants', () => { const output = ` .banana { color: yellow; } .chocolate { color: brown; } - .focus\\:banana:focus { color: yellow; } - .focus\\:chocolate:focus { color: brown; } + .focus${separator}banana:focus { color: yellow; } + .focus${separator}chocolate:focus { color: brown; } ` return run(input).then(result => { @@ -58,10 +61,10 @@ test('it can generate hover and focus variants', () => { const output = ` .banana { color: yellow; } .chocolate { color: brown; } - .focus\\:banana:focus { color: yellow; } - .focus\\:chocolate:focus { color: brown; } - .hover\\:banana:hover { color: yellow; } - .hover\\:chocolate:hover { color: brown; } + .focus${separator}banana:focus { color: yellow; } + .focus${separator}chocolate:focus { color: brown; } + .hover${separator}banana:hover { color: yellow; } + .hover${separator}chocolate:hover { color: brown; } ` return run(input).then(result => { @@ -82,10 +85,10 @@ test('it wraps the output in a responsive at-rule if responsive is included as a @responsive { .banana { color: yellow; } .chocolate { color: brown; } - .focus\\:banana:focus { color: yellow; } - .focus\\:chocolate:focus { color: brown; } - .hover\\:banana:hover { color: yellow; } - .hover\\:chocolate:hover { color: brown; } + .focus${separator}banana:focus { color: yellow; } + .focus${separator}chocolate:focus { color: brown; } + .hover${separator}banana:hover { color: yellow; } + .hover${separator}chocolate:hover { color: brown; } } ` diff --git a/defaultConfig.stub.js b/defaultConfig.stub.js index 3731eb808..8e61947eb 100644 --- a/defaultConfig.stub.js +++ b/defaultConfig.stub.js @@ -769,6 +769,7 @@ module.exports = { options: { prefix: '', + separator: '\\:', important: false, }, diff --git a/src/lib/substituteFocusableAtRules.js b/src/lib/substituteFocusableAtRules.js index 8d4cb25d0..7c681b236 100644 --- a/src/lib/substituteFocusableAtRules.js +++ b/src/lib/substituteFocusableAtRules.js @@ -1,12 +1,13 @@ -export default function() { +export default function(config) { return function(css) { + const separator = config().options.separator css.walkAtRules('focusable', atRule => { const clonedRule = atRule.clone() clonedRule.walkRules(rule => { // Might be wise to error if the rule has multiple selectors, // or weird compound selectors like .bg-blue>p>h1 - rule.selector = `.focus\\:${rule.selector.slice(1)}:focus` + rule.selector = `.focus${separator}${rule.selector.slice(1)}:focus` }) atRule.before(atRule.clone().nodes) diff --git a/src/lib/substituteHoverableAtRules.js b/src/lib/substituteHoverableAtRules.js index b11f9a317..d5b9c0319 100644 --- a/src/lib/substituteHoverableAtRules.js +++ b/src/lib/substituteHoverableAtRules.js @@ -1,12 +1,13 @@ -export default function() { +export default function(config) { return function(css) { + const separator = config().options.separator css.walkAtRules('hoverable', atRule => { const clonedRule = atRule.clone() clonedRule.walkRules(rule => { // Might be wise to error if the rule has multiple selectors, // or weird compound selectors like .bg-blue>p>h1 - rule.selector = `.hover\\:${rule.selector.slice(1)}:hover` + rule.selector = `.hover${separator}${rule.selector.slice(1)}:hover` }) atRule.before(atRule.clone().nodes) diff --git a/src/lib/substituteResponsiveAtRules.js b/src/lib/substituteResponsiveAtRules.js index 52a51918f..bb26e314b 100644 --- a/src/lib/substituteResponsiveAtRules.js +++ b/src/lib/substituteResponsiveAtRules.js @@ -6,6 +6,7 @@ import buildMediaQuery from '../util/buildMediaQuery' export default function(config) { return function(css) { const screens = config().screens + const separator = config().options.separator const responsiveRules = [] let finalRules = [] @@ -25,7 +26,10 @@ export default function(config) { mediaQuery.append( responsiveRules.map(rule => { const cloned = rule.clone() - cloned.selectors = _.map(rule.selectors, selector => `.${screen}\\:${selector.slice(1)}`) + cloned.selectors = _.map( + rule.selectors, + selector => `.${screen}${separator}${selector.slice(1)}` + ) return cloned }) ) diff --git a/src/lib/substituteVariantsAtRules.js b/src/lib/substituteVariantsAtRules.js index fd8c85484..ffe358098 100644 --- a/src/lib/substituteVariantsAtRules.js +++ b/src/lib/substituteVariantsAtRules.js @@ -2,27 +2,29 @@ import _ from 'lodash' import postcss from 'postcss' const variantGenerators = { - hover: container => { + hover: (separator, container) => { const cloned = container.clone() cloned.walkRules(rule => { - rule.selector = `.hover\\:${rule.selector.slice(1)}:hover` + rule.selector = `.hover${separator}${rule.selector.slice(1)}:hover` }) return cloned.nodes }, - focus: container => { + focus: (separator, container) => { const cloned = container.clone() cloned.walkRules(rule => { - rule.selector = `.focus\\:${rule.selector.slice(1)}:focus` + rule.selector = `.focus${separator}${rule.selector.slice(1)}:focus` }) return cloned.nodes }, } -export default function() { +export default function(config) { + const separator = config().options.separator + return function(css) { css.walkAtRules('variants', atRule => { const variants = postcss.list.comma(atRule.params) @@ -37,7 +39,7 @@ export default function() { _.forEach(['focus', 'hover'], variant => { if (variants.includes(variant)) { - atRule.before(variantGenerators[variant](atRule)) + atRule.before(variantGenerators[variant](separator, atRule)) } })