@@ -378,13 +378,18 @@ export class ShadowCss {
378378 string {
379379 // In Android browser, the lastIndex is not reset when the regex is used in String.replace()
380380 _polyfillHostRe . lastIndex = 0 ;
381-
382381 if ( _polyfillHostRe . test ( selector ) ) {
383382 const replaceBy = this . strictStyling ? `[${ hostSelector } ]` : scopeSelector ;
384383 return selector
385384 . replace (
386385 _polyfillHostNoCombinatorRe ,
387- ( hnc , selector ) => selector [ 0 ] === ':' ? replaceBy + selector : selector + replaceBy )
386+ ( hnc , selector ) => {
387+ return selector . replace (
388+ / ( [ ^ : ] * ) ( : * ) ( .* ) / ,
389+ ( _ : string , before : string , colon : string , after : string ) => {
390+ return before + replaceBy + colon + after ;
391+ } ) ;
392+ } )
388393 . replace ( _polyfillHostRe , replaceBy + ' ' ) ;
389394 }
390395
@@ -411,10 +416,10 @@ export class ShadowCss {
411416 scopedP = this . _applySimpleSelectorScope ( p , scopeSelector , hostSelector ) ;
412417 } else {
413418 // remove :host since it should be unnecessary
414- var t = p . replace ( _polyfillHostRe , '' ) ;
419+ const t = p . replace ( _polyfillHostRe , '' ) ;
415420 if ( t . length > 0 ) {
416421 const matches = t . match ( / ( [ ^ : ] * ) ( : * ) ( .* ) / ) ;
417- if ( matches !== null ) {
422+ if ( matches ) {
418423 scopedP = matches [ 1 ] + attrName + matches [ 2 ] + matches [ 3 ] ;
419424 }
420425 }
@@ -423,17 +428,8 @@ export class ShadowCss {
423428 return scopedP ;
424429 } ;
425430
426- let attrSelectorIndex = 0 ;
427- const attrSelectors : string [ ] = [ ] ;
428-
429- // replace attribute selectors with placeholders to avoid issue with white space being treated
430- // as separator
431- selector = selector . replace ( / \[ [ ^ \] ] * \] / g, ( attrSelector ) => {
432- const replaceBy = `__attr_sel_${ attrSelectorIndex } __` ;
433- attrSelectors . push ( attrSelector ) ;
434- attrSelectorIndex ++ ;
435- return replaceBy ;
436- } ) ;
431+ const safeContent = new SafeSelector ( selector ) ;
432+ selector = safeContent . content ( ) ;
437433
438434 let scopedSelector = '' ;
439435 let startIndex = 0 ;
@@ -454,14 +450,47 @@ export class ShadowCss {
454450 scopedSelector += _scopeSelectorPart ( selector . substring ( startIndex ) ) ;
455451
456452 // replace the placeholders with their original values
457- return scopedSelector . replace ( / _ _ a t t r _ s e l _ ( \d + ) _ _ / g , ( ph , index ) => attrSelectors [ + index ] ) ;
453+ return safeContent . restore ( scopedSelector ) ;
458454 }
459455
460456 private _insertPolyfillHostInCssText ( selector : string ) : string {
461457 return selector . replace ( _colonHostContextRe , _polyfillHostContext )
462458 . replace ( _colonHostRe , _polyfillHost ) ;
463459 }
464460}
461+
462+ class SafeSelector {
463+ private placeholders : string [ ] = [ ] ;
464+ private index = 0 ;
465+ private _content : string ;
466+
467+ constructor ( selector : string ) {
468+ // Replaces attribute selectors with placeholders.
469+ // The WS in [attr="va lue"] would otherwise be interpreted as a selector separator.
470+ selector = selector . replace ( / ( \[ [ ^ \] ] * \] ) / g, ( _ , keep ) => {
471+ const replaceBy = `__ph-${ this . index } __` ;
472+ this . placeholders . push ( keep ) ;
473+ this . index ++ ;
474+ return replaceBy ;
475+ } ) ;
476+
477+ // Replaces the expression in `:nth-child(2n + 1)` with a placeholder.
478+ // WS and "+" would otherwise be interpreted as selector separators.
479+ this . _content = selector . replace ( / ( : n t h - [ - \w ] + ) ( \( [ ^ ) ] + \) ) / g, ( _ , pseudo , exp ) => {
480+ const replaceBy = `__ph-${ this . index } __` ;
481+ this . placeholders . push ( exp ) ;
482+ this . index ++ ;
483+ return pseudo + replaceBy ;
484+ } ) ;
485+ } ;
486+
487+ restore ( content : string ) : string {
488+ return content . replace ( / _ _ p h - ( \d + ) _ _ / g, ( ph , index ) => this . placeholders [ + index ] ) ;
489+ }
490+
491+ content ( ) : string { return this . _content ; }
492+ }
493+
465494const _cssContentNextSelectorRe =
466495 / p o l y f i l l - n e x t - s e l e c t o r [ ^ } ] * c o n t e n t : [ \s ] * ?( [ ' " ] ) ( .* ?) \1[ ; \s ] * } ( [ ^ { ] * ?) { / gim;
467496const _cssContentRuleRe = / ( p o l y f i l l - r u l e ) [ ^ } ] * ( c o n t e n t : [ \s ] * ( [ ' " ] ) ( .* ?) \3) [ ; \s ] * [ ^ } ] * } / gim;
0 commit comments