@wordpress/block-editor 15.6.1-next.36001005c.0 → 15.6.2

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.
Files changed (169) hide show
  1. package/build/components/background-image-control/index.js +2 -2
  2. package/build/components/background-image-control/index.js.map +2 -2
  3. package/build/components/block-list/block.js +3 -3
  4. package/build/components/block-list/block.js.map +2 -2
  5. package/build/components/block-list/index.js +2 -2
  6. package/build/components/block-list/index.js.map +1 -1
  7. package/build/components/block-quick-navigation/index.js +0 -1
  8. package/build/components/block-quick-navigation/index.js.map +2 -2
  9. package/build/components/global-styles/border-panel.js +1 -2
  10. package/build/components/global-styles/border-panel.js.map +2 -2
  11. package/build/components/global-styles/color-panel.js +1 -2
  12. package/build/components/global-styles/color-panel.js.map +2 -2
  13. package/build/components/global-styles/dimensions-panel.js +2 -3
  14. package/build/components/global-styles/dimensions-panel.js.map +2 -2
  15. package/build/components/global-styles/filters-panel.js +1 -2
  16. package/build/components/global-styles/filters-panel.js.map +2 -2
  17. package/build/components/global-styles/get-block-css-selector.js +78 -0
  18. package/build/components/global-styles/get-block-css-selector.js.map +7 -0
  19. package/build/components/global-styles/hooks.js +95 -23
  20. package/build/components/global-styles/hooks.js.map +2 -2
  21. package/build/components/global-styles/index.js +14 -0
  22. package/build/components/global-styles/index.js.map +2 -2
  23. package/build/components/global-styles/typography-panel.js +19 -3
  24. package/build/components/global-styles/typography-panel.js.map +2 -2
  25. package/build/components/global-styles/typography-utils.js +49 -2
  26. package/build/components/global-styles/typography-utils.js.map +2 -2
  27. package/build/components/global-styles/use-global-styles-output.js +998 -0
  28. package/build/components/global-styles/use-global-styles-output.js.map +7 -0
  29. package/build/components/global-styles/utils.js +377 -0
  30. package/build/components/global-styles/utils.js.map +2 -2
  31. package/build/components/rich-text/index.js +8 -7
  32. package/build/components/rich-text/index.js.map +2 -2
  33. package/build/hooks/allowed-blocks.js +50 -1
  34. package/build/hooks/allowed-blocks.js.map +2 -2
  35. package/build/hooks/block-bindings.js +111 -170
  36. package/build/hooks/block-bindings.js.map +2 -2
  37. package/build/hooks/block-style-variation.js +10 -6
  38. package/build/hooks/block-style-variation.js.map +2 -2
  39. package/build/hooks/custom-class-name.js +1 -1
  40. package/build/hooks/custom-class-name.js.map +1 -1
  41. package/build/hooks/duotone.js +3 -3
  42. package/build/hooks/duotone.js.map +2 -2
  43. package/build/hooks/fit-text.js +33 -20
  44. package/build/hooks/fit-text.js.map +2 -2
  45. package/build/hooks/font-size.js +6 -5
  46. package/build/hooks/font-size.js.map +2 -2
  47. package/build/hooks/metadata.js +48 -2
  48. package/build/hooks/metadata.js.map +2 -2
  49. package/build/hooks/typography.js +11 -4
  50. package/build/hooks/typography.js.map +3 -3
  51. package/build/hooks/use-typography-props.js +2 -2
  52. package/build/hooks/use-typography-props.js.map +2 -2
  53. package/build/store/private-selectors.js +3 -3
  54. package/build/store/private-selectors.js.map +2 -2
  55. package/build/store/selectors.js +38 -13
  56. package/build/store/selectors.js.map +2 -2
  57. package/build/store/utils.js +2 -1
  58. package/build/store/utils.js.map +2 -2
  59. package/build/utils/fit-text-utils.js +4 -4
  60. package/build/utils/fit-text-utils.js.map +2 -2
  61. package/build-module/components/background-image-control/index.js +1 -1
  62. package/build-module/components/background-image-control/index.js.map +2 -2
  63. package/build-module/components/block-list/block.js +3 -3
  64. package/build-module/components/block-list/block.js.map +2 -2
  65. package/build-module/components/block-list/index.js +2 -2
  66. package/build-module/components/block-list/index.js.map +1 -1
  67. package/build-module/components/block-quick-navigation/index.js +0 -1
  68. package/build-module/components/block-quick-navigation/index.js.map +2 -2
  69. package/build-module/components/global-styles/border-panel.js +1 -2
  70. package/build-module/components/global-styles/border-panel.js.map +2 -2
  71. package/build-module/components/global-styles/color-panel.js +1 -2
  72. package/build-module/components/global-styles/color-panel.js.map +2 -2
  73. package/build-module/components/global-styles/dimensions-panel.js +1 -2
  74. package/build-module/components/global-styles/dimensions-panel.js.map +2 -2
  75. package/build-module/components/global-styles/filters-panel.js +1 -2
  76. package/build-module/components/global-styles/filters-panel.js.map +2 -2
  77. package/build-module/components/global-styles/get-block-css-selector.js +54 -0
  78. package/build-module/components/global-styles/get-block-css-selector.js.map +7 -0
  79. package/build-module/components/global-styles/hooks.js +95 -27
  80. package/build-module/components/global-styles/hooks.js.map +2 -2
  81. package/build-module/components/global-styles/index.js +14 -0
  82. package/build-module/components/global-styles/index.js.map +2 -2
  83. package/build-module/components/global-styles/typography-panel.js +19 -3
  84. package/build-module/components/global-styles/typography-panel.js.map +2 -2
  85. package/build-module/components/global-styles/typography-utils.js +49 -1
  86. package/build-module/components/global-styles/typography-utils.js.map +2 -2
  87. package/build-module/components/global-styles/use-global-styles-output.js +979 -0
  88. package/build-module/components/global-styles/use-global-styles-output.js.map +7 -0
  89. package/build-module/components/global-styles/utils.js +364 -0
  90. package/build-module/components/global-styles/utils.js.map +2 -2
  91. package/build-module/components/rich-text/index.js +8 -7
  92. package/build-module/components/rich-text/index.js.map +2 -2
  93. package/build-module/hooks/allowed-blocks.js +49 -1
  94. package/build-module/hooks/allowed-blocks.js.map +2 -2
  95. package/build-module/hooks/block-bindings.js +112 -172
  96. package/build-module/hooks/block-bindings.js.map +2 -2
  97. package/build-module/hooks/block-style-variation.js +12 -4
  98. package/build-module/hooks/block-style-variation.js.map +2 -2
  99. package/build-module/hooks/custom-class-name.js +1 -1
  100. package/build-module/hooks/custom-class-name.js.map +1 -1
  101. package/build-module/hooks/duotone.js +3 -3
  102. package/build-module/hooks/duotone.js.map +2 -2
  103. package/build-module/hooks/fit-text.js +34 -21
  104. package/build-module/hooks/fit-text.js.map +2 -2
  105. package/build-module/hooks/font-size.js +5 -4
  106. package/build-module/hooks/font-size.js.map +2 -2
  107. package/build-module/hooks/metadata.js +46 -1
  108. package/build-module/hooks/metadata.js.map +2 -2
  109. package/build-module/hooks/typography.js +11 -4
  110. package/build-module/hooks/typography.js.map +3 -3
  111. package/build-module/hooks/use-typography-props.js +1 -1
  112. package/build-module/hooks/use-typography-props.js.map +2 -2
  113. package/build-module/store/private-selectors.js +2 -2
  114. package/build-module/store/private-selectors.js.map +2 -2
  115. package/build-module/store/selectors.js +39 -14
  116. package/build-module/store/selectors.js.map +2 -2
  117. package/build-module/store/utils.js +3 -2
  118. package/build-module/store/utils.js.map +2 -2
  119. package/build-module/utils/fit-text-utils.js +4 -4
  120. package/build-module/utils/fit-text-utils.js.map +2 -2
  121. package/build-style/style-rtl.css +6 -10
  122. package/build-style/style.css +6 -10
  123. package/package.json +35 -36
  124. package/src/components/background-image-control/index.js +1 -1
  125. package/src/components/block-card/style.scss +1 -1
  126. package/src/components/block-list/block.js +1 -1
  127. package/src/components/block-list/index.js +2 -2
  128. package/src/components/block-navigation/style.scss +1 -1
  129. package/src/components/block-quick-navigation/index.js +0 -1
  130. package/src/components/block-switcher/style.scss +1 -1
  131. package/src/components/color-palette/test/__snapshots__/control.js.snap +1 -1
  132. package/src/components/global-styles/border-panel.js +1 -2
  133. package/src/components/global-styles/color-panel.js +1 -2
  134. package/src/components/global-styles/color-panel.native.js +1 -1
  135. package/src/components/global-styles/dimensions-panel.js +1 -2
  136. package/src/components/global-styles/filters-panel.js +1 -2
  137. package/src/components/global-styles/get-block-css-selector.js +114 -0
  138. package/src/components/global-styles/hooks.js +108 -29
  139. package/src/components/global-styles/index.js +8 -0
  140. package/src/components/global-styles/test/typography-utils.js +806 -0
  141. package/src/components/global-styles/test/use-global-styles-output.js +1131 -0
  142. package/src/components/global-styles/test/utils.js +442 -1
  143. package/src/components/global-styles/typography-panel.js +27 -3
  144. package/src/components/global-styles/typography-utils.js +133 -0
  145. package/src/components/global-styles/use-global-styles-output.js +1487 -0
  146. package/src/components/global-styles/utils.js +537 -0
  147. package/src/components/inserter/style.scss +2 -2
  148. package/src/components/multi-selection-inspector/style.scss +1 -1
  149. package/src/components/rich-text/index.js +8 -14
  150. package/src/hooks/allowed-blocks.js +89 -1
  151. package/src/hooks/block-bindings.js +79 -153
  152. package/src/hooks/block-style-variation.js +12 -4
  153. package/src/hooks/custom-class-name.js +1 -1
  154. package/src/hooks/duotone.js +3 -3
  155. package/src/hooks/fit-text.js +39 -30
  156. package/src/hooks/font-size.js +8 -4
  157. package/src/hooks/metadata.js +89 -0
  158. package/src/hooks/test/allowed-blocks.js +278 -0
  159. package/src/hooks/test/metadata.js +316 -0
  160. package/src/hooks/typography.js +15 -4
  161. package/src/hooks/use-typography-props.js +1 -1
  162. package/src/store/private-selectors.js +2 -2
  163. package/src/store/selectors.js +59 -21
  164. package/src/store/test/selectors.js +1 -1
  165. package/src/store/utils.js +2 -1
  166. package/src/style.scss +0 -1
  167. package/src/utils/fit-text-utils.js +4 -16
  168. package/tsconfig.json +0 -1
  169. package/src/components/block-quick-navigation/style.scss +0 -5
