File tree Expand file tree Collapse file tree 3 files changed +74
-5
lines changed Expand file tree Collapse file tree 3 files changed +74
-5
lines changed Original file line number Diff line number Diff line change
1
+ ---
2
+ ' @vanilla-extract/css ' : patch
3
+ ---
4
+
5
+ Fixes a bug that caused invalid selectors to be generated when adjacent classnames contained a substring equal to another local classname
Original file line number Diff line number Diff line change @@ -2299,6 +2299,61 @@ describe('transformCss', () => {
2299
2299
}
2300
2300
` ) ;
2301
2301
} ) ;
2302
+
2303
+ it ( 'should handle adjacent classnames containing a separate local classname as a substring' , ( ) => {
2304
+ // Note that `classname2` starts and ends with the same character, so when two `classname1`s are
2305
+ // adjacent, the resulting string will contain `classname2` as a substring
2306
+ const classname1 = 'debugName_hash1' ;
2307
+ const classname2 = 'debugName_hash1d' ;
2308
+
2309
+ expect (
2310
+ transformCss ( {
2311
+ composedClassLists : [ ] ,
2312
+ localClassNames : [ classname1 , classname2 ] ,
2313
+
2314
+ cssObjs : [
2315
+ {
2316
+ type : 'local' ,
2317
+ selector : classname1 ,
2318
+ rule : {
2319
+ selectors : {
2320
+ [ '&&' ] : {
2321
+ background : 'black' ,
2322
+ } ,
2323
+ [ `${ classname2 } &` ] : {
2324
+ background : 'orange' ,
2325
+ } ,
2326
+ [ `&${ classname2 } &` ] : {
2327
+ background : 'orange' ,
2328
+ } ,
2329
+ [ `${ classname2 } ${ classname2 } &` ] : {
2330
+ background : 'orange' ,
2331
+ } ,
2332
+ } ,
2333
+ } ,
2334
+ } ,
2335
+ {
2336
+ type : 'local' ,
2337
+ selector : classname2 ,
2338
+ rule : { } ,
2339
+ } ,
2340
+ ] ,
2341
+ } ) . join ( '\n' ) ,
2342
+ ) . toMatchInlineSnapshot ( `
2343
+ .debugName_hash1.debugName_hash1 {
2344
+ background: black;
2345
+ }
2346
+ .debugName_hash1d.debugName_hash1 {
2347
+ background: orange;
2348
+ }
2349
+ .debugName_hash1.debugName_hash1d.debugName_hash1 {
2350
+ background: orange;
2351
+ }
2352
+ .debugName_hash1d.debugName_hash1d.debugName_hash1 {
2353
+ background: orange;
2354
+ }
2355
+ ` ) ;
2356
+ } ) ;
2302
2357
} ) ;
2303
2358
2304
2359
endFileScope ( ) ;
Original file line number Diff line number Diff line change @@ -317,11 +317,20 @@ class Stylesheet {
317
317
const [ endIndex , [ firstMatch ] ] = results [ i ] ;
318
318
const startIndex = endIndex - firstMatch . length + 1 ;
319
319
320
- if ( startIndex >= lastReplaceIndex ) {
321
- // Class names can be substrings of other class names
322
- // e.g. '_1g1ptzo1' and '_1g1ptzo10'
323
- // If the startIndex >= lastReplaceIndex, then
324
- // this is the case and this replace should be skipped
320
+ // Class names can be substrings of other class names
321
+ // e.g. '_1g1ptzo1' and '_1g1ptzo10'
322
+ //
323
+ // Additionally, concatenated classnames can contain substrings equal to other classnames
324
+ // e.g. '&&' where '&' is 'debugName_hash1' and 'debugName_hash1d' is also a local classname
325
+ // Before transforming the selector, this would look like `debugName_hash1debugName_hash1`
326
+ // which contains the substring `debugName_hash1d`’.
327
+ //
328
+ // In either of these cases, the last replace index will occur either before or within the
329
+ // current replacement range (from `startIndex` to `endIndex`).
330
+ // If this occurs, we skip the replacement to avoid transforming the selector incorrectly.
331
+ const skipReplacement = lastReplaceIndex <= endIndex ;
332
+
333
+ if ( skipReplacement ) {
325
334
continue ;
326
335
}
327
336
You can’t perform that action at this time.
0 commit comments