Change casing of utilities with named values to kebab-case to match u… (#18017)
Fixes #16156 ## Summary This PR adds a new 3 -> 4 template migration that changes the casing of in both utility values and modifier values from camelCase to kebab-case to match the updated CSS variable names. ## Test plan - Added integration test, see the diff in the PR.
This commit is contained in:
parent
4db711d1e4
commit
e57a2f5a3a
5 changed files with 93 additions and 3 deletions
|
|
@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
- `lightningcss` now statically links Visual Studio redistributables ([#17979](https://github.com/tailwindlabs/tailwindcss/pull/17979))
|
||||
- Ensure that running the Standalone build does not leave temporary files behind ([#17981](https://github.com/tailwindlabs/tailwindcss/pull/17981))
|
||||
- Fix `-rotate-*` utilities with arbitrary values ([#18014](https://github.com/tailwindlabs/tailwindcss/pull/18014))
|
||||
- Upgrade: Change casing of utilities with named values to kebab-case to match updated theme variables ([#18017](https://github.com/tailwindlabs/tailwindcss/pull/18017))
|
||||
|
||||
### Added
|
||||
|
||||
|
|
|
|||
|
|
@ -30,9 +30,13 @@ test(
|
|||
400: '#f87171',
|
||||
500: 'red',
|
||||
},
|
||||
superRed: '#ff0000',
|
||||
steel: 'rgb(70 130 180 / <alpha-value>)',
|
||||
smoke: 'rgba(245, 245, 245, var(--smoke-alpha, <alpha-value>))',
|
||||
},
|
||||
opacity: {
|
||||
superOpaque: '0.95',
|
||||
},
|
||||
fontSize: {
|
||||
xs: ['0.75rem', { lineHeight: '1rem' }],
|
||||
sm: ['0.875rem', { lineHeight: '1.5rem' }],
|
||||
|
|
@ -144,9 +148,10 @@ test(
|
|||
}
|
||||
`,
|
||||
'src/index.html': html`
|
||||
<div
|
||||
<div
|
||||
class="[letter-spacing:theme(letterSpacing.superWide)] [line-height:theme(lineHeight.superLoose)]"
|
||||
></div>
|
||||
<div class="text-red-superRed/superOpaque leading-superLoose"></div>
|
||||
`,
|
||||
'node_modules/my-external-lib/src/template.html': html`
|
||||
<div class="text-red-500">
|
||||
|
|
@ -162,8 +167,9 @@ test(
|
|||
"
|
||||
--- src/index.html ---
|
||||
<div
|
||||
class="[letter-spacing:var(--tracking-super-wide)] [line-height:var(--leading-super-loose)]"
|
||||
></div>
|
||||
class="[letter-spacing:var(--tracking-super-wide)] [line-height:var(--leading-super-loose)]"
|
||||
></div>
|
||||
<div class="text-red-super-red/super-opaque leading-super-loose"></div>
|
||||
|
||||
--- src/input.css ---
|
||||
@import 'tailwindcss';
|
||||
|
|
@ -181,9 +187,13 @@ test(
|
|||
--color-red-500: #ef4444;
|
||||
--color-red-600: #dc2626;
|
||||
|
||||
--color-super-red: #ff0000;
|
||||
--color-steel: rgb(70 130 180);
|
||||
--color-smoke: rgba(245, 245, 245, var(--smoke-alpha, 1));
|
||||
|
||||
--opacity-*: initial;
|
||||
--opacity-super-opaque: 95%;
|
||||
|
||||
--text-*: initial;
|
||||
--text-xs: 0.75rem;
|
||||
--text-xs--line-height: 1rem;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
import { __unstable__loadDesignSystem } from '@tailwindcss/node'
|
||||
import { expect, test, vi } from 'vitest'
|
||||
import * as versions from '../../utils/version'
|
||||
import { migrateCamelcaseInNamedValue } from './migrate-camelcase-in-named-value'
|
||||
vi.spyOn(versions, 'isMajor').mockReturnValue(true)
|
||||
|
||||
test.each([
|
||||
['text-superRed', 'text-super-red'],
|
||||
['text-red/superOpaque', 'text-red/super-opaque'],
|
||||
['text-superRed/superOpaque', 'text-super-red/super-opaque'],
|
||||
|
||||
// Should not migrate named values in modifiers
|
||||
['group-hover/superGroup:underline', 'group-hover/superGroup:underline'],
|
||||
|
||||
['hover:text-superRed', 'hover:text-super-red'],
|
||||
['hover:text-red/superOpaque', 'hover:text-red/super-opaque'],
|
||||
['hover:text-superRed/superOpaque', 'hover:text-super-red/super-opaque'],
|
||||
])('%s => %s', async (candidate, result) => {
|
||||
let designSystem = await __unstable__loadDesignSystem('@import "tailwindcss";', {
|
||||
base: __dirname,
|
||||
})
|
||||
|
||||
expect(migrateCamelcaseInNamedValue(designSystem, {}, candidate)).toEqual(result)
|
||||
})
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
import type { Config } from '../../../../tailwindcss/src/compat/plugin-api'
|
||||
import type { DesignSystem } from '../../../../tailwindcss/src/design-system'
|
||||
import * as version from '../../utils/version'
|
||||
|
||||
// Converts named values to use kebab-case. This is necessary because the
|
||||
// upgrade tool also renames the theme values to kebab-case, so `text-superRed`
|
||||
// will have its theme value renamed to `--color-super-red` and thus the utility
|
||||
// will be renamed to `text-super-red`.
|
||||
export function migrateCamelcaseInNamedValue(
|
||||
designSystem: DesignSystem,
|
||||
_userConfig: Config | null,
|
||||
rawCandidate: string,
|
||||
): string {
|
||||
if (!version.isMajor(3)) return rawCandidate
|
||||
|
||||
for (let candidate of designSystem.parseCandidate(rawCandidate)) {
|
||||
if (candidate.kind !== 'functional') continue
|
||||
let clone = structuredClone(candidate)
|
||||
let didChange = false
|
||||
|
||||
if (
|
||||
candidate.value &&
|
||||
clone.value &&
|
||||
candidate.value.kind === 'named' &&
|
||||
clone.value.kind === 'named' &&
|
||||
candidate.value.value.match(/[A-Z]/)
|
||||
) {
|
||||
clone.value.value = camelToKebab(candidate.value.value)
|
||||
didChange = true
|
||||
}
|
||||
|
||||
if (
|
||||
candidate.modifier &&
|
||||
clone.modifier &&
|
||||
candidate.modifier.kind === 'named' &&
|
||||
clone.modifier.kind === 'named' &&
|
||||
candidate.modifier.value.match(/[A-Z]/)
|
||||
) {
|
||||
clone.modifier.value = camelToKebab(candidate.modifier.value)
|
||||
didChange = true
|
||||
}
|
||||
|
||||
if (didChange) {
|
||||
return designSystem.printCandidate(clone)
|
||||
}
|
||||
}
|
||||
|
||||
return rawCandidate
|
||||
}
|
||||
|
||||
function camelToKebab(str: string): string {
|
||||
return str.replace(/([A-Z])/g, '-$1').toLowerCase()
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@ import { migrateArbitraryVariants } from './migrate-arbitrary-variants'
|
|||
import { migrateAutomaticVarInjection } from './migrate-automatic-var-injection'
|
||||
import { migrateBareValueUtilities } from './migrate-bare-utilities'
|
||||
import { migrateBgGradient } from './migrate-bg-gradient'
|
||||
import { migrateCamelcaseInNamedValue } from './migrate-camelcase-in-named-value'
|
||||
import { migrateDropUnnecessaryDataTypes } from './migrate-drop-unnecessary-data-types'
|
||||
import { migrateEmptyArbitraryValues } from './migrate-handle-empty-arbitrary-values'
|
||||
import { migrateImportant } from './migrate-important'
|
||||
|
|
@ -41,6 +42,7 @@ export const DEFAULT_MIGRATIONS: Migration[] = [
|
|||
migrateImportant,
|
||||
migrateBgGradient,
|
||||
migrateSimpleLegacyClasses,
|
||||
migrateCamelcaseInNamedValue,
|
||||
migrateLegacyClasses,
|
||||
migrateMaxWidthScreen,
|
||||
migrateThemeToVar,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue