From d526d09a222fe529decafbae58afdbe09f8a2b4e Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Tue, 4 Feb 2025 13:55:32 -0500 Subject: [PATCH 1/6] Clarify how the configFile option works with v4 --- packages/vscode-tailwindcss/README.md | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/packages/vscode-tailwindcss/README.md b/packages/vscode-tailwindcss/README.md index 24b7ca68..7dd38044 100644 --- a/packages/vscode-tailwindcss/README.md +++ b/packages/vscode-tailwindcss/README.md @@ -164,7 +164,28 @@ Enable the Node.js inspector agent for the language server and listen on the spe **Default: `null`** -By default the extension will automatically use the first `tailwind.config.{js,cjs,mjs,ts,cts,mts}` file that it can find to provide Tailwind CSS IntelliSense. Use this setting to manually specify the config file(s) yourself instead. +By default the extension scans your project for CSS files and determines your "root" CSS file when looking for a Tailwind CSS v4 project. Likewise, for v3 projects, the extension will automatically use the first `tailwind.config.{js,cjs,mjs,ts,cts,mts}` file that it can find. + +If IntelliSense is unable to detect your project you can use this setting to manually specify the CSS files (for v4) or config file(s) (for v3) yourself instead. + +#### v4.x + +If your project contains a single CSS entrypoint you can specify a string value: + +```json +"tailwindCSS.experimental.configFile": "src/styles/app.css" +``` + +For projects with multiple CSS entrypoints use an object where each key is a file path and each value is a glob pattern (or array of glob patterns) representing the set of files that the file applies to: + +```json +"tailwindCSS.experimental.configFile": { + "packages/a/src/app.css": "packages/a/src/**", + "packages/b/src/app.css": "packages/b/src/**" +} +``` + +#### v3.x and below If your project contains a single Tailwind config file you can specify a string value: From 7066bb46d64f011276995815badc5e27fdc036ec Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Tue, 4 Feb 2025 15:21:09 -0500 Subject: [PATCH 2/6] Allow `openDocument` to specify the filename --- packages/tailwindcss-language-server/tests/common.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/tailwindcss-language-server/tests/common.ts b/packages/tailwindcss-language-server/tests/common.ts index e78b94ea..37339159 100644 --- a/packages/tailwindcss-language-server/tests/common.ts +++ b/packages/tailwindcss-language-server/tests/common.ts @@ -261,14 +261,16 @@ export async function init( text, lang = 'html', dir = '', + name = null, settings = {}, }: { text: string lang?: string dir?: string + name?: string settings?: Settings }) { - let uri = resolveUri(dir, `file-${counter++}`) + let uri = resolveUri(dir, name ?? `file-${counter++}`) docSettings.set(uri, settings) let openPromise = openingDocuments.remember(uri, () => { From ffe4ca305f79712033ab191c87710429c50288f1 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Tue, 4 Feb 2025 15:21:52 -0500 Subject: [PATCH 3/6] Fix use of `tailwindCSS.experimental.configFile` when using the bundled v4 --- .../src/project-locator.ts | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/packages/tailwindcss-language-server/src/project-locator.ts b/packages/tailwindcss-language-server/src/project-locator.ts index 0bb3947d..e708be0a 100644 --- a/packages/tailwindcss-language-server/src/project-locator.ts +++ b/packages/tailwindcss-language-server/src/project-locator.ts @@ -101,14 +101,23 @@ export class ProjectLocator { configPath: string, selectors: string[], ): Promise { - let config: ConfigEntry = { - type: 'js', - path: configPath, - source: 'js', - entries: [], - content: [], - packageRoot: '', - } + let config: ConfigEntry = configPath.endsWith('.css') + ? { + type: 'css', + path: configPath, + source: 'css', + entries: [], + content: [], + packageRoot: '', + } + : { + type: 'js', + path: configPath, + source: 'js', + entries: [], + content: [], + packageRoot: '', + } let tailwind = await this.detectTailwindVersion(config) From fc40218f7ba002bef566c3e74e95f5f0b1892b97 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Tue, 4 Feb 2025 15:22:14 -0500 Subject: [PATCH 4/6] Add tests verifying behavior --- .../tests/env/v4.test.js | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) diff --git a/packages/tailwindcss-language-server/tests/env/v4.test.js b/packages/tailwindcss-language-server/tests/env/v4.test.js index 9f14f06a..56de119b 100644 --- a/packages/tailwindcss-language-server/tests/env/v4.test.js +++ b/packages/tailwindcss-language-server/tests/env/v4.test.js @@ -344,3 +344,188 @@ defineTest({ }) }, }) + +defineTest({ + name: 'v4, using local, with explicit CSS entrypoints', + fs: { + 'package.json': json` + { + "dependencies": { + "tailwindcss": "4.0.1" + } + } + `, + 'a/app.css': css` + @import 'tailwindcss'; + @theme { + --color-primary: #000000; + } + `, + 'b/app.css': css` + @import 'tailwindcss'; + @theme { + --color-primary: #ffffff; + } + `, + }, + prepare: async ({ root }) => ({ c: await init(root) }), + handle: async ({ c }) => { + await c.updateSettings({ + tailwindCSS: { + experimental: { + configFile: { + 'a/app.css': 'c/a/**', + 'b/app.css': 'c/b/**', + }, + }, + }, + }) + + let documentA = await c.openDocument({ + lang: 'html', + text: '
', + name: 'c/a/index.html', + }) + + let documentB = await c.openDocument({ + lang: 'html', + text: '
', + name: 'c/b/index.html', + }) + + let hoverA = await c.sendRequest(HoverRequest.type, { + textDocument: documentA, + + //
+ // ^ + position: { line: 0, character: 13 }, + }) + + let hoverB = await c.sendRequest(HoverRequest.type, { + textDocument: documentB, + + //
+ // ^ + position: { line: 0, character: 13 }, + }) + + expect(hoverA).toEqual({ + contents: { + language: 'css', + value: dedent` + .bg-primary { + background-color: var(--color-primary) /* #000000 */; + } + `, + }, + range: { + start: { line: 0, character: 12 }, + end: { line: 0, character: 22 }, + }, + }) + + expect(hoverB).toEqual({ + contents: { + language: 'css', + value: dedent` + .bg-primary { + background-color: var(--color-primary) /* #ffffff */; + } + `, + }, + range: { + start: { line: 0, character: 12 }, + end: { line: 0, character: 22 }, + }, + }) + }, +}) + +defineTest({ + name: 'v4, using fallback, with explicit CSS entrypoints', + fs: { + 'a/app.css': css` + @import 'tailwindcss'; + @theme { + --color-primary: #000000; + } + `, + 'b/app.css': css` + @import 'tailwindcss'; + @theme { + --color-primary: #ffffff; + } + `, + }, + prepare: async ({ root }) => ({ c: await init(root) }), + handle: async ({ c }) => { + await c.updateSettings({ + tailwindCSS: { + experimental: { + configFile: { + 'a/app.css': 'c/a/**', + 'b/app.css': 'c/b/**', + }, + }, + }, + }) + + let documentA = await c.openDocument({ + lang: 'html', + text: '
', + name: 'c/a/index.html', + }) + + let documentB = await c.openDocument({ + lang: 'html', + text: '
', + name: 'c/b/index.html', + }) + + let hoverA = await c.sendRequest(HoverRequest.type, { + textDocument: documentA, + + //
+ // ^ + position: { line: 0, character: 13 }, + }) + + let hoverB = await c.sendRequest(HoverRequest.type, { + textDocument: documentB, + + //
+ // ^ + position: { line: 0, character: 13 }, + }) + + expect(hoverA).toEqual({ + contents: { + language: 'css', + value: dedent` + .bg-primary { + background-color: var(--color-primary) /* #000000 */; + } + `, + }, + range: { + start: { line: 0, character: 12 }, + end: { line: 0, character: 22 }, + }, + }) + + expect(hoverB).toEqual({ + contents: { + language: 'css', + value: dedent` + .bg-primary { + background-color: var(--color-primary) /* #ffffff */; + } + `, + }, + range: { + start: { line: 0, character: 12 }, + end: { line: 0, character: 22 }, + }, + }) + }, +}) From 6545d13dcf210a3021fd1bc40cd6daebfdcdb334 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Tue, 4 Feb 2025 15:22:53 -0500 Subject: [PATCH 5/6] Update changelog --- packages/vscode-tailwindcss/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/vscode-tailwindcss/CHANGELOG.md b/packages/vscode-tailwindcss/CHANGELOG.md index 2abdb546..ca62ab97 100644 --- a/packages/vscode-tailwindcss/CHANGELOG.md +++ b/packages/vscode-tailwindcss/CHANGELOG.md @@ -11,6 +11,7 @@ - Support style-rule like completions inside `@variant` ([#1165](https://github.com/tailwindlabs/tailwindcss-intellisense/pull/1165)) - Make sure `@slot` isn't considered an unknown at-rule ([#1165](https://github.com/tailwindlabs/tailwindcss-intellisense/pull/1165)) - Fix equivalent calculation when using prefixes in v4 ([#1166](https://github.com/tailwindlabs/tailwindcss-intellisense/pull/1166)) +- Fix use of `tailwindCSS.experimental.configFile` option when using the bundled version of v4 ([#1167](https://github.com/tailwindlabs/tailwindcss-intellisense/pull/1167)) ## 0.14.2 From f4225ce3fa7f752739a79d9a1f7eedc121967a41 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Wed, 5 Feb 2025 08:59:12 -0500 Subject: [PATCH 6/6] Update readme Co-authored-by: Jonathan Reinink --- packages/vscode-tailwindcss/README.md | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/packages/vscode-tailwindcss/README.md b/packages/vscode-tailwindcss/README.md index 7dd38044..62165308 100644 --- a/packages/vscode-tailwindcss/README.md +++ b/packages/vscode-tailwindcss/README.md @@ -164,19 +164,24 @@ Enable the Node.js inspector agent for the language server and listen on the spe **Default: `null`** -By default the extension scans your project for CSS files and determines your "root" CSS file when looking for a Tailwind CSS v4 project. Likewise, for v3 projects, the extension will automatically use the first `tailwind.config.{js,cjs,mjs,ts,cts,mts}` file that it can find. +This setting allows you to manually specify the CSS entrypoints (for v4 projects) or the Tailwind configuration file (for v3 projects). By default, the extension attempts to detect your project setup automatically: -If IntelliSense is unable to detect your project you can use this setting to manually specify the CSS files (for v4) or config file(s) (for v3) yourself instead. +- **For Tailwind CSS v4**: The extension scans your project for CSS files and determines the "root" CSS file. +- **For Tailwind CSS v3 (and earlier)**: The extension automatically uses the first `tailwind.config.{js,cjs,mjs,ts,cts,mts}` file it finds. -#### v4.x +If IntelliSense is unable to detect your project, you can use this setting to define your config files manually. -If your project contains a single CSS entrypoint you can specify a string value: +#### Tailwind CSS v4.x (CSS entrypoints) + +For v4 projects, specify the CSS file(s) that serve as your Tailwind entrypoints. + +If your project contains a single CSS entrypoint, set this option to a string: ```json "tailwindCSS.experimental.configFile": "src/styles/app.css" ``` -For projects with multiple CSS entrypoints use an object where each key is a file path and each value is a glob pattern (or array of glob patterns) representing the set of files that the file applies to: +For projects with multiple CSS entrypoints, use an object where each key is a file path and each value is a glob pattern (or array of patterns) representing the files it applies to: ```json "tailwindCSS.experimental.configFile": { @@ -185,15 +190,17 @@ For projects with multiple CSS entrypoints use an object where each key is a fil } ``` -#### v3.x and below +#### Tailwind CSS v3.x and earlier (config files) + +For v3 projects and below, specify the Tailwind configuration file(s) instead. -If your project contains a single Tailwind config file you can specify a string value: +If your project contains a single Tailwind config, set this option to a string: ```json "tailwindCSS.experimental.configFile": ".config/tailwind.config.js" ``` -For projects with multiple config files use an object where each key is a config file path and each value is a glob pattern (or array of glob patterns) representing the set of files that the config file applies to: +For projects with multiple config files, use an object where each key is a config file path and each value is a glob pattern (or array of patterns) representing the files it applies to: ```json "tailwindCSS.experimental.configFile": {