Skip to content

Commit 8bbdb57

Browse files
authored
CSS codemod: ensure we don't lose selectors (#14518)
This PR fixes an issue where a CSS rule with a selector that contains multiple selectors lost everything but the last selector. While testing the `npx @tailwindcss/upgrade` codemods on real world projects, I noticed that we lost one of the selectors in the `docker/docs` repository. ```diff diff --git a/assets/css/toc.css b/assets/css/toc.css index 91ff92d7cd..3b2432e913 100644 --- a/assets/css/toc.css +++ b/assets/css/toc.css @@ -2,7 +2,7 @@ #TableOfContents { .toc a { @apply block max-w-full truncate py-1 pl-2 hover:font-medium hover:no-underline; - &[aria-current="true"], + &:hover { @apply border-l-2 border-l-gray-light bg-gradient-to-r from-gray-light-100 font-medium text-black dark:border-l-gray-dark dark:from-gray-dark-200 dark:text-white; } ``` This PR fixes the issue by not overriding the `node.selector` internally with the last selector we handled. Instead, we let the selector parser handle it entirely.
1 parent 732147a commit 8bbdb57

File tree

3 files changed

+40
-6
lines changed

3 files changed

+40
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1717
- _Experimental_: Fix incorrect empty `layer()` at the end of `@import` at-rules when running codemods ([#14513](https://github.com/tailwindlabs/tailwindcss/pull/14513))
1818
- _Experimental_: Migrate `@import "tailwindcss/tailwind.css"` to `@import "tailwindcss"` ([#14514](https://github.com/tailwindlabs/tailwindcss/pull/14514))
1919
- _Experimental_: Do not wrap comment nodes in `@layer` when running codemods ([#14517](https://github.com/tailwindlabs/tailwindcss/pull/14517))
20+
- _Experimental_: Ensure we don't lose selectors when running codemods ([#14518](https://github.com/tailwindlabs/tailwindcss/pull/14518))
2021

2122
## [4.0.0-alpha.25] - 2024-09-24
2223

packages/@tailwindcss-upgrade/src/codemods/migrate-at-layer-utilities.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -783,3 +783,40 @@ describe('comments', () => {
783783
`)
784784
})
785785
})
786+
787+
// Saw this when testing codemods on https://github.com/docker/docs
788+
it('should not lose attribute selectors', async () => {
789+
expect(
790+
await migrate(css`
791+
@layer components {
792+
#TableOfContents {
793+
.toc a {
794+
@apply block max-w-full truncate py-1 pl-2 hover:font-medium hover:no-underline;
795+
&[aria-current='true'],
796+
&:hover {
797+
@apply border-l-2 border-l-gray-light bg-gradient-to-r from-gray-light-100 font-medium text-black dark:border-l-gray-dark dark:from-gray-dark-200 dark:text-white;
798+
}
799+
&:not([aria-current='true']) {
800+
@apply text-gray-light-600 hover:text-black dark:text-gray-dark-700 dark:hover:text-white;
801+
}
802+
}
803+
}
804+
}
805+
`),
806+
).toMatchInlineSnapshot(`
807+
"@layer components {
808+
#TableOfContents {
809+
.toc a {
810+
@apply block max-w-full truncate py-1 pl-2 hover:font-medium hover:no-underline;
811+
&[aria-current='true'],
812+
&:hover {
813+
@apply border-l-2 border-l-gray-light bg-gradient-to-r from-gray-light-100 font-medium text-black dark:border-l-gray-dark dark:from-gray-dark-200 dark:text-white;
814+
}
815+
&:not([aria-current='true']) {
816+
@apply text-gray-light-600 hover:text-black dark:text-gray-dark-700 dark:hover:text-white;
817+
}
818+
}
819+
}
820+
}"
821+
`)
822+
})

packages/@tailwindcss-upgrade/src/codemods/migrate-at-layer-utilities.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,8 @@ export function migrateAtLayerUtilities(): Plugin {
7575
return WalkAction.Stop
7676
}
7777
})
78-
node.selector = selector.toString()
7978
})
80-
}).processSync(node.selector, { updateSelector: false })
79+
}).processSync(node, { updateSelector: true })
8180
})
8281

8382
// Upgrade every Rule in `@layer utilities` to an `@utility` at-rule.
@@ -157,10 +156,7 @@ export function migrateAtLayerUtilities(): Plugin {
157156
}
158157
})
159158
})
160-
161-
// Update the selector
162-
node.selector = selectors.toString()
163-
}).processSync(node.selector)
159+
}).processSync(node, { updateSelector: true })
164160

165161
// Cleanup all the nodes that should not be part of the `@utility` rule.
166162
if (!containsClass) {

0 commit comments

Comments
 (0)