@elementor/editor-canvas 4.2.0-862 → 4.2.0-863
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/dist/index.js
CHANGED
|
@@ -4083,6 +4083,7 @@ var validateInput = {
|
|
|
4083
4083
|
};
|
|
4084
4084
|
|
|
4085
4085
|
// src/composition-builder/composition-builder.ts
|
|
4086
|
+
var CREATE_ELEMENT_INVALID_CONTAINER_MESSAGE = "createElement did not return an element container with a model.";
|
|
4086
4087
|
var CompositionBuilder = class _CompositionBuilder {
|
|
4087
4088
|
elementConfig = {};
|
|
4088
4089
|
elementStylesConfig = {};
|
|
@@ -4301,6 +4302,9 @@ ${childTypeErrors.join("\n")}`);
|
|
|
4301
4302
|
model: modelTree,
|
|
4302
4303
|
options: { useHistory: false }
|
|
4303
4304
|
});
|
|
4305
|
+
if (!newElement?.model) {
|
|
4306
|
+
throw new Error(CREATE_ELEMENT_INVALID_CONTAINER_MESSAGE);
|
|
4307
|
+
}
|
|
4304
4308
|
this.rootContainers.push(newElement);
|
|
4305
4309
|
await this.awaitViewRender(newElement);
|
|
4306
4310
|
} catch (e) {
|
package/dist/index.mjs
CHANGED
|
@@ -4078,6 +4078,7 @@ var validateInput = {
|
|
|
4078
4078
|
};
|
|
4079
4079
|
|
|
4080
4080
|
// src/composition-builder/composition-builder.ts
|
|
4081
|
+
var CREATE_ELEMENT_INVALID_CONTAINER_MESSAGE = "createElement did not return an element container with a model.";
|
|
4081
4082
|
var CompositionBuilder = class _CompositionBuilder {
|
|
4082
4083
|
elementConfig = {};
|
|
4083
4084
|
elementStylesConfig = {};
|
|
@@ -4296,6 +4297,9 @@ ${childTypeErrors.join("\n")}`);
|
|
|
4296
4297
|
model: modelTree,
|
|
4297
4298
|
options: { useHistory: false }
|
|
4298
4299
|
});
|
|
4300
|
+
if (!newElement?.model) {
|
|
4301
|
+
throw new Error(CREATE_ELEMENT_INVALID_CONTAINER_MESSAGE);
|
|
4302
|
+
}
|
|
4299
4303
|
this.rootContainers.push(newElement);
|
|
4300
4304
|
await this.awaitViewRender(newElement);
|
|
4301
4305
|
} catch (e) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-canvas",
|
|
3
3
|
"description": "Elementor Editor Canvas",
|
|
4
|
-
"version": "4.2.0-
|
|
4
|
+
"version": "4.2.0-863",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -37,25 +37,25 @@
|
|
|
37
37
|
"react-dom": "^18.3.1"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@elementor/editor": "4.2.0-
|
|
40
|
+
"@elementor/editor": "4.2.0-863",
|
|
41
41
|
"dompurify": "^3.2.6",
|
|
42
|
-
"@elementor/editor-controls": "4.2.0-
|
|
43
|
-
"@elementor/editor-documents": "4.2.0-
|
|
44
|
-
"@elementor/editor-elements": "4.2.0-
|
|
45
|
-
"@elementor/editor-interactions": "4.2.0-
|
|
46
|
-
"@elementor/editor-mcp": "4.2.0-
|
|
47
|
-
"@elementor/editor-notifications": "4.2.0-
|
|
48
|
-
"@elementor/editor-props": "4.2.0-
|
|
49
|
-
"@elementor/editor-responsive": "4.2.0-
|
|
50
|
-
"@elementor/editor-styles": "4.2.0-
|
|
51
|
-
"@elementor/editor-styles-repository": "4.2.0-
|
|
52
|
-
"@elementor/editor-ui": "4.2.0-
|
|
53
|
-
"@elementor/editor-v1-adapters": "4.2.0-
|
|
54
|
-
"@elementor/schema": "4.2.0-
|
|
55
|
-
"@elementor/twing": "4.2.0-
|
|
42
|
+
"@elementor/editor-controls": "4.2.0-863",
|
|
43
|
+
"@elementor/editor-documents": "4.2.0-863",
|
|
44
|
+
"@elementor/editor-elements": "4.2.0-863",
|
|
45
|
+
"@elementor/editor-interactions": "4.2.0-863",
|
|
46
|
+
"@elementor/editor-mcp": "4.2.0-863",
|
|
47
|
+
"@elementor/editor-notifications": "4.2.0-863",
|
|
48
|
+
"@elementor/editor-props": "4.2.0-863",
|
|
49
|
+
"@elementor/editor-responsive": "4.2.0-863",
|
|
50
|
+
"@elementor/editor-styles": "4.2.0-863",
|
|
51
|
+
"@elementor/editor-styles-repository": "4.2.0-863",
|
|
52
|
+
"@elementor/editor-ui": "4.2.0-863",
|
|
53
|
+
"@elementor/editor-v1-adapters": "4.2.0-863",
|
|
54
|
+
"@elementor/schema": "4.2.0-863",
|
|
55
|
+
"@elementor/twing": "4.2.0-863",
|
|
56
56
|
"@elementor/ui": "1.37.5",
|
|
57
|
-
"@elementor/utils": "4.2.0-
|
|
58
|
-
"@elementor/wp-media": "4.2.0-
|
|
57
|
+
"@elementor/utils": "4.2.0-863",
|
|
58
|
+
"@elementor/wp-media": "4.2.0-863",
|
|
59
59
|
"@floating-ui/react": "^0.27.5",
|
|
60
60
|
"@wordpress/i18n": "^5.13.0"
|
|
61
61
|
},
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { type V1Element } from '@elementor/editor-elements';
|
|
2
|
+
|
|
3
|
+
import { CompositionBuilder } from '../composition-builder';
|
|
4
|
+
|
|
5
|
+
const ROOT_CHILD_TAG = 'column';
|
|
6
|
+
const GENERATED_ELEMENT_ID = 'generated-element-id';
|
|
7
|
+
const CONFIG_ID = 'cfg-a';
|
|
8
|
+
const ELEMENT_CONFIG_PROPERTY = 'title';
|
|
9
|
+
const ELEMENT_CONFIG_VALUE = 'configured-value';
|
|
10
|
+
|
|
11
|
+
const xmlStringWithConfiguration = `<${ ROOT_CHILD_TAG } configuration-id="${ CONFIG_ID }" />`;
|
|
12
|
+
|
|
13
|
+
const createElementConfigPayload = () => ( {
|
|
14
|
+
[ CONFIG_ID ]: {
|
|
15
|
+
[ ELEMENT_CONFIG_PROPERTY ]: ELEMENT_CONFIG_VALUE,
|
|
16
|
+
},
|
|
17
|
+
} );
|
|
18
|
+
|
|
19
|
+
const createMinimalWidgetsCache = () =>
|
|
20
|
+
( {
|
|
21
|
+
[ ROOT_CHILD_TAG ]: {
|
|
22
|
+
elType: 'column',
|
|
23
|
+
},
|
|
24
|
+
} ) as Record< string, { elType: string } >;
|
|
25
|
+
|
|
26
|
+
const createMockRootContainer = (): V1Element =>
|
|
27
|
+
( {
|
|
28
|
+
id: 'root',
|
|
29
|
+
model: { get: jest.fn(), set: jest.fn(), toJSON: jest.fn() },
|
|
30
|
+
settings: { get: jest.fn(), set: jest.fn(), toJSON: jest.fn() },
|
|
31
|
+
children: [],
|
|
32
|
+
} ) as unknown as V1Element;
|
|
33
|
+
|
|
34
|
+
const createMockPartialContainer = ( id: string ): V1Element =>
|
|
35
|
+
( {
|
|
36
|
+
id,
|
|
37
|
+
model: { get: jest.fn(), set: jest.fn(), toJSON: jest.fn() },
|
|
38
|
+
settings: { get: jest.fn(), set: jest.fn(), toJSON: jest.fn() },
|
|
39
|
+
children: [],
|
|
40
|
+
} ) as unknown as V1Element;
|
|
41
|
+
|
|
42
|
+
describe( 'CompositionBuilder.build createElement failure cleanup', () => {
|
|
43
|
+
it( 'calls deleteElement when createElement fails and getContainer returns a container', async () => {
|
|
44
|
+
// Arrange
|
|
45
|
+
const partialContainer = createMockPartialContainer( GENERATED_ELEMENT_ID );
|
|
46
|
+
const deleteElement = jest.fn();
|
|
47
|
+
const doUpdateElementProperty = jest.fn();
|
|
48
|
+
const createElement = jest.fn().mockImplementation( () => {
|
|
49
|
+
throw new Error( 'create failed' );
|
|
50
|
+
} );
|
|
51
|
+
const getContainer = jest
|
|
52
|
+
.fn()
|
|
53
|
+
.mockImplementation( ( id: string ) => ( id === GENERATED_ELEMENT_ID ? partialContainer : undefined ) );
|
|
54
|
+
const builder = CompositionBuilder.fromXMLString( xmlStringWithConfiguration, {
|
|
55
|
+
createElement,
|
|
56
|
+
deleteElement,
|
|
57
|
+
getContainer,
|
|
58
|
+
generateElementId: jest.fn().mockReturnValue( GENERATED_ELEMENT_ID ),
|
|
59
|
+
getWidgetsCache: jest.fn().mockReturnValue( createMinimalWidgetsCache() ),
|
|
60
|
+
doUpdateElementProperty,
|
|
61
|
+
} );
|
|
62
|
+
builder.setElementConfig( createElementConfigPayload() );
|
|
63
|
+
|
|
64
|
+
// Act
|
|
65
|
+
await expect( builder.build( createMockRootContainer() ) ).rejects.toThrow( 'create failed' );
|
|
66
|
+
|
|
67
|
+
// Assert
|
|
68
|
+
expect( getContainer ).toHaveBeenCalledWith( GENERATED_ELEMENT_ID );
|
|
69
|
+
expect( deleteElement ).toHaveBeenCalledTimes( 1 );
|
|
70
|
+
expect( deleteElement ).toHaveBeenCalledWith( { container: partialContainer } );
|
|
71
|
+
expect( doUpdateElementProperty ).not.toHaveBeenCalled();
|
|
72
|
+
} );
|
|
73
|
+
|
|
74
|
+
it( 'does not call deleteElement when createElement fails and getContainer returns undefined', async () => {
|
|
75
|
+
// Arrange
|
|
76
|
+
const deleteElement = jest.fn();
|
|
77
|
+
const doUpdateElementProperty = jest.fn();
|
|
78
|
+
const createElement = jest.fn().mockImplementation( () => {
|
|
79
|
+
throw new Error( 'create failed' );
|
|
80
|
+
} );
|
|
81
|
+
const getContainer = jest.fn().mockReturnValue( undefined );
|
|
82
|
+
const builder = CompositionBuilder.fromXMLString( xmlStringWithConfiguration, {
|
|
83
|
+
createElement,
|
|
84
|
+
deleteElement,
|
|
85
|
+
getContainer,
|
|
86
|
+
generateElementId: jest.fn().mockReturnValue( GENERATED_ELEMENT_ID ),
|
|
87
|
+
getWidgetsCache: jest.fn().mockReturnValue( createMinimalWidgetsCache() ),
|
|
88
|
+
doUpdateElementProperty,
|
|
89
|
+
} );
|
|
90
|
+
builder.setElementConfig( createElementConfigPayload() );
|
|
91
|
+
|
|
92
|
+
// Act
|
|
93
|
+
await expect( builder.build( createMockRootContainer() ) ).rejects.toThrow( 'create failed' );
|
|
94
|
+
|
|
95
|
+
// Assert
|
|
96
|
+
expect( getContainer ).toHaveBeenCalledWith( GENERATED_ELEMENT_ID );
|
|
97
|
+
expect( deleteElement ).not.toHaveBeenCalled();
|
|
98
|
+
expect( doUpdateElementProperty ).not.toHaveBeenCalled();
|
|
99
|
+
} );
|
|
100
|
+
|
|
101
|
+
it( 'calls deleteElement when createElement returns without a model', async () => {
|
|
102
|
+
// Arrange
|
|
103
|
+
const partialContainer = createMockPartialContainer( GENERATED_ELEMENT_ID );
|
|
104
|
+
const deleteElement = jest.fn();
|
|
105
|
+
const doUpdateElementProperty = jest.fn();
|
|
106
|
+
const createElement = jest.fn().mockReturnValue( {} as V1Element );
|
|
107
|
+
const getContainer = jest
|
|
108
|
+
.fn()
|
|
109
|
+
.mockImplementation( ( id: string ) => ( id === GENERATED_ELEMENT_ID ? partialContainer : undefined ) );
|
|
110
|
+
const builder = CompositionBuilder.fromXMLString( xmlStringWithConfiguration, {
|
|
111
|
+
createElement,
|
|
112
|
+
deleteElement,
|
|
113
|
+
getContainer,
|
|
114
|
+
generateElementId: jest.fn().mockReturnValue( GENERATED_ELEMENT_ID ),
|
|
115
|
+
getWidgetsCache: jest.fn().mockReturnValue( createMinimalWidgetsCache() ),
|
|
116
|
+
doUpdateElementProperty,
|
|
117
|
+
} );
|
|
118
|
+
builder.setElementConfig( createElementConfigPayload() );
|
|
119
|
+
|
|
120
|
+
// Act
|
|
121
|
+
await expect( builder.build( createMockRootContainer() ) ).rejects.toThrow(
|
|
122
|
+
'createElement did not return an element container with a model.'
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
// Assert
|
|
126
|
+
expect( getContainer ).toHaveBeenCalledWith( GENERATED_ELEMENT_ID );
|
|
127
|
+
expect( deleteElement ).toHaveBeenCalledTimes( 1 );
|
|
128
|
+
expect( deleteElement ).toHaveBeenCalledWith( { container: partialContainer } );
|
|
129
|
+
expect( doUpdateElementProperty ).not.toHaveBeenCalled();
|
|
130
|
+
} );
|
|
131
|
+
} );
|
|
132
|
+
|
|
133
|
+
describe( 'CompositionBuilder.build applyProperties after create', () => {
|
|
134
|
+
it( 'calls doUpdateElementProperty when create succeeds with element config', async () => {
|
|
135
|
+
// Arrange
|
|
136
|
+
const deleteElement = jest.fn();
|
|
137
|
+
const doUpdateElementProperty = jest.fn();
|
|
138
|
+
const createdElement = createMockPartialContainer( GENERATED_ELEMENT_ID );
|
|
139
|
+
const createElement = jest.fn().mockReturnValue( createdElement );
|
|
140
|
+
const getContainer = jest
|
|
141
|
+
.fn()
|
|
142
|
+
.mockImplementation( ( id: string ) => ( id === GENERATED_ELEMENT_ID ? createdElement : undefined ) );
|
|
143
|
+
const builder = CompositionBuilder.fromXMLString( xmlStringWithConfiguration, {
|
|
144
|
+
createElement,
|
|
145
|
+
deleteElement,
|
|
146
|
+
getContainer,
|
|
147
|
+
generateElementId: jest.fn().mockReturnValue( GENERATED_ELEMENT_ID ),
|
|
148
|
+
getWidgetsCache: jest.fn().mockReturnValue( createMinimalWidgetsCache() ),
|
|
149
|
+
doUpdateElementProperty,
|
|
150
|
+
} );
|
|
151
|
+
builder.setElementConfig( createElementConfigPayload() );
|
|
152
|
+
|
|
153
|
+
// Act
|
|
154
|
+
await builder.build( createMockRootContainer() );
|
|
155
|
+
|
|
156
|
+
// Assert
|
|
157
|
+
expect( deleteElement ).not.toHaveBeenCalled();
|
|
158
|
+
expect( createElement ).toHaveBeenCalledTimes( 1 );
|
|
159
|
+
expect( doUpdateElementProperty ).toHaveBeenCalledTimes( 1 );
|
|
160
|
+
expect( doUpdateElementProperty ).toHaveBeenCalledWith( {
|
|
161
|
+
elementId: GENERATED_ELEMENT_ID,
|
|
162
|
+
propertyName: ELEMENT_CONFIG_PROPERTY,
|
|
163
|
+
propertyValue: ELEMENT_CONFIG_VALUE,
|
|
164
|
+
elementType: ROOT_CHILD_TAG,
|
|
165
|
+
} );
|
|
166
|
+
} );
|
|
167
|
+
|
|
168
|
+
it( 'does not call doUpdateElementProperty when create succeeds without element config', async () => {
|
|
169
|
+
// Arrange
|
|
170
|
+
const deleteElement = jest.fn();
|
|
171
|
+
const doUpdateElementProperty = jest.fn();
|
|
172
|
+
const createdElement = createMockPartialContainer( GENERATED_ELEMENT_ID );
|
|
173
|
+
const createElement = jest.fn().mockReturnValue( createdElement );
|
|
174
|
+
const builder = CompositionBuilder.fromXMLString( `<${ ROOT_CHILD_TAG } />`, {
|
|
175
|
+
createElement,
|
|
176
|
+
deleteElement,
|
|
177
|
+
getContainer: jest.fn(),
|
|
178
|
+
generateElementId: jest.fn().mockReturnValue( GENERATED_ELEMENT_ID ),
|
|
179
|
+
getWidgetsCache: jest.fn().mockReturnValue( createMinimalWidgetsCache() ),
|
|
180
|
+
doUpdateElementProperty,
|
|
181
|
+
} );
|
|
182
|
+
|
|
183
|
+
// Act
|
|
184
|
+
await builder.build( createMockRootContainer() );
|
|
185
|
+
|
|
186
|
+
// Assert
|
|
187
|
+
expect( deleteElement ).not.toHaveBeenCalled();
|
|
188
|
+
expect( doUpdateElementProperty ).not.toHaveBeenCalled();
|
|
189
|
+
} );
|
|
190
|
+
} );
|
|
@@ -17,6 +17,8 @@ import { validateInput } from '../mcp/utils/validate-input';
|
|
|
17
17
|
type AnyValue = z.infer< z.ZodTypeAny >;
|
|
18
18
|
type AnyConfig = Record< string, Record< string, AnyValue > >;
|
|
19
19
|
|
|
20
|
+
const CREATE_ELEMENT_INVALID_CONTAINER_MESSAGE = 'createElement did not return an element container with a model.';
|
|
21
|
+
|
|
20
22
|
type API = {
|
|
21
23
|
createElement: typeof createElement;
|
|
22
24
|
deleteElement: typeof deleteElement;
|
|
@@ -296,6 +298,9 @@ export class CompositionBuilder {
|
|
|
296
298
|
model: modelTree as CreateElementParams[ 'model' ],
|
|
297
299
|
options: { useHistory: false },
|
|
298
300
|
} );
|
|
301
|
+
if ( ! newElement?.model ) {
|
|
302
|
+
throw new Error( CREATE_ELEMENT_INVALID_CONTAINER_MESSAGE );
|
|
303
|
+
}
|
|
299
304
|
this.rootContainers.push( newElement );
|
|
300
305
|
await this.awaitViewRender( newElement );
|
|
301
306
|
} catch ( e: unknown ) {
|