@elementor/editor-canvas 0.6.1 → 0.7.1
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.
- package/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +48 -0
- package/dist/index.js +147 -98
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +150 -99
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -9
- package/src/__tests__/init-styles-renderer.test.ts +26 -12
- package/src/init-styles-renderer.ts +26 -6
- package/src/styles-renderer/__tests__/__mocks__/styles-schema.ts +40 -1
- package/src/styles-renderer/__tests__/enqueue-used-fonts.test.ts +8 -2
- package/src/styles-renderer/__tests__/index.test.ts +113 -47
- package/src/styles-renderer/enqueue-used-fonts.ts +4 -3
- package/src/styles-renderer/errors.ts +6 -0
- package/src/styles-renderer/render.ts +69 -68
- package/src/styles-renderer/resolve.ts +28 -24
- package/src/styles-renderer/transformers/background-image-overlay-transformer.ts +23 -3
- package/src/styles-renderer/transformers/dimensions.ts +1 -1
- package/src/styles-renderer/transformers/image-attachment.ts +14 -0
- package/src/styles-renderer/transformers/image-src.ts +11 -0
- package/src/styles-renderer/transformers/index.ts +8 -2
- package/src/styles-renderer/transformers/{gap-transformer.ts → layout-direction-transformer.ts} +3 -3
- package/src/styles-renderer/types.ts +11 -1
- package/src/styles-renderer/get-styles-schema.ts +0 -17
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
import { type Props } from '@elementor/editor-props';
|
|
2
|
-
import { type Breakpoint, type
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
import { type Breakpoint, type BreakpointsMap } from '@elementor/editor-responsive';
|
|
3
|
+
import {
|
|
4
|
+
getStylesSchema,
|
|
5
|
+
type StyleDefinition,
|
|
6
|
+
type StyleDefinitionState,
|
|
7
|
+
type StyleDefinitionType,
|
|
8
|
+
} from '@elementor/editor-styles';
|
|
9
|
+
|
|
10
|
+
import { UnknownStyleTypeError } from './errors';
|
|
7
11
|
import { resolve } from './resolve';
|
|
8
12
|
import { type TransformersMap } from './types';
|
|
9
13
|
|
|
@@ -11,81 +15,87 @@ type RenderParams = {
|
|
|
11
15
|
transformers: TransformersMap;
|
|
12
16
|
styles: StyleDefinition[];
|
|
13
17
|
breakpoints: BreakpointsMap;
|
|
18
|
+
selectorPrefix?: string;
|
|
19
|
+
signal?: AbortSignal;
|
|
14
20
|
};
|
|
15
21
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
try {
|
|
20
|
-
styles.forEach( ( styleDef ) => {
|
|
21
|
-
const style = renderStyle( styleDef, transformers, breakpoints );
|
|
22
|
+
const SELECTORS_MAP: Record< StyleDefinitionType, string > = {
|
|
23
|
+
class: '.',
|
|
24
|
+
};
|
|
22
25
|
|
|
23
|
-
|
|
26
|
+
export default async function render( {
|
|
27
|
+
transformers,
|
|
28
|
+
styles,
|
|
29
|
+
breakpoints,
|
|
30
|
+
selectorPrefix = '',
|
|
31
|
+
signal,
|
|
32
|
+
}: RenderParams ) {
|
|
33
|
+
const stylesCssPromises = styles.map( async ( style ) => {
|
|
34
|
+
const variantCssPromises = Object.values( style.variants ).map( async ( variant ) => {
|
|
35
|
+
const css = await propsToCss( variant.props, transformers, signal );
|
|
36
|
+
|
|
37
|
+
return createStyleWrapper()
|
|
38
|
+
.forStyle( style )
|
|
39
|
+
.withPrefix( selectorPrefix )
|
|
40
|
+
.withState( variant.meta.state )
|
|
41
|
+
.withMediaQuery( variant.meta.breakpoint ? breakpoints[ variant.meta.breakpoint ] : null )
|
|
42
|
+
.wrap( css );
|
|
24
43
|
} );
|
|
25
|
-
} catch ( error: unknown ) {
|
|
26
|
-
// eslint-disable-next-line no-console
|
|
27
|
-
console.error( `Cannot render style': ${ ensureError( error ).message }` );
|
|
28
|
-
}
|
|
29
44
|
|
|
30
|
-
|
|
31
|
-
}
|
|
45
|
+
const variantsCss = await Promise.all( variantCssPromises );
|
|
32
46
|
|
|
33
|
-
|
|
34
|
-
|
|
47
|
+
return wrapCssWithStyleElement( style.id, variantsCss.join( '' ) );
|
|
48
|
+
} );
|
|
35
49
|
|
|
36
|
-
|
|
37
|
-
return '';
|
|
38
|
-
}
|
|
50
|
+
const stylesCss = await Promise.all( stylesCssPromises );
|
|
39
51
|
|
|
40
|
-
|
|
52
|
+
return stylesCss.join( '' );
|
|
53
|
+
}
|
|
41
54
|
|
|
42
|
-
|
|
43
|
-
|
|
55
|
+
function createStyleWrapper( value: string = '', wrapper?: ( css: string ) => string ) {
|
|
56
|
+
return {
|
|
57
|
+
forStyle: ( { id, type }: StyleDefinition ) => {
|
|
58
|
+
const symbol = SELECTORS_MAP[ type ];
|
|
44
59
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
} );
|
|
60
|
+
if ( ! symbol ) {
|
|
61
|
+
throw new UnknownStyleTypeError( { context: { type } } );
|
|
62
|
+
}
|
|
49
63
|
|
|
50
|
-
|
|
51
|
-
}
|
|
64
|
+
return createStyleWrapper( `${ value }${ symbol }${ id }`, wrapper );
|
|
65
|
+
},
|
|
52
66
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
class: '.',
|
|
56
|
-
};
|
|
67
|
+
withPrefix: ( prefix: string ) =>
|
|
68
|
+
createStyleWrapper( [ prefix, value ].filter( Boolean ).join( ' ' ), wrapper ),
|
|
57
69
|
|
|
58
|
-
|
|
59
|
-
}
|
|
70
|
+
withState: ( state: StyleDefinitionState ) =>
|
|
71
|
+
createStyleWrapper( state ? `${ value }:${ state }` : value, wrapper ),
|
|
60
72
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
breakpoints: BreakpointsMap
|
|
66
|
-
) {
|
|
67
|
-
const css = propsToCss( variant.props, transformers );
|
|
73
|
+
withMediaQuery: ( breakpoint: Breakpoint | null ) => {
|
|
74
|
+
if ( ! breakpoint?.type ) {
|
|
75
|
+
return createStyleWrapper( value, wrapper );
|
|
76
|
+
}
|
|
68
77
|
|
|
69
|
-
|
|
70
|
-
return '';
|
|
71
|
-
}
|
|
78
|
+
const size = `${ breakpoint.type }:${ breakpoint.width }px`;
|
|
72
79
|
|
|
73
|
-
|
|
74
|
-
|
|
80
|
+
return createStyleWrapper( value, ( css ) => `@media(${ size }){${ css }}` );
|
|
81
|
+
},
|
|
75
82
|
|
|
76
|
-
|
|
83
|
+
wrap: ( css: string ) => {
|
|
84
|
+
const res = `${ value }{${ css }}`;
|
|
77
85
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
86
|
+
if ( ! wrapper ) {
|
|
87
|
+
return res;
|
|
88
|
+
}
|
|
81
89
|
|
|
82
|
-
|
|
90
|
+
return wrapper( res );
|
|
91
|
+
},
|
|
92
|
+
};
|
|
83
93
|
}
|
|
84
94
|
|
|
85
|
-
function propsToCss( props: Props, transformers: TransformersMap )
|
|
95
|
+
async function propsToCss( props: Props, transformers: TransformersMap, signal?: AbortSignal ) {
|
|
86
96
|
const schema = getStylesSchema();
|
|
87
97
|
|
|
88
|
-
const transformed = resolve( { props, schema, transformers } );
|
|
98
|
+
const transformed = await resolve( { props, schema, transformers, signal } );
|
|
89
99
|
|
|
90
100
|
return Object.entries( transformed )
|
|
91
101
|
.reduce< string[] >( ( acc, [ propName, propValue ] ) => {
|
|
@@ -96,15 +106,6 @@ function propsToCss( props: Props, transformers: TransformersMap ): string {
|
|
|
96
106
|
.join( '' );
|
|
97
107
|
}
|
|
98
108
|
|
|
99
|
-
function
|
|
100
|
-
|
|
101
|
-
return size ? `@media(${ size }){${ css }}` : css;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function getBreakpointSize( breakpoint: Breakpoint ) {
|
|
105
|
-
return breakpoint.type ? `${ breakpoint.type }:${ breakpoint.width }px` : null;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function wrapWithStyleElement( id: string, content: string ) {
|
|
109
|
-
return `<style data-style-id="${ id }">${ content }</style>`;
|
|
109
|
+
function wrapCssWithStyleElement( id: string, css: string ) {
|
|
110
|
+
return `<style data-style-id="${ id }">${ css }</style>`;
|
|
110
111
|
}
|
|
@@ -10,38 +10,39 @@ type ResolveArgs = {
|
|
|
10
10
|
props: Props;
|
|
11
11
|
schema: PropsSchema;
|
|
12
12
|
transformers: TransformersMap;
|
|
13
|
+
signal?: AbortSignal;
|
|
13
14
|
};
|
|
14
15
|
|
|
15
|
-
export function resolve( { props, schema, transformers }: ResolveArgs ) {
|
|
16
|
-
const
|
|
16
|
+
export async function resolve( { props, schema, transformers, signal }: ResolveArgs ) {
|
|
17
|
+
const promises = Promise.all(
|
|
18
|
+
Object.entries( schema ).map( async ( [ propKey, propType ] ) => {
|
|
19
|
+
const value = props[ propKey ] ?? propType.default;
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
const value = props[ key ] ?? propType.default;
|
|
21
|
+
const transformed = await transform( value, propKey, propType, transformers, 0, signal );
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
if ( transformed === null ) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
22
26
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
if ( isMultiProps( transformed ) ) {
|
|
28
|
-
Object.assign( resolved, getMultiPropsValue( transformed ) );
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
27
|
+
if ( isMultiProps( transformed ) ) {
|
|
28
|
+
return getMultiPropsValue( transformed );
|
|
29
|
+
}
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
return { [ propKey ]: transformed };
|
|
32
|
+
} )
|
|
33
|
+
);
|
|
34
34
|
|
|
35
|
-
return
|
|
35
|
+
return Object.assign( {}, ...( await promises ).filter( Boolean ) );
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
function transform(
|
|
38
|
+
async function transform(
|
|
39
39
|
value: PropValue,
|
|
40
40
|
propKey: PropKey,
|
|
41
41
|
propType: PropType,
|
|
42
42
|
transformers: TransformersMap,
|
|
43
|
-
depth: number = 0
|
|
44
|
-
|
|
43
|
+
depth: number = 0,
|
|
44
|
+
signal?: AbortSignal
|
|
45
|
+
): Promise< unknown > {
|
|
45
46
|
if ( ! value && value !== 0 ) {
|
|
46
47
|
return null;
|
|
47
48
|
}
|
|
@@ -70,16 +71,19 @@ function transform(
|
|
|
70
71
|
let resolvedValue = value.value;
|
|
71
72
|
|
|
72
73
|
if ( propType.kind === 'object' ) {
|
|
73
|
-
resolvedValue = resolve( {
|
|
74
|
+
resolvedValue = await resolve( {
|
|
74
75
|
transformers,
|
|
75
76
|
props: resolvedValue,
|
|
76
77
|
schema: propType.shape,
|
|
78
|
+
signal,
|
|
77
79
|
} );
|
|
78
80
|
}
|
|
79
81
|
|
|
80
82
|
if ( propType.kind === 'array' ) {
|
|
81
|
-
resolvedValue =
|
|
82
|
-
|
|
83
|
+
resolvedValue = await Promise.all(
|
|
84
|
+
resolvedValue.map( ( item: PropValue ) =>
|
|
85
|
+
transform( item, propKey, propType.item_prop_type, transformers, depth, signal )
|
|
86
|
+
)
|
|
83
87
|
);
|
|
84
88
|
}
|
|
85
89
|
|
|
@@ -90,9 +94,9 @@ function transform(
|
|
|
90
94
|
}
|
|
91
95
|
|
|
92
96
|
try {
|
|
93
|
-
const transformed = transformer( resolvedValue, propKey );
|
|
97
|
+
const transformed = await transformer( resolvedValue, { key: propKey, signal } );
|
|
94
98
|
|
|
95
|
-
return transform( transformed, propKey, propType, transformers, depth + 1 );
|
|
99
|
+
return transform( transformed, propKey, propType, transformers, depth + 1, signal );
|
|
96
100
|
} catch {
|
|
97
101
|
return null;
|
|
98
102
|
}
|
|
@@ -2,10 +2,30 @@ import { type BackgroundImageOverlayPropValue } from '@elementor/editor-props';
|
|
|
2
2
|
|
|
3
3
|
import { type Transformer } from '../types';
|
|
4
4
|
|
|
5
|
-
export const
|
|
5
|
+
export const defaultPositionValue = '0% 0%';
|
|
6
6
|
|
|
7
|
-
const backgroundImageOverlayTransformer: Transformer< BackgroundImageOverlayPropValue > = () => {
|
|
8
|
-
|
|
7
|
+
const backgroundImageOverlayTransformer: Transformer< BackgroundImageOverlayPropValue[ 'value' ] > = ( value ) => {
|
|
8
|
+
const { 'image-src': imageSrc, size = null, position = null, repeat = null, attachment = null } = value;
|
|
9
|
+
|
|
10
|
+
let resultBackgroundStyle = imageSrc;
|
|
11
|
+
|
|
12
|
+
if ( repeat ) {
|
|
13
|
+
resultBackgroundStyle += ` ${ repeat }`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
if ( attachment ) {
|
|
17
|
+
resultBackgroundStyle += ` ${ attachment }`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if ( position && ! size ) {
|
|
21
|
+
resultBackgroundStyle += ` ${ position }`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if ( size ) {
|
|
25
|
+
resultBackgroundStyle += ` ${ position || defaultPositionValue } / ${ size }`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return resultBackgroundStyle;
|
|
9
29
|
};
|
|
10
30
|
|
|
11
31
|
export default backgroundImageOverlayTransformer;
|
|
@@ -5,7 +5,7 @@ import { type Transformer } from '../types';
|
|
|
5
5
|
|
|
6
6
|
const validKeys = [ 'top', 'right', 'bottom', 'left' ];
|
|
7
7
|
|
|
8
|
-
const dimensions: Transformer< DimensionsPropValue[ 'value' ] > = ( value, key ) => {
|
|
8
|
+
const dimensions: Transformer< DimensionsPropValue[ 'value' ] > = ( value, { key } ) => {
|
|
9
9
|
const parsed = Object.entries( value ).reduce< Props >( ( acc, [ dimensionKey, dimensionValue ] ) => {
|
|
10
10
|
if ( dimensionValue && validKeys.includes( dimensionKey ) ) {
|
|
11
11
|
acc[ `${ key }-${ dimensionKey }` ] = dimensionValue;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ImageSrcPropValue } from '@elementor/editor-props';
|
|
2
|
+
import { getMediaAttachment } from '@elementor/wp-media';
|
|
3
|
+
|
|
4
|
+
import { type Transformer } from '../types';
|
|
5
|
+
|
|
6
|
+
export const imageAttachmentTransformer: Transformer< ImageSrcPropValue[ 'value' ][ 'id' ] > = async ( value ) => {
|
|
7
|
+
const attachment = await getMediaAttachment( { id: value } );
|
|
8
|
+
|
|
9
|
+
if ( ! attachment ) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return attachment.url;
|
|
14
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ImageSrcPropValue } from '@elementor/editor-props';
|
|
2
|
+
|
|
3
|
+
import { type Transformer } from '../types';
|
|
4
|
+
|
|
5
|
+
export const imageSrcTransformer: Transformer< ImageSrcPropValue[ 'value' ] > = ( value ) => {
|
|
6
|
+
const url = value.id ?? value.url?.value;
|
|
7
|
+
|
|
8
|
+
if ( url ) {
|
|
9
|
+
return `url(${ url })`;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
@@ -6,7 +6,9 @@ import { default as createCombineArrayTransformer } from './create-combine-array
|
|
|
6
6
|
import createCornerSizesTransformer from './create-corner-sizes-transformer';
|
|
7
7
|
import createEdgeSizesTransformer from './create-edge-sizes-transformer';
|
|
8
8
|
import { default as dimensions } from './dimensions';
|
|
9
|
-
import {
|
|
9
|
+
import { imageAttachmentTransformer } from './image-attachment';
|
|
10
|
+
import { imageSrcTransformer } from './image-src';
|
|
11
|
+
import { default as layoutDirection } from './layout-direction-transformer';
|
|
10
12
|
import { primitiveTransformer } from './primitive-transformer';
|
|
11
13
|
import { default as shadow } from './shadow-transformer';
|
|
12
14
|
import { default as size } from './size-transformer';
|
|
@@ -16,7 +18,6 @@ export default {
|
|
|
16
18
|
size,
|
|
17
19
|
shadow,
|
|
18
20
|
stroke,
|
|
19
|
-
gap,
|
|
20
21
|
background,
|
|
21
22
|
|
|
22
23
|
color: primitiveTransformer,
|
|
@@ -32,4 +33,9 @@ export default {
|
|
|
32
33
|
|
|
33
34
|
'border-width': createEdgeSizesTransformer( ( edgeKey ) => `border-${ edgeKey }-width` ),
|
|
34
35
|
'border-radius': createCornerSizesTransformer( ( cornerKey ) => `border-${ cornerKey }-radius` ),
|
|
36
|
+
|
|
37
|
+
'image-attachment-id': imageAttachmentTransformer,
|
|
38
|
+
'image-src': imageSrcTransformer,
|
|
39
|
+
|
|
40
|
+
'layout-direction': layoutDirection,
|
|
35
41
|
} satisfies TransformersMap;
|
package/src/styles-renderer/transformers/{gap-transformer.ts → layout-direction-transformer.ts}
RENAMED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type LayoutDirectionPropValue, type Props } from '@elementor/editor-props';
|
|
2
2
|
|
|
3
3
|
import { createMultiPropsValue } from '../multi-props';
|
|
4
4
|
import { type Transformer } from '../types';
|
|
5
5
|
|
|
6
6
|
const validKeys = [ 'row', 'column' ];
|
|
7
7
|
|
|
8
|
-
const
|
|
8
|
+
const layoutDirectionTransformer: Transformer< LayoutDirectionPropValue[ 'value' ] > = ( value, { key } ) => {
|
|
9
9
|
const parsed = Object.entries( value ).reduce< Props >( ( acc, [ dimensionKey, dimensionValue ] ) => {
|
|
10
10
|
if ( dimensionValue && validKeys.includes( dimensionKey ) ) {
|
|
11
11
|
acc[ `${ dimensionKey }-${ key }` ] = dimensionValue;
|
|
@@ -17,4 +17,4 @@ const gapTransformer: Transformer< GapPropValue[ 'value' ] > = ( value, key ) =>
|
|
|
17
17
|
return createMultiPropsValue( parsed );
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
export default
|
|
20
|
+
export default layoutDirectionTransformer;
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
import { type PropValue } from '@elementor/editor-props';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
type TransformerOptions = {
|
|
4
|
+
key: string;
|
|
5
|
+
signal?: AbortSignal;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
type MaybePromise< T > = T | Promise< T >;
|
|
9
|
+
|
|
10
|
+
export type Transformer< TValue extends PropValue > = (
|
|
11
|
+
value: TValue,
|
|
12
|
+
options: TransformerOptions
|
|
13
|
+
) => MaybePromise< PropValue >;
|
|
4
14
|
|
|
5
15
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
16
|
export type TransformersMap = Record< string, Transformer< any > >;
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { type PropKey, type PropType } from '@elementor/editor-props';
|
|
2
|
-
|
|
3
|
-
type ExtendedWindow = Window & {
|
|
4
|
-
elementor?: {
|
|
5
|
-
config?: {
|
|
6
|
-
atomic?: {
|
|
7
|
-
styles_schema?: Record< PropKey, PropType >;
|
|
8
|
-
};
|
|
9
|
-
};
|
|
10
|
-
};
|
|
11
|
-
};
|
|
12
|
-
|
|
13
|
-
export const getStylesSchema = () => {
|
|
14
|
-
const extendedWindow = window as unknown as ExtendedWindow;
|
|
15
|
-
|
|
16
|
-
return extendedWindow.elementor?.config?.atomic?.styles_schema ?? {};
|
|
17
|
-
};
|