mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
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,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…
x
Reference in New Issue
Block a user