@wordpress/global-styles-engine 1.13.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -19,6 +19,34 @@ import { getValueFromObjectPath } from './object';
19
19
  export const ROOT_BLOCK_SELECTOR = 'body';
20
20
  export const ROOT_CSS_PROPERTIES_SELECTOR = ':root';
21
21
 
22
+ export function splitSelectorList( selector: string ) {
23
+ if ( ! selector.includes( ',' ) ) {
24
+ return [ selector ];
25
+ }
26
+
27
+ const selectors: string[] = [];
28
+ let currentSelector = '';
29
+ let parenthesesDepth = 0;
30
+
31
+ for ( const char of selector ) {
32
+ if ( char === '(' ) {
33
+ parenthesesDepth++;
34
+ } else if ( char === ')' && parenthesesDepth > 0 ) {
35
+ parenthesesDepth--;
36
+ } else if ( char === ',' && parenthesesDepth === 0 ) {
37
+ selectors.push( currentSelector );
38
+ currentSelector = '';
39
+ continue;
40
+ }
41
+
42
+ currentSelector += char;
43
+ }
44
+
45
+ selectors.push( currentSelector );
46
+
47
+ return selectors;
48
+ }
49
+
22
50
  export const PRESET_METADATA = [
23
51
  {
24
52
  path: [ 'color', 'palette' ],
@@ -170,8 +198,8 @@ export function scopeSelector( scope: string | undefined, selector: string ) {
170
198
  return selector;
171
199
  }
172
200
 
173
- const scopes = scope.split( ',' );
174
- const selectors = selector.split( ',' );
201
+ const scopes = splitSelectorList( scope );
202
+ const selectors = splitSelectorList( selector );
175
203
 
176
204
  const selectorsScoped: string[] = [];
177
205
  scopes.forEach( ( outer ) => {
@@ -257,7 +285,7 @@ export function appendToSelector( selector: string, toAppend: string ) {
257
285
  if ( ! selector.includes( ',' ) ) {
258
286
  return selector + toAppend;
259
287
  }
260
- const selectors = selector.split( ',' );
288
+ const selectors = splitSelectorList( selector );
261
289
  const newSelectors = selectors.map( ( sel ) => sel + toAppend );
262
290
  return newSelectors.join( ',' );
263
291
  }
@@ -298,13 +326,49 @@ export function getBlockStyleVariationSelector(
298
326
  return group1 + group2 + variationClass;
299
327
  };
300
328
 
301
- const result = blockSelector
302
- .split( ',' )
303
- .map( ( part ) => part.replace( ancestorRegex, addVariationClass ) );
329
+ const result = splitSelectorList( blockSelector ).map( ( part ) =>
330
+ part.replace( ancestorRegex, addVariationClass )
331
+ );
304
332
 
305
333
  return result.join( ',' );
306
334
  }
307
335
 
336
+ /**
337
+ * Generates the selector for a block style variation feature selector.
338
+ *
339
+ * Feature selectors can target a different element than the block root
340
+ * selector. Apply the variation class directly to the selector that receives
341
+ * the declarations instead of deriving it from the block root selector.
342
+ *
343
+ * @param variation Name for the variation.
344
+ * @param featureSelector CSS selector for the feature.
345
+ *
346
+ * @return CSS selector for the block style variation feature.
347
+ */
348
+ export function getBlockStyleVariationFeatureSelector(
349
+ variation: string,
350
+ featureSelector: string
351
+ ) {
352
+ const variationClass = `.is-style-${ variation }`;
353
+ const selectorParts = splitSelectorList( featureSelector ).map(
354
+ ( selector ) => {
355
+ const trimmedSelector = selector.trim();
356
+ const prefix = `${ variationClass } `;
357
+
358
+ if ( trimmedSelector.startsWith( prefix ) ) {
359
+ return trimmedSelector.slice( prefix.length );
360
+ }
361
+
362
+ return trimmedSelector;
363
+ }
364
+ );
365
+
366
+ return getBlockStyleVariationSelector(
367
+ variation,
368
+ selectorParts.join( ',' )
369
+ );
370
+ }
371
+
308
372
  /**
309
373
  * Resolves ref values in theme JSON.
310
374
  *