Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix matchVariants that use at-rules and placeholders #8392

Merged
merged 4 commits into from May 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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