PluginProbe
Elementor Website Builder – more than just a page builder / 4.3.1
Elementor Website Builder – more than just a page builder v4.3.1
4.3.2 4.3.1 4.3.0 4.3.0-beta3 4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 All 455 releases
elementor / modules / atomic-widgets / css-converter / converter-registry-factory.php

converter-registry-factory.php in Elementor Website Builder – more than just a page builder 4.3.1, at modules/atomic-widgets/css-converter/converter-registry-factory.php

577 lines 21.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Elementor\Modules\AtomicWidgets\CssConverter;
4
5 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Background_Image_Converter;
6 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Rejected_Converter;
7 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Background_Layer_Field_Converter;
8 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Background_Position_Property_Converter;
9 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Box_Shadow_Property_Converter;
10 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Border_Radius_Property_Converter;
11 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Color_Property_Converter;
12 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Dimensions_Property_Converter;
13 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Filter_Property_Converter;
14 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Flex_Longhand_Converter;
15 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Flex_Property_Converter;
16 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Transform_Origin_Property_Converter;
17 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Transform_Property_Converter;
18 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Transition_Property_Converter;
19 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Noop_Converter;
20 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Number_Property_Converter;
21 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Object_Field_Merge_Converter;
22 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Object_Position_Property_Converter;
23 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Object_Side_Merge_Converter;
24 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Size_Property_Converter;
25 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\Span_Property_Converter;
26 use Elementor\Modules\AtomicWidgets\CssConverter\Converters\String_Property_Converter;
27 use Elementor\Modules\AtomicWidgets\CssConverter\ValueParsers\Size_Value_Parser;
28 use Elementor\Modules\AtomicWidgets\PropTypes\Background_Image_Overlay_Size_Scale_Prop_Type;
29 use Elementor\Modules\AtomicWidgets\PropTypes\Background_Prop_Type;
30 use Elementor\Modules\AtomicWidgets\PropTypes\Border_Radius_Prop_Type;
31 use Elementor\Modules\AtomicWidgets\PropTypes\Dimensions_Prop_Type;
32 use Elementor\Modules\AtomicWidgets\PropTypes\Border_Width_Prop_Type;
33 use Elementor\Modules\AtomicWidgets\PropTypes\Color_Prop_Type;
34 use Elementor\Modules\AtomicWidgets\PropTypes\Primitives\Number_Prop_Type;
35 use Elementor\Modules\AtomicWidgets\PropTypes\Primitives\String_Prop_Type;
36 use Elementor\Modules\AtomicWidgets\PropTypes\Size_Prop_Type;
37 use Elementor\Modules\AtomicWidgets\Styles\Style_Schema;
38 use Elementor\Modules\Variables\Services\Variables_Service;
39
40 if ( ! defined( 'ABSPATH' ) ) {
41 exit; // Exit if accessed directly.
42 }
43
44 class Converter_Registry_Factory {
45 /**
46 * Every Style_Schema property whose value is a single Size leaf (the schema prop is a Size_Prop_Type,
47 * or a Union with a Size member like `gap` — a size PropValue validates against the union). All are
48 * handled uniformly by Size_Property_Converter + Size_Value_Parser; per-property unit sets are not
49 * enforced here because Size_Prop_Type::validate accepts any all_supported_units() unit.
50 */
51 const SIZE_PROPERTIES = [
52 'width',
53 'height',
54 'min-width',
55 'min-height',
56 'max-width',
57 'max-height',
58 'inset-block-start',
59 'inset-inline-end',
60 'inset-block-end',
61 'inset-inline-start',
62 'scroll-margin-top',
63 'font-size',
64 'letter-spacing',
65 'word-spacing',
66 'column-gap',
67 'line-height',
68 'outline-width',
69 'outline-offset',
70 'opacity',
71 'gap',
72 'grid-auto-rows',
73 'grid-auto-columns',
74 ];
75
76 /**
77 * Size properties that also accept a unitless number (a multiplier, e.g. `line-height: 1.1`). The
78 * value is kept verbatim as a `custom` unit so it renders without a unit; every other size property
79 * declines a unitless non-zero value to custom_css.
80 */
81 const UNITLESS_SIZE_PROPERTIES = [
82 'line-height',
83 ];
84
85 /**
86 * Every Style_Schema property backed by a Number_Prop_Type. Handled uniformly by
87 * Number_Property_Converter (strict numeric, no units/functions).
88 */
89 const NUMBER_PROPERTIES = [
90 'z-index',
91 'column-count',
92 'order',
93 ];
94
95 /**
96 * Every Style_Schema property backed by a plain Color_Prop_Type. Handled uniformly by
97 * Color_Property_Converter (raw passthrough; any non-empty value is a valid color).
98 */
99 const COLOR_PROPERTIES = [
100 'color',
101 'border-color',
102 'outline-color',
103 ];
104
105 /**
106 * Every Style_Schema property backed by a Span_Prop_Type (grid placement). Handled uniformly by
107 * Span_Property_Converter, with the validation regex sourced from the live schema.
108 */
109 const SPAN_PROPERTIES = [
110 'grid-column',
111 'grid-row',
112 ];
113
114 /**
115 * Union props whose string member accepts a raw value (e.g. Union(String | Grid_Track_Size)). A
116 * free-string String_Property_Converter emits a `string` PropValue that validates against the union's
117 * String member, covering `1fr 1fr`, `repeat(3, 1fr)`, `minmax(...)`, named lines, etc. The structured
118 * member is intentionally not produced (raw passthrough, mirroring color). NOT wired via
119 * STRING_PROPERTIES because the schema entry is a Union and has no get_enum().
120 */
121 const STRING_PASSTHROUGH_PROPERTIES = [
122 'grid-template-columns',
123 'grid-template-rows',
124 ];
125
126 /**
127 * Box shorthands backed by Union(Dimensions | Size). Handled uniformly by
128 * Dimensions_Property_Converter (single value -> Size; 2-4 values -> logical Dimensions).
129 */
130 const DIMENSIONS_PROPERTIES = [
131 'padding',
132 'margin',
133 ];
134
135 /**
136 * Props that each own a bespoke single-property converter (no shared family). Listed here for the
137 * covered set; each is wired explicitly in real_converters() (unlike the family arrays above, the
138 * members do not share a converter class, so there is no uniform loop). Distinct from
139 * NOOP_PROPERTIES, which have no real converter yet.
140 *
141 * - border-radius: Union(Border_Radius | Size); single value -> Size, 2-4 values -> logical
142 * Border_Radius. Elliptical "/" values decline to custom_css (no two-radii-per-corner shape).
143 * - border-width: Union(Border_Width | Size); shares the four logical sides with the Dimensions
144 * shorthand, so it reuses Dimensions_Property_Converter with the Border_Width wrapper injected.
145 */
146 const OTHER_PROPERTIES = [
147 'border-radius',
148 'border-width',
149 'object-position',
150 'flex',
151 'transition',
152 'transform',
153 'transform-origin',
154 'box-shadow',
155 ];
156
157 /**
158 * Scalar background longhands that each fill one field of the aggregate `background` object. Not
159 * Style_Schema properties (the schema only has the `background` aggregate); they are accumulated into
160 * it by Object_Field_Merge_Converter, wired explicitly in real_converters() so each field's leaf prop
161 * type / enum is sourced from the live schema. The overlay array (image/gradient layers) is separate.
162 */
163 const BACKGROUND_FIELD_PROPERTIES = [
164 'background-color',
165 'background-clip',
166 ];
167
168 /**
169 * Background overlay longhands that are not Style_Schema properties. `background-image` creates the
170 * image layer array in the aggregate; the rest update fields on existing layers via
171 * Background_Layer_Field_Converter. Enums are hardcoded to match the background-image-overlay shape
172 * without needing to instantiate the prop type (which would require WP for image sizes).
173 */
174 const BACKGROUND_LAYER_PROPERTIES = [
175 'background-image',
176 'background-repeat',
177 'background-attachment',
178 'background-size',
179 'background-position',
180 ];
181
182 const BACKGROUND_REPEAT_ENUM = [ 'repeat', 'repeat-x', 'repeat-y', 'no-repeat' ];
183 const BACKGROUND_ATTACHMENT_ENUM = [ 'fixed', 'scroll' ];
184 const BACKGROUND_SIZE_ENUM = [ 'auto', 'cover', 'contain' ];
185
186 /**
187 * Logical side keys of the Border_Width / Dimensions objects, and corner keys of the Border_Radius
188 * object, in the order used to seed every side/corner from a single Size.
189 */
190 const BORDER_WIDTH_SIDE_KEYS = [ 'block-start', 'inline-end', 'block-end', 'inline-start' ];
191 const BORDER_RADIUS_CORNER_KEYS = [ 'start-start', 'start-end', 'end-end', 'end-start' ];
192
193 /**
194 * Physical padding/margin longhands -> [ target schema prop, logical side key ].
195 * Not Style_Schema properties themselves; accumulated into the schema aggregate by
196 * Object_Side_Merge_Converter (same pattern as border_side_specs()).
197 */
198 const DIMENSIONS_SIDE_SPECS = [
199 'padding-top' => [ 'padding', 'block-start' ],
200 'padding-right' => [ 'padding', 'inline-end' ],
201 'padding-bottom' => [ 'padding', 'block-end' ],
202 'padding-left' => [ 'padding', 'inline-start' ],
203 'padding-block-start' => [ 'padding', 'block-start' ],
204 'padding-block-end' => [ 'padding', 'block-end' ],
205 'padding-inline-start' => [ 'padding', 'inline-start' ],
206 'padding-inline-end' => [ 'padding', 'inline-end' ],
207 'margin-top' => [ 'margin', 'block-start' ],
208 'margin-right' => [ 'margin', 'inline-end' ],
209 'margin-bottom' => [ 'margin', 'block-end' ],
210 'margin-left' => [ 'margin', 'inline-start' ],
211 'margin-block-start' => [ 'margin', 'block-start' ],
212 'margin-block-end' => [ 'margin', 'block-end' ],
213 'margin-inline-start' => [ 'margin', 'inline-start' ],
214 'margin-inline-end' => [ 'margin', 'inline-end' ],
215 ];
216
217 /**
218 * Flex longhands that each contribute one field to the aggregate `flex` prop
219 * (Flex_Prop_Type). Not Style_Schema properties themselves; accumulated into
220 * the schema aggregate by Flex_Longhand_Converter.
221 *
222 * @return array<string, string> input property -> Flex_Prop_Type field key
223 */
224 public static function flex_longhand_specs(): array {
225 return [
226 'flex-grow' => 'flexGrow',
227 'flex-shrink' => 'flexShrink',
228 'flex-basis' => 'flexBasis',
229 ];
230 }
231
232 /**
233 * CSS-wide keywords accepted as `custom` size values for flex-basis. The UI exposes a free
234 * "custom" input for flex-basis, so these are stored verbatim as {size: "<keyword>", unit: "custom"}.
235 */
236 const FLEX_BASIS_CUSTOM_KEYWORDS = [ 'initial', 'inherit', 'unset', 'revert', 'revert-layer' ];
237
238 /**
239 * Filter-function lists backed by Array(Css_Filter_Func) (filter, backdrop-filter). Handled
240 * uniformly by Filter_Property_Converter + Filter_Value_Parser; the two share inner items and
241 * differ only by the wrapping $$type, which is sourced from the live schema.
242 */
243 const FILTER_PROPERTIES = [
244 'filter',
245 'backdrop-filter',
246 ];
247
248 /**
249 * Hardcoded Style_Schema properties with no real converter yet (objects, unions, shorthands). They
250 * still get a Noop_Converter so they keep routing to custom_css. Combined with the real-converter
251 * families via covered_properties() to form the exhaustive covered set. Intentionally NOT derived
252 * from Style_Schema: a coverage test diffs the live schema against the covered set so adding a schema
253 * property without coverage fails CI until it is added here.
254 */
255 const NOOP_PROPERTIES = [
256 // SVG-only family. The editor UI does not expose stroke controls, so there is no
257 // LLM-facing use case worth converting. All stroke-* longhands are listed explicitly
258 // (rather than relying on silent fallthrough) so the intent is "preserve verbatim in
259 // customCss by-design", not "forgot to wire". `stroke` itself is the only top-level
260 // Style_Schema entry; the longhands are not in the schema and only need coverage here.
261 'stroke',
262 'stroke-width',
263 'stroke-opacity',
264 'stroke-dasharray',
265 'stroke-dashoffset',
266 'stroke-linecap',
267 'stroke-linejoin',
268 'stroke-miterlimit',
269 // Last-resort fallback for `background` values the shorthand expander cannot decompose
270 // (e.g. exotic syntax). The expander handles the common forms; this entry keeps the
271 // raw declaration in customCss when expansion fails.
272 'background',
273 ];
274
275 /**
276 * Properties that are structurally incompatible with Elementor's inline style system.
277 * They are explicitly rejected (not routed to customCss) so the client can surface a
278 * hint to the LLM that these constructs are unsupported in element style definitions.
279 *
280 * `animation` and its longhands rely on @keyframes which cannot be declared inline.
281 */
282 const REJECTED_PROPERTIES = [
283 'animation',
284 'animation-name',
285 'animation-duration',
286 'animation-timing-function',
287 'animation-delay',
288 'animation-iteration-count',
289 'animation-direction',
290 'animation-fill-mode',
291 'animation-play-state',
292 ];
293
294 /**
295 * Every Style_Schema property backed by a plain String_Prop_Type. Enum-backed and free-string
296 * props are handled the same way: get_enum() returns the allowlist (enum props) or null
297 * (free-string props), so the allowlist is always sourced from the schema, never duplicated.
298 */
299 const STRING_PROPERTIES = [
300 'overflow',
301 'aspect-ratio',
302 'object-fit',
303 'position',
304 'font-family',
305 'font-weight',
306 'text-align',
307 'font-style',
308 'text-decoration',
309 'text-transform',
310 'direction',
311 'all',
312 'cursor',
313 'border-style',
314 'outline-style',
315 'mix-blend-mode',
316 'display',
317 'flex-direction',
318 'flex-wrap',
319 'grid-auto-flow',
320 'justify-content',
321 'justify-items',
322 'align-content',
323 'align-items',
324 'align-self',
325 'content',
326 'appearance',
327 'clip-path',
328 ];
329
330 /**
331 * The exhaustive covered set: every family with a real converter plus the remaining no-ops. Single
332 * source of truth for the coverage test, with no property listed twice.
333 *
334 * @return string[]
335 */
336 public static function covered_properties(): array {
337 return array_merge(
338 self::STRING_PROPERTIES,
339 self::SIZE_PROPERTIES,
340 self::NUMBER_PROPERTIES,
341 self::COLOR_PROPERTIES,
342 self::SPAN_PROPERTIES,
343 self::STRING_PASSTHROUGH_PROPERTIES,
344 self::DIMENSIONS_PROPERTIES,
345 self::FILTER_PROPERTIES,
346 self::OTHER_PROPERTIES,
347 array_keys( self::border_side_specs() ),
348 array_keys( self::flex_longhand_specs() ),
349 self::BACKGROUND_FIELD_PROPERTIES,
350 self::BACKGROUND_LAYER_PROPERTIES,
351 self::NOOP_PROPERTIES,
352 self::REJECTED_PROPERTIES
353 );
354 }
355
356 /**
357 * Per-side/per-corner border longhands that each contribute one fragment to an aggregate object prop
358 * (border-width / border-radius), keyed by input property -> [ target prop, object key ]. These are
359 * not Style_Schema properties; they are accumulated into the schema aggregate by
360 * Object_Side_Merge_Converter. Per-side style/color have no faithful single-valued representation, so
361 * they are intentionally absent and route to custom_css.
362 *
363 * @return array<string, array{0: string, 1: string}>
364 */
365 public static function border_side_specs(): array {
366 return [
367 'border-top-width' => [ 'border-width', 'block-start' ],
368 'border-right-width' => [ 'border-width', 'inline-end' ],
369 'border-bottom-width' => [ 'border-width', 'block-end' ],
370 'border-left-width' => [ 'border-width', 'inline-start' ],
371 'border-top-left-radius' => [ 'border-radius', 'start-start' ],
372 'border-top-right-radius' => [ 'border-radius', 'start-end' ],
373 'border-bottom-right-radius' => [ 'border-radius', 'end-end' ],
374 'border-bottom-left-radius' => [ 'border-radius', 'end-start' ],
375 'border-start-start-radius' => [ 'border-radius', 'start-start' ],
376 'border-start-end-radius' => [ 'border-radius', 'start-end' ],
377 'border-end-end-radius' => [ 'border-radius', 'end-end' ],
378 'border-end-start-radius' => [ 'border-radius', 'end-start' ],
379 ];
380 }
381
382 public static function create( ?Variables_Service $variables_service = null ): Converter_Registry {
383 $registry = new Converter_Registry();
384 $real_converters = self::real_converters( $variables_service );
385
386 foreach ( $real_converters as $converter ) {
387 $registry->register( $converter );
388 }
389
390 foreach ( self::REJECTED_PROPERTIES as $property ) {
391 $registry->register( new Rejected_Converter( $property ) );
392 }
393
394 foreach ( self::covered_properties() as $property ) {
395 if ( isset( $real_converters[ $property ] ) ) {
396 continue;
397 }
398
399 if ( in_array( $property, self::REJECTED_PROPERTIES, true ) ) {
400 continue;
401 }
402
403 $registry->register( new Noop_Converter( $property ) );
404 }
405
406 return $registry;
407 }
408
409 /**
410 * Real converters keyed by the property they own. Every remaining covered_properties() entry
411 * falls back to a Noop_Converter, so the "exactly one converter per property" invariant holds.
412 * Enum allowlists are sourced from the live Style_Schema to avoid duplicating (and drifting from)
413 * the schema's enums.
414 *
415 * @return array<string, \Elementor\Modules\AtomicWidgets\CssConverter\Property_Converter>
416 */
417 private static function real_converters( ?Variables_Service $variables_service = null ): array {
418 $schema = Style_Schema::get_style_schema();
419 $converters = [];
420
421 foreach ( self::STRING_PROPERTIES as $property ) {
422 $converters[ $property ] = new String_Property_Converter( $property, $schema[ $property ]->get_enum(), $schema[ $property ]->get_key() );
423 }
424
425 foreach ( self::SIZE_PROPERTIES as $property ) {
426 $allow_unitless = in_array( $property, self::UNITLESS_SIZE_PROPERTIES, true );
427 $converters[ $property ] = new Size_Property_Converter( $property, $allow_unitless );
428 }
429
430 foreach ( self::NUMBER_PROPERTIES as $property ) {
431 $converters[ $property ] = new Number_Property_Converter( $property );
432 }
433
434 foreach ( self::COLOR_PROPERTIES as $property ) {
435 $converters[ $property ] = new Color_Property_Converter( $property );
436 }
437
438 foreach ( self::SPAN_PROPERTIES as $property ) {
439 $converters[ $property ] = new Span_Property_Converter( $property, $schema[ $property ]->get_regex() );
440 }
441
442 foreach ( self::STRING_PASSTHROUGH_PROPERTIES as $property ) {
443 $converters[ $property ] = new String_Property_Converter( $property );
444 }
445
446 foreach ( self::DIMENSIONS_PROPERTIES as $property ) {
447 $converters[ $property ] = new Dimensions_Property_Converter( $property );
448 }
449
450 $converters['border-radius'] = new Border_Radius_Property_Converter( 'border-radius' );
451 $converters['border-width'] = new Dimensions_Property_Converter( 'border-width', Border_Width_Prop_Type::class );
452 $converters['object-position'] = new Object_Position_Property_Converter();
453 $converters['flex'] = new Flex_Property_Converter();
454
455 $converters['flex-grow'] = new Flex_Longhand_Converter(
456 'flex-grow',
457 'flexGrow',
458 static function ( string $v ): ?array {
459 if ( ! is_numeric( $v ) ) {
460 return null;
461 }
462 return Number_Prop_Type::generate( (float) $v );
463 }
464 );
465
466 $converters['flex-shrink'] = new Flex_Longhand_Converter(
467 'flex-shrink',
468 'flexShrink',
469 static function ( string $v ): ?array {
470 if ( ! is_numeric( $v ) ) {
471 return null;
472 }
473 return Number_Prop_Type::generate( (float) $v );
474 }
475 );
476
477 $converters['flex-basis'] = new Flex_Longhand_Converter(
478 'flex-basis',
479 'flexBasis',
480 static function ( string $v ): ?array {
481 if ( in_array( strtolower( $v ), self::FLEX_BASIS_CUSTOM_KEYWORDS, true ) ) {
482 return Size_Prop_Type::generate( [
483 'size' => $v,
484 'unit' => 'custom',
485 ] );
486 }
487 $parsed = Size_Value_Parser::parse( $v );
488 return null !== $parsed ? Size_Prop_Type::generate( $parsed ) : null;
489 }
490 );
491 $converters['transition'] = new Transition_Property_Converter();
492 $converters['transform'] = new Transform_Property_Converter();
493 $converters['transform-origin'] = new Transform_Origin_Property_Converter();
494 $converters['box-shadow'] = new Box_Shadow_Property_Converter();
495
496 foreach ( self::DIMENSIONS_SIDE_SPECS as $property => [ $target, $side_key ] ) {
497 $converters[ $property ] = new Object_Side_Merge_Converter(
498 $property,
499 $target,
500 Dimensions_Prop_Type::get_key(),
501 $side_key,
502 self::BORDER_WIDTH_SIDE_KEYS,
503 Dimensions_Prop_Type::class,
504 $variables_service
505 );
506 }
507
508 foreach ( self::border_side_specs() as $property => [ $target, $side_key ] ) {
509 $is_radius = 'border-radius' === $target;
510 $prop_type_class = $is_radius ? Border_Radius_Prop_Type::class : Border_Width_Prop_Type::class;
511
512 $converters[ $property ] = new Object_Side_Merge_Converter(
513 $property,
514 $target,
515 $prop_type_class::get_key(),
516 $side_key,
517 $is_radius ? self::BORDER_RADIUS_CORNER_KEYS : self::BORDER_WIDTH_SIDE_KEYS,
518 $prop_type_class,
519 $variables_service
520 );
521 }
522
523 foreach ( self::FILTER_PROPERTIES as $property ) {
524 $converters[ $property ] = new Filter_Property_Converter( $property, $schema[ $property ]->get_key() );
525 }
526
527 $background_key = Background_Prop_Type::get_key();
528
529 $converters['background-color'] = new Object_Field_Merge_Converter(
530 'background-color',
531 $background_key,
532 $background_key,
533 'color',
534 Color_Prop_Type::class,
535 Background_Prop_Type::class,
536 null,
537 true
538 );
539
540 $converters['background-clip'] = new Object_Field_Merge_Converter(
541 'background-clip',
542 $background_key,
543 $background_key,
544 'clip',
545 String_Prop_Type::class,
546 Background_Prop_Type::class,
547 $schema[ $background_key ]->get_shape_field( 'clip' )->get_enum()
548 );
549
550 $converters['background-image'] = new Background_Image_Converter();
551
552 $converters['background-repeat'] = new Background_Layer_Field_Converter(
553 'background-repeat',
554 'repeat',
555 self::BACKGROUND_REPEAT_ENUM
556 );
557
558 $converters['background-attachment'] = new Background_Layer_Field_Converter(
559 'background-attachment',
560 'attachment',
561 self::BACKGROUND_ATTACHMENT_ENUM
562 );
563
564 $converters['background-size'] = new Background_Layer_Field_Converter(
565 'background-size',
566 'size',
567 self::BACKGROUND_SIZE_ENUM,
568 Background_Image_Overlay_Size_Scale_Prop_Type::class,
569 [ 'width', 'height' ]
570 );
571
572 $converters['background-position'] = new Background_Position_Property_Converter();
573
574 return $converters;
575 }
576 }
577