@@ -271,7 +271,9 @@ export class CSSSelectorParser {
271
271
end : number ,
272
272
parent : VCSSNode ,
273
273
) : VCSSSelectorNode | null {
274
- let source = this . sourceCode . text . slice ( start , end ) ;
274
+ const sourceCode = this . sourceCode ;
275
+ const code = sourceCode . text ;
276
+ let source = code . slice ( start , end ) ;
275
277
const beforeSpaces = / ^ \s + / u. exec ( source ) ;
276
278
if ( beforeSpaces ?. [ 0 ] ) {
277
279
// adjust before spaces
@@ -292,24 +294,63 @@ export class CSSSelectorParser {
292
294
loc . end = this . sourceCode . getLocFromIndex ( end ) ;
293
295
source = source . slice ( 0 , - afterSpaces [ 0 ] . length ) ;
294
296
}
295
- const beforeTrivials = / ^ \( \s * / u. exec ( source ) ;
296
- const afterTrivials = / \s * \) $ / u. exec ( source ) ;
297
- if ( beforeTrivials ?. [ 0 ] && afterTrivials ?. [ 0 ] ) {
298
- // adjust before trivial tokens
299
- // `:not(.bar)`
300
- // ^ ^
301
297
298
+ adjustBeforeParenLocation ( ) ;
299
+ adjustAfterParenLocation ( ) ;
300
+
301
+ return new VCSSSelector ( node , loc , start , end , {
302
+ parent : parent as VCSSStyleRule | VCSSAtRule ,
303
+ } ) ;
304
+
305
+ /**
306
+ * Adjust before paren token
307
+ * `:not(.bar)`
308
+ * ^
309
+ */
310
+ function adjustBeforeParenLocation ( ) {
311
+ const beforeTrivials = / ^ \( \s * / u. exec ( source ) ;
312
+ if ( ! beforeTrivials ?. [ 0 ] ) return ;
313
+ let withinParen = false ;
314
+ for ( let index = end - 1 ; index < code . length ; index ++ ) {
315
+ const ch = code [ index ] ;
316
+ if ( ch === ")" ) {
317
+ withinParen = true ;
318
+ break ;
319
+ } else if ( ch ?. trim ( ) && index !== end - 1 ) {
320
+ return ;
321
+ }
322
+ }
323
+ if ( ! withinParen ) return ;
302
324
// eslint-disable-next-line no-param-reassign -- ignore
303
325
start = start + beforeTrivials [ 0 ] . length ;
304
- loc . start = this . sourceCode . getLocFromIndex ( start ) ;
326
+ loc . start = sourceCode . getLocFromIndex ( start ) ;
327
+ source = source . slice ( beforeTrivials [ 0 ] . length ) ;
328
+ }
329
+
330
+ /**
331
+ * Adjust after paren token
332
+ * `:not(.bar)`
333
+ * ^
334
+ */
335
+ function adjustAfterParenLocation ( ) {
336
+ const afterTrivials = / \s * \) $ / u. exec ( source ) ;
337
+ if ( ! afterTrivials ?. [ 0 ] ) return ;
338
+ let withinParen = false ;
339
+ for ( let index = start ; index >= 0 ; index -- ) {
340
+ const ch = code [ index ] ;
341
+ if ( ch === "(" ) {
342
+ withinParen = true ;
343
+ break ;
344
+ } else if ( ch ?. trim ( ) && index !== start ) {
345
+ return ;
346
+ }
347
+ }
348
+ if ( ! withinParen ) return ;
305
349
// eslint-disable-next-line no-param-reassign -- ignore
306
350
end = end - afterTrivials [ 0 ] . length ;
307
- loc . end = this . sourceCode . getLocFromIndex ( end ) ;
308
- source = source . slice ( beforeTrivials [ 0 ] . length , - afterTrivials [ 0 ] . length ) ;
351
+ loc . end = sourceCode . getLocFromIndex ( end ) ;
352
+ source = source . slice ( 0 , - afterTrivials [ 0 ] . length ) ;
309
353
}
310
- return new VCSSSelector ( node , loc , start , end , {
311
- parent : parent as VCSSStyleRule | VCSSAtRule ,
312
- } ) ;
313
354
}
314
355
315
356
/**
0 commit comments