Support for basic variant generator plugins
Allows you to write a plugin that registers a new variant but only allows you to modify the selector (like what our built-in generators do.) Next steps are to support variants that wrap rules with at-rules (like @supports for example), variants that can modify properties (as opposed to just selectors), and to give variant plugin authors control over how responsive variants interact with their own variants.
This commit is contained in:
parent
9eca69ad83
commit
d77bc055ee
4 changed files with 59 additions and 2 deletions
|
|
@ -4,7 +4,10 @@
|
|||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"sourceType": "module"
|
||||
"sourceType": "module",
|
||||
"ecmaFeatures": {
|
||||
"experimentalObjectRestSpread": true
|
||||
}
|
||||
},
|
||||
"extends": ["eslint-config-postcss", "prettier"],
|
||||
"plugins": ["prettier"],
|
||||
|
|
|
|||
|
|
@ -166,3 +166,34 @@ test('variants are generated in the order specified', () => {
|
|||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
test('plugin variants work', () => {
|
||||
const input = `
|
||||
@variants first-child {
|
||||
.banana { color: yellow; }
|
||||
.chocolate { color: brown; }
|
||||
}
|
||||
`
|
||||
|
||||
const output = `
|
||||
.banana { color: yellow; }
|
||||
.chocolate { color: brown; }
|
||||
.first-child\\:banana:first-child { color: yellow; }
|
||||
.first-child\\:chocolate:first-child { color: brown; }
|
||||
`
|
||||
|
||||
return run(input, () => ({
|
||||
...config,
|
||||
plugins: [
|
||||
...config.plugins,
|
||||
function({ addVariant }) {
|
||||
addVariant('first-child', ({ className, separator }) => {
|
||||
return `.first-child${separator}${className}:first-child`
|
||||
})
|
||||
},
|
||||
],
|
||||
})).then(result => {
|
||||
expect(result.css).toMatchCss(output)
|
||||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import _ from 'lodash'
|
||||
import postcss from 'postcss'
|
||||
import buildSelectorVariant from '../util/buildSelectorVariant'
|
||||
import processPlugins from '../util/processPlugins'
|
||||
|
||||
function buildPseudoClassVariant(selector, pseudoClass, separator) {
|
||||
return `${buildSelectorVariant(selector, pseudoClass, separator)}:${pseudoClass}`
|
||||
|
|
@ -18,7 +19,7 @@ function generatePseudoClassVariant(pseudoClass) {
|
|||
}
|
||||
}
|
||||
|
||||
const variantGenerators = {
|
||||
const defaultVariantGenerators = {
|
||||
'group-hover': (container, { options: { separator } }) => {
|
||||
const cloned = container.clone()
|
||||
|
||||
|
|
@ -40,6 +41,10 @@ const variantGenerators = {
|
|||
export default function(config) {
|
||||
return function(css) {
|
||||
const unwrappedConfig = config()
|
||||
const variantGenerators = {
|
||||
...defaultVariantGenerators,
|
||||
...processPlugins(unwrappedConfig).variantGenerators,
|
||||
}
|
||||
|
||||
css.walkAtRules('variants', atRule => {
|
||||
const variants = postcss.list.comma(atRule.params).filter(variant => variant !== '')
|
||||
|
|
|
|||
|
|
@ -14,6 +14,21 @@ function parseStyles(styles) {
|
|||
return _.flatMap(styles, style => (style instanceof Node ? style : parseObjectStyles(style)))
|
||||
}
|
||||
|
||||
function generateVariantFunction(generator) {
|
||||
return (container, config) => {
|
||||
const cloned = container.clone()
|
||||
|
||||
cloned.walkRules(rule => {
|
||||
rule.selector = generator({
|
||||
className: rule.selector.slice(1),
|
||||
separator: escapeClassName(config.options.separator),
|
||||
})
|
||||
})
|
||||
|
||||
container.before(cloned.nodes)
|
||||
}
|
||||
}
|
||||
|
||||
export default function(config) {
|
||||
const pluginComponents = []
|
||||
const pluginUtilities = []
|
||||
|
|
@ -60,6 +75,9 @@ export default function(config) {
|
|||
|
||||
pluginComponents.push(...styles.nodes)
|
||||
},
|
||||
addVariant: (name, generator) => {
|
||||
pluginVariantGenerators[name] = generateVariantFunction(generator)
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue