Upgrade: Migrate prefixed group and peer classes (#15208)

Resolves #15193

This PR fixes an issue where `group` and `peer` would not have their
prefixes migrated as part of the upgrade script. We do this by
registering `group` and `peer` as utilities during the codemods. This
way, `parseCandidate` will find these classes to be valid Tailwind
candidates and the prefix can be migrated just like any other utility.

## Test Plan

Tried it with the v3 upgrade playground in the repo and it worked fine: 

<img width="1257" alt="Screenshot 2024-11-27 at 12 17 25"
src="https://github.com/user-attachments/assets/1ee101e1-1d6a-4ce0-b0d4-8d51e5f6b0d2">

I've also added tests to our prefix upgrade integration test and the
prefix migration unit tests.
This commit is contained in:
Philipp Spiess 2024-11-27 17:34:27 +01:00 • committed by GitHub
parent bfcc144798
commit 317cf089b9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 27 additions and 3 deletions

View file

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- _Upgrade (experimental)_: Migrate prefixes for `.group` and `.peer` classes ([#15208](https://github.com/tailwindlabs/tailwindcss/pull/15208))
### Fixed
- Ensure any necessary vendor prefixes are generated for iOS Safari, Firefox, and Chrome ([#15166](https://github.com/tailwindlabs/tailwindcss/pull/15166))

View file

@ -187,6 +187,9 @@ test(
<div
class="!tw__flex sm:!tw__block tw__bg-gradient-to-t flex [color:red] group-[]:tw__flex"
></div>
<div
class="tw__group tw__group/foo tw__peer tw__peer/foo group-hover:tw__flex group-hover/foo:tw__flex peer-hover:tw__flex peer-hover/foo:tw__flex"
></div>
`,
'src/input.css': css`
@tailwind base;
@ -208,6 +211,9 @@ test(
<div
class="tw:flex! tw:sm:block! tw:bg-linear-to-t flex tw:[color:red] tw:in-[.tw\\:group]:flex"
></div>
<div
class="tw:group tw:group/foo tw:peer tw:peer/foo tw:group-hover:flex tw:group-hover/foo:flex tw:peer-hover:flex tw:peer-hover/foo:flex"
></div>
--- ./src/input.css ---
@import 'tailwindcss' prefix(tw);

View file

@ -20,6 +20,12 @@ describe('for projects with configured prefix', () => {
// Adds prefix to arbitrary candidates
['[color:red]', 'tw:[color:red]'],
// `.group` and `.peer` classes
['tw-group', 'tw:group'],
['tw-group/foo', 'tw:group/foo'],
['tw-peer', 'tw:peer'],
['tw-peer/foo', 'tw:peer/foo'],
])('%s => %s', async (candidate, result) => {
let designSystem = await __unstable__loadDesignSystem('@import "tailwindcss" prefix(tw);', {
base: __dirname,

View file

@ -4,6 +4,8 @@ import type { DesignSystem } from '../../../../tailwindcss/src/design-system'
import { segment } from '../../../../tailwindcss/src/utils/segment'
import { printCandidate } from '../candidates'
let seenDesignSystems = new WeakSet<DesignSystem>()
export function prefix(
designSystem: DesignSystem,
userConfig: Config,
@ -11,6 +13,12 @@ export function prefix(
): string {
if (!designSystem.theme.prefix) return rawCandidate
if (!seenDesignSystems.has(designSystem)) {
designSystem.utilities.functional('group', () => null)
designSystem.utilities.functional('peer', () => null)
seenDesignSystems.add(designSystem)
}
let v3Base = extractV3Base(designSystem, userConfig, rawCandidate)
if (!v3Base) return rawCandidate

View file

@ -19,7 +19,7 @@ const LEGACY_CLASS_MAP = {
'outline-none': 'outline-hidden',
}
const SEEDED = new WeakSet<DesignSystem>()
let seenDesignSystems = new WeakSet<DesignSystem>()
export function simpleLegacyClasses(
designSystem: DesignSystem,
@ -27,11 +27,11 @@ export function simpleLegacyClasses(
rawCandidate: string,
): string {
// Prepare design system with the unknown legacy classes
if (!SEEDED.has(designSystem)) {
if (!seenDesignSystems.has(designSystem)) {
for (let old in LEGACY_CLASS_MAP) {
designSystem.utilities.static(old, () => [])
}
SEEDED.add(designSystem)
seenDesignSystems.add(designSystem)
}
for (let candidate of designSystem.parseCandidate(rawCandidate)) {