Skip to content

Commit 5893c1b

Browse files
committed
simplify, track parens via number
Some characters, such as `{`, `}`, and `;` are allowed inside CSS functions, e.g.: `url(https://example?q={query;limit=5})`. Notice that the example is not in quotes, and this is a valid URL. If we don't handle these characters when inside of `(` and `)`, it means that the `{` would start a nested block, `}` would end the block, and `;` would end the current declaration. Instead, if we are in parens, we do allow the values.
1 parent 40b5834 commit 5893c1b

File tree

1 file changed

+15
-25
lines changed

1 file changed

+15
-25
lines changed

packages/tailwindcss/src/css-parser.ts

Lines changed: 15 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ export function parse(input: string) {
4242

4343
let buffer = ''
4444
let closingBracketStack = ''
45+
let parenStack = 0
4546

4647
let peekChar
4748

@@ -331,10 +332,7 @@ export function parse(input: string) {
331332
// }
332333
// ```
333334
//
334-
else if (
335-
currentChar === SEMICOLON &&
336-
(closingBracketStack.length === 0 || !closingBracketStack.includes(')'))
337-
) {
335+
else if (currentChar === SEMICOLON && parenStack <= 0) {
338336
let declaration = parseDeclaration(buffer)
339337
if (parent) {
340338
parent.nodes.push(declaration)
@@ -346,10 +344,7 @@ export function parse(input: string) {
346344
}
347345

348346
// Start of a block.
349-
else if (
350-
currentChar === OPEN_CURLY &&
351-
(closingBracketStack.length === 0 || !closingBracketStack.includes(')'))
352-
) {
347+
else if (currentChar === OPEN_CURLY && parenStack <= 0) {
353348
closingBracketStack += '}'
354349

355350
// At this point `buffer` should resemble a selector or an at-rule.
@@ -374,10 +369,7 @@ export function parse(input: string) {
374369
}
375370

376371
// End of a block.
377-
else if (
378-
currentChar === CLOSE_CURLY &&
379-
(closingBracketStack.length === 0 || !closingBracketStack.includes(')'))
380-
) {
372+
else if (currentChar === CLOSE_CURLY && parenStack <= 0) {
381373
if (closingBracketStack === '') {
382374
throw new Error('Missing opening {')
383375
}
@@ -465,22 +457,20 @@ export function parse(input: string) {
465457
node = null
466458
}
467459

468-
//
469-
else if (currentChar === OPEN_CURLY) {
470-
closingBracketStack += '}'
471-
buffer += '{'
472-
} else if (currentChar === OPEN_PAREN) {
473-
closingBracketStack += ')'
460+
// `(`
461+
else if (currentChar === OPEN_PAREN) {
462+
parenStack += 1
474463
buffer += '('
475-
} else if (currentChar === CLOSE_CURLY || currentChar === CLOSE_PAREN) {
476-
if (
477-
closingBracketStack.length > 0 &&
478-
input[i] === closingBracketStack[closingBracketStack.length - 1]
479-
) {
480-
closingBracketStack = closingBracketStack.slice(0, -1)
464+
}
465+
466+
// `)`
467+
else if (currentChar === CLOSE_PAREN) {
468+
if (parenStack <= 0) {
469+
throw new Error('Missing opening (')
481470
}
482471

483-
buffer += String.fromCharCode(currentChar)
472+
parenStack -= 1
473+
buffer += ')'
484474
}
485475

486476
// Any other character is part of the current node.

0 commit comments

Comments
 (0)