Skip to content

Commit

Permalink
Fix matchVariants that use at-rules and placeholders (#8392)
Browse files Browse the repository at this point in the history
* Fix matchVariants that use at-rules and placeholders

* update changelog

* Update CHANGELOG.md

* Only parseVariant when result is defined

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
  • Loading branch information
adamwathan and RobinMalfait committed May 20, 2022
1 parent 1a564fa commit bb4f5da
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 16 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Move `important` selector to the front when `@apply`-ing selector-modifying variants in custom utilities ([#8313](https://github.com/tailwindlabs/tailwindcss/pull/8313))
- Error when registering an invalid custom variant ([#8345](https://github.com/tailwindlabs/tailwindcss/pull/8345))
- Create tailwind.config.cjs file in ESM package when running init ([#8363](https://github.com/tailwindlabs/tailwindcss/pull/8363))
- Fix `matchVariants` that use at-rules and placeholders ([#8392](https://github.com/tailwindlabs/tailwindcss/pull/8392))

### Changed

Expand Down
21 changes: 5 additions & 16 deletions src/lib/setupContextUtils.js
Expand Up @@ -439,7 +439,8 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
variantFunctions = [].concat(variantFunctions).map((variantFunction) => {
if (typeof variantFunction !== 'string') {
// Safelist public API functions
return ({ args, modifySelectors, container, separator, wrap, format }) => {
return (api) => {
let { args, modifySelectors, container, separator, wrap, format } = api
let result = variantFunction(
Object.assign(
{ modifySelectors, container, separator },
Expand All @@ -453,7 +454,8 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs
)
}

return result
// result may be undefined with legacy variants that use APIs like `modifySelectors`
return result && parseVariant(result)(api)
}
}

Expand All @@ -477,20 +479,7 @@ function buildPluginApi(tailwindConfig, context, { variantList, variantMap, offs

api.addVariant(
variant,
Object.assign(
({ args, wrap }) => {
let formatString = variants[variant](args)
if (!formatString) return null

if (!formatString.startsWith('@')) {
return formatString
}

let [, name, params] = /@(.*?)( .+|[({].*)/g.exec(formatString)
return wrap(postcss.atRule({ name, params: params.trim() }))
},
{ [MATCH_VARIANT]: true }
),
Object.assign(({ args }) => variants[variant](args), { [MATCH_VARIANT]: true }),
options
)
}
Expand Down
76 changes: 76 additions & 0 deletions tests/match-variants.test.js
Expand Up @@ -35,6 +35,82 @@ test('partial arbitrary variants', () => {
})
})

test('partial arbitrary variants with at-rules', () => {
let config = {
content: [
{
raw: html`<div class="potato-[yellow]:bg-yellow-200 potato-[baked]:w-3"></div> `,
},
],
corePlugins: { preflight: false },
plugins: [
({ matchVariant }) => {
matchVariant({
potato: (flavor) => `@media (potato: ${flavor})`,
})
},
],
}

let input = css`
@tailwind utilities;
`

return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
@media (potato: baked) {
.potato-\[baked\]\:w-3 {
width: 0.75rem;
}
}
@media (potato: yellow) {
.potato-\[yellow\]\:bg-yellow-200 {
--tw-bg-opacity: 1;
background-color: rgb(254 240 138 / var(--tw-bg-opacity));
}
}
`)
})
})

test('partial arbitrary variants with at-rules and placeholder', () => {
let config = {
content: [
{
raw: html`<div class="potato-[yellow]:bg-yellow-200 potato-[baked]:w-3"></div> `,
},
],
corePlugins: { preflight: false },
plugins: [
({ matchVariant }) => {
matchVariant({
potato: (flavor) => `@media (potato: ${flavor}) { &:potato }`,
})
},
],
}

let input = css`
@tailwind utilities;
`

return run(input, config).then((result) => {
expect(result.css).toMatchFormattedCss(css`
@media (potato: baked) {
.potato-\[baked\]\:w-3:potato {
width: 0.75rem;
}
}
@media (potato: yellow) {
.potato-\[yellow\]\:bg-yellow-200:potato {
--tw-bg-opacity: 1;
background-color: rgb(254 240 138 / var(--tw-bg-opacity));
}
}
`)
})
})

test('partial arbitrary variants with default values', () => {
let config = {
content: [
Expand Down

0 comments on commit bb4f5da

Please sign in to comment.