From 9bd52a5ff1c060c68cbec253e2c6e9dc5ab03816 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Thu, 10 Oct 2024 23:13:09 +0200 Subject: [PATCH 1/5] migrate `data-*` and `aria-*` variants from arbitrary values to bare values --- .../arbitrary-value-to-bare-value.test.ts | 27 ++++++++ .../codemods/arbitrary-value-to-bare-value.ts | 61 +++++++++++++++++++ .../src/template/migrate.ts | 2 + 3 files changed, 90 insertions(+) create mode 100644 packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.test.ts create mode 100644 packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.ts diff --git a/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.test.ts b/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.test.ts new file mode 100644 index 000000000000..644c12a35617 --- /dev/null +++ b/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.test.ts @@ -0,0 +1,27 @@ +import { __unstable__loadDesignSystem } from '@tailwindcss/node' +import { expect, test } from 'vitest' +import { arbitraryValueToBareValue } from './arbitrary-value-to-bare-value' + +test.each([ + ['data-[selected]:flex', 'data-selected:flex'], + ['data-[foo=bar]:flex', 'data-[foo=bar]:flex'], + + ['group-data-[selected]:flex', 'group-data-selected:flex'], + ['group-data-[foo=bar]:flex', 'group-data-[foo=bar]:flex'], + ['group-has-data-[selected]:flex', 'group-has-data-selected:flex'], + + ['aria-[selected]:flex', 'aria-[selected]:flex'], + ['aria-[selected="true"]:flex', 'aria-selected:flex'], + + ['group-aria-[selected]:flex', 'group-aria-[selected]:flex'], + ['group-aria-[selected="true"]:flex', 'group-aria-selected:flex'], + ['group-has-aria-[selected]:flex', 'group-has-aria-[selected]:flex'], + + ['max-lg:hover:data-[selected]:flex!', 'max-lg:hover:data-selected:flex!'], +])('%s => %s', async (candidate, result) => { + let designSystem = await __unstable__loadDesignSystem('@import "tailwindcss";', { + base: __dirname, + }) + + expect(arbitraryValueToBareValue(designSystem, {}, candidate)).toEqual(result) +}) diff --git a/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.ts b/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.ts new file mode 100644 index 000000000000..aac8b2ea1dd5 --- /dev/null +++ b/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.ts @@ -0,0 +1,61 @@ +import type { Config } from 'tailwindcss' +import { parseCandidate, type Candidate, type Variant } from '../../../../tailwindcss/src/candidate' +import type { DesignSystem } from '../../../../tailwindcss/src/design-system' +import { printCandidate } from '../candidates' + +export function arbitraryValueToBareValue( + designSystem: DesignSystem, + _userConfig: Config, + rawCandidate: string, +): string { + for (let candidate of parseCandidate(rawCandidate, designSystem)) { + let clone = structuredClone(candidate) + let changed = false + for (let variant of variants(clone)) { + // Convert `data-[selected]` to `data-selected` + if ( + variant.kind === 'functional' && + variant.root === 'data' && + variant.value?.kind === 'arbitrary' && + !variant.value.value.includes('=') + ) { + changed = true + variant.value = { + kind: 'named', + value: variant.value.value, + } + } + + // Convert `aria-[selected="true"]` to `aria-selected` + else if ( + variant.kind === 'functional' && + variant.root === 'aria' && + variant.value?.kind === 'arbitrary' && + variant.value.value.endsWith('="true"') + ) { + changed = true + variant.value = { + kind: 'named', + value: variant.value.value.slice(0, variant.value.value.indexOf('=')), + } + } + } + + return changed ? printCandidate(designSystem, clone) : rawCandidate + } + + return rawCandidate +} + +function* variants(candidate: Candidate) { + function* inner(variant: Variant): Iterable { + yield variant + if (variant.kind === 'compound') { + yield* inner(variant.variant) + } + } + + for (let variant of candidate.variants) { + yield* inner(variant) + } +} diff --git a/packages/@tailwindcss-upgrade/src/template/migrate.ts b/packages/@tailwindcss-upgrade/src/template/migrate.ts index df9d22b15af8..50f2ca60e87f 100644 --- a/packages/@tailwindcss-upgrade/src/template/migrate.ts +++ b/packages/@tailwindcss-upgrade/src/template/migrate.ts @@ -3,6 +3,7 @@ import path, { extname } from 'node:path' import type { Config } from 'tailwindcss' import type { DesignSystem } from '../../../tailwindcss/src/design-system' import { extractRawCandidates, replaceCandidateInContent } from './candidates' +import { arbitraryValueToBareValue } from './codemods/arbitrary-value-to-bare-value' import { automaticVarInjection } from './codemods/automatic-var-injection' import { bgGradient } from './codemods/bg-gradient' import { important } from './codemods/important' @@ -22,6 +23,7 @@ export const DEFAULT_MIGRATIONS: Migration[] = [ automaticVarInjection, bgGradient, simpleLegacyClasses, + arbitraryValueToBareValue, variantOrder, ] From 1181ec3e84e1a41c0ce169edc1a55c8ef7442cf7 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Thu, 10 Oct 2024 23:19:12 +0200 Subject: [PATCH 2/5] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e62f00b5122..4065f09ba3f0 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 - _Upgrade (experimental)_: Fully convert simple JS configs to CSS ([#14639](https://github.com/tailwindlabs/tailwindcss/pull/14639)) - _Upgrade (experimental)_: Migrate `@media screen(…)` when running codemods ([#14603](https://github.com/tailwindlabs/tailwindcss/pull/14603)) - _Upgrade (experimental)_: Inject `@config "…"` when a `tailwind.config.{js,ts,…}` is detected ([#14635](https://github.com/tailwindlabs/tailwindcss/pull/14635)) +- _Upgrade (experimental)_: Migrate `data-*` and `aria-*` variants from arbitrary values to bare values ([#14644](https://github.com/tailwindlabs/tailwindcss/pull/14644)) ### Fixed From 37cc8d1efd116140f58741508f06ae82b83dc2fc Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 11 Oct 2024 14:54:25 +0200 Subject: [PATCH 3/5] ensure only `foo="true"` is valid, and not `foo~="true"` --- .../arbitrary-value-to-bare-value.test.ts | 1 + .../codemods/arbitrary-value-to-bare-value.ts | 21 ++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.test.ts b/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.test.ts index 644c12a35617..d5645d054f6d 100644 --- a/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.test.ts +++ b/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.test.ts @@ -12,6 +12,7 @@ test.each([ ['aria-[selected]:flex', 'aria-[selected]:flex'], ['aria-[selected="true"]:flex', 'aria-selected:flex'], + ['aria-[selected*="true"]:flex', 'aria-[selected*="true"]:flex'], ['group-aria-[selected]:flex', 'group-aria-[selected]:flex'], ['group-aria-[selected="true"]:flex', 'group-aria-selected:flex'], diff --git a/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.ts b/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.ts index aac8b2ea1dd5..1146bbeeef90 100644 --- a/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.ts +++ b/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.ts @@ -1,6 +1,7 @@ import type { Config } from 'tailwindcss' import { parseCandidate, type Candidate, type Variant } from '../../../../tailwindcss/src/candidate' import type { DesignSystem } from '../../../../tailwindcss/src/design-system' +import { segment } from '../../../../tailwindcss/src/utils/segment' import { printCandidate } from '../candidates' export function arbitraryValueToBareValue( @@ -31,8 +32,26 @@ export function arbitraryValueToBareValue( variant.kind === 'functional' && variant.root === 'aria' && variant.value?.kind === 'arbitrary' && - variant.value.value.endsWith('="true"') + (variant.value.value.endsWith('=true') || + variant.value.value.endsWith('="true"') || + variant.value.value.endsWith("='true'")) ) { + let [key, _value] = segment(variant.value.value, '=') + if ( + // aria-[foo~="true"] + key[key.length - 1] === '~' || + // aria-[foo|="true"] + key[key.length - 1] === '|' || + // aria-[foo^="true"] + key[key.length - 1] === '^' || + // aria-[foo$="true"] + key[key.length - 1] === '$' || + // aria-[foo*="true"] + key[key.length - 1] === '*' + ) { + continue + } + changed = true variant.value = { kind: 'named', From 497a41eb8d7a1fcf2dd429e65054f3029063aeec Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 11 Oct 2024 15:31:58 +0200 Subject: [PATCH 4/5] migrate `supports-[foo]` to `supports-foo` if we can --- .../codemods/arbitrary-value-to-bare-value.test.ts | 3 +++ .../codemods/arbitrary-value-to-bare-value.ts | 14 ++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.test.ts b/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.test.ts index d5645d054f6d..2f29c130fb67 100644 --- a/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.test.ts +++ b/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.test.ts @@ -6,6 +6,9 @@ test.each([ ['data-[selected]:flex', 'data-selected:flex'], ['data-[foo=bar]:flex', 'data-[foo=bar]:flex'], + ['supports-[gap]:flex', 'supports-gap:flex'], + ['supports-[display:grid]:flex', 'supports-[display:grid]:flex'], + ['group-data-[selected]:flex', 'group-data-selected:flex'], ['group-data-[foo=bar]:flex', 'group-data-[foo=bar]:flex'], ['group-has-data-[selected]:flex', 'group-has-data-selected:flex'], diff --git a/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.ts b/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.ts index 1146bbeeef90..065f10807326 100644 --- a/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.ts +++ b/packages/@tailwindcss-upgrade/src/template/codemods/arbitrary-value-to-bare-value.ts @@ -58,6 +58,20 @@ export function arbitraryValueToBareValue( value: variant.value.value.slice(0, variant.value.value.indexOf('=')), } } + + // Convert `supports-[gap]` to `supports-gap` + else if ( + variant.kind === 'functional' && + variant.root === 'supports' && + variant.value?.kind === 'arbitrary' && + /^[a-z-][a-z0-9-]*$/i.test(variant.value.value) + ) { + changed = true + variant.value = { + kind: 'named', + value: variant.value.value, + } + } } return changed ? printCandidate(designSystem, clone) : rawCandidate From 524cdbc59638f0495b30e724ba1f2e737d5b3698 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Fri, 11 Oct 2024 15:34:49 +0200 Subject: [PATCH 5/5] update CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4065f09ba3f0..b7304af6781c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - _Upgrade (experimental)_: Fully convert simple JS configs to CSS ([#14639](https://github.com/tailwindlabs/tailwindcss/pull/14639)) - _Upgrade (experimental)_: Migrate `@media screen(…)` when running codemods ([#14603](https://github.com/tailwindlabs/tailwindcss/pull/14603)) - _Upgrade (experimental)_: Inject `@config "…"` when a `tailwind.config.{js,ts,…}` is detected ([#14635](https://github.com/tailwindlabs/tailwindcss/pull/14635)) -- _Upgrade (experimental)_: Migrate `data-*` and `aria-*` variants from arbitrary values to bare values ([#14644](https://github.com/tailwindlabs/tailwindcss/pull/14644)) +- _Upgrade (experimental)_: Migrate `aria-*`, `data-*`, and `supports-*` variants from arbitrary values to bare values ([#14644](https://github.com/tailwindlabs/tailwindcss/pull/14644)) ### Fixed