Skip to content

Commit 5cdb3e3

Browse files
committed
move migrate-optimize-modifier to core
1 parent df62457 commit 5cdb3e3

File tree

5 files changed

+106
-152
lines changed

5 files changed

+106
-152
lines changed

packages/@tailwindcss-upgrade/src/codemods/template/migrate-optimize-modifier.test.ts

Lines changed: 0 additions & 68 deletions
This file was deleted.

packages/@tailwindcss-upgrade/src/codemods/template/migrate-optimize-modifier.ts

Lines changed: 0 additions & 80 deletions
This file was deleted.

packages/@tailwindcss-upgrade/src/codemods/template/migrate.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import { migrateLegacyArbitraryValues } from './migrate-legacy-arbitrary-values'
1515
import { migrateLegacyClasses } from './migrate-legacy-classes'
1616
import { migrateMaxWidthScreen } from './migrate-max-width-screen'
1717
import { migrateModernizeArbitraryValues } from './migrate-modernize-arbitrary-values'
18-
import { migrateOptimizeModifier } from './migrate-optimize-modifier'
1918
import { migratePrefix } from './migrate-prefix'
2019
import { migrateSimpleLegacyClasses } from './migrate-simple-legacy-classes'
2120
import { migrateVariantOrder } from './migrate-variant-order'
@@ -38,7 +37,6 @@ export const DEFAULT_MIGRATIONS: Migration[] = [
3837
migrateAutomaticVarInjection, // sync, v3 → v4
3938
migrateLegacyArbitraryValues, // sync, v3 → v4 (could also consider it a v4 optimization)
4039
migrateModernizeArbitraryValues, // sync, v3 and v4 optimizations, split up?
41-
migrateOptimizeModifier, // sync, v4 (optimization)
4240
]
4341

4442
let migrateCached = new DefaultMap<

packages/tailwindcss/src/canonicalize-candidates.test.ts

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ describe.each([['default'], ['with-variant'], ['important'], ['prefix']])('%s',
162162
// as bare modifiers). Convert the complex numbers to arbitrary values instead.
163163
['[color:theme(colors.red.500/12.34%)]', 'text-red-500/[12.34%]'],
164164
['[color:theme(colors.red.500/var(--opacity))]', 'text-red-500/(--opacity)'],
165-
['[color:theme(colors.red.500/.12345)]', 'text-red-500/[12.345]'],
166-
['[color:theme(colors.red.500/50.25%)]', 'text-red-500/[50.25%]'],
165+
['[color:theme(colors.red.500/.12345)]', 'text-red-500/1234.5'],
166+
['[color:theme(colors.red.500/50.25%)]', 'text-red-500/50.25'],
167167

168168
// Arbitrary value
169169
['bg-[theme(colors.red.500/75%)]', 'bg-red-500/75'],
@@ -726,6 +726,36 @@ describe.each([['default'], ['with-variant'], ['important'], ['prefix']])('%s',
726726
await expectCanonicalization(input, candidate, expected)
727727
})
728728
})
729+
730+
describe('optimize modifier', () => {
731+
let input = css`
732+
@import 'tailwindcss';
733+
@theme {
734+
--*: initial;
735+
--color-red-500: red;
736+
}
737+
`
738+
739+
test.each([
740+
// Keep the modifier as-is, nothing to optimize
741+
['bg-red-500/25', 'bg-red-500/25'],
742+
743+
// Use a bare value modifier
744+
['bg-red-500/[25%]', 'bg-red-500/25'],
745+
746+
// Convert 0-1 values to bare values
747+
['bg-[#f00]/[0.16]', 'bg-[#f00]/16'],
748+
749+
// Drop unnecessary modifiers
750+
['bg-red-500/[100%]', 'bg-red-500'],
751+
['bg-red-500/100', 'bg-red-500'],
752+
753+
// Keep modifiers on classes that don't _really_ exist
754+
['group/name', 'group/name'],
755+
])(testName, async (candidate, expected) => {
756+
await expectCanonicalization(input, candidate, expected)
757+
})
758+
})
729759
})
730760

731761
describe('theme to var', () => {

packages/tailwindcss/src/canonicalize-candidates.ts

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ const CANONICALIZATIONS = [
5252
arbitraryVariants,
5353
dropUnnecessaryDataTypes,
5454
arbitraryValueToBareValue,
55+
optimizeModifier,
5556
print,
5657
]
5758

@@ -1106,3 +1107,76 @@ function* tryValueReplacements(
11061107
yield* tryValueReplacements(candidate, option, seen)
11071108
}
11081109
}
1110+
1111+
// ----
1112+
1113+
// Optimize the modifier
1114+
//
1115+
// E.g.:
1116+
//
1117+
// - `/[25%]` → `/25`
1118+
// - `/[100%]` → `/100` → <empty>
1119+
// - `/100` → <empty>
1120+
//
1121+
function optimizeModifier(designSystem: DesignSystem, rawCandidate: string): string {
1122+
let signatures = computeUtilitySignature.get(designSystem)
1123+
1124+
for (let readonlyCandidate of designSystem.parseCandidate(rawCandidate)) {
1125+
let candidate = structuredClone(readonlyCandidate) as Writable<typeof readonlyCandidate>
1126+
if (
1127+
(candidate.kind === 'functional' && candidate.modifier !== null) ||
1128+
(candidate.kind === 'arbitrary' && candidate.modifier !== null)
1129+
) {
1130+
let targetSignature = signatures.get(rawCandidate)
1131+
let modifier = candidate.modifier
1132+
let changed = false
1133+
1134+
// 1. Try to drop the modifier entirely
1135+
if (
1136+
targetSignature ===
1137+
signatures.get(designSystem.printCandidate({ ...candidate, modifier: null }))
1138+
) {
1139+
changed = true
1140+
candidate.modifier = null
1141+
}
1142+
1143+
// 2. Try to remove the square brackets and the `%` sign
1144+
if (!changed) {
1145+
let newModifier: NamedUtilityValue = {
1146+
kind: 'named',
1147+
value: modifier.value.endsWith('%') ? modifier.value.slice(0, -1) : modifier.value,
1148+
fraction: null,
1149+
}
1150+
1151+
if (
1152+
targetSignature ===
1153+
signatures.get(designSystem.printCandidate({ ...candidate, modifier: newModifier }))
1154+
) {
1155+
changed = true
1156+
candidate.modifier = newModifier
1157+
}
1158+
}
1159+
1160+
// 3. Try to remove the square brackets, but multiply by 100. E.g.: `[0.16]` -> `16`
1161+
if (!changed) {
1162+
let newModifier: NamedUtilityValue = {
1163+
kind: 'named',
1164+
value: `${parseFloat(modifier.value) * 100}`,
1165+
fraction: null,
1166+
}
1167+
1168+
if (
1169+
targetSignature ===
1170+
signatures.get(designSystem.printCandidate({ ...candidate, modifier: newModifier }))
1171+
) {
1172+
changed = true
1173+
candidate.modifier = newModifier
1174+
}
1175+
}
1176+
1177+
return changed ? designSystem.printCandidate(candidate) : rawCandidate
1178+
}
1179+
}
1180+
1181+
return rawCandidate
1182+
}

0 commit comments

Comments
 (0)