@@ -92,8 +92,26 @@ const _polyfillHostRe = /-shadowcsshost/gim;
9292 * @param selector The CSS selector we want to match for replacement
9393 * @returns A look-behind regex containing the selector
9494 */
95- const createSupportsRuleRe = ( selector : string ) =>
96- new RegExp ( `((?<!(^@supports(.*)))|(?<=\{.*))(${ selector } \\b)` , 'gim' ) ;
95+ const createSupportsRuleRe = ( selector : string ) => {
96+ // We need to match any occurrence of the selector that's NOT inside @supports selector(...)
97+ const safeSelector = escapeRegExpSpecialCharacters ( selector ) ;
98+
99+ // This regex needs to:
100+ // 1. Skip selectors inside @supports selector(...) rule conditions
101+ // 2. Match selectors in normal CSS rules
102+ // 3. Match selectors inside declaration blocks of @supports rules
103+
104+ // To avoid matching selectors inside @supports selector() conditions, we need to carefully
105+ // construct the pattern to look for context that indicates we're NOT inside such a condition.
106+ return new RegExp (
107+ // First capture group: match any context before the selector that's not inside @supports selector()
108+ // Using negative lookahead to avoid matching inside @supports selector(...) condition
109+ `(^|[^@]|@(?!supports\\s+selector\\s*\\([^{]*?${ safeSelector } ))` +
110+ // Then match the selector
111+ `(${ safeSelector } \\b)` ,
112+ 'g' ,
113+ ) ;
114+ } ;
97115const _colonSlottedRe = createSupportsRuleRe ( '::slotted' ) ;
98116const _colonHostRe = createSupportsRuleRe ( ':host' ) ;
99117const _colonHostContextRe = createSupportsRuleRe ( ':host-context' ) ;
@@ -212,6 +230,17 @@ const escapeBlocks = (input: string) => {
212230 * @returns The modified CSS string
213231 */
214232const insertPolyfillHostInCssText = ( cssText : string ) => {
233+ // Special handling for @supports selector() rules
234+ // We need to preserve the original selector in the condition but replace it in the declaration
235+ const supportsBlocks : string [ ] = [ ] ;
236+
237+ // First, extract and preserve @supports selector(...) conditions
238+ cssText = cssText . replace ( / @ s u p p o r t s \s + s e l e c t o r \s * \( \s * ( [ ^ ) ] * ) \s * \) / g, ( _ , selectorContent ) => {
239+ const placeholder = `__supports_${ supportsBlocks . length } __` ;
240+ supportsBlocks . push ( selectorContent ) ;
241+ return `@supports selector(${ placeholder } )` ;
242+ } ) ;
243+
215244 // These replacements use a special syntax with the `$1`. When the replacement
216245 // occurs, `$1` maps to the content of the string leading up to the selector
217246 // to be replaced.
@@ -225,6 +254,11 @@ const insertPolyfillHostInCssText = (cssText: string) => {
225254 . replace ( _colonHostRe , `$1${ _polyfillHost } ` )
226255 . replace ( _colonSlottedRe , `$1${ _polyfillSlotted } ` ) ;
227256
257+ // Now restore the original @supports selector conditions
258+ supportsBlocks . forEach ( ( originalSelector , index ) => {
259+ cssText = cssText . replace ( `__supports_${ index } __` , originalSelector ) ;
260+ } ) ;
261+
228262 return cssText ;
229263} ;
230264
0 commit comments