Problem:
`find_tailwind_global_css` attempted to address #4204, where `experimental.configFile` was set using the return value of `vim.fs.find()`.
The language server rejected this with `Invalid experimental.configFile
configuration, not initializing` because `configFile` expects either a string or
a key-value record (object), not an array/list. This was a syntax issue, not
a detection issue.
Using the correct syntax for `configFile` in Lua should be
sufficient to address the original issue. Right now, `find_tailwind_global_css`
always runs for users who haven't explicitly set `configFile` — overriding the
LSP's native detection and **forcing anyone who wants to opt out to manually set
all entry-points by hand.**
Solution:
- Remove `find_tailwind_global_css` entirely and restores `configFile` to its
default `nil` so the `tailwindcss` LSP handles project detection natively.
- Simplify `before_init` based on [this suggestion from the initial
PR](https://github.com/neovim/nvim-lspconfig/pull/4222#discussion_r3018499628).
The following syntax worked for me while testing to explicitly set the
`configFile` based on the [official
docs](https://github.com/tailwindlabs/tailwindcss-intellisense#tailwindcssexperimentalconfigfile)
for single entry-point:
> [!NOTE]
> Single entry-point is resolved relative to the workspace root (`root_dir` — verify with `:checkhealth vim.lsp`)
```lua
vim.lsp.config('tailwindcss', {
settings = {
tailwindCSS = {
experimental = {
-- v3: config file
configFile = 'tailwind.config.js',
-- v4: CSS entry-point
-- configFile = 'src/styles/app.css',
},
},
},
})
```
For projects with multiple entry-points, or different projects, the following
syntax can be used for multiple entry-points:
> [!NOTE]
> Keys are relative to `root_dir` as above, but from my testing on macOS, absolute paths worked better
```lua
vim.lsp.config('tailwindcss', {
settings = {
tailwindCSS = {
experimental = {
configFile = {
['tailwind.config.js'] = '/Users/username/path/to/project-a/**',
['src/main.css'] = '/Users/username/path/to/project-b/**',
},
},
},
},
})
```
#### Project or Local Configuration
For project-specific settings without modifying your global Neovim config:
1. Enable in your Neovim config:
```lua
vim.o.exrc = true
```
2. Create `.nvim.lua` in the project root:
```lua
vim.lsp.config('tailwindcss', {
settings = {
tailwindCSS = {
experimental = {
configFile = 'tailwind.config.ts',
},
},
},
})
```
3. Open `.nvim.lua` and run `:trust` to allow the file, then restart Neovim.
4. Verify with `:checkhealth vim.lsp`.
Since tailwind v4 it is not required to have a tailwind.config.* in
the project 1. The current configuration is preventing the LSP to attach to the configured file types in cases when no tailwind.config.* or none of the other markers (package.json etc.) is present. This commit fixes this limitation by providing .git as a fallback and by documenting this limitation.
The location of the config in Rails and Phoenix does not represent the
root of the project. We can look inside mix.lock and Gemfile.lock for
the existence of tailwind, which guarantees that it's the root.
This is copying some additions that tailwind-tools.nvim makes. There
are web frameworks such as Rails, Django, and older Phoenix that places
tailwind config files in asset folders.
tailwind-intellisense won't activate unless the filetype is detected
as an HTML-based file. Elixir `.ex` files can have `~H` sigils with
HEEX syntax inside or `~E` sigils with eelixir syntax. It's also typical
to have `.html.heex` files entirely of HEEX syntax. Both of these are
recognized in Elixir's tree-sitter injections.scm
Enhance root directory detection for the latest versions of
TailwindCSS v4, which no longer require tailwind.config.* or
postcss.config.*.
For Phoenix projects, they are typically generated or add Tailwind
installed via https://github.com/phoenixframework/tailwind which will
now be detected by scanning the mix.lock file for the included package.
Phoenix projects that install tailwindcss via package.json should still
work.