Skip to content

Commit d644a3f

Browse files
committed
replace candidates based on type
1 parent 851a645 commit d644a3f

File tree

2 files changed

+49
-38
lines changed

2 files changed

+49
-38
lines changed

packages/@tailwindcss-upgrade/src/template/codemods/legacy-classes.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ test.each([
1919

2020
['blur', 'blur-sm'],
2121
['blur-sm', 'blur-xs'],
22+
23+
['blur!', 'blur-sm!'],
24+
['hover:blur', 'hover:blur-sm'],
25+
['hover:blur!', 'hover:blur-sm!'],
26+
27+
['hover:blur-sm', 'hover:blur-xs'],
28+
['blur-sm!', 'blur-xs!'],
29+
['hover:blur-sm!', 'hover:blur-xs!'],
2230
])('%s => %s', async (candidate, result) => {
2331
let designSystem = await __unstable__loadDesignSystem('@import "tailwindcss";', {
2432
base: __dirname,

packages/@tailwindcss-upgrade/src/template/codemods/legacy-classes.ts

Lines changed: 41 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { __unstable__loadDesignSystem } from '@tailwindcss/node'
22
import path from 'node:path'
33
import url from 'node:url'
44
import type { Config } from 'tailwindcss'
5+
import type { Candidate } from '../../../../tailwindcss/src/candidate'
56
import type { DesignSystem } from '../../../../tailwindcss/src/design-system'
67
import { DefaultMap } from '../../../../tailwindcss/src/utils/default-map'
78
import { printCandidate } from '../candidates'
@@ -51,7 +52,6 @@ const THEME_KEYS = {
5152
const DESIGN_SYSTEMS = new DefaultMap((base) => {
5253
return __unstable__loadDesignSystem('@import "tailwindcss";', { base })
5354
})
54-
const SEEDED = new WeakSet<DesignSystem>()
5555

5656
export async function legacyClasses(
5757
designSystem: DesignSystem,
@@ -63,56 +63,59 @@ export async function legacyClasses(
6363
end: number
6464
},
6565
): Promise<string> {
66-
// Ensure the "old" classes exist as static utilities to make the migration
67-
// easier because the "root" will point to the full class.
68-
if (!SEEDED.has(designSystem)) {
69-
for (let old in LEGACY_CLASS_MAP) {
70-
designSystem.utilities.static(old, () => [])
71-
}
72-
SEEDED.add(designSystem)
73-
}
74-
7566
let defaultDesignSystem = await DESIGN_SYSTEMS.get(__dirname)
7667

7768
for (let candidate of designSystem.parseCandidate(rawCandidate)) {
78-
if (candidate.kind === 'static' && Object.hasOwn(LEGACY_CLASS_MAP, candidate.root)) {
79-
let newRoot = LEGACY_CLASS_MAP[candidate.root as keyof typeof LEGACY_CLASS_MAP]
80-
81-
if (location && !candidate.root.includes('-') && !isSafeMigration(location)) {
82-
continue
69+
if (candidate.kind === 'functional') {
70+
let parts = [candidate.root]
71+
if (candidate.value?.kind === 'named') {
72+
parts.push(candidate.value.value)
8373
}
8474

85-
let fromThemeKey = THEME_KEYS[candidate.root as keyof typeof THEME_KEYS]
86-
let toThemeKey = THEME_KEYS[newRoot as keyof typeof THEME_KEYS]
87-
88-
if (fromThemeKey && toThemeKey) {
89-
// Migrating something that resolves to a value in the theme.
90-
let customFrom = designSystem.resolveThemeValue(fromThemeKey)
91-
let defaultFrom = defaultDesignSystem.resolveThemeValue(fromThemeKey)
92-
let customTo = designSystem.resolveThemeValue(toThemeKey)
93-
let defaultTo = defaultDesignSystem.resolveThemeValue(toThemeKey)
75+
let root = parts.join('-')
76+
if (Object.hasOwn(LEGACY_CLASS_MAP, root)) {
77+
let newRoot = LEGACY_CLASS_MAP[root as keyof typeof LEGACY_CLASS_MAP]
9478

95-
// The new theme value is not defined, which means we can't safely
96-
// migrate the utility.
97-
if (customTo === undefined) {
79+
if (location && !root.includes('-') && !isSafeMigration(location)) {
9880
continue
9981
}
10082

101-
// The "from" theme value changed compared to the default theme value.
102-
if (customFrom !== defaultFrom) {
103-
continue
83+
let fromThemeKey = THEME_KEYS[root as keyof typeof THEME_KEYS]
84+
let toThemeKey = THEME_KEYS[newRoot as keyof typeof THEME_KEYS]
85+
86+
if (fromThemeKey && toThemeKey) {
87+
// Migrating something that resolves to a value in the theme.
88+
let customFrom = designSystem.resolveThemeValue(fromThemeKey)
89+
let defaultFrom = defaultDesignSystem.resolveThemeValue(fromThemeKey)
90+
let customTo = designSystem.resolveThemeValue(toThemeKey)
91+
let defaultTo = defaultDesignSystem.resolveThemeValue(toThemeKey)
92+
93+
// The new theme value is not defined, which means we can't safely
94+
// migrate the utility.
95+
if (customTo === undefined) {
96+
continue
97+
}
98+
99+
// The "from" theme value changed compared to the default theme value.
100+
if (customFrom !== defaultFrom) {
101+
continue
102+
}
103+
104+
// The "to" theme value changed compared to the default theme value.
105+
if (customTo !== defaultTo) {
106+
continue
107+
}
104108
}
105109

106-
// The "to" theme value changed compared to the default theme value.
107-
if (customTo !== defaultTo) {
108-
continue
110+
for (let newCandidate of designSystem.parseCandidate(newRoot)) {
111+
let clone = structuredClone(newCandidate) as Candidate
112+
113+
clone.important = candidate.important
114+
clone.variants = candidate.variants
115+
116+
return printCandidate(designSystem, clone)
109117
}
110118
}
111-
112-
return printCandidate(designSystem, {
113-
...candidate,
114-
root: newRoot,
115-
})
116119
}
117120
}
118121

0 commit comments

Comments
 (0)