@@ -92,8 +92,26 @@ const _polyfillHostRe = /-shadowcsshost/gim;
92
92
* @param selector The CSS selector we want to match for replacement
93
93
* @returns A look-behind regex containing the selector
94
94
*/
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
+ } ;
97
115
const _colonSlottedRe = createSupportsRuleRe ( '::slotted' ) ;
98
116
const _colonHostRe = createSupportsRuleRe ( ':host' ) ;
99
117
const _colonHostContextRe = createSupportsRuleRe ( ':host-context' ) ;
@@ -212,6 +230,17 @@ const escapeBlocks = (input: string) => {
212
230
* @returns The modified CSS string
213
231
*/
214
232
const 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
+
215
244
// These replacements use a special syntax with the `$1`. When the replacement
216
245
// occurs, `$1` maps to the content of the string leading up to the selector
217
246
// to be replaced.
@@ -225,6 +254,11 @@ const insertPolyfillHostInCssText = (cssText: string) => {
225
254
. replace ( _colonHostRe , `$1${ _polyfillHost } ` )
226
255
. replace ( _colonSlottedRe , `$1${ _polyfillSlotted } ` ) ;
227
256
257
+ // Now restore the original @supports selector conditions
258
+ supportsBlocks . forEach ( ( originalSelector , index ) => {
259
+ cssText = cssText . replace ( `__supports_${ index } __` , originalSelector ) ;
260
+ } ) ;
261
+
228
262
return cssText ;
229
263
} ;
230
264
0 commit comments