Discard candidates with an empty data type (#19172)

Fixes
https://github.com/tailwindlabs/tailwindcss-intellisense/issues/1479

Maybe should close
https://github.com/tailwindlabs/tailwindcss-intellisense/pull/1480 —
perhaps we can find a workaround there for older versions?

We're building up a class name in code to validate if something is a
valid variant: `{variant}:[color:red]`

if `{variant}` got replaced with `bg-[` then we'd produce
`bg-[:[color:red]` and this parsed as a valid candidate:
```
bg-[:[color:red]
^^                root: `bg`
   ^              data type: `` (empty string) — this should be invalid
     ^^^^^^^^^^   value: `[color:red`
```

The value isn't valid _but_ the syntax for arbitrary values is pretty
lax in core. Oxide already won't pick something like this up though so
no problem there. Only a problem for something like IntelliSense or
clients using the compile() API directly.
This commit is contained in:
Jordan Pittman 2025-10-22 06:14:43 -04:00 • committed by GitHub
parent 56e7f3b2c2
commit 29687e0183
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 15 additions and 1 deletions

View file

@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- _Experimental_: Add `@container-size` utility ([#18901](https://github.com/tailwindlabs/tailwindcss/pull/18901))
### Fixed
- Discard candidates with an empty data type ([#19172](https://github.com/tailwindlabs/tailwindcss/pull/19172))
## [4.1.15] - 2025-10-20
### Fixed

View file

@ -1776,6 +1776,14 @@ it('should not parse compound group with a non-compoundable variant', () => {
expect(run('group-*:flex', { utilities, variants })).toMatchInlineSnapshot(`[]`)
})
it('empty data types are invalid', () => {
let utilities = new Utilities()
utilities.functional('bg', () => [])
let variants = new Variants()
expect(run('bg-[:foo]', { utilities, variants })).toMatchInlineSnapshot(`[]`)
})
it('should parse a variant containing an arbitrary string with unbalanced parens, brackets, curlies and other quotes', () => {
let utilities = new Utilities()
utilities.static('flex', () => [])

View file

@ -554,7 +554,7 @@ export function* parseCandidate(input: string, designSystem: DesignSystem): Iter
if (!isValidArbitrary(arbitraryValue)) continue
// Extract an explicit typehint if present, e.g. `bg-[color:var(--my-var)])`
let typehint = ''
let typehint: string | null = null
for (let i = 0; i < arbitraryValue.length; i++) {
let code = arbitraryValue.charCodeAt(i)
@ -580,6 +580,8 @@ export function* parseCandidate(input: string, designSystem: DesignSystem): Iter
continue
}
if (typehint === '') continue
candidate.value = {
kind: 'arbitrary',
dataType: typehint || null,