Add support for writing variant plugins with raw PostCSS API
This commit is contained in:
parent
9b22ff3513
commit
f974b8df03
3 changed files with 108 additions and 27 deletions
|
|
@ -168,7 +168,43 @@ test('variants are generated in the order specified', () => {
|
|||
})
|
||||
})
|
||||
|
||||
test('plugin variants work', () => {
|
||||
test('plugin variants can modify rules using the raw PostCSS API', () => {
|
||||
const input = `
|
||||
@variants important {
|
||||
.banana { color: yellow; }
|
||||
.chocolate { color: brown; }
|
||||
}
|
||||
`
|
||||
|
||||
const output = `
|
||||
.banana { color: yellow; }
|
||||
.chocolate { color: brown; }
|
||||
.\\!banana { color: yellow !important; }
|
||||
.\\!chocolate { color: brown !important; }
|
||||
`
|
||||
|
||||
return run(input, {
|
||||
...config,
|
||||
plugins: [
|
||||
...config.plugins,
|
||||
function({ addVariant }) {
|
||||
addVariant('important', ({ container }) => {
|
||||
container.walkRules(rule => {
|
||||
rule.selector = `.\\!${rule.selector.slice(1)}`
|
||||
rule.walkDecls(decl => {
|
||||
decl.important = true
|
||||
})
|
||||
})
|
||||
})
|
||||
},
|
||||
],
|
||||
}).then(result => {
|
||||
expect(result.css).toMatchCss(output)
|
||||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
test('plugin variants can modify selectors with a simplified API', () => {
|
||||
const input = `
|
||||
@variants first-child {
|
||||
.banana { color: yellow; }
|
||||
|
|
@ -188,8 +224,48 @@ test('plugin variants work', () => {
|
|||
plugins: [
|
||||
...config.plugins,
|
||||
function({ addVariant }) {
|
||||
addVariant('first-child', ({ className, separator }) => {
|
||||
return `.first-child${separator}${className}:first-child`
|
||||
addVariant('first-child', ({ modifySelectors, separator }) => {
|
||||
modifySelectors(({ className }) => {
|
||||
return `.first-child${separator}${className}:first-child`
|
||||
})
|
||||
})
|
||||
},
|
||||
],
|
||||
}).then(result => {
|
||||
expect(result.css).toMatchCss(output)
|
||||
expect(result.warnings().length).toBe(0)
|
||||
})
|
||||
})
|
||||
|
||||
test('plugin variants can wrap rules in another at-rule using the raw PostCSS API', () => {
|
||||
const input = `
|
||||
@variants supports-grid {
|
||||
.banana { color: yellow; }
|
||||
.chocolate { color: brown; }
|
||||
}
|
||||
`
|
||||
|
||||
const output = `
|
||||
.banana { color: yellow; }
|
||||
.chocolate { color: brown; }
|
||||
@supports (display: grid) {
|
||||
.supports-grid\\:banana { color: yellow; }
|
||||
.supports-grid\\:chocolate { color: brown; }
|
||||
}
|
||||
`
|
||||
|
||||
return run(input, {
|
||||
...config,
|
||||
plugins: [
|
||||
...config.plugins,
|
||||
function({ addVariant }) {
|
||||
addVariant('supports-grid', ({ container, separator }) => {
|
||||
const supportsRule = postcss.atRule({ name: 'supports', params: '(display: grid)' })
|
||||
supportsRule.nodes = container.nodes
|
||||
container.nodes = [supportsRule]
|
||||
supportsRule.walkRules(rule => {
|
||||
rule.selector = `.supports-grid${separator}${rule.selector.slice(1)}`
|
||||
})
|
||||
})
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -1,28 +1,21 @@
|
|||
import _ from 'lodash'
|
||||
import postcss from 'postcss'
|
||||
import buildSelectorVariant from '../util/buildSelectorVariant'
|
||||
import generateVariantFunction from '../util/generateVariantFunction'
|
||||
|
||||
function generatePseudoClassVariant(pseudoClass) {
|
||||
return generateVariantFunction(({ className, separator }) => {
|
||||
return `.${pseudoClass}${separator}${className}:${pseudoClass}`
|
||||
return generateVariantFunction(({ modifySelectors, separator }) => {
|
||||
return modifySelectors(({ className }) => {
|
||||
return `.${pseudoClass}${separator}${className}:${pseudoClass}`
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const defaultVariantGenerators = {
|
||||
'group-hover': (container, { options: { separator } }) => {
|
||||
const cloned = container.clone()
|
||||
|
||||
cloned.walkRules(rule => {
|
||||
rule.selector = `.group:hover ${buildSelectorVariant(
|
||||
rule.selector,
|
||||
'group-hover',
|
||||
separator
|
||||
)}`
|
||||
'group-hover': generateVariantFunction(({ modifySelectors, separator }) => {
|
||||
return modifySelectors(({ className }) => {
|
||||
return `.group:hover .group-hover${separator}${className}`
|
||||
})
|
||||
|
||||
container.before(cloned.nodes)
|
||||
},
|
||||
}),
|
||||
hover: generatePseudoClassVariant('hover'),
|
||||
focus: generatePseudoClassVariant('focus'),
|
||||
active: generatePseudoClassVariant('active'),
|
||||
|
|
|
|||
|
|
@ -1,16 +1,28 @@
|
|||
import _ from 'lodash'
|
||||
import postcss from 'postcss'
|
||||
import escapeClassName from './escapeClassName'
|
||||
|
||||
export default function generateVariantFunction(generator) {
|
||||
return (container, config) => {
|
||||
const cloned = container.clone()
|
||||
const cloned = postcss.root({ nodes: container.clone().nodes })
|
||||
|
||||
cloned.walkRules(rule => {
|
||||
rule.selector = generator({
|
||||
className: rule.selector.slice(1),
|
||||
separator: escapeClassName(config.options.separator),
|
||||
})
|
||||
})
|
||||
|
||||
container.before(cloned.nodes)
|
||||
container.before(
|
||||
_.defaultTo(
|
||||
generator({
|
||||
container: cloned,
|
||||
separator: escapeClassName(config.options.separator),
|
||||
modifySelectors: modifierFunction => {
|
||||
cloned.walkRules(rule => {
|
||||
rule.selector = modifierFunction({
|
||||
className: rule.selector.slice(1),
|
||||
selector: rule.selector,
|
||||
})
|
||||
})
|
||||
return cloned
|
||||
},
|
||||
}),
|
||||
cloned
|
||||
).nodes
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue