@@ -11,7 +11,7 @@ export function getVariantsFromClassName(
11
11
}
12
12
return [ variant . name ]
13
13
} )
14
- let parts = Array . from ( splitAtTopLevelOnly ( className , state . separator ) ) . filter ( Boolean )
14
+ let parts = splitAtTopLevelOnly ( className , state . separator ) . filter ( Boolean )
15
15
let variants = new Set < string > ( )
16
16
let offset = 0
17
17
@@ -34,66 +34,34 @@ export function getVariantsFromClassName(
34
34
return { variants : Array . from ( variants ) , offset }
35
35
}
36
36
37
- const REGEX_SPECIAL = / [ \\ ^ $ . * + ? ( ) [ \] { } | ] / g
38
- const REGEX_HAS_SPECIAL = RegExp ( REGEX_SPECIAL . source )
37
+ // https://github.com/tailwindlabs/tailwindcss/blob/a8a2e2a7191fbd4bee044523aecbade5823a8664/src/util/splitAtTopLevelOnly.js
38
+ function splitAtTopLevelOnly ( input : string , separator : string ) : string [ ] {
39
+ let stack : string [ ] = [ ]
40
+ let parts : string [ ] = [ ]
41
+ let lastPos = 0
39
42
40
- function regexEscape ( string : string ) : string {
41
- return string && REGEX_HAS_SPECIAL . test ( string )
42
- ? string . replace ( REGEX_SPECIAL , '\\$&' )
43
- : string || ''
44
- }
45
-
46
- function * splitAtTopLevelOnly ( input : string , separator : string ) : Generator < string > {
47
- let SPECIALS = new RegExp ( `[(){}\\[\\]${ regexEscape ( separator ) } ]` , 'g' )
48
-
49
- let depth = 0
50
- let lastIndex = 0
51
- let found = false
52
- let separatorIndex = 0
53
- let separatorStart = 0
54
- let separatorLength = separator . length
43
+ for ( let idx = 0 ; idx < input . length ; idx ++ ) {
44
+ let char = input [ idx ]
55
45
56
- // Find all paren-like things & character
57
- // And only split on commas if they're top-level
58
- for ( let match of input . matchAll ( SPECIALS ) ) {
59
- let matchesSeparator = match [ 0 ] === separator [ separatorIndex ]
60
- let atEndOfSeparator = separatorIndex === separatorLength - 1
61
- let matchesFullSeparator = matchesSeparator && atEndOfSeparator
62
-
63
- if ( match [ 0 ] === '(' ) depth ++
64
- if ( match [ 0 ] === ')' ) depth --
65
- if ( match [ 0 ] === '[' ) depth ++
66
- if ( match [ 0 ] === ']' ) depth --
67
- if ( match [ 0 ] === '{' ) depth ++
68
- if ( match [ 0 ] === '}' ) depth --
69
-
70
- if ( matchesSeparator && depth === 0 ) {
71
- if ( separatorStart === 0 ) {
72
- separatorStart = match . index
46
+ if ( stack . length === 0 && char === separator [ 0 ] ) {
47
+ if ( separator . length === 1 || input . slice ( idx , idx + separator . length ) === separator ) {
48
+ parts . push ( input . slice ( lastPos , idx ) )
49
+ lastPos = idx + separator . length
73
50
}
74
-
75
- separatorIndex ++
76
51
}
77
52
78
- if ( matchesFullSeparator && depth === 0 ) {
79
- found = true
80
-
81
- yield input . substring ( lastIndex , separatorStart )
82
- lastIndex = separatorStart + separatorLength
83
- }
84
-
85
- if ( separatorIndex === separatorLength ) {
86
- separatorIndex = 0
87
- separatorStart = 0
53
+ if ( char === '(' || char === '[' || char === '{' ) {
54
+ stack . push ( char )
55
+ } else if (
56
+ ( char === ')' && stack [ stack . length - 1 ] === '(' ) ||
57
+ ( char === ']' && stack [ stack . length - 1 ] === '[' ) ||
58
+ ( char === '}' && stack [ stack . length - 1 ] === '{' )
59
+ ) {
60
+ stack . pop ( )
88
61
}
89
62
}
90
63
91
- // Provide the last segment of the string if available
92
- // Otherwise the whole string since no `char`s were found
93
- // This mirrors the behavior of string.split()
94
- if ( found ) {
95
- yield input . substring ( lastIndex )
96
- } else {
97
- yield input
98
- }
64
+ parts . push ( input . slice ( lastPos ) )
65
+
66
+ return parts
99
67
}
0 commit comments