Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Ensure `flex` is suggested ([#15014](https://github.com/tailwindlabs/tailwindcss/pull/15014))
- _Upgrade (experimental)_: Resolve imports when specifying a CSS entry point on the command-line ([#15010](https://github.com/tailwindlabs/tailwindcss/pull/15010))
- _Upgrade (experimental)_: Resolve nearest Tailwind config file when CSS file does not contain `@config` ([#15001](https://github.com/tailwindlabs/tailwindcss/pull/15001))
- _Upgrade (experimental)_: Improve output when CSS imports can not be found ([#15038](https://github.com/tailwindlabs/tailwindcss/pull/15038))
- _Upgrade (experimental)_: Ignore analyzing imports with external URLs (e.g.: `@import "https://fonts.google.com"`) ([#15040](https://github.com/tailwindlabs/tailwindcss/pull/15040))
- _Upgrade (experimental)_: Ignore analyzing imports with `url(…)` (e.g.: `@import url("https://fonts.google.com")`) ([#15040](https://github.com/tailwindlabs/tailwindcss/pull/15040))

### Changed

Expand Down
19 changes: 7 additions & 12 deletions packages/@tailwindcss-upgrade/src/codemods/migrate-import.test.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,22 @@
import { __unstable__loadDesignSystem } from '@tailwindcss/node'
import dedent from 'dedent'
import postcss from 'postcss'
import { expect, it } from 'vitest'
import type { UserConfig } from '../../../tailwindcss/src/compat/config/types'
import { migrateImport } from './migrate-import'

const css = dedent

async function migrate(input: string, userConfig: UserConfig = {}) {
async function migrate(input: string) {
return postcss()
.use(
migrateImport({
designSystem: await __unstable__loadDesignSystem(`@import 'tailwindcss';`, {
base: __dirname,
}),
userConfig,
}),
)
.use(migrateImport())
.process(input, { from: expect.getState().testPath })
.then((result) => result.css)
}

it('prints relative file imports as relative paths', async () => {
expect(
await migrate(css`
@import url('https://example.com');

@import 'fixtures/test';
@import 'fixtures/test.css';
@import './fixtures/test.css';
Expand Down Expand Up @@ -62,7 +55,9 @@ it('prints relative file imports as relative paths', async () => {
@import 'tailwindcss/theme';
`),
).toMatchInlineSnapshot(`
"@import './fixtures/test.css';
"@import url('https://example.com');

@import './fixtures/test.css';
@import './fixtures/test.css';
@import './fixtures/test.css';
@import './fixtures/test.css';
Expand Down
46 changes: 26 additions & 20 deletions packages/@tailwindcss-upgrade/src/codemods/migrate-import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,27 +12,33 @@ export function migrateImport(): Plugin {

let promises: Promise<void>[] = []
root.walkAtRules('import', (rule) => {
let [firstParam, ...rest] = segment(rule.params, ' ')

let params = parseImportParams(ValueParser.parse(firstParam))

let isRelative = params.uri[0] === '.'
let hasCssExtension = params.uri.endsWith('.css')

if (isRelative && hasCssExtension) {
return
try {
let [firstParam, ...rest] = segment(rule.params, ' ')

let params = parseImportParams(ValueParser.parse(firstParam))

let isRelative = params.uri[0] === '.'
let hasCssExtension = params.uri.endsWith('.css')

if (isRelative && hasCssExtension) {
return
}

let fullPath = resolve(dirname(file), params.uri)
if (!hasCssExtension) fullPath += '.css'

promises.push(
fs.stat(fullPath).then(() => {
let ext = hasCssExtension ? '' : '.css'
let path = isRelative ? params.uri : `./${params.uri}`
rule.params = [`'${path}${ext}'`, ...rest].join(' ')
}),
)
} catch {
// When an error occurs while parsing the `@import` statement, we skip
// the import. This will happen in cases where you import an external
// URL.
}

let fullPath = resolve(dirname(file), params.uri)
if (!hasCssExtension) fullPath += '.css'

promises.push(
fs.stat(fullPath).then(() => {
let ext = hasCssExtension ? '' : '.css'
let path = isRelative ? params.uri : `./${params.uri}`
rule.params = [`'${path}${ext}'`, ...rest].join(' ')
}),
)
})

await Promise.allSettled(promises)
Expand Down
7 changes: 7 additions & 0 deletions packages/@tailwindcss-upgrade/src/migrate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ export async function analyze(stylesheets: Stylesheet[]) {
resolvedPath = resolveCssId(id, basePath)
}
} catch (err) {
// Import is a URL, we don't want to process these, but also don't
// want to show an error message for them.
if (id.startsWith('http://') || id.startsWith('https://') || id.startsWith('//')) {
return
}

// Something went wrong, we can't resolve the import.
error(
`Failed to resolve import: ${highlight(id)} in ${highlight(relative(node.source?.input.file!, basePath))}. Skipping.`,
{ prefix: '↳ ' },
Expand Down