Robin Malfait 3ae22f1f9d
Migrate @media screen(…) (#14603)
This PR adds a codemod that migrates the `@media screen(…)` to the
properly expanded `@media (…)` syntax.

```css
@media screen(md) {
  .foo {
    color: red;
  }
}
```

Will be converted to:
```css
@media (width >= 48rem) {
  .foo {
    color: red;
  }
}
```

If you happen to have custom screens (even complex ones), the screen
will be converted to a custom media query.

```css
@media screen(foo) {
  .foo {
    color: red;
  }
}
```
With a custom `tailwind.config.js` file with a config like this:
```js
module.exports = {
  // …
  theme: {
    screens: {
      foo: { min: '100px', max: '123px' },
    },
  }
}
```

Then the codemod will convert it to:
```css
@media (123px >= width >= 100px) {
  .foo {
    color: red;
  }
}
```
2024-10-10 15:06:53 +02:00

45 lines
1.4 KiB
TypeScript

import { type Plugin, type Root } from 'postcss'
import type { Config } from 'tailwindcss'
import { resolveConfig } from '../../../tailwindcss/src/compat/config/resolve-config'
import { buildMediaQuery } from '../../../tailwindcss/src/compat/screens-config'
import type { DesignSystem } from '../../../tailwindcss/src/design-system'
import { DefaultMap } from '../../../tailwindcss/src/utils/default-map'
export function migrateMediaScreen({
designSystem,
userConfig,
}: {
designSystem?: DesignSystem
userConfig?: Config
} = {}): Plugin {
function migrate(root: Root) {
if (!designSystem || !userConfig) return
let resolvedUserConfig = resolveConfig(designSystem, [{ base: '', config: userConfig }])
let screens = resolvedUserConfig?.theme?.screens || {}
let mediaQueries = new DefaultMap<string, string | null>((name) => {
let value = designSystem?.resolveThemeValue(`--breakpoint-${name}`) ?? screens?.[name]
if (typeof value === 'string') return `(width >= theme(--breakpoint-${name}))`
return value ? buildMediaQuery(value) : null
})
root.walkAtRules((rule) => {
if (rule.name !== 'media') return
let screen = rule.params.match(/screen\(([^)]+)\)/)
if (!screen) return
let value = mediaQueries.get(screen[1])
if (!value) return
rule.params = value
})
}
return {
postcssPlugin: '@tailwindcss/upgrade/migrate-media-screen',
OnceExit: migrate,
}
}