diff --git a/CHANGELOG.md b/CHANGELOG.md index a86400e06..fb91cb4f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - Discard invalid classes such as `bg-red-[#000]` ([#13970](https://github.com/tailwindlabs/tailwindcss/pull/13970)) +- Fix parsing body-less at-rule without terminating semicolon ([#13978](https://github.com/tailwindlabs/tailwindcss/pull/13978)) ## [4.0.0-alpha.17] - 2024-07-04 diff --git a/packages/tailwindcss/src/css-parser.test.ts b/packages/tailwindcss/src/css-parser.test.ts index f3146d04a..fa3f122ce 100644 --- a/packages/tailwindcss/src/css-parser.test.ts +++ b/packages/tailwindcss/src/css-parser.test.ts @@ -633,6 +633,14 @@ describe.each(['Unix', 'Windows'])('Line endings: %s', (lineEndings) => { ).toEqual([{ kind: 'rule', selector: '@charset "UTF-8"', nodes: [] }]) }) + it('should parse an at-rule without a block or semicolon', () => { + expect( + parse(` + @tailwind utilities + `), + ).toEqual([{ kind: 'rule', selector: '@tailwind utilities', nodes: [] }]) + }) + it("should parse an at-rule without a block or semicolon when it's the last rule in a block", () => { expect( parse(` diff --git a/packages/tailwindcss/src/css-parser.ts b/packages/tailwindcss/src/css-parser.ts index 88a2a0640..f5eb5979f 100644 --- a/packages/tailwindcss/src/css-parser.ts +++ b/packages/tailwindcss/src/css-parser.ts @@ -461,6 +461,13 @@ export function parse(input: string) { } } + // If we have a leftover `buffer` that happens to start with an `@` then it + // means that we have an at-rule that is not terminated with a semicolon at + // the end of the input. + if (buffer[0] === '@') { + ast.push(rule(buffer.trim(), [])) + } + // When we are done parsing then everything should be balanced. If we still // have a leftover `parent`, then it means that we have an unterminated block. if (closingBracketStack.length > 0 && parent) {