@@ -0,0 +1,1131 @@
1
+ /**
2
+ * WordPress dependencies
3
+ */
4
+ import { __EXPERIMENTAL_ELEMENTS as ELEMENTS } from '@wordpress/blocks';
5
+
6
+ /**
7
+ * Internal dependencies
8
+ */
9
+ import {
10
+ getLayoutStyles,
11
+ getNodesWithSettings,
12
+ getNodesWithStyles,
13
+ getBlockSelectors,
14
+ toCustomProperties,
15
+ toStyles,
16
+ getStylesDeclarations,
17
+ processCSSNesting,
18
+ } from '../use-global-styles-output';
19
+ import { ROOT_BLOCK_SELECTOR, ROOT_CSS_PROPERTIES_SELECTOR } from '../utils';
20
+
21
+ describe( 'global styles renderer', () => {
22
+ describe( 'getNodesWithStyles', () => {
23
+ it( 'should return the nodes with styles', () => {
24
+ const tree = {
25
+ styles: {
26
+ color: {
27
+ background: 'red',
28
+ text: 'red',
29
+ },
30
+ blocks: {
31
+ 'core/heading': {
32
+ color: {
33
+ background: 'blue',
34
+ text: 'blue',
35
+ },
36
+ elements: {
37
+ h1: {
38
+ typography: {
39
+ fontSize: '42px',
40
+ },
41
+ },
42
+ h2: {
43
+ typography: {
44
+ fontSize: '23px',
45
+ },
46
+ },
47
+ link: {
48
+ ':hover': {
49
+ color: {
50
+ background: 'green',
51
+ text: 'yellow',
52
+ },
53
+ },
54
+ ':focus': {
55
+ color: {
56
+ background: 'green',
57
+ text: 'yellow',
58
+ },
59
+ },
60
+ },
61
+ },
62
+ },
63
+ 'core/image': {
64
+ border: {
65
+ radius: '9999px',
66
+ },
67
+ },
68
+ },
69
+ elements: {
70
+ link: {
71
+ color: {
72
+ background: 'yellow',
73
+ text: 'yellow',
74
+ },
75
+ ':hover': {
76
+ color: {
77
+ background: 'hotpink',
78
+ text: 'black',
79
+ },
80
+ },
81
+ ':focus': {
82
+ color: {
83
+ background: 'hotpink',
84
+ text: 'black',
85
+ },
86
+ },
87
+ },
88
+ },
89
+ },
90
+ };
91
+ const blockSelectors = {
92
+ 'core/heading': {
93
+ selector: '.my-heading1, .my-heading2',
94
+ },
95
+ 'core/image': {
96
+ selector: '.my-image',
97
+ featureSelectors: '.my-image img, .my-image .crop-area',
98
+ },
99
+ };
100
+
101
+ expect( getNodesWithStyles( tree, blockSelectors ) ).toEqual( [
102
+ {
103
+ styles: {
104
+ color: {
105
+ background: 'red',
106
+ text: 'red',
107
+ },
108
+ },
109
+ selector: ROOT_BLOCK_SELECTOR,
110
+ skipSelectorWrapper: true,
111
+ },
112
+ {
113
+ styles: {
114
+ color: {
115
+ background: 'yellow',
116
+ text: 'yellow',
117
+ },
118
+ ':hover': {
119
+ color: {
120
+ background: 'hotpink',
121
+ text: 'black',
122
+ },
123
+ },
124
+ ':focus': {
125
+ color: {
126
+ background: 'hotpink',
127
+ text: 'black',
128
+ },
129
+ },
130
+ },
131
+ selector: ELEMENTS.link,
132
+ skipSelectorWrapper: true,
133
+ },
134
+ {
135
+ styles: {
136
+ color: {
137
+ background: 'blue',
138
+ text: 'blue',
139
+ },
140
+ },
141
+ selector: '.my-heading1, .my-heading2',
142
+ },
143
+ {
144
+ styles: {
145
+ typography: {
146
+ fontSize: '42px',
147
+ },
148
+ },
149
+ selector: '.my-heading1 h1, .my-heading2 h1',
150
+ },
151
+ {
152
+ styles: {
153
+ typography: {
154
+ fontSize: '23px',
155
+ },
156
+ },
157
+ selector: '.my-heading1 h2, .my-heading2 h2',
158
+ },
159
+ {
160
+ styles: {
161
+ ':hover': {
162
+ color: {
163
+ background: 'green',
164
+ text: 'yellow',
165
+ },
166
+ },
167
+ ':focus': {
168
+ color: {
169
+ background: 'green',
170
+ text: 'yellow',
171
+ },
172
+ },
173
+ },
174
+ selector:
175
+ '.my-heading1 a:where(:not(.wp-element-button)), .my-heading2 a:where(:not(.wp-element-button))',
176
+ },
177
+ {
178
+ styles: {
179
+ border: {
180
+ radius: '9999px',
181
+ },
182
+ },
183
+ selector: '.my-image',
184
+ featureSelectors: '.my-image img, .my-image .crop-area',
185
+ },
186
+ ] );
187
+ } );
188
+ } );
189
+ describe( 'getNodesWithSettings', () => {
190
+ it( 'should return nodes with settings', () => {
191
+ const tree = {
192
+ styles: {
193
+ color: {
194
+ background: 'red',
195
+ text: 'red',
196
+ },
197
+ },
198
+ settings: {
199
+ color: {
200
+ palette: [
201
+ { name: 'White', slug: 'white', color: 'white' },
202
+ { name: 'Black', slug: 'black', color: 'black' },
203
+ ],
204
+ },
205
+ blocks: {
206
+ 'core/paragraph': {
207
+ typography: {
208
+ fontSizes: [
209
+ {
210
+ name: 'small',
211
+ slug: 'small',
212
+ size: '12px',
213
+ },
214
+ {
215
+ name: 'medium',
216
+ slug: 'medium',
217
+ size: '23px',
218
+ },
219
+ ],
220
+ },
221
+ },
222
+ },
223
+ },
224
+ };
225
+
226
+ const blockSelectors = {
227
+ 'core/paragraph': {
228
+ selector: 'p',
229
+ elements: {
230
+ link: 'p a',
231
+ h1: 'p h1',
232
+ h2: 'p h2',
233
+ h3: 'p h3',
234
+ h4: 'p h4',
235
+ h5: 'p h5',
236
+ h6: 'p h6',
237
+ },
238
+ },
239
+ };
240
+
241
+ expect( getNodesWithSettings( tree, blockSelectors ) ).toEqual( [
242
+ {
243
+ presets: {
244
+ color: {
245
+ palette: [
246
+ {
247
+ name: 'White',
248
+ slug: 'white',
249
+ color: 'white',
250
+ },
251
+ {
252
+ name: 'Black',
253
+ slug: 'black',
254
+ color: 'black',
255
+ },
256
+ ],
257
+ },
258
+ },
259
+ selector: ROOT_CSS_PROPERTIES_SELECTOR,
260
+ },
261
+ {
262
+ presets: {
263
+ typography: {
264
+ fontSizes: [
265
+ {
266
+ name: 'small',
267
+ slug: 'small',
268
+ size: '12px',
269
+ },
270
+ {
271
+ name: 'medium',
272
+ slug: 'medium',
273
+ size: '23px',
274
+ },
275
+ ],
276
+ },
277
+ },
278
+ selector: 'p',
279
+ },
280
+ ] );
281
+ } );
282
+ } );
283
+
284
+ describe( 'toCustomProperties', () => {
285
+ it( 'should return a ruleset', () => {
286
+ const tree = {
287
+ settings: {
288
+ color: {
289
+ palette: {
290
+ custom: [
291
+ {
292
+ name: 'White',
293
+ slug: 'white',
294
+ color: 'white',
295
+ },
296
+ {
297
+ name: 'Black',
298
+ slug: 'black',
299
+ color: 'black',
300
+ },
301
+ {
302
+ name: 'White to Black',
303
+ slug: 'white2black',
304
+ color: 'value',
305
+ },
306
+ ],
307
+ },
308
+ },
309
+ custom: {
310
+ white2black: 'value',
311
+ 'font-primary': 'value',
312
+ 'line-height': {
313
+ body: 1.7,
314
+ heading: 1.3,
315
+ },
316
+ },
317
+ blocks: {
318
+ 'core/heading': {
319
+ typography: {
320
+ fontSizes: {
321
+ theme: [
322
+ {
323
+ name: 'small',
324
+ slug: 'small',
325
+ size: '12px',
326
+ },
327
+ {
328
+ name: 'medium',
329
+ slug: 'medium',
330
+ size: '23px',
331
+ },
332
+ ],
333
+ },
334
+ },
335
+ },
336
+ },
337
+ },
338
+ };
339
+
340
+ const blockSelectors = {
341
+ 'core/heading': {
342
+ selector: 'h1,h2,h3,h4,h5,h6',
343
+ },
344
+ };
345
+
346
+ expect( toCustomProperties( tree, blockSelectors ) ).toEqual(
347
+ ':root{--wp--preset--color--white: white;--wp--preset--color--black: black;--wp--preset--color--white-2-black: value;--wp--custom--white-2-black: value;--wp--custom--font-primary: value;--wp--custom--line-height--body: 1.7;--wp--custom--line-height--heading: 1.3;}h1,h2,h3,h4,h5,h6{--wp--preset--font-size--small: 12px;--wp--preset--font-size--medium: 23px;}'
348
+ );
349
+ } );
350
+ } );
351
+
352
+ describe( 'toStyles', () => {
353
+ it( 'should return a ruleset', () => {
354
+ const tree = {
355
+ settings: {
356
+ color: {
357
+ palette: {
358
+ default: [
359
+ {
360
+ name: 'White',
361
+ slug: 'white',
362
+ color: 'white',
363
+ },
364
+ {
365
+ name: 'Black',
366
+ slug: 'black',
367
+ color: 'black',
368
+ },
369
+ ],
370
+ },
371
+ },
372
+ blocks: {
373
+ 'core/heading': {
374
+ color: {
375
+ palette: {
376
+ default: [
377
+ {
378
+ name: 'Blue',
379
+ slug: 'blue',
380
+ color: 'blue',
381
+ },
382
+ ],
383
+ },
384
+ },
385
+ },
386
+ },
387
+ },
388
+ styles: {
389
+ spacing: {
390
+ margin: '10px',
391
+ padding: '10px',
392
+ },
393
+ color: {
394
+ background: 'red',
395
+ },
396
+ elements: {
397
+ h1: {
398
+ typography: {
399
+ fontSize: '42px',
400
+ },
401
+ },
402
+ link: {
403
+ color: {
404
+ text: 'blue',
405
+ },
406
+ ':hover': {
407
+ color: {
408
+ text: 'orange',
409
+ },
410
+ },
411
+ ':focus': {
412
+ color: {
413
+ text: 'orange',
414
+ },
415
+ },
416
+ },
417
+ },
418
+ blocks: {
419
+ 'core/group': {
420
+ spacing: {
421
+ margin: {
422
+ top: '10px',
423
+ right: '20px',
424
+ bottom: '30px',
425
+ left: '40px',
426
+ },
427
+ padding: {
428
+ top: '11px',
429
+ right: '22px',
430
+ bottom: '33px',
431
+ left: '44px',
432
+ },
433
+ },
434
+ },
435
+ 'core/heading': {
436
+ color: {
437
+ text: 'orange',
438
+ },
439
+ elements: {
440
+ link: {
441
+ color: {
442
+ text: 'hotpink',
443
+ },
444
+ ':hover': {
445
+ color: {
446
+ text: 'red',
447
+ },
448
+ },
449
+ ':focus': {
450
+ color: {
451
+ text: 'red',
452
+ },
453
+ },
454
+ },
455
+ },
456
+ },
457
+ 'core/image': {
458
+ color: {
459
+ text: 'red',
460
+ },
461
+ border: {
462
+ radius: '9999px',
463
+ },
464
+ },
465
+ },
466
+ },
467
+ };
468
+
469
+ const blockSelectors = {
470
+ 'core/group': {
471
+ selector: '.wp-block-group',
472
+ },
473
+ 'core/heading': {
474
+ selector: 'h1,h2,h3,h4,h5,h6',
475
+ },
476
+ 'core/image': {
477
+ selector: '.wp-block-image',
478
+ featureSelectors: {
479
+ border: '.wp-block-image img, .wp-block-image .wp-crop-area',
480
+ },
481
+ },
482
+ };
483
+
484
+ expect( toStyles( tree, blockSelectors ) ).toEqual(
485
+ ':where(body) {margin: 0;}.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > :is(*, div) { margin: 0; }body .is-layout-grid { display:grid; }.is-layout-grid > :is(*, div) { margin: 0; }body{background-color: red;margin: 10px;padding: 10px;}a:where(:not(.wp-element-button)){color: blue;}:root :where(a:where(:not(.wp-element-button)):hover){color: orange;}:root :where(a:where(:not(.wp-element-button)):focus){color: orange;}h1{font-size: 42px;}:root :where(.wp-block-group){margin-top: 10px;margin-right: 20px;margin-bottom: 30px;margin-left: 40px;padding-top: 11px;padding-right: 22px;padding-bottom: 33px;padding-left: 44px;}:root :where(h1,h2,h3,h4,h5,h6){color: orange;}:root :where(h1 a:where(:not(.wp-element-button)),h2 a:where(:not(.wp-element-button)),h3 a:where(:not(.wp-element-button)),h4 a:where(:not(.wp-element-button)),h5 a:where(:not(.wp-element-button)),h6 a:where(:not(.wp-element-button))){color: hotpink;}:root :where(h1 a:where(:not(.wp-element-button)):hover,h2 a:where(:not(.wp-element-button)):hover,h3 a:where(:not(.wp-element-button)):hover,h4 a:where(:not(.wp-element-button)):hover,h5 a:where(:not(.wp-element-button)):hover,h6 a:where(:not(.wp-element-button)):hover){color: red;}:root :where(h1 a:where(:not(.wp-element-button)):focus,h2 a:where(:not(.wp-element-button)):focus,h3 a:where(:not(.wp-element-button)):focus,h4 a:where(:not(.wp-element-button)):focus,h5 a:where(:not(.wp-element-button)):focus,h6 a:where(:not(.wp-element-button)):focus){color: red;}:root :where(.wp-block-image img, .wp-block-image .wp-crop-area){border-radius: 9999px;}:root :where(.wp-block-image){color: red;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }.has-white-color{color: var(--wp--preset--color--white) !important;}.has-white-background-color{background-color: var(--wp--preset--color--white) !important;}.has-white-border-color{border-color: var(--wp--preset--color--white) !important;}.has-black-color{color: var(--wp--preset--color--black) !important;}.has-black-background-color{background-color: var(--wp--preset--color--black) !important;}.has-black-border-color{border-color: var(--wp--preset--color--black) !important;}h1.has-blue-color,h2.has-blue-color,h3.has-blue-color,h4.has-blue-color,h5.has-blue-color,h6.has-blue-color{color: var(--wp--preset--color--blue) !important;}h1.has-blue-background-color,h2.has-blue-background-color,h3.has-blue-background-color,h4.has-blue-background-color,h5.has-blue-background-color,h6.has-blue-background-color{background-color: var(--wp--preset--color--blue) !important;}h1.has-blue-border-color,h2.has-blue-border-color,h3.has-blue-border-color,h4.has-blue-border-color,h5.has-blue-border-color,h6.has-blue-border-color{border-color: var(--wp--preset--color--blue) !important;}'
486
+ );
487
+ } );
488
+
489
+ it( 'should handle feature selectors', () => {
490
+ const tree = {
491
+ styles: {
492
+ blocks: {
493
+ 'core/image': {
494
+ color: {
495
+ text: 'red',
496
+ },
497
+ spacing: {
498
+ padding: {
499
+ top: '1px',
500
+ },
501
+ },
502
+ border: {
503
+ color: 'red',
504
+ radius: '9999px',
505
+ },
506
+ },
507
+ },
508
+ },
509
+ };
510
+
511
+ const blockSelectors = {
512
+ 'core/image': {
513
+ selector: '.wp-image',
514
+ featureSelectors: {
515
+ spacing: '.wp-image-spacing',
516
+ border: {
517
+ root: '.wp-image-border',
518
+ color: '.wp-image-border-color',
519
+ },
520
+ },
521
+ },
522
+ };
523
+
524
+ expect( toStyles( Object.freeze( tree ), blockSelectors ) ).toEqual(
525
+ ':where(body) {margin: 0;}.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > :is(*, div) { margin: 0; }body .is-layout-grid { display:grid; }.is-layout-grid > :is(*, div) { margin: 0; }:root :where(.wp-image-spacing){padding-top: 1px;}:root :where(.wp-image-border-color){border-color: red;}:root :where(.wp-image-border){border-radius: 9999px;}:root :where(.wp-image){color: red;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'
526
+ );
527
+ } );
528
+
529
+ it( 'should handle block variations', () => {
530
+ const tree = {
531
+ styles: {
532
+ blocks: {
533
+ 'core/image': {
534
+ variations: {
535
+ foo: {
536
+ color: {
537
+ text: 'blue',
538
+ },
539
+ spacing: {
540
+ padding: {
541
+ top: '2px',
542
+ },
543
+ },
544
+ border: {
545
+ color: 'blue',
546
+ },
547
+ },
548
+ },
549
+ },
550
+ },
551
+ },
552
+ };
553
+
554
+ const blockSelectors = {
555
+ 'core/image': {
556
+ selector: '.wp-image',
557
+ featureSelectors: {
558
+ spacing: '.wp-image-spacing',
559
+ border: {
560
+ root: '.wp-image-border',
561
+ color: '.wp-image-border-color',
562
+ },
563
+ },
564
+ styleVariationSelectors: {
565
+ foo: '.is-style-foo.wp-image',
566
+ },
567
+ },
568
+ };
569
+
570
+ const hasBlockGapSupport = false;
571
+ const hasFallbackGapSupport = true;
572
+ const disableLayoutStyles = true;
573
+ const disableRootPadding = true;
574
+ const styleOptions = {
575
+ blockGap: false,
576
+ blockStyles: true,
577
+ layoutStyles: false,
578
+ marginReset: false,
579
+ presets: false,
580
+ rootPadding: false,
581
+ };
582
+
583
+ // Confirm no variation styles by default.
584
+ const withoutVariations = toStyles(
585
+ Object.freeze( tree ),
586
+ blockSelectors,
587
+ hasBlockGapSupport,
588
+ hasFallbackGapSupport,
589
+ disableLayoutStyles,
590
+ disableRootPadding,
591
+ styleOptions
592
+ );
593
+ expect( withoutVariations ).toEqual( '' );
594
+
595
+ // Includes variation styles when requested.
596
+ styleOptions.variationStyles = true;
597
+ const withVariations = toStyles(
598
+ Object.freeze( tree ),
599
+ blockSelectors,
600
+ hasBlockGapSupport,
601
+ hasFallbackGapSupport,
602
+ disableLayoutStyles,
603
+ disableRootPadding,
604
+ styleOptions
605
+ );
606
+ expect( withVariations ).toEqual(
607
+ ':root :where(.is-style-foo.wp-image.wp-image-spacing){padding-top: 2px;}:root :where(.is-style-foo.wp-image.wp-image-border-color){border-color: blue;}:root :where(.is-style-foo.wp-image){color: blue;}'
608
+ );
609
+ } );
610
+
611
+ it( 'should handle duotone filter', () => {
612
+ const tree = {
613
+ styles: {
614
+ blocks: {
615
+ 'core/image': {
616
+ filter: {
617
+ duotone: 'blur(5px)',
618
+ },
619
+ },
620
+ },
621
+ },
622
+ };
623
+
624
+ const blockSelectors = {
625
+ 'core/image': {
626
+ selector: '.wp-image',
627
+ duotoneSelector: '.wp-image img',
628
+ },
629
+ };
630
+
631
+ expect( toStyles( Object.freeze( tree ), blockSelectors ) ).toEqual(
632
+ ':where(body) {margin: 0;}.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-constrained > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-constrained > .aligncenter { margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > :where(:not(.alignleft):not(.alignright):not(.alignfull)) { max-width: var(--wp--style--global--content-size); margin-left: auto !important; margin-right: auto !important; }.is-layout-constrained > .alignwide { max-width: var(--wp--style--global--wide-size); }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > :is(*, div) { margin: 0; }body .is-layout-grid { display:grid; }.is-layout-grid > :is(*, div) { margin: 0; }.wp-image img{filter: blur(5px);}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'
633
+ );
634
+ } );
635
+
636
+ it( 'should output content and wide size variables if values are specified', () => {
637
+ const tree = {
638
+ settings: {
639
+ layout: {
640
+ contentSize: '840px',
641
+ wideSize: '1100px',
642
+ },
643
+ },
644
+ };
645
+ expect( toStyles( Object.freeze( tree ), 'body' ) ).toEqual(
646
+ ':root { --wp--style--global--content-size: 840px; --wp--style--global--wide-size: 1100px;}:where(body) {margin: 0;}.wp-site-blocks > .alignleft { float: left; margin-right: 2em; }.wp-site-blocks > .alignright { float: right; margin-left: 2em; }.wp-site-blocks > .aligncenter { justify-content: center; margin-left: auto; margin-right: auto; }'
647
+ );
648
+ } );
649
+ } );
650
+
651
+ describe( 'getLayoutStyles', () => {
652
+ const layoutDefinitionsTree = {
653
+ settings: {
654
+ layout: {
655
+ definitions: {
656
+ default: {
657
+ name: 'default',
658
+ slug: 'flow',
659
+ className: 'is-layout-flow',
660
+ baseStyles: [
661
+ {
662
+ selector: ' > .alignleft',
663
+ rules: {
664
+ float: 'left',
665
+ 'margin-inline-start': '0',
666
+ 'margin-inline-end': '2em',
667
+ },
668
+ },
669
+ {
670
+ selector: ' > .alignright',
671
+ rules: {
672
+ float: 'right',
673
+ 'margin-inline-start': '2em',
674
+ 'margin-inline-end': '0',
675
+ },
676
+ },
677
+ {
678
+ selector: ' > .aligncenter',
679
+ rules: {
680
+ 'margin-left': 'auto !important',
681
+ 'margin-right': 'auto !important',
682
+ },
683
+ },
684
+ ],
685
+ spacingStyles: [
686
+ {
687
+ selector: ' > *',
688
+ rules: {
689
+ 'margin-block-start': '0',
690
+ 'margin-block-end': '0',
691
+ },
692
+ },
693
+ {
694
+ selector: ' > * + *',
695
+ rules: {
696
+ 'margin-block-start': null,
697
+ 'margin-block-end': '0',
698
+ },
699
+ },
700
+ ],
701
+ },
702
+ flex: {
703
+ name: 'flex',
704
+ slug: 'flex',
705
+ className: 'is-layout-flex',
706
+ displayMode: 'flex',
707
+ baseStyles: [
708
+ {
709
+ selector: '',
710
+ rules: {
711
+ 'flex-wrap': 'wrap',
712
+ 'align-items': 'center',
713
+ },
714
+ },
715
+ {
716
+ selector: ' > *',
717
+ rules: {
718
+ margin: '0',
719
+ },
720
+ },
721
+ ],
722
+ spacingStyles: [
723
+ {
724
+ selector: '',
725
+ rules: {
726
+ gap: null,
727
+ },
728
+ },
729
+ ],
730
+ },
731
+ },
732
+ },
733
+ },
734
+ };
735
+
736
+ it( 'should return fallback gap flex layout style, and all base styles, if block styles are enabled and blockGap is disabled', () => {
737
+ const style = { spacing: { blockGap: '12px' } };
738
+
739
+ const layoutStyles = getLayoutStyles( {
740
+ layoutDefinitions:
741
+ layoutDefinitionsTree.settings.layout.definitions,
742
+ style,
743
+ selector: 'body',
744
+ hasBlockGapSupport: false,
745
+ hasFallbackGapSupport: true,
746
+ } );
747
+
748
+ expect( layoutStyles ).toEqual(
749
+ ':where(.is-layout-flex) { gap: 0.5em; }.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > * { margin: 0; }'
750
+ );
751
+ } );
752
+
753
+ it( 'should return fallback gap layout styles, and base styles, if blockGap is enabled, but there is no blockGap value', () => {
754
+ const style = {};
755
+
756
+ const layoutStyles = getLayoutStyles( {
757
+ layoutDefinitions:
758
+ layoutDefinitionsTree.settings.layout.definitions,
759
+ style,
760
+ selector: 'body',
761
+ hasBlockGapSupport: true,
762
+ hasFallbackGapSupport: true,
763
+ } );
764
+
765
+ expect( layoutStyles ).toEqual(
766
+ ':root :where(.is-layout-flow) > * { margin-block-start: 0; margin-block-end: 0; }:root :where(.is-layout-flow) > * + * { margin-block-start: 0.5em; margin-block-end: 0; }:root :where(.is-layout-flex) { gap: 0.5em; }:root { --wp--style--block-gap: 0.5em; }.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > * { margin: 0; }'
767
+ );
768
+ } );
769
+
770
+ it( 'should return real gap layout style if blockGap is enabled, and base styles', () => {
771
+ const style = { spacing: { blockGap: '12px' } };
772
+
773
+ const layoutStyles = getLayoutStyles( {
774
+ layoutDefinitions:
775
+ layoutDefinitionsTree.settings.layout.definitions,
776
+ style,
777
+ selector: 'body',
778
+ hasBlockGapSupport: true,
779
+ hasFallbackGapSupport: true,
780
+ } );
781
+
782
+ expect( layoutStyles ).toEqual(
783
+ ':root :where(.is-layout-flow) > * { margin-block-start: 0; margin-block-end: 0; }:root :where(.is-layout-flow) > * + * { margin-block-start: 12px; margin-block-end: 0; }:root :where(.is-layout-flex) { gap: 12px; }:root { --wp--style--block-gap: 12px; }.is-layout-flow > .alignleft { float: left; margin-inline-start: 0; margin-inline-end: 2em; }.is-layout-flow > .alignright { float: right; margin-inline-start: 2em; margin-inline-end: 0; }.is-layout-flow > .aligncenter { margin-left: auto !important; margin-right: auto !important; }body .is-layout-flex { display:flex; }.is-layout-flex { flex-wrap: wrap; align-items: center; }.is-layout-flex > * { margin: 0; }'
784
+ );
785
+ } );
786
+
787
+ it( 'should return real gap layout style if blockGap is enabled', () => {
788
+ const style = { spacing: { blockGap: '12px' } };
789
+
790
+ const layoutStyles = getLayoutStyles( {
791
+ layoutDefinitions:
792
+ layoutDefinitionsTree.settings.layout.definitions,
793
+ style,
794
+ selector: '.wp-block-group',
795
+ hasBlockGapSupport: true,
796
+ hasFallbackGapSupport: true,
797
+ } );
798
+
799
+ expect( layoutStyles ).toEqual(
800
+ ':root :where(.wp-block-group-is-layout-flow) > * { margin-block-start: 0; margin-block-end: 0; }:root :where(.wp-block-group-is-layout-flow) > * + * { margin-block-start: 12px; margin-block-end: 0; }:root :where(.wp-block-group-is-layout-flex) { gap: 12px; }'
801
+ );
802
+ } );
803
+
804
+ it( 'should return fallback gap flex layout style for a block if blockGap is disabled, and a fallback value is provided', () => {
805
+ const style = { spacing: { blockGap: '12px' } };
806
+
807
+ const layoutStyles = getLayoutStyles( {
808
+ layoutDefinitions:
809
+ layoutDefinitionsTree.settings.layout.definitions,
810
+ style,
811
+ selector: '.wp-block-group',
812
+ hasBlockGapSupport: false, // This means that the fallback value will be used instead of the "real" one.
813
+ hasFallbackGapSupport: true,
814
+ fallbackGapValue: '2em',
815
+ } );
816
+
817
+ expect( layoutStyles ).toEqual(
818
+ ':where(.wp-block-group.is-layout-flex) { gap: 2em; }'
819
+ );
820
+ } );
821
+ } );
822
+
823
+ describe( 'getBlockSelectors', () => {
824
+ it( 'should return block selectors data', () => {
825
+ const imageSelectors = {
826
+ root: '.my-image',
827
+ border: '.my-image img, .my-image .crop-area',
828
+ filter: { duotone: 'img' },
829
+ };
830
+ const imageBlock = {
831
+ name: 'core/image',
832
+ selectors: imageSelectors,
833
+ };
834
+ const blockTypes = [ imageBlock ];
835
+ const getBlockStyles = () => [ { name: 'foo' } ];
836
+
837
+ expect( getBlockSelectors( blockTypes, getBlockStyles ) ).toEqual( {
838
+ 'core/image': {
839
+ name: imageBlock.name,
840
+ selector: imageSelectors.root,
841
+ duotoneSelector: imageSelectors.filter.duotone,
842
+ fallbackGapValue: undefined,
843
+ featureSelectors: {
844
+ root: '.my-image',
845
+ border: '.my-image img, .my-image .crop-area',
846
+ filter: { duotone: 'img' },
847
+ },
848
+ styleVariationSelectors: {
849
+ foo: '.my-image.is-style-foo',
850
+ },
851
+ hasLayoutSupport: false,
852
+ },
853
+ } );
854
+ } );
855
+
856
+ it( 'should return block selectors data with old experimental selectors', () => {
857
+ const imageSupports = {
858
+ __experimentalBorder: {
859
+ radius: true,
860
+ __experimentalSelector: 'img, .crop-area',
861
+ },
862
+ color: {
863
+ __experimentalDuotone: 'img',
864
+ },
865
+ __experimentalSelector: '.my-image',
866
+ };
867
+ const imageBlock = { name: 'core/image', supports: imageSupports };
868
+ const blockTypes = [ imageBlock ];
869
+
870
+ expect( getBlockSelectors( blockTypes, () => {} ) ).toEqual( {
871
+ 'core/image': {
872
+ name: imageBlock.name,
873
+ selector: imageSupports.__experimentalSelector,
874
+ duotoneSelector: '.my-image img',
875
+ fallbackGapValue: undefined,
876
+ featureSelectors: {
877
+ root: '.my-image',
878
+ border: '.my-image img, .my-image .crop-area',
879
+ },
880
+ hasLayoutSupport: false,
881
+ },
882
+ } );
883
+ } );
884
+ } );
885
+
886
+ describe( 'getStylesDeclarations', () => {
887
+ const blockStyles = {
888
+ spacing: {
889
+ padding: {
890
+ top: '33px',
891
+ right: '33px',
892
+ bottom: '33px',
893
+ left: '33px',
894
+ },
895
+ },
896
+ color: {
897
+ background: 'var:preset|color|light-green-cyan',
898
+ },
899
+ typography: {
900
+ fontFamily: 'sans-serif',
901
+ fontSize: '15px',
902
+ },
903
+ };
904
+
905
+ it( 'should output padding variables and other properties if useRootPaddingAwareAlignments is enabled', () => {
906
+ expect(
907
+ getStylesDeclarations( blockStyles, 'body', true )
908
+ ).toEqual( [
909
+ '--wp--style--root--padding-top: 33px',
910
+ '--wp--style--root--padding-right: 33px',
911
+ '--wp--style--root--padding-bottom: 33px',
912
+ '--wp--style--root--padding-left: 33px',
913
+ 'background-color: var(--wp--preset--color--light-green-cyan)',
914
+ 'font-family: sans-serif',
915
+ 'font-size: 15px',
916
+ ] );
917
+ } );
918
+
919
+ it( 'should output padding and other properties if useRootPaddingAwareAlignments is disabled', () => {
920
+ expect(
921
+ getStylesDeclarations( blockStyles, 'body', false )
922
+ ).toEqual( [
923
+ 'background-color: var(--wp--preset--color--light-green-cyan)',
924
+ 'padding-top: 33px',
925
+ 'padding-right: 33px',
926
+ 'padding-bottom: 33px',
927
+ 'padding-left: 33px',
928
+ 'font-family: sans-serif',
929
+ 'font-size: 15px',
930
+ ] );
931
+ } );
932
+
933
+ it( 'should not output padding variables if selector is not root', () => {
934
+ expect(
935
+ getStylesDeclarations(
936
+ blockStyles,
937
+ '.wp-block-button__link',
938
+ true
939
+ )
940
+ ).toEqual( [
941
+ 'background-color: var(--wp--preset--color--light-green-cyan)',
942
+ 'padding-top: 33px',
943
+ 'padding-right: 33px',
944
+ 'padding-bottom: 33px',
945
+ 'padding-left: 33px',
946
+ 'font-family: sans-serif',
947
+ 'font-size: 15px',
948
+ ] );
949
+ } );
950
+
951
+ it( 'should output clamp values for font-size when fluid typography is enabled', () => {
952
+ expect(
953
+ getStylesDeclarations(
954
+ blockStyles,
955
+ '.wp-block-site-title',
956
+ true,
957
+ {
958
+ settings: {
959
+ typography: {
960
+ fluid: true,
961
+ },
962
+ },
963
+ }
964
+ )
965
+ ).toEqual( [
966
+ 'background-color: var(--wp--preset--color--light-green-cyan)',
967
+ 'padding-top: 33px',
968
+ 'padding-right: 33px',
969
+ 'padding-bottom: 33px',
970
+ 'padding-left: 33px',
971
+ 'font-family: sans-serif',
972
+ 'font-size: clamp(14px, 0.875rem + ((1vw - 3.2px) * 0.078), 15px)',
973
+ ] );
974
+ } );
975
+
976
+ it( 'should output direct values for font-size when fluid typography is disabled', () => {
977
+ expect(
978
+ getStylesDeclarations(
979
+ blockStyles,
980
+ '.wp-block-site-title',
981
+ true,
982
+ {
983
+ settings: {
984
+ typography: {
985
+ fluid: false,
986
+ },
987
+ },
988
+ }
989
+ )
990
+ ).toEqual( [
991
+ 'background-color: var(--wp--preset--color--light-green-cyan)',
992
+ 'padding-top: 33px',
993
+ 'padding-right: 33px',
994
+ 'padding-bottom: 33px',
995
+ 'padding-left: 33px',
996
+ 'font-family: sans-serif',
997
+ 'font-size: 15px',
998
+ ] );
999
+ } );
1000
+
1001
+ it( 'should correctly resolve referenced values', () => {
1002
+ const stylesWithRef = {
1003
+ typography: {
1004
+ fontSize: {
1005
+ ref: 'styles.elements.h1.typography.fontSize',
1006
+ },
1007
+ letterSpacing: {
1008
+ ref: 'styles.elements.h1.typography.letterSpacing',
1009
+ },
1010
+ },
1011
+ background: {
1012
+ backgroundImage: {
1013
+ ref: 'styles.background.backgroundImage',
1014
+ },
1015
+ backgroundSize: {
1016
+ ref: 'styles.background.backgroundSize',
1017
+ },
1018
+ },
1019
+ };
1020
+ const tree = {
1021
+ styles: {
1022
+ background: {
1023
+ backgroundImage: {
1024
+ url: 'http://my-image.org/image.gif',
1025
+ },
1026
+ backgroundSize: 'cover',
1027
+ },
1028
+ elements: {
1029
+ h1: {
1030
+ typography: {
1031
+ fontSize: 'var:preset|font-size|xx-large',
1032
+ letterSpacing: '2px',
1033
+ },
1034
+ },
1035
+ },
1036
+ },
1037
+ };
1038
+ expect(
1039
+ getStylesDeclarations( stylesWithRef, '.wp-block', false, tree )
1040
+ ).toEqual( [
1041
+ 'font-size: var(--wp--preset--font-size--xx-large)',
1042
+ 'letter-spacing: 2px',
1043
+ "background-image: url( 'http://my-image.org/image.gif' )",
1044
+ 'background-size: cover',
1045
+ ] );
1046
+ } );
1047
+ it( 'should set default values for block background styles', () => {
1048
+ const backgroundStyles = {
1049
+ background: {
1050
+ backgroundImage: {
1051
+ url: 'https://wordpress.org/assets/image.jpg',
1052
+ id: 123,
1053
+ },
1054
+ },
1055
+ };
1056
+ expect(
1057
+ getStylesDeclarations( backgroundStyles, '.wp-block-group' )
1058
+ ).toEqual( [
1059
+ "background-image: url( 'https://wordpress.org/assets/image.jpg' )",
1060
+ 'background-size: cover',
1061
+ ] );
1062
+ // Test with root-level styles.
1063
+ expect(
1064
+ getStylesDeclarations( backgroundStyles, ROOT_BLOCK_SELECTOR )
1065
+ ).toEqual( [
1066
+ "background-image: url( 'https://wordpress.org/assets/image.jpg' )",
1067
+ ] );
1068
+ expect(
1069
+ getStylesDeclarations(
1070
+ {
1071
+ background: {
1072
+ ...backgroundStyles.background,
1073
+ backgroundSize: 'contain',
1074
+ },
1075
+ },
1076
+ '.wp-block-group'
1077
+ )
1078
+ ).toEqual( [
1079
+ "background-image: url( 'https://wordpress.org/assets/image.jpg' )",
1080
+ 'background-position: 50% 50%',
1081
+ 'background-size: contain',
1082
+ ] );
1083
+ } );
1084
+ } );
1085
+
1086
+ describe( 'processCSSNesting', () => {
1087
+ it( 'should return empty string when supplied css is empty', () => {
1088
+ expect( processCSSNesting( '', '.foo' ) ).toEqual( '' );
1089
+ } );
1090
+ it( 'should return processed CSS without any nested selectors', () => {
1091
+ expect(
1092
+ processCSSNesting( 'color: red; margin: auto;', '.foo' )
1093
+ ).toEqual( ':root :where(.foo){color: red; margin: auto;}' );
1094
+ } );
1095
+ it( 'should return processed CSS when there are no root selectors', () => {
1096
+ expect(
1097
+ processCSSNesting( '&::before{color: red;}', '.foo' )
1098
+ ).toEqual( ':root :where(.foo)::before{color: red;}' );
1099
+ } );
1100
+ it( 'should return processed CSS with nested selectors', () => {
1101
+ expect(
1102
+ processCSSNesting(
1103
+ 'color: red; margin: auto; &.one{color: blue;} & .two{color: green;}',
1104
+ '.foo'
1105
+ )
1106
+ ).toEqual(
1107
+ ':root :where(.foo){color: red; margin: auto;}:root :where(.foo.one){color: blue;}:root :where(.foo .two){color: green;}'
1108
+ );
1109
+ } );
1110
+ it( 'should return processed CSS with pseudo elements', () => {
1111
+ expect(
1112
+ processCSSNesting(
1113
+ 'color: red; margin: auto; &::before{color: blue;} & ::before{color: green;} &.one::before{color: yellow;} & .two::before{color: purple;} & > ::before{color: darkseagreen;}',
1114
+ '.foo'
1115
+ )
1116
+ ).toEqual(
1117
+ ':root :where(.foo){color: red; margin: auto;}:root :where(.foo)::before{color: blue;}:root :where(.foo) ::before{color: green;}:root :where(.foo.one)::before{color: yellow;}:root :where(.foo .two)::before{color: purple;}:root :where(.foo) > ::before{color: darkseagreen;}'
1118
+ );
1119
+ } );
1120
+ it( 'should return processed CSS with multiple root selectors', () => {
1121
+ expect(
1122
+ processCSSNesting(
1123
+ 'color: red; margin: auto; &.one{color: blue;} & .two{color: green;} &::before{color: yellow;} & ::before{color: purple;} &.three::before{color: orange;} & .four::before{color: skyblue;} & > ::before{color: darkseagreen;}',
1124
+ '.foo, .bar'
1125
+ )
1126
+ ).toEqual(
1127
+ ':root :where(.foo, .bar){color: red; margin: auto;}:root :where(.foo.one, .bar.one){color: blue;}:root :where(.foo .two, .bar .two){color: green;}:root :where(.foo, .bar)::before{color: yellow;}:root :where(.foo, .bar) ::before{color: purple;}:root :where(.foo.three, .bar.three)::before{color: orange;}:root :where(.foo .four, .bar .four)::before{color: skyblue;}:root :where(.foo, .bar) > ::before{color: darkseagreen;}'
1128
+ );
1129
+ } );
1130
+ } );
1131
+ } );