tailwindcss/packages/@tailwindcss-upgrade/src/codemods/migrate-at-apply.ts
Philipp Spiess 7be5346e2e
Ensure upgrade tool has access to a JS config (#14597)
In order to properly migrate your Tailwind CSS v3 project to v4, we need
access to the JavaScript configuration object. This was previously only
required for template migrations, but in this PR we're making it so that
this is also a prerequisite of the CSS migrations. This is because some
migrations, like `@apply`, also need to convert candidates that to the
v4 syntax and we need the full config in order to properly validate
them.

In addition to requiring a JS config, we also now attempt to
automatically find the right configuration file inside the current
working directory. This is now matching the behavior of the Tailwind CSS
v3 CLI where it will find the config automatically if it's in the
current directory and called `tailwind.conf.js`.

---------

Co-authored-by: Robin Malfait <malfait.robin@gmail.com>
2024-10-07 18:02:28 +02:00

50 lines
1.5 KiB
TypeScript

import type { AtRule, Plugin } from 'postcss'
import type { Config } from 'tailwindcss'
import type { DesignSystem } from '../../../tailwindcss/src/design-system'
import { segment } from '../../../tailwindcss/src/utils/segment'
import { migrateCandidate } from '../template/migrate'
export function migrateAtApply({
designSystem,
userConfig,
}: {
designSystem: DesignSystem
userConfig: Config
}): Plugin {
function migrate(atRule: AtRule) {
let utilities = atRule.params.split(/(\s+)/)
let important =
utilities[utilities.length - 1] === '!important' ||
utilities[utilities.length - 1] === '#{!important}' // Sass/SCSS
if (important) utilities.pop() // Remove `!important`
let params = utilities.map((part) => {
// Keep whitespace
if (part.trim() === '') return part
let variants = segment(part, ':')
let utility = variants.pop()!
// Apply the important modifier to all the rules if necessary
if (important && utility[0] !== '!' && utility[utility.length - 1] !== '!') {
utility += '!'
}
// Reconstruct the utility with the variants
return [...variants, utility].join(':')
})
// If we have a valid designSystem and config setup, we can run all
// candidate migrations on each utility
params = params.map((param) => migrateCandidate(designSystem, userConfig, param))
atRule.params = params.join('').trim()
}
return {
postcssPlugin: '@tailwindcss/upgrade/migrate-at-apply',
OnceExit(root) {
root.walkAtRules('apply', migrate)
},
}
}