From 8bbdb57457246d503d4faab26de8b2d38492760d Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Wed, 25 Sep 2024 18:39:00 +0200 Subject: [PATCH] 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. --- CHANGELOG.md | 1 + .../migrate-at-layer-utilities.test.ts | 37 +++++++++++++++++++ .../codemods/migrate-at-layer-utilities.ts | 8 +--- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 26610bd8d..e288aa2b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - _Experimental_: Fix incorrect empty `layer()` at the end of `@import` at-rules when running codemods ([#14513](https://github.com/tailwindlabs/tailwindcss/pull/14513)) - _Experimental_: Migrate `@import "tailwindcss/tailwind.css"` to `@import "tailwindcss"` ([#14514](https://github.com/tailwindlabs/tailwindcss/pull/14514)) - _Experimental_: Do not wrap comment nodes in `@layer` when running codemods ([#14517](https://github.com/tailwindlabs/tailwindcss/pull/14517)) +- _Experimental_: Ensure we don't lose selectors when running codemods ([#14518](https://github.com/tailwindlabs/tailwindcss/pull/14518)) ## [4.0.0-alpha.25] - 2024-09-24 diff --git a/packages/@tailwindcss-upgrade/src/codemods/migrate-at-layer-utilities.test.ts b/packages/@tailwindcss-upgrade/src/codemods/migrate-at-layer-utilities.test.ts index 6f1a03301..f53e3f3c9 100644 --- a/packages/@tailwindcss-upgrade/src/codemods/migrate-at-layer-utilities.test.ts +++ b/packages/@tailwindcss-upgrade/src/codemods/migrate-at-layer-utilities.test.ts @@ -783,3 +783,40 @@ describe('comments', () => { `) }) }) + +// Saw this when testing codemods on https://github.com/docker/docs +it('should not lose attribute selectors', async () => { + expect( + await migrate(css` + @layer components { + #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; + } + &:not([aria-current='true']) { + @apply text-gray-light-600 hover:text-black dark:text-gray-dark-700 dark:hover:text-white; + } + } + } + } + `), + ).toMatchInlineSnapshot(` + "@layer components { + #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; + } + &:not([aria-current='true']) { + @apply text-gray-light-600 hover:text-black dark:text-gray-dark-700 dark:hover:text-white; + } + } + } + }" + `) +}) diff --git a/packages/@tailwindcss-upgrade/src/codemods/migrate-at-layer-utilities.ts b/packages/@tailwindcss-upgrade/src/codemods/migrate-at-layer-utilities.ts index c1e383ef5..cedef0545 100644 --- a/packages/@tailwindcss-upgrade/src/codemods/migrate-at-layer-utilities.ts +++ b/packages/@tailwindcss-upgrade/src/codemods/migrate-at-layer-utilities.ts @@ -75,9 +75,8 @@ export function migrateAtLayerUtilities(): Plugin { return WalkAction.Stop } }) - node.selector = selector.toString() }) - }).processSync(node.selector, { updateSelector: false }) + }).processSync(node, { updateSelector: true }) }) // Upgrade every Rule in `@layer utilities` to an `@utility` at-rule. @@ -157,10 +156,7 @@ export function migrateAtLayerUtilities(): Plugin { } }) }) - - // Update the selector - node.selector = selectors.toString() - }).processSync(node.selector) + }).processSync(node, { updateSelector: true }) // Cleanup all the nodes that should not be part of the `@utility` rule. if (!containsClass) {