Skip to content

Commit ca488cd

Browse files
committed
Skip preprocessor files
1 parent 8fcb2dc commit ca488cd

File tree

3 files changed

+145
-1
lines changed

3 files changed

+145
-1
lines changed

packages/tailwindcss-language-server/src/project-locator.test.ts

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { test } from 'vitest'
1+
import { expect, test } from 'vitest'
22
import * as path from 'node:path'
33
import { ProjectLocator } from './project-locator'
44
import { URL, fileURLToPath } from 'url'
55
import { Settings } from '@tailwindcss/language-service/src/util/state'
66
import { createResolver } from './resolver'
7+
import { css, defineTest, js, json, scss, Storage, TestUtils } from './testing'
78

89
let settings: Settings = {
910
tailwindCSS: {
@@ -227,3 +228,125 @@ testFixture('v4/invalid-import-order', [
227228
content: ['{URL}/package.json'],
228229
},
229230
])
231+
232+
// ---
233+
234+
testLocator({
235+
name: 'Sass files are not supported detected with v4',
236+
fs: {
237+
'package.json': json`
238+
{
239+
"dependencies": {
240+
"tailwindcss": "^4.0.2"
241+
}
242+
}
243+
`,
244+
'src/app1.scss': scss`
245+
@import 'tailwindcss';
246+
`,
247+
'src/app2.scss': scss`
248+
@use 'tailwindcss';
249+
`,
250+
},
251+
252+
// We want to ignore `node_modules` folders otherwise we'll pick up the
253+
// default Tailwind CSS `index.css` file as a CSS-based config.
254+
settings: {
255+
tailwindCSS: {
256+
files: {
257+
exclude: ['**/node_modules'],
258+
},
259+
} as any,
260+
},
261+
262+
expected: [],
263+
})
264+
265+
// ---
266+
267+
function testLocator({
268+
name,
269+
fs,
270+
expected,
271+
settings,
272+
}: {
273+
name: string
274+
fs: Storage
275+
settings?: Partial<Settings>
276+
expected: any[]
277+
}) {
278+
defineTest({
279+
name,
280+
fs,
281+
prepare,
282+
async handle({ search }) {
283+
let projects = await search(settings)
284+
285+
let details = projects.map((project) => ({
286+
version: project.tailwind.isDefaultVersion
287+
? `${project.tailwind.version} (bundled)`
288+
: project.tailwind.version,
289+
config: project.config.path,
290+
content: project.documentSelector
291+
.filter((selector) => selector.priority === 1 /** content */)
292+
.map((selector) => selector.pattern)
293+
.sort(),
294+
selectors: project.documentSelector.map((selector) => selector.pattern).sort(),
295+
}))
296+
297+
expect(details).toMatchObject(expected)
298+
},
299+
})
300+
}
301+
302+
async function prepare({ root }: TestUtils) {
303+
let defaultSettings = {
304+
tailwindCSS: {
305+
files: {
306+
exclude: [],
307+
},
308+
},
309+
} as Settings
310+
311+
function adjustPath(filepath: string) {
312+
filepath = filepath.replace(root, '{URL}')
313+
314+
if (filepath.startsWith('{URL}/')) {
315+
filepath = filepath.slice(5)
316+
}
317+
318+
return filepath
319+
}
320+
321+
async function search(overrides?: Partial<Settings>) {
322+
let settings = {
323+
...defaultSettings,
324+
...overrides,
325+
}
326+
327+
let resolver = await createResolver({ root, tsconfig: true })
328+
let locator = new ProjectLocator(root, settings, resolver)
329+
let projects = await locator.search()
330+
331+
// Normalize all the paths for easier testing
332+
for (let project of projects) {
333+
project.folder = adjustPath(project.folder)
334+
project.configPath = adjustPath(project.configPath)
335+
336+
// Config data
337+
project.config.path = adjustPath(project.config.path)
338+
project.config.packageRoot = adjustPath(project.config.packageRoot)
339+
for (let entry of project.config.entries) {
340+
entry.path = adjustPath(entry.path)
341+
}
342+
343+
for (let selector of project.documentSelector ?? []) {
344+
selector.pattern = adjustPath(selector.pattern)
345+
}
346+
}
347+
348+
return projects
349+
}
350+
351+
return { search }
352+
}

packages/tailwindcss-language-server/src/project-locator.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,15 @@ export class ProjectLocator {
159159
if (!tailwind.features.includes('css-at-theme')) {
160160
return null
161161
}
162+
163+
// v4 does not support .sass, .scss, .less, and .styl files as configs
164+
if (requiresPreprocessor(config.path)) {
165+
console.warn(
166+
`The config ${config.path} requires a preprocessor and is not supported by Tailwind CSS v4.0.`,
167+
)
168+
169+
return null
170+
}
162171
}
163172

164173
// Don't boot a project for the JS config if using Tailwind v4
@@ -649,6 +658,11 @@ class FileEntry {
649658
}
650659

651660
async resolveImports(resolver: Resolver) {
661+
// Files that require a preprocessor are not processed
662+
if (requiresPreprocessor(this.path)) {
663+
return
664+
}
665+
652666
try {
653667
let result = await resolveCssImports({ resolver, loose: true }).process(this.content, {
654668
from: this.path,
@@ -733,3 +747,9 @@ class FileEntry {
733747
)
734748
}
735749
}
750+
751+
function requiresPreprocessor(filepath: string) {
752+
let ext = path.extname(filepath)
753+
754+
return ext === '.scss' || ext === '.sass' || ext === '.less' || ext === '.styl'
755+
}

packages/tailwindcss-language-server/src/testing/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ async function installDependenciesIn(dir: string) {
103103
}
104104

105105
export const css = dedent
106+
export const scss = dedent
106107
export const html = dedent
107108
export const js = dedent
108109
export const json = dedent

0 commit comments

Comments
 (0)