mirror of
https://github.com/tailwindlabs/tailwindcss.git
synced 2025-12-08 21:36:08 +00:00
Upgrade deprecated order-none to order-0 (#18126)
This PR adds an initial version for deprecated utilities. Right now it's hardcoded to just the `order-none` utility. This means that `order-0` and `order-[0]` will not be migrated to `order-none` anymore. We did that automatically because we prefer named utilities over bare values and arbitrary values. With this PR, `order-none` is ignored. Similarly, `order-none` will be migrated to `order-0` instead (defined in a separate migration for deprecated values). Made it a new migration instead of using the legacy migration because there all utilities still exist, but are defined differently (e.g.: `shadow`, `shadow-sm`, `shadow-xs`). This PR is also an initial version, it doesn't add any form of `deprecated` flag or feature on a per-utility implementation basis. This therefor has the side effect that if you have a custom `order-none` defined, that it will also be ignored during migrations. ## Test plan 1. Added tests to ensure the `order-0` is not migrated to `order-none` 2. Added tests to ensure `order-none` is migrated to `order-0` (if it's safe to do so, the signature is still computed to ensure the output is the same). 3. Ran this on the Tailwind Plus codebase and ensured that `order-0` is not migrated to `order-none` and that `order-none` is migrated to `order-0`. --------- Co-authored-by: Jordan Pittman <jordan@cryptica.me>
This commit is contained in:
parent
ed3cecd39d
commit
9cb38993d2
@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
- Upgrade: Do not migrate declarations that look like candidates in `<style>` blocks ([#18057](https://github.com/tailwindlabs/tailwindcss/pull/18057), [18068](https://github.com/tailwindlabs/tailwindcss/pull/18068))
|
||||
- Upgrade: Improve `pnpm` workspaces support ([#18065](https://github.com/tailwindlabs/tailwindcss/pull/18065))
|
||||
- Upgrade: Migrate deprecated `order-none` to `order-0` ([#18126](https://github.com/tailwindlabs/tailwindcss/pull/18126))
|
||||
- Support Leptos `class:` attributes when extracting classes ([#18093](https://github.com/tailwindlabs/tailwindcss/pull/18093))
|
||||
|
||||
## [4.1.7] - 2025-05-15
|
||||
|
||||
@ -33,3 +33,11 @@ export function parseCandidate(designSystem: DesignSystem, input: string) {
|
||||
: input,
|
||||
)
|
||||
}
|
||||
|
||||
export function printUnprefixedCandidate(designSystem: DesignSystem, candidate: Candidate) {
|
||||
let candidateString = designSystem.printCandidate(candidate)
|
||||
|
||||
return designSystem.theme.prefix && candidateString.startsWith(`${designSystem.theme.prefix}:`)
|
||||
? candidateString.slice(designSystem.theme.prefix.length + 1)
|
||||
: candidateString
|
||||
}
|
||||
|
||||
@ -0,0 +1,52 @@
|
||||
import type { Config } from '../../../../tailwindcss/src/compat/plugin-api'
|
||||
import type { DesignSystem } from '../../../../tailwindcss/src/design-system'
|
||||
import type { Writable } from '../../utils/types'
|
||||
import { baseCandidate, parseCandidate, printUnprefixedCandidate } from './candidates'
|
||||
import { computeUtilitySignature } from './signatures'
|
||||
|
||||
const DEPRECATION_MAP = new Map([['order-none', 'order-0']])
|
||||
|
||||
export async function migrateDeprecatedUtilities(
|
||||
designSystem: DesignSystem,
|
||||
_userConfig: Config | null,
|
||||
rawCandidate: string,
|
||||
): Promise<string> {
|
||||
let signatures = computeUtilitySignature.get(designSystem)
|
||||
|
||||
for (let readonlyCandidate of designSystem.parseCandidate(rawCandidate)) {
|
||||
// The below logic makes use of mutation. Since candidates in the
|
||||
// DesignSystem are cached, we can't mutate them directly.
|
||||
let candidate = structuredClone(readonlyCandidate) as Writable<typeof readonlyCandidate>
|
||||
|
||||
// Create a basic stripped candidate without variants or important flag. We
|
||||
// will re-add those later but they are irrelevant for what we are trying to
|
||||
// do here (and will increase cache hits because we only have to deal with
|
||||
// the base utility, nothing more).
|
||||
let targetCandidate = baseCandidate(candidate)
|
||||
let targetCandidateString = printUnprefixedCandidate(designSystem, targetCandidate)
|
||||
|
||||
let replacementString = DEPRECATION_MAP.get(targetCandidateString) ?? null
|
||||
if (replacementString === null) return rawCandidate
|
||||
|
||||
let legacySignature = signatures.get(targetCandidateString)
|
||||
if (typeof legacySignature !== 'string') return rawCandidate
|
||||
|
||||
let replacementSignature = signatures.get(replacementString)
|
||||
if (typeof replacementSignature !== 'string') return rawCandidate
|
||||
|
||||
// Not the same signature, not safe to migrate
|
||||
if (legacySignature !== replacementSignature) return rawCandidate
|
||||
|
||||
let [replacement] = parseCandidate(designSystem, replacementString)
|
||||
|
||||
// Re-add the variants and important flag from the original candidate
|
||||
return designSystem.printCandidate(
|
||||
Object.assign(structuredClone(replacement), {
|
||||
variants: candidate.variants,
|
||||
important: candidate.important,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
return rawCandidate
|
||||
}
|
||||
@ -45,6 +45,14 @@ describe.each([['default'], ['with-variant'], ['important'], ['prefix']])('%s',
|
||||
|
||||
// Promote inferred data type to more specific utility if it exists
|
||||
['bg-[123px]', 'bg-position-[123px]'],
|
||||
|
||||
// Do not migrate bare values or arbitrary values to named values that are
|
||||
// deprecated
|
||||
['order-[0]', 'order-0'],
|
||||
['order-0', 'order-0'],
|
||||
|
||||
// Migrate deprecated named values to bare values
|
||||
['order-none', 'order-0'],
|
||||
])(testName, async (candidate, result) => {
|
||||
if (strategy === 'with-variant') {
|
||||
candidate = `focus:${candidate}`
|
||||
@ -63,4 +71,38 @@ describe.each([['default'], ['with-variant'], ['important'], ['prefix']])('%s',
|
||||
let migrated = await migrate(designSystem, {}, candidate)
|
||||
expect(migrated).toEqual(result)
|
||||
})
|
||||
|
||||
test.each([
|
||||
['order-[0]', 'order-0'],
|
||||
['order-0', 'order-0'],
|
||||
|
||||
// Do not migrate `order-none` if defined as a custom utility as it is then
|
||||
// not safe to migrate to `order-0`
|
||||
['order-none', 'order-none'],
|
||||
])(`${testName} with custom implementations`, async (candidate, result) => {
|
||||
if (strategy === 'with-variant') {
|
||||
candidate = `focus:${candidate}`
|
||||
result = `focus:${result}`
|
||||
} else if (strategy === 'important') {
|
||||
candidate = `${candidate}!`
|
||||
result = `${result}!`
|
||||
} else if (strategy === 'prefix') {
|
||||
// Not only do we need to prefix the candidate, we also have to make
|
||||
// sure that we prefix all CSS variables.
|
||||
candidate = `tw:${candidate.replaceAll('var(--', 'var(--tw-')}`
|
||||
result = `tw:${result.replaceAll('var(--', 'var(--tw-')}`
|
||||
}
|
||||
|
||||
let localInput = css`
|
||||
${input}
|
||||
|
||||
@utility order-none {
|
||||
order: none; /* imagine this exists */
|
||||
}
|
||||
`
|
||||
|
||||
let designSystem = await designSystems.get(__dirname).get(localInput)
|
||||
let migrated = await migrate(designSystem, {}, candidate)
|
||||
expect(migrated).toEqual(result)
|
||||
})
|
||||
})
|
||||
|
||||
@ -14,6 +14,7 @@ import { migrateBareValueUtilities } from './migrate-bare-utilities'
|
||||
import { migrateBgGradient } from './migrate-bg-gradient'
|
||||
import { migrateCamelcaseInNamedValue } from './migrate-camelcase-in-named-value'
|
||||
import { migrateCanonicalizeCandidate } from './migrate-canonicalize-candidate'
|
||||
import { migrateDeprecatedUtilities } from './migrate-deprecated-utilities'
|
||||
import { migrateDropUnnecessaryDataTypes } from './migrate-drop-unnecessary-data-types'
|
||||
import { migrateEmptyArbitraryValues } from './migrate-handle-empty-arbitrary-values'
|
||||
import { migrateLegacyArbitraryValues } from './migrate-legacy-arbitrary-values'
|
||||
@ -48,6 +49,7 @@ export const DEFAULT_MIGRATIONS: Migration[] = [
|
||||
migrateLegacyArbitraryValues,
|
||||
migrateArbitraryUtilities,
|
||||
migrateBareValueUtilities,
|
||||
migrateDeprecatedUtilities,
|
||||
migrateModernizeArbitraryValues,
|
||||
migrateArbitraryVariants,
|
||||
migrateDropUnnecessaryDataTypes,
|
||||
|
||||
@ -8079,7 +8079,6 @@ exports[`getClassList 1`] = `
|
||||
"order-12",
|
||||
"order-first",
|
||||
"order-last",
|
||||
"order-none",
|
||||
"ordinal",
|
||||
"origin-bottom",
|
||||
"origin-bottom-left",
|
||||
|
||||
@ -90,4 +90,6 @@ export function registerLegacyUtilities(designSystem: DesignSystem) {
|
||||
return [decl('flex-grow', candidate.value.value)]
|
||||
}
|
||||
})
|
||||
|
||||
designSystem.utilities.static('order-none', () => [decl('order', '0')])
|
||||
}
|
||||
|
||||
@ -649,7 +649,6 @@ export function createUtilities(theme: Theme) {
|
||||
*/
|
||||
staticUtility('order-first', [['order', '-9999']])
|
||||
staticUtility('order-last', [['order', '9999']])
|
||||
staticUtility('order-none', [['order', '0']])
|
||||
functionalUtility('order', {
|
||||
supportsNegative: true,
|
||||
handleBareValue: ({ value }) => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user