diff --git a/CHANGELOG.md b/CHANGELOG.md index 14e0f19fb6a7..ad67eb77b4f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Find utilities when using functions inside arrays ([#15974](https://github.com/tailwindlabs/tailwindcss/pull/15974)) - Ensure that `@tailwindcss/browser` does not pollute the global namespace ([#15978](https://github.com/tailwindlabs/tailwindcss/pull/15978)) - Fix crash when project lives in the `/` directory ([#15988](https://github.com/tailwindlabs/tailwindcss/pull/15988)) +- Ensure `@custom-variant` has a non-empty selector list ([#16009](https://github.com/tailwindlabs/tailwindcss/pull/16009)) - _Upgrade_: Ensure JavaScript config files on different drives are correctly migrated ([#15927](https://github.com/tailwindlabs/tailwindcss/pull/15927)) - _Upgrade_: Migrate `leading-[1]` to `leading-none` ([#16004](https://github.com/tailwindlabs/tailwindcss/pull/16004)) - _Upgrade_: Do not migrate arbitrary leading utilities to bare utilities ([#16004](https://github.com/tailwindlabs/tailwindcss/pull/16004)) diff --git a/packages/tailwindcss/src/index.test.ts b/packages/tailwindcss/src/index.test.ts index 0b5851b70c8b..fdf06077bc3c 100644 --- a/packages/tailwindcss/src/index.test.ts +++ b/packages/tailwindcss/src/index.test.ts @@ -2514,6 +2514,26 @@ describe('@custom-variant', () => { ).rejects.toThrowErrorMatchingInlineSnapshot(`[Error: \`@custom-variant\` cannot be nested.]`) }) + test('@custom-variant must not have an empty selector', () => { + return expect( + compileCss(css` + @custom-variant foo (); + `), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `[Error: \`@custom-variant foo ()\` selector is invalid.]`, + ) + }) + + test('@custom-variant with multiple selectors, cannot be empty', () => { + return expect( + compileCss(css` + @custom-variant foo (.foo, .bar, ); + `), + ).rejects.toThrowErrorMatchingInlineSnapshot( + `[Error: \`@custom-variant foo (.foo, .bar, )\` selector is invalid.]`, + ) + }) + test('@custom-variant with no body must include a selector', () => { return expect( compileCss(css` diff --git a/packages/tailwindcss/src/index.ts b/packages/tailwindcss/src/index.ts index 3e4bc5a3cce0..77951a3e8591 100644 --- a/packages/tailwindcss/src/index.ts +++ b/packages/tailwindcss/src/index.ts @@ -281,6 +281,11 @@ async function parseCss( } let selectors = segment(selector.slice(1, -1), ',') + if (selectors.length === 0 || selectors.some((selector) => selector.trim() === '')) { + throw new Error( + `\`@custom-variant ${name} (${selectors.join(',')})\` selector is invalid.`, + ) + } let atRuleParams: string[] = [] let styleRuleSelectors: string[] = []