Skip to content

Commit 49a0983

Browse files
content rules from the JS config that are also covered by the automatic source detection should not be migrated to CSS
1 parent b701ed6 commit 49a0983

3 files changed

Lines changed: 49 additions & 11 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10-
- Nothing yet!
10+
### Changed
11+
12+
- _Upgrade (experimental)_: `content` rules from the JS configuration that are also covered by the automatic source detection are no longer migrated to CSS
1113

1214
## [4.0.0-alpha.28] - 2024-10-17
1315

integrations/upgrade/js-config.test.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { expect } from 'vitest'
2-
import { css, json, test, ts } from '../utils'
2+
import { css, html, json, test, ts } from '../utils'
33

44
test(
55
`upgrade JS config files with flat theme values, darkMode, and content fields`,
@@ -18,7 +18,7 @@ test(
1818
1919
module.exports = {
2020
darkMode: 'selector',
21-
content: ['./src/**/*.{html,js}', './my-app/**/*.{html,js}'],
21+
content: ['./src/**/*.{html,js}', './node_modules/my-external-lib/**/*.{html}'],
2222
theme: {
2323
boxShadow: {
2424
sm: '0 2px 6px rgb(15 23 42 / 0.08)',
@@ -72,6 +72,11 @@ test(
7272
@tailwind components;
7373
@tailwind utilities;
7474
`,
75+
'node_modules/my-external-lib/src/template.html': html`
76+
<div class="text-red-500">
77+
Hello world!
78+
</div>
79+
`,
7580
},
7681
},
7782
async ({ exec, fs }) => {
@@ -82,8 +87,7 @@ test(
8287
--- src/input.css ---
8388
@import 'tailwindcss';
8489
85-
@source './**/*.{html,js}';
86-
@source '../my-app/**/*.{html,js}';
90+
@source '../node_modules/my-external-lib/**/*.{html}';
8791
8892
@variant dark (&:where(.dark, .dark *));
8993

packages/@tailwindcss-upgrade/src/migrate-js-config.ts

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import { Scanner } from '@tailwindcss/oxide'
12
import fs from 'node:fs/promises'
23
import { dirname } from 'path'
3-
import type { Config } from 'tailwindcss'
4+
import { type Config } from 'tailwindcss'
45
import defaultTheme from 'tailwindcss/defaultTheme'
56
import { fileURLToPath } from 'url'
67
import { loadModule } from '../../@tailwindcss-node/src/compile'
@@ -15,7 +16,7 @@ import type { ThemeConfig } from '../../tailwindcss/src/compat/config/types'
1516
import { darkModePlugin } from '../../tailwindcss/src/compat/dark-mode'
1617
import type { DesignSystem } from '../../tailwindcss/src/design-system'
1718
import { findStaticPlugins } from './utils/extract-static-plugins'
18-
import { info } from './utils/renderer'
19+
import { info, warn } from './utils/renderer'
1920

2021
const __filename = fileURLToPath(import.meta.url)
2122
const __dirname = dirname(__filename)
@@ -54,7 +55,7 @@ export async function migrateJsConfig(
5455
}
5556

5657
if ('content' in unresolvedConfig) {
57-
sources = migrateContent(unresolvedConfig as any, base)
58+
sources = await migrateContent(unresolvedConfig as any, base)
5859
}
5960

6061
if ('theme' in unresolvedConfig) {
@@ -158,16 +159,35 @@ function createSectionKey(key: string[]): string {
158159
return sectionSegments.join('-')
159160
}
160161

161-
function migrateContent(
162+
async function migrateContent(
162163
unresolvedConfig: Config & { content: any },
163164
base: string,
164-
): { base: string; pattern: string }[] {
165+
): Promise<{ base: string; pattern: string }[]> {
166+
let autoContentFiles = listAutoContentFiles(base)
167+
165168
let sources = []
166169
for (let content of unresolvedConfig.content) {
167170
if (typeof content !== 'string') {
168171
throw new Error('Unsupported content value: ' + content)
169172
}
170-
sources.push({ base, pattern: content })
173+
174+
let sourceFiles = listSourceContentFiles({ base, pattern: content })
175+
176+
let autoContentContainsAllSourceFiles = true
177+
for (let sourceFile of sourceFiles) {
178+
if (!autoContentFiles.includes(sourceFile)) {
179+
autoContentContainsAllSourceFiles = false
180+
break
181+
}
182+
}
183+
184+
if (autoContentContainsAllSourceFiles) {
185+
warn(
186+
'The `content` configuration `${content}` is already included in the automatic content file discovery and will not be migrated.',
187+
)
188+
} else {
189+
sources.push({ base, pattern: content })
190+
}
171191
}
172192
return sources
173193
}
@@ -253,3 +273,15 @@ function keyframesToCss(keyframes: Record<string, unknown>): string {
253273
let ast: AstNode[] = keyframesToRules({ theme: { keyframes } })
254274
return toCss(ast).trim() + '\n'
255275
}
276+
277+
function listAutoContentFiles(base: string) {
278+
let scanner = new Scanner({ detectSources: { base } })
279+
scanner.scan()
280+
return scanner.files
281+
}
282+
283+
function listSourceContentFiles(source: { base: string; pattern: string }): string[] {
284+
let scanner = new Scanner({ sources: [source] })
285+
scanner.scan()
286+
return scanner.files
287+
}

0 commit comments

Comments
 (0)