Improve upgrade migrations (#18184)
This PR fixes 2 issues with the migration tool where certain classes
weren't migrated. This PR fixes those 2 scenarios:
### Scenario 1
When you have an arbitrary opacity modifier that doesn't use `%`, but is
just a number typically between `0` and `1` then this was not converted
to the bare value equivalent before.
E.g.:
```html
<div class="bg-[#f00]/[0.16]"></dv>
```
Will now be converted to:
```html
<div class="bg-[#f00]/16"></dv>
```
### Scenario 2
Fixes a bug when a CSS function was used in a fallback value in the CSS
variable shorthand syntax. In that case we didn't migrate the class to
the new syntax.
This was because we assumed that a `(` was found, that we are dealing
with a CSS function.
E.g.:
```html
<div class="w-[--spacing(1)]"></div>
^ This indicates a CSS function, we should not be
converting this to `w-(--spacing(1))`
```
But if a function was used as a fallback value, for example:
```html
<div class="bg-[--my-color,theme(colors.red.500)]"></dv>
```
Then we also didn't migrate it, but since the function call is in the
fallback, we can still migrate it.
Will now properly be converted to:
```html
<div class="bg-(--my-color,var(--color-red-500))"></dv>
```
## Test plan
1. Added a test for the first case
2. Added a test for the second case
3. Also added an integration-like test that runs all the migration steps
to make sure that the `theme(…)` in the fallback also gets updated to
`var(…)`. This one caught an issue because the `var(…)` wasn't handling
prefixes correctly.
This commit is contained in:
parent
3c629dec86
commit
31c0a21452
7 changed files with 56 additions and 4 deletions
|
|
@ -7,7 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
- Nothing yet!
|
||||
### Fixed
|
||||
|
||||
- Upgrade: migrate arbitrary modifiers with values without percentage sign to bare values `/[0.16]` -> `/16` ([#18184](https://github.com/tailwindlabs/tailwindcss/pull/18184))
|
||||
- Upgrade: migrate CSS variable shorthand if fallback value contains function call ([#18184](https://github.com/tailwindlabs/tailwindcss/pull/18184))
|
||||
|
||||
## [4.1.8] - 2025-05-27
|
||||
|
||||
|
|
|
|||
|
|
@ -40,6 +40,11 @@ test.each([
|
|||
['w-[--spacing(5)]', 'w-[--spacing(5)]'],
|
||||
['bg-[--theme(--color-red-500)]', 'bg-[--theme(--color-red-500)]'],
|
||||
|
||||
// Fallback values should be included inside the `var(…)` function
|
||||
['bg-[--my-color,red]', 'bg-(--my-color,red)'],
|
||||
// Fallback values can contain CSS functions
|
||||
['bg-[--my-color,theme(spacing.1)]', 'bg-(--my-color,theme(spacing.1))'],
|
||||
|
||||
// Some properties never had var() injection in v3.
|
||||
['[scroll-timeline-name:--myTimeline]', '[scroll-timeline-name:--myTimeline]'],
|
||||
['[timeline-scope:--myScope]', '[timeline-scope:--myScope]'],
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import { walk, WalkAction } from '../../../../tailwindcss/src/ast'
|
|||
import { type Candidate, type Variant } from '../../../../tailwindcss/src/candidate'
|
||||
import type { Config } from '../../../../tailwindcss/src/compat/plugin-api'
|
||||
import type { DesignSystem } from '../../../../tailwindcss/src/design-system'
|
||||
import * as ValueParser from '../../../../tailwindcss/src/value-parser'
|
||||
|
||||
export function migrateAutomaticVarInjection(
|
||||
designSystem: DesignSystem,
|
||||
|
|
@ -73,9 +74,23 @@ export function migrateAutomaticVarInjection(
|
|||
|
||||
function injectVar(value: string): { value: string; didChange: boolean } {
|
||||
let didChange = false
|
||||
if (value.startsWith('--') && !value.includes('(')) {
|
||||
value = `var(${value})`
|
||||
didChange = true
|
||||
if (value.startsWith('--')) {
|
||||
// E.g.:
|
||||
//
|
||||
// - `--my-color` → `var(--my-color)` Convert variable
|
||||
// - `--my-color,red` → `var(--my-color,red)` Convert variable with fallback
|
||||
// - `--theme(color.red)` → `--theme(color.red)` Do not convert functions
|
||||
//
|
||||
if (
|
||||
// No `(` definitely means there is no function
|
||||
!value.includes('(') ||
|
||||
// There could be a function call in the fallback value, but it cannot be
|
||||
// top-level, so we can safely check the first part
|
||||
ValueParser.parse(value)[0]?.kind !== 'function'
|
||||
) {
|
||||
value = `var(${value})`
|
||||
didChange = true
|
||||
}
|
||||
} else if (value.startsWith(' --')) {
|
||||
value = value.slice(1)
|
||||
didChange = true
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ describe.each([['default'], ['with-variant'], ['important'], ['prefix']])('%s',
|
|||
// Use a bare value modifier
|
||||
['bg-red-500/[25%]', 'bg-red-500/25'],
|
||||
|
||||
// Convert 0-1 values to bare values
|
||||
['bg-[#f00]/[0.16]', 'bg-[#f00]/16'],
|
||||
|
||||
// Drop unnecessary modifiers
|
||||
['bg-red-500/[100%]', 'bg-red-500'],
|
||||
['bg-red-500/100', 'bg-red-500'],
|
||||
|
|
|
|||
|
|
@ -55,6 +55,23 @@ export function migrateOptimizeModifier(
|
|||
}
|
||||
}
|
||||
|
||||
// 3. Try to remove the square brackets, but multiply by 100. E.g.: `[0.16]` -> `16`
|
||||
if (!changed) {
|
||||
let newModifier: NamedUtilityValue = {
|
||||
kind: 'named',
|
||||
value: `${parseFloat(modifier.value) * 100}`,
|
||||
fraction: null,
|
||||
}
|
||||
|
||||
if (
|
||||
targetSignature ===
|
||||
signatures.get(designSystem.printCandidate({ ...candidate, modifier: newModifier }))
|
||||
) {
|
||||
changed = true
|
||||
candidate.modifier = newModifier
|
||||
}
|
||||
}
|
||||
|
||||
return changed ? designSystem.printCandidate(candidate) : rawCandidate
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -193,6 +193,10 @@ export function createConverter(designSystem: DesignSystem, { prettyPrint = fals
|
|||
let variable = `--${keyPathToCssProperty(toKeyPath(path))}` as const
|
||||
if (!designSystem.theme.get([variable])) return null
|
||||
|
||||
if (designSystem.theme.prefix) {
|
||||
return `--${designSystem.theme.prefix}-${variable.slice(2)}`
|
||||
}
|
||||
|
||||
return variable
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -64,6 +64,11 @@ describe.each([['default'], ['with-variant'], ['important'], ['prefix']])('%s',
|
|||
// non-negative version first so we can replace `-mt-[0px]` with `mt-[0px]`.
|
||||
['mt-[0px]', 'mt-[0px]'],
|
||||
['-mt-[0px]', 'mt-[0px]'],
|
||||
|
||||
// Shorthand CSS Variables should be converted to the new syntax, even if
|
||||
// the fallback contains functions. The fallback should also be migrated to
|
||||
// the newest syntax.
|
||||
['bg-[--my-color,theme(colors.red.500)]', 'bg-(--my-color,var(--color-red-500))'],
|
||||
])(testName, async (candidate, result) => {
|
||||
if (strategy === 'with-variant') {
|
||||
candidate = `focus:${candidate}`
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue