From fe43014ae1d0110dcd8b40ea249db01826638160 Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Fri, 23 May 2025 14:45:36 -0400 Subject: [PATCH] Ignore consecutive semicolons in the CSS parser --- packages/tailwindcss/src/css-parser.test.ts | 48 ++++++++++++++------- packages/tailwindcss/src/css-parser.ts | 2 +- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/packages/tailwindcss/src/css-parser.test.ts b/packages/tailwindcss/src/css-parser.test.ts index f7ee47a61145..0a180f6be90d 100644 --- a/packages/tailwindcss/src/css-parser.test.ts +++ b/packages/tailwindcss/src/css-parser.test.ts @@ -1063,6 +1063,38 @@ describe.each(['Unix', 'Windows'])('Line endings: %s', (lineEndings) => { }, ]) }) + + it('should ignore consecutive semicolons', () => { + expect(parse(';;;')).toEqual([]) + }) + + it('should ignore semicolons after an at-rule with a body', () => { + expect(parse('@plugin "foo" {} ;')).toEqual([ + { + kind: 'at-rule', + name: '@plugin', + params: '"foo"', + nodes: [], + }, + ]) + }) + + it('should ignore consecutive semicolons a declaration', () => { + expect(parse('.foo { color: red;;; }')).toEqual([ + { + kind: 'rule', + selector: '.foo', + nodes: [ + { + kind: 'declaration', + property: 'color', + value: 'red', + important: false, + }, + ], + }, + ]) + }) }) describe('errors', () => { @@ -1137,22 +1169,6 @@ describe.each(['Unix', 'Windows'])('Line endings: %s', (lineEndings) => { `[Error: Invalid declaration: \`bar\`]`, ) }) - - it('should error when a semicolon exists after an at-rule with a body', () => { - expect(() => parse('@plugin "foo" {} ;')).toThrowErrorMatchingInlineSnapshot( - `[Error: Unexpected semicolon]`, - ) - }) - - it('should error when consecutive semicolons exist', () => { - expect(() => parse(';;;')).toThrowErrorMatchingInlineSnapshot(`[Error: Unexpected semicolon]`) - }) - - it('should error when consecutive semicolons exist after a declaration', () => { - expect(() => parse('.foo { color: red;;; }')).toThrowErrorMatchingInlineSnapshot( - `[Error: Unexpected semicolon]`, - ) - }) }) it('ignores BOM at the beginning of a file', () => { diff --git a/packages/tailwindcss/src/css-parser.ts b/packages/tailwindcss/src/css-parser.ts index 6a5ce83204bd..fe621e3fa134 100644 --- a/packages/tailwindcss/src/css-parser.ts +++ b/packages/tailwindcss/src/css-parser.ts @@ -391,7 +391,7 @@ export function parse(input: string, opts?: ParseOptions) { ) { let declaration = parseDeclaration(buffer) if (!declaration) { - if (buffer.length === 0) throw new Error('Unexpected semicolon') + if (buffer.length === 0) continue throw new Error(`Invalid declaration: \`${buffer.trim()}\``) }