@elementor/editor-canvas 4.2.0-868 → 4.2.0-869

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
@@ -3987,6 +3987,15 @@ var doUpdateElementProperty = (params) => {
3987
3987
  }
3988
3988
  const propKey = elementPropSchema[propertyName].key;
3989
3989
  const value = resolvePropValue(propertyValue, propKey);
3990
+ const { valid, jsonSchema } = import_editor_props6.Schema.validatePropValue(elementPropSchema[propertyName], propertyValue);
3991
+ if (!valid) {
3992
+ throw new Error(
3993
+ `Invalid PropValue for elementId: ${elementId}. PropKey: ${propKey}, PropValue: ${JSON.stringify(
3994
+ propertyValue
3995
+ )}
3996
+ Expected Schema: ${jsonSchema}`
3997
+ );
3998
+ }
3990
3999
  (0, import_editor_elements11.updateElementSettings)({
3991
4000
  id: elementId,
3992
4001
  props: {
@@ -4564,24 +4573,32 @@ var initBuildCompositionsTool = (reg) => {
4564
4573
  compositionBuilder.setElementConfig(elementConfig);
4565
4574
  compositionBuilder.setStylesConfig(stylesConfig);
4566
4575
  compositionBuilder.setCustomCSS(customCSS);
4567
- const { invalidStyles, rootContainers: generatedRootContainers } = await compositionBuilder.build(targetContainer);
4576
+ const {
4577
+ invalidStyles,
4578
+ configErrors,
4579
+ rootContainers: generatedRootContainers
4580
+ } = await compositionBuilder.build(targetContainer);
4568
4581
  rootContainers.push(...generatedRootContainers);
4569
4582
  generatedXML = new XMLSerializer().serializeToString(compositionBuilder.getXML());
4570
- Object.entries(invalidStyles).forEach(([elementId, rawCssRules]) => {
4571
- const customCss = {
4572
- value: rawCssRules.join(";\n")
4573
- };
4574
- doUpdateElementProperty({
4575
- elementId,
4576
- propertyName: "_styles",
4577
- propertyValue: {
4578
- _styles: {
4579
- custom_css: customCss
4580
- }
4581
- },
4582
- elementType: "widget"
4583
+ if (configErrors.length) {
4584
+ errors.push(...configErrors.map((msg) => new Error(msg)));
4585
+ } else {
4586
+ Object.entries(invalidStyles).forEach(([elementId, rawCssRules]) => {
4587
+ const customCss = {
4588
+ value: rawCssRules.join(";\n")
4589
+ };
4590
+ doUpdateElementProperty({
4591
+ elementId,
4592
+ propertyName: "_styles",
4593
+ propertyValue: {
4594
+ _styles: {
4595
+ custom_css: customCss
4596
+ }
4597
+ },
4598
+ elementType: "widget"
4599
+ });
4583
4600
  });
4584
- });
4601
+ }
4585
4602
  } catch (error) {
4586
4603
  errors.push(error);
4587
4604
  }
package/dist/index.mjs CHANGED
@@ -3982,6 +3982,15 @@ var doUpdateElementProperty = (params) => {
3982
3982
  }
3983
3983
  const propKey = elementPropSchema[propertyName].key;
3984
3984
  const value = resolvePropValue(propertyValue, propKey);
3985
+ const { valid, jsonSchema } = Schema2.validatePropValue(elementPropSchema[propertyName], propertyValue);
3986
+ if (!valid) {
3987
+ throw new Error(
3988
+ `Invalid PropValue for elementId: ${elementId}. PropKey: ${propKey}, PropValue: ${JSON.stringify(
3989
+ propertyValue
3990
+ )}
3991
+ Expected Schema: ${jsonSchema}`
3992
+ );
3993
+ }
3985
3994
  updateElementSettings({
3986
3995
  id: elementId,
3987
3996
  props: {
@@ -4559,24 +4568,32 @@ var initBuildCompositionsTool = (reg) => {
4559
4568
  compositionBuilder.setElementConfig(elementConfig);
4560
4569
  compositionBuilder.setStylesConfig(stylesConfig);
4561
4570
  compositionBuilder.setCustomCSS(customCSS);
4562
- const { invalidStyles, rootContainers: generatedRootContainers } = await compositionBuilder.build(targetContainer);
4571
+ const {
4572
+ invalidStyles,
4573
+ configErrors,
4574
+ rootContainers: generatedRootContainers
4575
+ } = await compositionBuilder.build(targetContainer);
4563
4576
  rootContainers.push(...generatedRootContainers);
4564
4577
  generatedXML = new XMLSerializer().serializeToString(compositionBuilder.getXML());
4565
- Object.entries(invalidStyles).forEach(([elementId, rawCssRules]) => {
4566
- const customCss = {
4567
- value: rawCssRules.join(";\n")
4568
- };
4569
- doUpdateElementProperty({
4570
- elementId,
4571
- propertyName: "_styles",
4572
- propertyValue: {
4573
- _styles: {
4574
- custom_css: customCss
4575
- }
4576
- },
4577
- elementType: "widget"
4578
+ if (configErrors.length) {
4579
+ errors.push(...configErrors.map((msg) => new Error(msg)));
4580
+ } else {
4581
+ Object.entries(invalidStyles).forEach(([elementId, rawCssRules]) => {
4582
+ const customCss = {
4583
+ value: rawCssRules.join(";\n")
4584
+ };
4585
+ doUpdateElementProperty({
4586
+ elementId,
4587
+ propertyName: "_styles",
4588
+ propertyValue: {
4589
+ _styles: {
4590
+ custom_css: customCss
4591
+ }
4592
+ },
4593
+ elementType: "widget"
4594
+ });
4578
4595
  });
4579
- });
4596
+ }
4580
4597
  } catch (error) {
4581
4598
  errors.push(error);
4582
4599
  }
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-868",
4
+ "version": "4.2.0-869",
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-868",
40
+ "@elementor/editor": "4.2.0-869",
41
41
  "dompurify": "^3.2.6",
42
- "@elementor/editor-controls": "4.2.0-868",
43
- "@elementor/editor-documents": "4.2.0-868",
44
- "@elementor/editor-elements": "4.2.0-868",
45
- "@elementor/editor-interactions": "4.2.0-868",
46
- "@elementor/editor-mcp": "4.2.0-868",
47
- "@elementor/editor-notifications": "4.2.0-868",
48
- "@elementor/editor-props": "4.2.0-868",
49
- "@elementor/editor-responsive": "4.2.0-868",
50
- "@elementor/editor-styles": "4.2.0-868",
51
- "@elementor/editor-styles-repository": "4.2.0-868",
52
- "@elementor/editor-ui": "4.2.0-868",
53
- "@elementor/editor-v1-adapters": "4.2.0-868",
54
- "@elementor/schema": "4.2.0-868",
55
- "@elementor/twing": "4.2.0-868",
42
+ "@elementor/editor-controls": "4.2.0-869",
43
+ "@elementor/editor-documents": "4.2.0-869",
44
+ "@elementor/editor-elements": "4.2.0-869",
45
+ "@elementor/editor-interactions": "4.2.0-869",
46
+ "@elementor/editor-mcp": "4.2.0-869",
47
+ "@elementor/editor-notifications": "4.2.0-869",
48
+ "@elementor/editor-props": "4.2.0-869",
49
+ "@elementor/editor-responsive": "4.2.0-869",
50
+ "@elementor/editor-styles": "4.2.0-869",
51
+ "@elementor/editor-styles-repository": "4.2.0-869",
52
+ "@elementor/editor-ui": "4.2.0-869",
53
+ "@elementor/editor-v1-adapters": "4.2.0-869",
54
+ "@elementor/schema": "4.2.0-869",
55
+ "@elementor/twing": "4.2.0-869",
56
56
  "@elementor/ui": "1.37.5",
57
- "@elementor/utils": "4.2.0-868",
58
- "@elementor/wp-media": "4.2.0-868",
57
+ "@elementor/utils": "4.2.0-869",
58
+ "@elementor/wp-media": "4.2.0-869",
59
59
  "@floating-ui/react": "^0.27.5",
60
60
  "@wordpress/i18n": "^5.13.0"
61
61
  },
@@ -65,27 +65,34 @@ export const initBuildCompositionsTool = ( reg: MCPRegistryEntry ) => {
65
65
  compositionBuilder.setStylesConfig( stylesConfig );
66
66
  compositionBuilder.setCustomCSS( customCSS );
67
67
 
68
- const { invalidStyles, rootContainers: generatedRootContainers } =
69
- await compositionBuilder.build( targetContainer );
68
+ const {
69
+ invalidStyles,
70
+ configErrors,
71
+ rootContainers: generatedRootContainers,
72
+ } = await compositionBuilder.build( targetContainer );
70
73
 
71
74
  rootContainers.push( ...generatedRootContainers );
72
75
  generatedXML = new XMLSerializer().serializeToString( compositionBuilder.getXML() );
73
76
 
74
- Object.entries( invalidStyles ).forEach( ( [ elementId, rawCssRules ] ) => {
75
- const customCss = {
76
- value: rawCssRules.join( ';\n' ),
77
- };
78
- doUpdateElementProperty( {
79
- elementId,
80
- propertyName: '_styles',
81
- propertyValue: {
82
- _styles: {
83
- custom_css: customCss,
77
+ if ( configErrors.length ) {
78
+ errors.push( ...configErrors.map( ( msg ) => new Error( msg ) ) );
79
+ } else {
80
+ Object.entries( invalidStyles ).forEach( ( [ elementId, rawCssRules ] ) => {
81
+ const customCss = {
82
+ value: rawCssRules.join( ';\n' ),
83
+ };
84
+ doUpdateElementProperty( {
85
+ elementId,
86
+ propertyName: '_styles',
87
+ propertyValue: {
88
+ _styles: {
89
+ custom_css: customCss,
90
+ },
84
91
  },
85
- },
86
- elementType: 'widget',
92
+ elementType: 'widget',
93
+ } );
87
94
  } );
88
- } );
95
+ }
89
96
  } catch ( error ) {
90
97
  errors.push( error as Error );
91
98
  }
@@ -0,0 +1,135 @@
1
+ import { getWidgetsCache, updateElementSettings } from '@elementor/editor-elements';
2
+ import { Schema } from '@elementor/editor-props';
3
+ import { __privateRunCommandSync } from '@elementor/editor-v1-adapters';
4
+
5
+ import { doUpdateElementProperty } from '../do-update-element-property';
6
+
7
+ jest.mock( '@elementor/editor-elements', () => ( {
8
+ createElementStyle: jest.fn(),
9
+ getElementStyles: jest.fn(),
10
+ getWidgetsCache: jest.fn(),
11
+ updateElementSettings: jest.fn(),
12
+ updateElementStyle: jest.fn(),
13
+ } ) );
14
+
15
+ jest.mock( '@elementor/editor-props', () => ( {
16
+ getPropSchemaFromCache: jest.fn(),
17
+ Schema: {
18
+ adjustLlmPropValueSchema: jest.fn( ( value: unknown ) => value ),
19
+ validatePropValue: jest.fn(),
20
+ },
21
+ } ) );
22
+
23
+ jest.mock( '@elementor/editor-styles', () => ( {
24
+ getStylesSchema: jest.fn( () => ( {} ) ),
25
+ } ) );
26
+
27
+ jest.mock( '@elementor/editor-v1-adapters', () => ( {
28
+ __privateRunCommandSync: jest.fn(),
29
+ } ) );
30
+
31
+ const ELEMENT_ID = 'test-element-id';
32
+ const ELEMENT_TYPE = 'atomic-heading';
33
+ const EXPECTED_JSON_SCHEMA_SNIPPET = '{"type":"object"}';
34
+ const PROPERTY_NAME = 'title';
35
+ const PROP_SCHEMA_ENTRY = { key: 'titlePropKey' };
36
+
37
+ const widgetsCacheFixture = {
38
+ [ ELEMENT_TYPE ]: {
39
+ atomic_props_schema: {
40
+ [ PROPERTY_NAME ]: PROP_SCHEMA_ENTRY,
41
+ },
42
+ },
43
+ };
44
+
45
+ describe( 'doUpdateElementProperty', () => {
46
+ beforeEach( () => {
47
+ Object.assign( window, {
48
+ elementorV2: {
49
+ editorVariables: {
50
+ Utils: {
51
+ globalVariablesLLMResolvers: [],
52
+ },
53
+ },
54
+ },
55
+ } );
56
+ // @ts-ignore: Mock values for test
57
+ jest.mocked( getWidgetsCache ).mockReturnValue( widgetsCacheFixture );
58
+ // @ts-ignore: Mock values for test
59
+ jest.mocked( Schema.adjustLlmPropValueSchema ).mockImplementation( ( value: unknown ) => value );
60
+ jest.mocked( Schema.validatePropValue ).mockReset();
61
+ } );
62
+
63
+ afterEach( () => {
64
+ jest.clearAllMocks();
65
+ } );
66
+
67
+ it( 'throws when Schema.validatePropValue reports invalid PropValue and does not persist', () => {
68
+ // Arrange
69
+ const propertyValue = { invalid: true };
70
+ jest.mocked( Schema.validatePropValue ).mockReturnValue( {
71
+ jsonSchema: EXPECTED_JSON_SCHEMA_SNIPPET,
72
+ valid: false,
73
+ errorMessages: 'error',
74
+ errors: [],
75
+ } );
76
+
77
+ // Act
78
+ let thrown: unknown;
79
+ try {
80
+ doUpdateElementProperty( {
81
+ elementId: ELEMENT_ID,
82
+ elementType: ELEMENT_TYPE,
83
+ propertyName: PROPERTY_NAME,
84
+ propertyValue,
85
+ } );
86
+ } catch ( error ) {
87
+ thrown = error;
88
+ }
89
+
90
+ // Assert
91
+ expect( thrown ).toBeInstanceOf( Error );
92
+ expect( ( thrown as Error ).message ).toMatch( /Invalid PropValue/ );
93
+ expect( ( thrown as Error ).message ).toContain( ELEMENT_ID );
94
+ expect( ( thrown as Error ).message ).toContain( PROP_SCHEMA_ENTRY.key );
95
+ expect( ( thrown as Error ).message ).toContain( EXPECTED_JSON_SCHEMA_SNIPPET );
96
+ expect( Schema.validatePropValue ).toHaveBeenCalledWith( PROP_SCHEMA_ENTRY, propertyValue );
97
+ expect( updateElementSettings ).not.toHaveBeenCalled();
98
+ expect( __privateRunCommandSync ).not.toHaveBeenCalled();
99
+ } );
100
+
101
+ it( 'updates settings when Schema.validatePropValue reports valid PropValue', () => {
102
+ // Arrange
103
+ const propertyValue = 'resolved-title';
104
+ jest.mocked( Schema.validatePropValue ).mockReturnValue( {
105
+ jsonSchema: EXPECTED_JSON_SCHEMA_SNIPPET,
106
+ valid: true,
107
+ errorMessages: [],
108
+ errors: [],
109
+ } );
110
+
111
+ // Act
112
+ doUpdateElementProperty( {
113
+ elementId: ELEMENT_ID,
114
+ elementType: ELEMENT_TYPE,
115
+ propertyName: PROPERTY_NAME,
116
+ propertyValue,
117
+ } );
118
+
119
+ // Assert
120
+ expect( Schema.validatePropValue ).toHaveBeenCalledWith( PROP_SCHEMA_ENTRY, propertyValue );
121
+ expect( updateElementSettings ).toHaveBeenCalledTimes( 1 );
122
+ expect( updateElementSettings ).toHaveBeenCalledWith( {
123
+ id: ELEMENT_ID,
124
+ props: {
125
+ [ PROPERTY_NAME ]: propertyValue,
126
+ },
127
+ withHistory: false,
128
+ } );
129
+ expect( __privateRunCommandSync ).toHaveBeenCalledWith(
130
+ 'document/save/set-is-modified',
131
+ { status: true },
132
+ { internal: true }
133
+ );
134
+ } );
135
+ } );
@@ -129,6 +129,14 @@ export const doUpdateElementProperty = ( params: OwnParams ) => {
129
129
  }
130
130
  const propKey = elementPropSchema[ propertyName ].key;
131
131
  const value = resolvePropValue( propertyValue, propKey );
132
+ const { valid, jsonSchema } = Schema.validatePropValue( elementPropSchema[ propertyName ], propertyValue );
133
+ if ( ! valid ) {
134
+ throw new Error(
135
+ `Invalid PropValue for elementId: ${ elementId }. PropKey: ${ propKey }, PropValue: ${ JSON.stringify(
136
+ propertyValue
137
+ ) }\nExpected Schema: ${ jsonSchema }`
138
+ );
139
+ }
132
140
  updateElementSettings( {
133
141
  id: elementId,
134
142
  props: {