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

Don’t crash when important and parent selectors are equal in @apply #12112

Merged
merged 2 commits into from
Sep 29, 2023
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Batch reading content files to prevent `too many open files` error ([#12079](https://github.com/tailwindlabs/tailwindcss/pull/12079))
- Skip over classes inside `:not(…)` when nested in an at-rule ([#12105](https://github.com/tailwindlabs/tailwindcss/pull/12105))
- Update types to work with `Node16` module resolution ([#12097](https://github.com/tailwindlabs/tailwindcss/pull/12097))
- Don’t crash when important and parent selectors are equal in `@apply` ([#12112](https://github.com/tailwindlabs/tailwindcss/pull/12112))

### Added

Expand Down
7 changes: 7 additions & 0 deletions src/lib/expandApplyAtRules.js
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,13 @@ function processApply(root, context, localCache) {
? parent.selector.slice(importantSelector.length)
: parent.selector

// If the selector becomes empty after replacing the important selector
// This means that it's the same as the parent selector and we don't want to replace it
// Otherwise we'll crash
if (parentSelector === '') {
parentSelector = parent.selector
}

rule.selector = replaceSelector(parentSelector, rule.selector, applyCandidate)

// And then re-add it if it was removed
Expand Down
52 changes: 52 additions & 0 deletions tests/apply.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2081,3 +2081,55 @@ test('::ng-deep, ::deep, ::v-deep pseudo elements are left alone', () => {
`)
})
})

test('should not break replacing important selector when the same as the parent selector (pseudo)', async () => {
let config = {
important: ':root',
content: [],
}

let input = css`
@tailwind components;
@layer components {
:root {
@apply flex;
}
}
`

let result = await run(input, config)

expect(result.css).toMatchFormattedCss(css`
:root {
display: flex;
}
`)
})

test('should not break replacing important selector when the same as the parent selector (class)', async () => {
let config = {
important: '.foo',
content: [
{
raw: html` <div class="foo"></div> `,
},
],
}

let input = css`
@tailwind components;
@layer components {
.foo {
@apply flex;
}
}
`

let result = await run(input, config)

expect(result.css).toMatchFormattedCss(css`
.foo {
display: flex;
}
`)
})