@elementor/editor-canvas 3.35.0-353 → 3.35.0-354
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 +148 -26
- package/dist/index.mjs +148 -26
- package/package.json +18 -18
- package/src/mcp/mcp-description.ts +45 -1
- package/src/mcp/resources/breakpoints-resource.ts +2 -2
- package/src/mcp/resources/widgets-schema-resource.ts +54 -5
- package/src/mcp/tools/build-composition/prompt.ts +22 -6
- package/src/mcp/tools/build-composition/tool.ts +27 -7
- package/src/mcp/tools/configure-element/prompt.ts +2 -0
- package/src/mcp/tools/get-element-config/tool.ts +28 -1
- package/src/mcp/utils/validate-input.ts +2 -2
package/dist/index.js
CHANGED
|
@@ -50,7 +50,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
50
50
|
var import_editor_v1_adapters = require("@elementor/editor-v1-adapters");
|
|
51
51
|
var BREAKPOINTS_SCHEMA_URI = "elementor://breakpoints/list";
|
|
52
52
|
var initBreakpointsResource = (reg) => {
|
|
53
|
-
const { mcpServer } = reg;
|
|
53
|
+
const { mcpServer, sendResourceUpdated } = reg;
|
|
54
54
|
const getBreakpointsList = () => {
|
|
55
55
|
const { breakpoints } = window.elementor?.config?.responsive || {};
|
|
56
56
|
if (!breakpoints) {
|
|
@@ -78,7 +78,7 @@ var initBreakpointsResource = (reg) => {
|
|
|
78
78
|
return buildResourceResponse();
|
|
79
79
|
});
|
|
80
80
|
window.addEventListener((0, import_editor_v1_adapters.v1ReadyEvent)().name, () => {
|
|
81
|
-
|
|
81
|
+
sendResourceUpdated({
|
|
82
82
|
uri: BREAKPOINTS_SCHEMA_URI,
|
|
83
83
|
...buildResourceResponse()
|
|
84
84
|
});
|
|
@@ -93,6 +93,14 @@ var import_editor_styles = require("@elementor/editor-styles");
|
|
|
93
93
|
var WIDGET_SCHEMA_URI = "elementor://widgets/schema/{widgetType}";
|
|
94
94
|
var STYLE_SCHEMA_URI = "elementor://styles/schema/{category}";
|
|
95
95
|
var BEST_PRACTICES_URI = "elementor://styles/best-practices";
|
|
96
|
+
var checkIfUserHasPro = () => {
|
|
97
|
+
const extendedWindow = window;
|
|
98
|
+
const hasPro = extendedWindow.elementor?.helpers?.hasPro;
|
|
99
|
+
if (typeof hasPro === "function") {
|
|
100
|
+
return hasPro();
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
};
|
|
96
104
|
var initWidgetsSchemaResource = (reg) => {
|
|
97
105
|
const { mcpServer } = reg;
|
|
98
106
|
mcpServer.resource("styles-best-practices", BEST_PRACTICES_URI, async () => {
|
|
@@ -114,7 +122,11 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
114
122
|
"styles-schema",
|
|
115
123
|
new import_editor_mcp.ResourceTemplate(STYLE_SCHEMA_URI, {
|
|
116
124
|
list: () => {
|
|
117
|
-
const
|
|
125
|
+
const isPro = checkIfUserHasPro();
|
|
126
|
+
const categories = [...Object.keys((0, import_editor_styles.getStylesSchema)())];
|
|
127
|
+
if (!isPro) {
|
|
128
|
+
categories.push("custom_css");
|
|
129
|
+
}
|
|
118
130
|
return {
|
|
119
131
|
resources: categories.map((category) => ({
|
|
120
132
|
uri: `elementor://styles/schema/${category}`,
|
|
@@ -128,7 +140,7 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
128
140
|
},
|
|
129
141
|
async (uri, variables) => {
|
|
130
142
|
const category = typeof variables.category === "string" ? variables.category : variables.category?.[0];
|
|
131
|
-
if (category === "custom_css") {
|
|
143
|
+
if (category === "custom_css" && checkIfUserHasPro()) {
|
|
132
144
|
return {
|
|
133
145
|
contents: [
|
|
134
146
|
{
|
|
@@ -160,7 +172,7 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
160
172
|
list: () => {
|
|
161
173
|
const cache = (0, import_editor_elements.getWidgetsCache)() || {};
|
|
162
174
|
const availableWidgets = Object.keys(cache || {}).filter(
|
|
163
|
-
(widgetType) => cache[widgetType]?.atomic_props_schema
|
|
175
|
+
(widgetType) => cache[widgetType]?.atomic_props_schema && cache[widgetType].meta?.llm_support !== false
|
|
164
176
|
);
|
|
165
177
|
return {
|
|
166
178
|
resources: availableWidgets.map((widgetType) => ({
|
|
@@ -175,8 +187,9 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
175
187
|
},
|
|
176
188
|
async (uri, variables) => {
|
|
177
189
|
const widgetType = typeof variables.widgetType === "string" ? variables.widgetType : variables.widgetType?.[0];
|
|
178
|
-
const
|
|
179
|
-
|
|
190
|
+
const widgetData = (0, import_editor_elements.getWidgetsCache)()?.[widgetType];
|
|
191
|
+
const propSchema = widgetData?.atomic_props_schema;
|
|
192
|
+
if (!propSchema || !widgetData) {
|
|
180
193
|
throw new Error(`No prop schema found for element type: ${widgetType}`);
|
|
181
194
|
}
|
|
182
195
|
const asJson = Object.fromEntries(
|
|
@@ -188,6 +201,24 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
188
201
|
import_editor_props.Schema.nonConfigurablePropKeys.forEach((key) => {
|
|
189
202
|
delete asJson[key];
|
|
190
203
|
});
|
|
204
|
+
const description = typeof widgetData?.meta?.description === "string" ? widgetData.meta.description : void 0;
|
|
205
|
+
const defaultStyles = {};
|
|
206
|
+
const baseStyleSchema = widgetData?.base_styles;
|
|
207
|
+
if (baseStyleSchema) {
|
|
208
|
+
Object.values(baseStyleSchema).forEach((stylePropType) => {
|
|
209
|
+
stylePropType.variants.forEach((variant) => {
|
|
210
|
+
Object.assign(defaultStyles, variant.props);
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
const hasDefaultStyles = Object.keys(defaultStyles).length > 0;
|
|
215
|
+
const llmGuidance = {
|
|
216
|
+
can_have_children: !!widgetData?.meta?.is_container
|
|
217
|
+
};
|
|
218
|
+
if (hasDefaultStyles) {
|
|
219
|
+
llmGuidance.instructions = "These are the default styles applied to the widget. Override only when necessary.";
|
|
220
|
+
llmGuidance.default_styles = defaultStyles;
|
|
221
|
+
}
|
|
191
222
|
return {
|
|
192
223
|
contents: [
|
|
193
224
|
{
|
|
@@ -195,7 +226,9 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
195
226
|
mimeType: "application/json",
|
|
196
227
|
text: JSON.stringify({
|
|
197
228
|
type: "object",
|
|
198
|
-
properties: asJson
|
|
229
|
+
properties: asJson,
|
|
230
|
+
description,
|
|
231
|
+
llm_guidance: llmGuidance
|
|
199
232
|
})
|
|
200
233
|
}
|
|
201
234
|
]
|
|
@@ -2062,9 +2095,9 @@ var validateInput = {
|
|
|
2062
2095
|
} else if (!import_editor_props5.Schema.isPropKeyConfigurable(propName)) {
|
|
2063
2096
|
errors.push(`Property "${propName}" is not configurable.`);
|
|
2064
2097
|
} else {
|
|
2065
|
-
const { valid,
|
|
2098
|
+
const { valid, jsonSchema } = import_editor_props5.Schema.validatePropValue(propSchema, propValue);
|
|
2066
2099
|
if (!valid) {
|
|
2067
|
-
errors.push(`Invalid property "${propName}": ${
|
|
2100
|
+
errors.push(`Invalid property "${propName}". Expected schema: ${jsonSchema}`);
|
|
2068
2101
|
}
|
|
2069
2102
|
}
|
|
2070
2103
|
});
|
|
@@ -2126,6 +2159,24 @@ When in doubt between "safe" and "distinctive," choose distinctive - users can a
|
|
|
2126
2159
|
Always prefer this tool when the user requires to build a composition of elements, such as cards, heros, or inspired from other pages or HTML compositions.
|
|
2127
2160
|
Prefer this tool over any other tool for building HTML structure, unless you are specified to use a different tool.
|
|
2128
2161
|
|
|
2162
|
+
# **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
|
|
2163
|
+
1. [${WIDGET_SCHEMA_URI}]
|
|
2164
|
+
Required to understand which widgets are available, and what are their configuration schemas.
|
|
2165
|
+
Every widgetType (i.e. e-heading, e-button) that is supported has it's own property schema, that you must follow in order to apply property values correctly.
|
|
2166
|
+
2. [${STYLE_SCHEMA_URI}]
|
|
2167
|
+
Required to understand the styles schema for the widgets. All widgets share the same styles schema.
|
|
2168
|
+
3. List of allowed custom tags for building the structure is derived from the list of widgets schema resources.
|
|
2169
|
+
|
|
2170
|
+
# DESIGN QUALITY IMPERATIVE
|
|
2171
|
+
You are generating designs for real users who expect distinctive, intentional aesthetics - NOT generic AI output.
|
|
2172
|
+
**The Core Challenge**: Large language models naturally converge toward statistically common design patterns during generation. This creates predictable, uninspired results that users describe as "AI slop": safe color schemes, default typography hierarchies, minimal contrast, and timid spacing.
|
|
2173
|
+
**Your Mission**: Actively resist distributional convergence by making intentional, distinctive design choices across all aesthetic dimensions. Every design decision should have a clear purpose tied to visual hierarchy, brand personality, or user experience goals.
|
|
2174
|
+
When in doubt between "safe" and "distinctive," choose distinctive - users can always request refinements, but they cannot salvage generic foundations.
|
|
2175
|
+
|
|
2176
|
+
# When to use this tool
|
|
2177
|
+
Always prefer this tool when the user requires to build a composition of elements, such as cards, heros, or inspired from other pages or HTML compositions.
|
|
2178
|
+
Prefer this tool over any other tool for building HTML structure, unless you are specified to use a different tool.
|
|
2179
|
+
|
|
2129
2180
|
# Instructions
|
|
2130
2181
|
1. Understand the user requirements carefully.
|
|
2131
2182
|
2. Build a valid XML structure using only the allowed custom tags provided. For example, if you
|
|
@@ -2140,11 +2191,11 @@ Prefer this tool over any other tool for building HTML structure, unless you are
|
|
|
2140
2191
|
5. Ensure the XML structure is valid and parsable.
|
|
2141
2192
|
6. Do not add any attribute nodes, classes, id's, and no text nodes allowed.
|
|
2142
2193
|
Layout properties, such as margin, padding, align, etc. must be applied using the [${STYLE_SCHEMA_URI}] PropValues.
|
|
2143
|
-
7. Some elements allow nesting of other elements, and most of the DO NOT. The allowed elements that can have nested children are "e-div-block" and "e-flexbox".
|
|
2194
|
+
7. Some elements allow nesting of other elements, and most of the DO NOT. The allowed elements that can have nested children are "e-tabs", "e-div-block", and "e-flexbox".
|
|
2144
2195
|
8. Make sure that non-container elements do NOT have any nested elements.
|
|
2145
|
-
9. **CRITICAL - CUSTOM CSS
|
|
2196
|
+
9. **CRITICAL - CUSTOM CSS USAGE**: ALWAYS Prefer using style schema. Custom CSS is ONLY FOR UNSUPPRTED schema styles.
|
|
2146
2197
|
ALWAYS PRIORITIZE using the style schema PropValues for styling elements as they provide better user experience in the editor, and UI features for the end-users.
|
|
2147
|
-
|
|
2198
|
+
Use custom_css only for style attributes that ARE NOT SUPPORTED via the style schema AFTER YOU CHECK THE [${STYLE_SCHEMA_URI}].
|
|
2148
2199
|
|
|
2149
2200
|
# DESIGN VECTORS - Concrete Implementation Guidance
|
|
2150
2201
|
|
|
@@ -2363,10 +2414,8 @@ If unsure about the configuration of a specific property, read the schema resour
|
|
|
2363
2414
|
|
|
2364
2415
|
# About our widgets
|
|
2365
2416
|
Most widgets are self-explanatory by their name. Here is some additional information.
|
|
2417
|
+
Check for available llm_guidance property in the widget's schema.
|
|
2366
2418
|
SVG elements are bound to internal content upload. Avoid usage, unless you have tools to upload SVG content.
|
|
2367
|
-
e-div-block - By default is ceneterd aligned and vertically stacked. To modify this, apply style configuration.
|
|
2368
|
-
e-flexbox - By default is a flex container with row direction. To modify this, apply style configuration.
|
|
2369
|
-
|
|
2370
2419
|
When working with containers, do not forget to apply style schema for controlling the layout.
|
|
2371
2420
|
|
|
2372
2421
|
|
|
@@ -2482,21 +2531,27 @@ var initBuildCompositionsTool = (reg) => {
|
|
|
2482
2531
|
throw new Error("Failed to parse XML structure: " + errorNode.textContent);
|
|
2483
2532
|
}
|
|
2484
2533
|
const children = Array.from(xml.children);
|
|
2485
|
-
const iterate = (node, containerElement = documentContainer) => {
|
|
2534
|
+
const iterate = async (node, containerElement = documentContainer, childIndex) => {
|
|
2486
2535
|
const elementTag = node.tagName;
|
|
2487
2536
|
if (!widgetsCache[elementTag]) {
|
|
2488
2537
|
errors.push(new Error(`Unknown widget type: ${elementTag}`));
|
|
2489
2538
|
}
|
|
2490
|
-
const
|
|
2539
|
+
const CONTAINER_ELEMENTS = Object.values(widgetsCache).filter((widget) => widget.meta?.is_container).map((widget) => widget.elType);
|
|
2540
|
+
const isContainer = CONTAINER_ELEMENTS.includes(elementTag);
|
|
2541
|
+
const parentElType = containerElement.model.get("elType");
|
|
2542
|
+
let targetContainerId = parentElType === "e-tabs" ? containerElement.children?.[1].children?.[childIndex]?.id || containerElement.children?.[1].id : containerElement.id;
|
|
2543
|
+
if (!targetContainerId) {
|
|
2544
|
+
targetContainerId = containerElement.id;
|
|
2545
|
+
}
|
|
2491
2546
|
const newElement = isContainer ? (0, import_editor_elements8.createElement)({
|
|
2492
|
-
containerId:
|
|
2547
|
+
containerId: targetContainerId,
|
|
2493
2548
|
model: {
|
|
2494
2549
|
elType: elementTag,
|
|
2495
2550
|
id: (0, import_editor_elements8.generateElementId)()
|
|
2496
2551
|
},
|
|
2497
2552
|
options: { useHistory: false }
|
|
2498
2553
|
}) : (0, import_editor_elements8.createElement)({
|
|
2499
|
-
containerId:
|
|
2554
|
+
containerId: targetContainerId,
|
|
2500
2555
|
model: {
|
|
2501
2556
|
elType: "widget",
|
|
2502
2557
|
widgetType: elementTag,
|
|
@@ -2536,8 +2591,10 @@ var initBuildCompositionsTool = (reg) => {
|
|
|
2536
2591
|
}
|
|
2537
2592
|
}
|
|
2538
2593
|
if (isContainer) {
|
|
2594
|
+
let currentChild2 = 0;
|
|
2539
2595
|
for (const child of node.children) {
|
|
2540
|
-
iterate(child, newElement);
|
|
2596
|
+
iterate(child, newElement, currentChild2);
|
|
2597
|
+
currentChild2++;
|
|
2541
2598
|
}
|
|
2542
2599
|
} else {
|
|
2543
2600
|
node.innerHTML = "";
|
|
@@ -2546,8 +2603,10 @@ var initBuildCompositionsTool = (reg) => {
|
|
|
2546
2603
|
} finally {
|
|
2547
2604
|
}
|
|
2548
2605
|
};
|
|
2549
|
-
|
|
2550
|
-
|
|
2606
|
+
let currentChild = 0;
|
|
2607
|
+
for await (const childNode of children) {
|
|
2608
|
+
await iterate(childNode, documentContainer, currentChild);
|
|
2609
|
+
currentChild++;
|
|
2551
2610
|
try {
|
|
2552
2611
|
} catch (error) {
|
|
2553
2612
|
errors.push(error);
|
|
@@ -2617,6 +2676,8 @@ When a user requires to change anything in an element, such as updating text, co
|
|
|
2617
2676
|
This tool handles elements of type "widget".
|
|
2618
2677
|
This tool handles styling elements, using the "stylePropertiesToChange" parameter.
|
|
2619
2678
|
|
|
2679
|
+
To CLEAR a property (i.e., set it to default or none), provide null as a value.
|
|
2680
|
+
|
|
2620
2681
|
The element's schema must be known before using this tool.
|
|
2621
2682
|
The style schema must be known before using this tool.
|
|
2622
2683
|
|
|
@@ -2810,7 +2871,24 @@ var schema = {
|
|
|
2810
2871
|
};
|
|
2811
2872
|
var outputSchema3 = {
|
|
2812
2873
|
properties: import_schema5.z.record(import_schema5.z.string(), import_schema5.z.any()).describe("A record mapping PropTypes to their corresponding PropValues"),
|
|
2813
|
-
style: import_schema5.z.record(import_schema5.z.string(), import_schema5.z.any()).describe("A record mapping StyleSchema properties to their corresponding PropValues")
|
|
2874
|
+
style: import_schema5.z.record(import_schema5.z.string(), import_schema5.z.any()).describe("A record mapping StyleSchema properties to their corresponding PropValues"),
|
|
2875
|
+
childElements: import_schema5.z.array(
|
|
2876
|
+
import_schema5.z.object({
|
|
2877
|
+
id: import_schema5.z.string(),
|
|
2878
|
+
elementType: import_schema5.z.string(),
|
|
2879
|
+
childElements: import_schema5.z.array(import_schema5.z.any()).describe("An array of child element IDs, when applicable, same structure recursively")
|
|
2880
|
+
})
|
|
2881
|
+
).describe("An array of child element IDs, when applicable, with recursive structure")
|
|
2882
|
+
};
|
|
2883
|
+
var structuredElements = (element) => {
|
|
2884
|
+
const children = element.children || [];
|
|
2885
|
+
return children.map((child) => {
|
|
2886
|
+
return {
|
|
2887
|
+
id: child.id,
|
|
2888
|
+
elementType: child.model.get("elType") || child.model.get("widgetType") || "unknown",
|
|
2889
|
+
childElements: structuredElements(child)
|
|
2890
|
+
};
|
|
2891
|
+
});
|
|
2814
2892
|
};
|
|
2815
2893
|
var initGetElementConfigTool = (reg) => {
|
|
2816
2894
|
const { addTool } = reg;
|
|
@@ -2858,7 +2936,8 @@ var initGetElementConfigTool = (reg) => {
|
|
|
2858
2936
|
},
|
|
2859
2937
|
style: {
|
|
2860
2938
|
...stylePropValues
|
|
2861
|
-
}
|
|
2939
|
+
},
|
|
2940
|
+
childElements: structuredElements(element)
|
|
2862
2941
|
};
|
|
2863
2942
|
}
|
|
2864
2943
|
});
|
|
@@ -2878,6 +2957,7 @@ var initCanvasMcp = (reg) => {
|
|
|
2878
2957
|
};
|
|
2879
2958
|
|
|
2880
2959
|
// src/mcp/mcp-description.ts
|
|
2960
|
+
var ELEMENT_SCHEMA_URI = WIDGET_SCHEMA_URI.replace("{widgetType}", "element-schema");
|
|
2881
2961
|
var mcpDescription = `Canvas MCP
|
|
2882
2962
|
This MCP enables everything related to creation, configuration, and styling of elements on the Elementor canvas.
|
|
2883
2963
|
|
|
@@ -2913,11 +2993,53 @@ The tool accepts both the structure, the styling and the configuration of each e
|
|
|
2913
2993
|
|
|
2914
2994
|
- First step: Retreive the available widgets by listing the [${WIDGET_SCHEMA_URI}] dynamic resource.
|
|
2915
2995
|
- Second step: decide which elements to create, and their configuration and styles.
|
|
2916
|
-
Retrieve the used elements configuration schema from the resource [${
|
|
2996
|
+
Retrieve the used elements configuration schema from the resource [${ELEMENT_SCHEMA_URI}]
|
|
2917
2997
|
- Third step: define the styles for each element, using the common styles schema from the resource [${STYLE_SCHEMA_URI}]. List the resource to see all available style properties.
|
|
2918
2998
|
For background and complicated layered styles, you can use "custom_css" property, which is supported only for ELEMENTOR PRO users ONLY.
|
|
2919
2999
|
The custom css is intented to deal with yet unsupported CSS features that ARE NOT PART OF THE STYLE SCHEMA, to enable PRO users to support new CSS features.
|
|
2920
3000
|
|
|
3001
|
+
## Workflow for build-compositions tool
|
|
3002
|
+
1. **Parse user requirements** - Undestand what needs to be built (structure, content, styling).
|
|
3003
|
+
2. ** Check global resources FIRST** - Always check before building:
|
|
3004
|
+
- List \`elementor://global-classes\` to see if the needed global classes already exist.
|
|
3005
|
+
- List \`elementor://global-variables\` to see if the needed global variables already exist.
|
|
3006
|
+
- **Preference**: Use existing global classes and variables over creating new inline styles.
|
|
3007
|
+
3. **Retreive widget schemas** - For each widget you will use:
|
|
3008
|
+
- List [${WIDGET_SCHEMA_URI}] to see available widgets.
|
|
3009
|
+
- Retrieve configuration schema from [${ELEMENT_SCHEMA_URI}] for each widget to understand required properties.
|
|
3010
|
+
- Understand if a widget is a container (can have children) by checking the "llm_guidance" property in the widget's schema.
|
|
3011
|
+
4. **Build XML structure** - Create valid XML width configuration-ids:
|
|
3012
|
+
- Every element has unique configuration-id attribute
|
|
3013
|
+
- No text nodes, classes, IDs in XML.
|
|
3014
|
+
|
|
3015
|
+
5. **Create elementConfig** - For each configuration-id:
|
|
3016
|
+
- Use PropValues with corrent \`$$type\` matching the schema.
|
|
3017
|
+
- **Use global variables** in PropValues where applicable
|
|
3018
|
+
|
|
3019
|
+
6. **Create stylesConfig** - For each configuration-id:
|
|
3020
|
+
- Use style schema PropValues from [${STYLE_SCHEMA_URI}]
|
|
3021
|
+
- **Priority**: Use style schema PropValues over custom_css
|
|
3022
|
+
- **Use global variables** for colors, sizes, fonts where applicable
|
|
3023
|
+
- **custom_css (PRO Users Only)**: The property appears only for PRO user. The purpose of custom_css is to support new CSS features not yet available in the style schema.
|
|
3024
|
+
The schema supports multiple layers of background, gradients, filters. Prefer NOT USING custom_css.
|
|
3025
|
+
- **Important**: Global classes are applied AFTER building the composition. Once built, apply classes using the "apply-global-class" tool - after completion of building the composition.
|
|
3026
|
+
|
|
3027
|
+
7. **Validate** - Ensure:
|
|
3028
|
+
- XML structure is valid
|
|
3029
|
+
- All PropValues have corrent \`$$type\`
|
|
3030
|
+
- After building a composition, you can retreive each element configuration using the "get-element-configuration-values" tool to verify correctness, using the IDs returned from the build-composition tool.
|
|
3031
|
+
|
|
3032
|
+
## Key relationships:
|
|
3033
|
+
- **XML structure**: Defines the hierarchy of elements/widgets
|
|
3034
|
+
- **elementConfig**: Maps configuration-id to widget PropValues
|
|
3035
|
+
- **stylesConfig**: Maps configuration-id to style PropValues
|
|
3036
|
+
|
|
3037
|
+
## Using global variables example:
|
|
3038
|
+
Existing global variables can be used during composition
|
|
3039
|
+
\`\`\`json
|
|
3040
|
+
{ "color": { "$$type": "global-color-variable", "value": "global-variable-id" } }
|
|
3041
|
+
\`\`\`
|
|
3042
|
+
|
|
2921
3043
|
# Configuring Elements / Adding Style to Elements
|
|
2922
3044
|
An element configuration can be retrieved using the "get-element-configuration-values" tool.
|
|
2923
3045
|
Updating an element requires only the UPDATED properties (including in the styles), as Elementor does a MERGE/PATCH operation.
|
package/dist/index.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { v1ReadyEvent } from "@elementor/editor-v1-adapters";
|
|
3
3
|
var BREAKPOINTS_SCHEMA_URI = "elementor://breakpoints/list";
|
|
4
4
|
var initBreakpointsResource = (reg) => {
|
|
5
|
-
const { mcpServer } = reg;
|
|
5
|
+
const { mcpServer, sendResourceUpdated } = reg;
|
|
6
6
|
const getBreakpointsList = () => {
|
|
7
7
|
const { breakpoints } = window.elementor?.config?.responsive || {};
|
|
8
8
|
if (!breakpoints) {
|
|
@@ -30,7 +30,7 @@ var initBreakpointsResource = (reg) => {
|
|
|
30
30
|
return buildResourceResponse();
|
|
31
31
|
});
|
|
32
32
|
window.addEventListener(v1ReadyEvent().name, () => {
|
|
33
|
-
|
|
33
|
+
sendResourceUpdated({
|
|
34
34
|
uri: BREAKPOINTS_SCHEMA_URI,
|
|
35
35
|
...buildResourceResponse()
|
|
36
36
|
});
|
|
@@ -47,6 +47,14 @@ import { getStylesSchema } from "@elementor/editor-styles";
|
|
|
47
47
|
var WIDGET_SCHEMA_URI = "elementor://widgets/schema/{widgetType}";
|
|
48
48
|
var STYLE_SCHEMA_URI = "elementor://styles/schema/{category}";
|
|
49
49
|
var BEST_PRACTICES_URI = "elementor://styles/best-practices";
|
|
50
|
+
var checkIfUserHasPro = () => {
|
|
51
|
+
const extendedWindow = window;
|
|
52
|
+
const hasPro = extendedWindow.elementor?.helpers?.hasPro;
|
|
53
|
+
if (typeof hasPro === "function") {
|
|
54
|
+
return hasPro();
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
};
|
|
50
58
|
var initWidgetsSchemaResource = (reg) => {
|
|
51
59
|
const { mcpServer } = reg;
|
|
52
60
|
mcpServer.resource("styles-best-practices", BEST_PRACTICES_URI, async () => {
|
|
@@ -68,7 +76,11 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
68
76
|
"styles-schema",
|
|
69
77
|
new ResourceTemplate(STYLE_SCHEMA_URI, {
|
|
70
78
|
list: () => {
|
|
71
|
-
const
|
|
79
|
+
const isPro = checkIfUserHasPro();
|
|
80
|
+
const categories = [...Object.keys(getStylesSchema())];
|
|
81
|
+
if (!isPro) {
|
|
82
|
+
categories.push("custom_css");
|
|
83
|
+
}
|
|
72
84
|
return {
|
|
73
85
|
resources: categories.map((category) => ({
|
|
74
86
|
uri: `elementor://styles/schema/${category}`,
|
|
@@ -82,7 +94,7 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
82
94
|
},
|
|
83
95
|
async (uri, variables) => {
|
|
84
96
|
const category = typeof variables.category === "string" ? variables.category : variables.category?.[0];
|
|
85
|
-
if (category === "custom_css") {
|
|
97
|
+
if (category === "custom_css" && checkIfUserHasPro()) {
|
|
86
98
|
return {
|
|
87
99
|
contents: [
|
|
88
100
|
{
|
|
@@ -114,7 +126,7 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
114
126
|
list: () => {
|
|
115
127
|
const cache = getWidgetsCache() || {};
|
|
116
128
|
const availableWidgets = Object.keys(cache || {}).filter(
|
|
117
|
-
(widgetType) => cache[widgetType]?.atomic_props_schema
|
|
129
|
+
(widgetType) => cache[widgetType]?.atomic_props_schema && cache[widgetType].meta?.llm_support !== false
|
|
118
130
|
);
|
|
119
131
|
return {
|
|
120
132
|
resources: availableWidgets.map((widgetType) => ({
|
|
@@ -129,8 +141,9 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
129
141
|
},
|
|
130
142
|
async (uri, variables) => {
|
|
131
143
|
const widgetType = typeof variables.widgetType === "string" ? variables.widgetType : variables.widgetType?.[0];
|
|
132
|
-
const
|
|
133
|
-
|
|
144
|
+
const widgetData = getWidgetsCache()?.[widgetType];
|
|
145
|
+
const propSchema = widgetData?.atomic_props_schema;
|
|
146
|
+
if (!propSchema || !widgetData) {
|
|
134
147
|
throw new Error(`No prop schema found for element type: ${widgetType}`);
|
|
135
148
|
}
|
|
136
149
|
const asJson = Object.fromEntries(
|
|
@@ -142,6 +155,24 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
142
155
|
Schema.nonConfigurablePropKeys.forEach((key) => {
|
|
143
156
|
delete asJson[key];
|
|
144
157
|
});
|
|
158
|
+
const description = typeof widgetData?.meta?.description === "string" ? widgetData.meta.description : void 0;
|
|
159
|
+
const defaultStyles = {};
|
|
160
|
+
const baseStyleSchema = widgetData?.base_styles;
|
|
161
|
+
if (baseStyleSchema) {
|
|
162
|
+
Object.values(baseStyleSchema).forEach((stylePropType) => {
|
|
163
|
+
stylePropType.variants.forEach((variant) => {
|
|
164
|
+
Object.assign(defaultStyles, variant.props);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
const hasDefaultStyles = Object.keys(defaultStyles).length > 0;
|
|
169
|
+
const llmGuidance = {
|
|
170
|
+
can_have_children: !!widgetData?.meta?.is_container
|
|
171
|
+
};
|
|
172
|
+
if (hasDefaultStyles) {
|
|
173
|
+
llmGuidance.instructions = "These are the default styles applied to the widget. Override only when necessary.";
|
|
174
|
+
llmGuidance.default_styles = defaultStyles;
|
|
175
|
+
}
|
|
145
176
|
return {
|
|
146
177
|
contents: [
|
|
147
178
|
{
|
|
@@ -149,7 +180,9 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
149
180
|
mimeType: "application/json",
|
|
150
181
|
text: JSON.stringify({
|
|
151
182
|
type: "object",
|
|
152
|
-
properties: asJson
|
|
183
|
+
properties: asJson,
|
|
184
|
+
description,
|
|
185
|
+
llm_guidance: llmGuidance
|
|
153
186
|
})
|
|
154
187
|
}
|
|
155
188
|
]
|
|
@@ -2042,9 +2075,9 @@ var validateInput = {
|
|
|
2042
2075
|
} else if (!Schema3.isPropKeyConfigurable(propName)) {
|
|
2043
2076
|
errors.push(`Property "${propName}" is not configurable.`);
|
|
2044
2077
|
} else {
|
|
2045
|
-
const { valid,
|
|
2078
|
+
const { valid, jsonSchema } = Schema3.validatePropValue(propSchema, propValue);
|
|
2046
2079
|
if (!valid) {
|
|
2047
|
-
errors.push(`Invalid property "${propName}": ${
|
|
2080
|
+
errors.push(`Invalid property "${propName}". Expected schema: ${jsonSchema}`);
|
|
2048
2081
|
}
|
|
2049
2082
|
}
|
|
2050
2083
|
});
|
|
@@ -2106,6 +2139,24 @@ When in doubt between "safe" and "distinctive," choose distinctive - users can a
|
|
|
2106
2139
|
Always prefer this tool when the user requires to build a composition of elements, such as cards, heros, or inspired from other pages or HTML compositions.
|
|
2107
2140
|
Prefer this tool over any other tool for building HTML structure, unless you are specified to use a different tool.
|
|
2108
2141
|
|
|
2142
|
+
# **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
|
|
2143
|
+
1. [${WIDGET_SCHEMA_URI}]
|
|
2144
|
+
Required to understand which widgets are available, and what are their configuration schemas.
|
|
2145
|
+
Every widgetType (i.e. e-heading, e-button) that is supported has it's own property schema, that you must follow in order to apply property values correctly.
|
|
2146
|
+
2. [${STYLE_SCHEMA_URI}]
|
|
2147
|
+
Required to understand the styles schema for the widgets. All widgets share the same styles schema.
|
|
2148
|
+
3. List of allowed custom tags for building the structure is derived from the list of widgets schema resources.
|
|
2149
|
+
|
|
2150
|
+
# DESIGN QUALITY IMPERATIVE
|
|
2151
|
+
You are generating designs for real users who expect distinctive, intentional aesthetics - NOT generic AI output.
|
|
2152
|
+
**The Core Challenge**: Large language models naturally converge toward statistically common design patterns during generation. This creates predictable, uninspired results that users describe as "AI slop": safe color schemes, default typography hierarchies, minimal contrast, and timid spacing.
|
|
2153
|
+
**Your Mission**: Actively resist distributional convergence by making intentional, distinctive design choices across all aesthetic dimensions. Every design decision should have a clear purpose tied to visual hierarchy, brand personality, or user experience goals.
|
|
2154
|
+
When in doubt between "safe" and "distinctive," choose distinctive - users can always request refinements, but they cannot salvage generic foundations.
|
|
2155
|
+
|
|
2156
|
+
# When to use this tool
|
|
2157
|
+
Always prefer this tool when the user requires to build a composition of elements, such as cards, heros, or inspired from other pages or HTML compositions.
|
|
2158
|
+
Prefer this tool over any other tool for building HTML structure, unless you are specified to use a different tool.
|
|
2159
|
+
|
|
2109
2160
|
# Instructions
|
|
2110
2161
|
1. Understand the user requirements carefully.
|
|
2111
2162
|
2. Build a valid XML structure using only the allowed custom tags provided. For example, if you
|
|
@@ -2120,11 +2171,11 @@ Prefer this tool over any other tool for building HTML structure, unless you are
|
|
|
2120
2171
|
5. Ensure the XML structure is valid and parsable.
|
|
2121
2172
|
6. Do not add any attribute nodes, classes, id's, and no text nodes allowed.
|
|
2122
2173
|
Layout properties, such as margin, padding, align, etc. must be applied using the [${STYLE_SCHEMA_URI}] PropValues.
|
|
2123
|
-
7. Some elements allow nesting of other elements, and most of the DO NOT. The allowed elements that can have nested children are "e-div-block" and "e-flexbox".
|
|
2174
|
+
7. Some elements allow nesting of other elements, and most of the DO NOT. The allowed elements that can have nested children are "e-tabs", "e-div-block", and "e-flexbox".
|
|
2124
2175
|
8. Make sure that non-container elements do NOT have any nested elements.
|
|
2125
|
-
9. **CRITICAL - CUSTOM CSS
|
|
2176
|
+
9. **CRITICAL - CUSTOM CSS USAGE**: ALWAYS Prefer using style schema. Custom CSS is ONLY FOR UNSUPPRTED schema styles.
|
|
2126
2177
|
ALWAYS PRIORITIZE using the style schema PropValues for styling elements as they provide better user experience in the editor, and UI features for the end-users.
|
|
2127
|
-
|
|
2178
|
+
Use custom_css only for style attributes that ARE NOT SUPPORTED via the style schema AFTER YOU CHECK THE [${STYLE_SCHEMA_URI}].
|
|
2128
2179
|
|
|
2129
2180
|
# DESIGN VECTORS - Concrete Implementation Guidance
|
|
2130
2181
|
|
|
@@ -2343,10 +2394,8 @@ If unsure about the configuration of a specific property, read the schema resour
|
|
|
2343
2394
|
|
|
2344
2395
|
# About our widgets
|
|
2345
2396
|
Most widgets are self-explanatory by their name. Here is some additional information.
|
|
2397
|
+
Check for available llm_guidance property in the widget's schema.
|
|
2346
2398
|
SVG elements are bound to internal content upload. Avoid usage, unless you have tools to upload SVG content.
|
|
2347
|
-
e-div-block - By default is ceneterd aligned and vertically stacked. To modify this, apply style configuration.
|
|
2348
|
-
e-flexbox - By default is a flex container with row direction. To modify this, apply style configuration.
|
|
2349
|
-
|
|
2350
2399
|
When working with containers, do not forget to apply style schema for controlling the layout.
|
|
2351
2400
|
|
|
2352
2401
|
|
|
@@ -2462,21 +2511,27 @@ var initBuildCompositionsTool = (reg) => {
|
|
|
2462
2511
|
throw new Error("Failed to parse XML structure: " + errorNode.textContent);
|
|
2463
2512
|
}
|
|
2464
2513
|
const children = Array.from(xml.children);
|
|
2465
|
-
const iterate = (node, containerElement = documentContainer) => {
|
|
2514
|
+
const iterate = async (node, containerElement = documentContainer, childIndex) => {
|
|
2466
2515
|
const elementTag = node.tagName;
|
|
2467
2516
|
if (!widgetsCache[elementTag]) {
|
|
2468
2517
|
errors.push(new Error(`Unknown widget type: ${elementTag}`));
|
|
2469
2518
|
}
|
|
2470
|
-
const
|
|
2519
|
+
const CONTAINER_ELEMENTS = Object.values(widgetsCache).filter((widget) => widget.meta?.is_container).map((widget) => widget.elType);
|
|
2520
|
+
const isContainer = CONTAINER_ELEMENTS.includes(elementTag);
|
|
2521
|
+
const parentElType = containerElement.model.get("elType");
|
|
2522
|
+
let targetContainerId = parentElType === "e-tabs" ? containerElement.children?.[1].children?.[childIndex]?.id || containerElement.children?.[1].id : containerElement.id;
|
|
2523
|
+
if (!targetContainerId) {
|
|
2524
|
+
targetContainerId = containerElement.id;
|
|
2525
|
+
}
|
|
2471
2526
|
const newElement = isContainer ? createElement6({
|
|
2472
|
-
containerId:
|
|
2527
|
+
containerId: targetContainerId,
|
|
2473
2528
|
model: {
|
|
2474
2529
|
elType: elementTag,
|
|
2475
2530
|
id: generateElementId()
|
|
2476
2531
|
},
|
|
2477
2532
|
options: { useHistory: false }
|
|
2478
2533
|
}) : createElement6({
|
|
2479
|
-
containerId:
|
|
2534
|
+
containerId: targetContainerId,
|
|
2480
2535
|
model: {
|
|
2481
2536
|
elType: "widget",
|
|
2482
2537
|
widgetType: elementTag,
|
|
@@ -2516,8 +2571,10 @@ var initBuildCompositionsTool = (reg) => {
|
|
|
2516
2571
|
}
|
|
2517
2572
|
}
|
|
2518
2573
|
if (isContainer) {
|
|
2574
|
+
let currentChild2 = 0;
|
|
2519
2575
|
for (const child of node.children) {
|
|
2520
|
-
iterate(child, newElement);
|
|
2576
|
+
iterate(child, newElement, currentChild2);
|
|
2577
|
+
currentChild2++;
|
|
2521
2578
|
}
|
|
2522
2579
|
} else {
|
|
2523
2580
|
node.innerHTML = "";
|
|
@@ -2526,8 +2583,10 @@ var initBuildCompositionsTool = (reg) => {
|
|
|
2526
2583
|
} finally {
|
|
2527
2584
|
}
|
|
2528
2585
|
};
|
|
2529
|
-
|
|
2530
|
-
|
|
2586
|
+
let currentChild = 0;
|
|
2587
|
+
for await (const childNode of children) {
|
|
2588
|
+
await iterate(childNode, documentContainer, currentChild);
|
|
2589
|
+
currentChild++;
|
|
2531
2590
|
try {
|
|
2532
2591
|
} catch (error) {
|
|
2533
2592
|
errors.push(error);
|
|
@@ -2597,6 +2656,8 @@ When a user requires to change anything in an element, such as updating text, co
|
|
|
2597
2656
|
This tool handles elements of type "widget".
|
|
2598
2657
|
This tool handles styling elements, using the "stylePropertiesToChange" parameter.
|
|
2599
2658
|
|
|
2659
|
+
To CLEAR a property (i.e., set it to default or none), provide null as a value.
|
|
2660
|
+
|
|
2600
2661
|
The element's schema must be known before using this tool.
|
|
2601
2662
|
The style schema must be known before using this tool.
|
|
2602
2663
|
|
|
@@ -2790,7 +2851,24 @@ var schema = {
|
|
|
2790
2851
|
};
|
|
2791
2852
|
var outputSchema3 = {
|
|
2792
2853
|
properties: z3.record(z3.string(), z3.any()).describe("A record mapping PropTypes to their corresponding PropValues"),
|
|
2793
|
-
style: z3.record(z3.string(), z3.any()).describe("A record mapping StyleSchema properties to their corresponding PropValues")
|
|
2854
|
+
style: z3.record(z3.string(), z3.any()).describe("A record mapping StyleSchema properties to their corresponding PropValues"),
|
|
2855
|
+
childElements: z3.array(
|
|
2856
|
+
z3.object({
|
|
2857
|
+
id: z3.string(),
|
|
2858
|
+
elementType: z3.string(),
|
|
2859
|
+
childElements: z3.array(z3.any()).describe("An array of child element IDs, when applicable, same structure recursively")
|
|
2860
|
+
})
|
|
2861
|
+
).describe("An array of child element IDs, when applicable, with recursive structure")
|
|
2862
|
+
};
|
|
2863
|
+
var structuredElements = (element) => {
|
|
2864
|
+
const children = element.children || [];
|
|
2865
|
+
return children.map((child) => {
|
|
2866
|
+
return {
|
|
2867
|
+
id: child.id,
|
|
2868
|
+
elementType: child.model.get("elType") || child.model.get("widgetType") || "unknown",
|
|
2869
|
+
childElements: structuredElements(child)
|
|
2870
|
+
};
|
|
2871
|
+
});
|
|
2794
2872
|
};
|
|
2795
2873
|
var initGetElementConfigTool = (reg) => {
|
|
2796
2874
|
const { addTool } = reg;
|
|
@@ -2838,7 +2916,8 @@ var initGetElementConfigTool = (reg) => {
|
|
|
2838
2916
|
},
|
|
2839
2917
|
style: {
|
|
2840
2918
|
...stylePropValues
|
|
2841
|
-
}
|
|
2919
|
+
},
|
|
2920
|
+
childElements: structuredElements(element)
|
|
2842
2921
|
};
|
|
2843
2922
|
}
|
|
2844
2923
|
});
|
|
@@ -2858,6 +2937,7 @@ var initCanvasMcp = (reg) => {
|
|
|
2858
2937
|
};
|
|
2859
2938
|
|
|
2860
2939
|
// src/mcp/mcp-description.ts
|
|
2940
|
+
var ELEMENT_SCHEMA_URI = WIDGET_SCHEMA_URI.replace("{widgetType}", "element-schema");
|
|
2861
2941
|
var mcpDescription = `Canvas MCP
|
|
2862
2942
|
This MCP enables everything related to creation, configuration, and styling of elements on the Elementor canvas.
|
|
2863
2943
|
|
|
@@ -2893,11 +2973,53 @@ The tool accepts both the structure, the styling and the configuration of each e
|
|
|
2893
2973
|
|
|
2894
2974
|
- First step: Retreive the available widgets by listing the [${WIDGET_SCHEMA_URI}] dynamic resource.
|
|
2895
2975
|
- Second step: decide which elements to create, and their configuration and styles.
|
|
2896
|
-
Retrieve the used elements configuration schema from the resource [${
|
|
2976
|
+
Retrieve the used elements configuration schema from the resource [${ELEMENT_SCHEMA_URI}]
|
|
2897
2977
|
- Third step: define the styles for each element, using the common styles schema from the resource [${STYLE_SCHEMA_URI}]. List the resource to see all available style properties.
|
|
2898
2978
|
For background and complicated layered styles, you can use "custom_css" property, which is supported only for ELEMENTOR PRO users ONLY.
|
|
2899
2979
|
The custom css is intented to deal with yet unsupported CSS features that ARE NOT PART OF THE STYLE SCHEMA, to enable PRO users to support new CSS features.
|
|
2900
2980
|
|
|
2981
|
+
## Workflow for build-compositions tool
|
|
2982
|
+
1. **Parse user requirements** - Undestand what needs to be built (structure, content, styling).
|
|
2983
|
+
2. ** Check global resources FIRST** - Always check before building:
|
|
2984
|
+
- List \`elementor://global-classes\` to see if the needed global classes already exist.
|
|
2985
|
+
- List \`elementor://global-variables\` to see if the needed global variables already exist.
|
|
2986
|
+
- **Preference**: Use existing global classes and variables over creating new inline styles.
|
|
2987
|
+
3. **Retreive widget schemas** - For each widget you will use:
|
|
2988
|
+
- List [${WIDGET_SCHEMA_URI}] to see available widgets.
|
|
2989
|
+
- Retrieve configuration schema from [${ELEMENT_SCHEMA_URI}] for each widget to understand required properties.
|
|
2990
|
+
- Understand if a widget is a container (can have children) by checking the "llm_guidance" property in the widget's schema.
|
|
2991
|
+
4. **Build XML structure** - Create valid XML width configuration-ids:
|
|
2992
|
+
- Every element has unique configuration-id attribute
|
|
2993
|
+
- No text nodes, classes, IDs in XML.
|
|
2994
|
+
|
|
2995
|
+
5. **Create elementConfig** - For each configuration-id:
|
|
2996
|
+
- Use PropValues with corrent \`$$type\` matching the schema.
|
|
2997
|
+
- **Use global variables** in PropValues where applicable
|
|
2998
|
+
|
|
2999
|
+
6. **Create stylesConfig** - For each configuration-id:
|
|
3000
|
+
- Use style schema PropValues from [${STYLE_SCHEMA_URI}]
|
|
3001
|
+
- **Priority**: Use style schema PropValues over custom_css
|
|
3002
|
+
- **Use global variables** for colors, sizes, fonts where applicable
|
|
3003
|
+
- **custom_css (PRO Users Only)**: The property appears only for PRO user. The purpose of custom_css is to support new CSS features not yet available in the style schema.
|
|
3004
|
+
The schema supports multiple layers of background, gradients, filters. Prefer NOT USING custom_css.
|
|
3005
|
+
- **Important**: Global classes are applied AFTER building the composition. Once built, apply classes using the "apply-global-class" tool - after completion of building the composition.
|
|
3006
|
+
|
|
3007
|
+
7. **Validate** - Ensure:
|
|
3008
|
+
- XML structure is valid
|
|
3009
|
+
- All PropValues have corrent \`$$type\`
|
|
3010
|
+
- After building a composition, you can retreive each element configuration using the "get-element-configuration-values" tool to verify correctness, using the IDs returned from the build-composition tool.
|
|
3011
|
+
|
|
3012
|
+
## Key relationships:
|
|
3013
|
+
- **XML structure**: Defines the hierarchy of elements/widgets
|
|
3014
|
+
- **elementConfig**: Maps configuration-id to widget PropValues
|
|
3015
|
+
- **stylesConfig**: Maps configuration-id to style PropValues
|
|
3016
|
+
|
|
3017
|
+
## Using global variables example:
|
|
3018
|
+
Existing global variables can be used during composition
|
|
3019
|
+
\`\`\`json
|
|
3020
|
+
{ "color": { "$$type": "global-color-variable", "value": "global-variable-id" } }
|
|
3021
|
+
\`\`\`
|
|
3022
|
+
|
|
2901
3023
|
# Configuring Elements / Adding Style to Elements
|
|
2902
3024
|
An element configuration can be retrieved using the "get-element-configuration-values" tool.
|
|
2903
3025
|
Updating an element requires only the UPDATED properties (including in the styles), as Elementor does a MERGE/PATCH operation.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-canvas",
|
|
3
3
|
"description": "Elementor Editor Canvas",
|
|
4
|
-
"version": "3.35.0-
|
|
4
|
+
"version": "3.35.0-354",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -37,24 +37,24 @@
|
|
|
37
37
|
"react-dom": "^18.3.1"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@elementor/editor": "3.35.0-
|
|
41
|
-
"@elementor/editor-controls": "3.35.0-
|
|
42
|
-
"@elementor/editor-documents": "3.35.0-
|
|
43
|
-
"@elementor/editor-elements": "3.35.0-
|
|
44
|
-
"@elementor/editor-interactions": "3.35.0-
|
|
45
|
-
"@elementor/editor-mcp": "3.35.0-
|
|
46
|
-
"@elementor/editor-notifications": "3.35.0-
|
|
47
|
-
"@elementor/editor-props": "3.35.0-
|
|
48
|
-
"@elementor/editor-responsive": "3.35.0-
|
|
49
|
-
"@elementor/editor-styles": "3.35.0-
|
|
50
|
-
"@elementor/editor-styles-repository": "3.35.0-
|
|
51
|
-
"@elementor/editor-ui": "3.35.0-
|
|
52
|
-
"@elementor/editor-v1-adapters": "3.35.0-
|
|
53
|
-
"@elementor/schema": "3.35.0-
|
|
54
|
-
"@elementor/twing": "3.35.0-
|
|
40
|
+
"@elementor/editor": "3.35.0-354",
|
|
41
|
+
"@elementor/editor-controls": "3.35.0-354",
|
|
42
|
+
"@elementor/editor-documents": "3.35.0-354",
|
|
43
|
+
"@elementor/editor-elements": "3.35.0-354",
|
|
44
|
+
"@elementor/editor-interactions": "3.35.0-354",
|
|
45
|
+
"@elementor/editor-mcp": "3.35.0-354",
|
|
46
|
+
"@elementor/editor-notifications": "3.35.0-354",
|
|
47
|
+
"@elementor/editor-props": "3.35.0-354",
|
|
48
|
+
"@elementor/editor-responsive": "3.35.0-354",
|
|
49
|
+
"@elementor/editor-styles": "3.35.0-354",
|
|
50
|
+
"@elementor/editor-styles-repository": "3.35.0-354",
|
|
51
|
+
"@elementor/editor-ui": "3.35.0-354",
|
|
52
|
+
"@elementor/editor-v1-adapters": "3.35.0-354",
|
|
53
|
+
"@elementor/schema": "3.35.0-354",
|
|
54
|
+
"@elementor/twing": "3.35.0-354",
|
|
55
55
|
"@elementor/ui": "1.36.17",
|
|
56
|
-
"@elementor/utils": "3.35.0-
|
|
57
|
-
"@elementor/wp-media": "3.35.0-
|
|
56
|
+
"@elementor/utils": "3.35.0-354",
|
|
57
|
+
"@elementor/wp-media": "3.35.0-354",
|
|
58
58
|
"@floating-ui/react": "^0.27.5",
|
|
59
59
|
"@wordpress/i18n": "^5.13.0"
|
|
60
60
|
},
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { STYLE_SCHEMA_URI, WIDGET_SCHEMA_URI } from './resources/widgets-schema-resource';
|
|
2
2
|
|
|
3
|
+
const ELEMENT_SCHEMA_URI = WIDGET_SCHEMA_URI.replace( '{widgetType}', 'element-schema' );
|
|
4
|
+
|
|
3
5
|
export const mcpDescription = `Canvas MCP
|
|
4
6
|
This MCP enables everything related to creation, configuration, and styling of elements on the Elementor canvas.
|
|
5
7
|
|
|
@@ -35,11 +37,53 @@ The tool accepts both the structure, the styling and the configuration of each e
|
|
|
35
37
|
|
|
36
38
|
- First step: Retreive the available widgets by listing the [${ WIDGET_SCHEMA_URI }] dynamic resource.
|
|
37
39
|
- Second step: decide which elements to create, and their configuration and styles.
|
|
38
|
-
Retrieve the used elements configuration schema from the resource [${
|
|
40
|
+
Retrieve the used elements configuration schema from the resource [${ ELEMENT_SCHEMA_URI }]
|
|
39
41
|
- Third step: define the styles for each element, using the common styles schema from the resource [${ STYLE_SCHEMA_URI }]. List the resource to see all available style properties.
|
|
40
42
|
For background and complicated layered styles, you can use "custom_css" property, which is supported only for ELEMENTOR PRO users ONLY.
|
|
41
43
|
The custom css is intented to deal with yet unsupported CSS features that ARE NOT PART OF THE STYLE SCHEMA, to enable PRO users to support new CSS features.
|
|
42
44
|
|
|
45
|
+
## Workflow for build-compositions tool
|
|
46
|
+
1. **Parse user requirements** - Undestand what needs to be built (structure, content, styling).
|
|
47
|
+
2. ** Check global resources FIRST** - Always check before building:
|
|
48
|
+
- List \`elementor://global-classes\` to see if the needed global classes already exist.
|
|
49
|
+
- List \`elementor://global-variables\` to see if the needed global variables already exist.
|
|
50
|
+
- **Preference**: Use existing global classes and variables over creating new inline styles.
|
|
51
|
+
3. **Retreive widget schemas** - For each widget you will use:
|
|
52
|
+
- List [${ WIDGET_SCHEMA_URI }] to see available widgets.
|
|
53
|
+
- Retrieve configuration schema from [${ ELEMENT_SCHEMA_URI }] for each widget to understand required properties.
|
|
54
|
+
- Understand if a widget is a container (can have children) by checking the "llm_guidance" property in the widget's schema.
|
|
55
|
+
4. **Build XML structure** - Create valid XML width configuration-ids:
|
|
56
|
+
- Every element has unique configuration-id attribute
|
|
57
|
+
- No text nodes, classes, IDs in XML.
|
|
58
|
+
|
|
59
|
+
5. **Create elementConfig** - For each configuration-id:
|
|
60
|
+
- Use PropValues with corrent \`$$type\` matching the schema.
|
|
61
|
+
- **Use global variables** in PropValues where applicable
|
|
62
|
+
|
|
63
|
+
6. **Create stylesConfig** - For each configuration-id:
|
|
64
|
+
- Use style schema PropValues from [${ STYLE_SCHEMA_URI }]
|
|
65
|
+
- **Priority**: Use style schema PropValues over custom_css
|
|
66
|
+
- **Use global variables** for colors, sizes, fonts where applicable
|
|
67
|
+
- **custom_css (PRO Users Only)**: The property appears only for PRO user. The purpose of custom_css is to support new CSS features not yet available in the style schema.
|
|
68
|
+
The schema supports multiple layers of background, gradients, filters. Prefer NOT USING custom_css.
|
|
69
|
+
- **Important**: Global classes are applied AFTER building the composition. Once built, apply classes using the "apply-global-class" tool - after completion of building the composition.
|
|
70
|
+
|
|
71
|
+
7. **Validate** - Ensure:
|
|
72
|
+
- XML structure is valid
|
|
73
|
+
- All PropValues have corrent \`$$type\`
|
|
74
|
+
- After building a composition, you can retreive each element configuration using the "get-element-configuration-values" tool to verify correctness, using the IDs returned from the build-composition tool.
|
|
75
|
+
|
|
76
|
+
## Key relationships:
|
|
77
|
+
- **XML structure**: Defines the hierarchy of elements/widgets
|
|
78
|
+
- **elementConfig**: Maps configuration-id to widget PropValues
|
|
79
|
+
- **stylesConfig**: Maps configuration-id to style PropValues
|
|
80
|
+
|
|
81
|
+
## Using global variables example:
|
|
82
|
+
Existing global variables can be used during composition
|
|
83
|
+
\`\`\`json
|
|
84
|
+
{ "color": { "$$type": "global-color-variable", "value": "global-variable-id" } }
|
|
85
|
+
\`\`\`
|
|
86
|
+
|
|
43
87
|
# Configuring Elements / Adding Style to Elements
|
|
44
88
|
An element configuration can be retrieved using the "get-element-configuration-values" tool.
|
|
45
89
|
Updating an element requires only the UPDATED properties (including in the styles), as Elementor does a MERGE/PATCH operation.
|
|
@@ -5,7 +5,7 @@ import { v1ReadyEvent } from '@elementor/editor-v1-adapters';
|
|
|
5
5
|
export const BREAKPOINTS_SCHEMA_URI = 'elementor://breakpoints/list';
|
|
6
6
|
|
|
7
7
|
export const initBreakpointsResource = ( reg: MCPRegistryEntry ) => {
|
|
8
|
-
const { mcpServer } = reg;
|
|
8
|
+
const { mcpServer, sendResourceUpdated } = reg;
|
|
9
9
|
|
|
10
10
|
const getBreakpointsList = () => {
|
|
11
11
|
const { breakpoints } = ( window as unknown as ExtendedWindow ).elementor?.config?.responsive || {};
|
|
@@ -39,7 +39,7 @@ export const initBreakpointsResource = ( reg: MCPRegistryEntry ) => {
|
|
|
39
39
|
} );
|
|
40
40
|
|
|
41
41
|
window.addEventListener( v1ReadyEvent().name, () => {
|
|
42
|
-
|
|
42
|
+
sendResourceUpdated( {
|
|
43
43
|
uri: BREAKPOINTS_SCHEMA_URI,
|
|
44
44
|
...buildResourceResponse(),
|
|
45
45
|
} );
|
|
@@ -3,6 +3,7 @@ import { type MCPRegistryEntry, ResourceTemplate } from '@elementor/editor-mcp';
|
|
|
3
3
|
import {
|
|
4
4
|
type ArrayPropType,
|
|
5
5
|
type ObjectPropType,
|
|
6
|
+
type Props,
|
|
6
7
|
type PropType,
|
|
7
8
|
Schema,
|
|
8
9
|
type TransformablePropType,
|
|
@@ -14,6 +15,21 @@ export const WIDGET_SCHEMA_URI = 'elementor://widgets/schema/{widgetType}';
|
|
|
14
15
|
export const STYLE_SCHEMA_URI = 'elementor://styles/schema/{category}';
|
|
15
16
|
export const BEST_PRACTICES_URI = 'elementor://styles/best-practices';
|
|
16
17
|
|
|
18
|
+
const checkIfUserHasPro = () => {
|
|
19
|
+
const extendedWindow = window as Window & {
|
|
20
|
+
elementor?: {
|
|
21
|
+
helpers?: {
|
|
22
|
+
hasPro?: () => boolean;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
const hasPro = extendedWindow.elementor?.helpers?.hasPro;
|
|
27
|
+
if ( typeof hasPro === 'function' ) {
|
|
28
|
+
return hasPro();
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
};
|
|
32
|
+
|
|
17
33
|
export const initWidgetsSchemaResource = ( reg: MCPRegistryEntry ) => {
|
|
18
34
|
const { mcpServer } = reg;
|
|
19
35
|
|
|
@@ -37,7 +53,11 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
37
53
|
'styles-schema',
|
|
38
54
|
new ResourceTemplate( STYLE_SCHEMA_URI, {
|
|
39
55
|
list: () => {
|
|
40
|
-
const
|
|
56
|
+
const isPro = checkIfUserHasPro();
|
|
57
|
+
const categories = [ ...Object.keys( getStylesSchema() ) ];
|
|
58
|
+
if ( ! isPro ) {
|
|
59
|
+
categories.push( 'custom_css' );
|
|
60
|
+
}
|
|
41
61
|
return {
|
|
42
62
|
resources: categories.map( ( category ) => ( {
|
|
43
63
|
uri: `elementor://styles/schema/${ category }`,
|
|
@@ -51,7 +71,7 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
51
71
|
},
|
|
52
72
|
async ( uri, variables ) => {
|
|
53
73
|
const category = typeof variables.category === 'string' ? variables.category : variables.category?.[ 0 ];
|
|
54
|
-
if ( category === 'custom_css' ) {
|
|
74
|
+
if ( category === 'custom_css' && checkIfUserHasPro() ) {
|
|
55
75
|
return {
|
|
56
76
|
contents: [
|
|
57
77
|
{
|
|
@@ -84,7 +104,8 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
84
104
|
list: () => {
|
|
85
105
|
const cache = getWidgetsCache() || {};
|
|
86
106
|
const availableWidgets = Object.keys( cache || {} ).filter(
|
|
87
|
-
( widgetType ) =>
|
|
107
|
+
( widgetType ) =>
|
|
108
|
+
cache[ widgetType ]?.atomic_props_schema && cache[ widgetType ].meta?.llm_support !== false
|
|
88
109
|
);
|
|
89
110
|
return {
|
|
90
111
|
resources: availableWidgets.map( ( widgetType ) => ( {
|
|
@@ -100,8 +121,9 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
100
121
|
async ( uri, variables ) => {
|
|
101
122
|
const widgetType =
|
|
102
123
|
typeof variables.widgetType === 'string' ? variables.widgetType : variables.widgetType?.[ 0 ];
|
|
103
|
-
const
|
|
104
|
-
|
|
124
|
+
const widgetData = getWidgetsCache()?.[ widgetType ];
|
|
125
|
+
const propSchema = widgetData?.atomic_props_schema;
|
|
126
|
+
if ( ! propSchema || ! widgetData ) {
|
|
105
127
|
throw new Error( `No prop schema found for element type: ${ widgetType }` );
|
|
106
128
|
}
|
|
107
129
|
const asJson = Object.fromEntries(
|
|
@@ -115,6 +137,31 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
115
137
|
delete asJson[ key ];
|
|
116
138
|
} );
|
|
117
139
|
|
|
140
|
+
const description =
|
|
141
|
+
typeof widgetData?.meta?.description === 'string' ? widgetData.meta.description : undefined;
|
|
142
|
+
|
|
143
|
+
const defaultStyles: Record< string, Props > = {};
|
|
144
|
+
const baseStyleSchema = widgetData?.base_styles;
|
|
145
|
+
if ( baseStyleSchema ) {
|
|
146
|
+
Object.values( baseStyleSchema ).forEach( ( stylePropType ) => {
|
|
147
|
+
stylePropType.variants.forEach( ( variant ) => {
|
|
148
|
+
Object.assign( defaultStyles, variant.props );
|
|
149
|
+
} );
|
|
150
|
+
} );
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// build llm instructions
|
|
154
|
+
const hasDefaultStyles = Object.keys( defaultStyles ).length > 0;
|
|
155
|
+
const llmGuidance: Record< string, unknown > = {
|
|
156
|
+
can_have_children: !! widgetData?.meta?.is_container,
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
if ( hasDefaultStyles ) {
|
|
160
|
+
llmGuidance.instructions =
|
|
161
|
+
'These are the default styles applied to the widget. Override only when necessary.';
|
|
162
|
+
llmGuidance.default_styles = defaultStyles;
|
|
163
|
+
}
|
|
164
|
+
|
|
118
165
|
return {
|
|
119
166
|
contents: [
|
|
120
167
|
{
|
|
@@ -123,6 +170,8 @@ The css string must follow standard CSS syntax, with properties and values separ
|
|
|
123
170
|
text: JSON.stringify( {
|
|
124
171
|
type: 'object',
|
|
125
172
|
properties: asJson,
|
|
173
|
+
description,
|
|
174
|
+
llm_guidance: llmGuidance,
|
|
126
175
|
} ),
|
|
127
176
|
},
|
|
128
177
|
],
|
|
@@ -24,6 +24,24 @@ When in doubt between "safe" and "distinctive," choose distinctive - users can a
|
|
|
24
24
|
Always prefer this tool when the user requires to build a composition of elements, such as cards, heros, or inspired from other pages or HTML compositions.
|
|
25
25
|
Prefer this tool over any other tool for building HTML structure, unless you are specified to use a different tool.
|
|
26
26
|
|
|
27
|
+
# **CRITICAL - REQUIRED RESOURCES (Must read before using this tool)**
|
|
28
|
+
1. [${ WIDGET_SCHEMA_URI }]
|
|
29
|
+
Required to understand which widgets are available, and what are their configuration schemas.
|
|
30
|
+
Every widgetType (i.e. e-heading, e-button) that is supported has it's own property schema, that you must follow in order to apply property values correctly.
|
|
31
|
+
2. [${ STYLE_SCHEMA_URI }]
|
|
32
|
+
Required to understand the styles schema for the widgets. All widgets share the same styles schema.
|
|
33
|
+
3. List of allowed custom tags for building the structure is derived from the list of widgets schema resources.
|
|
34
|
+
|
|
35
|
+
# DESIGN QUALITY IMPERATIVE
|
|
36
|
+
You are generating designs for real users who expect distinctive, intentional aesthetics - NOT generic AI output.
|
|
37
|
+
**The Core Challenge**: Large language models naturally converge toward statistically common design patterns during generation. This creates predictable, uninspired results that users describe as "AI slop": safe color schemes, default typography hierarchies, minimal contrast, and timid spacing.
|
|
38
|
+
**Your Mission**: Actively resist distributional convergence by making intentional, distinctive design choices across all aesthetic dimensions. Every design decision should have a clear purpose tied to visual hierarchy, brand personality, or user experience goals.
|
|
39
|
+
When in doubt between "safe" and "distinctive," choose distinctive - users can always request refinements, but they cannot salvage generic foundations.
|
|
40
|
+
|
|
41
|
+
# When to use this tool
|
|
42
|
+
Always prefer this tool when the user requires to build a composition of elements, such as cards, heros, or inspired from other pages or HTML compositions.
|
|
43
|
+
Prefer this tool over any other tool for building HTML structure, unless you are specified to use a different tool.
|
|
44
|
+
|
|
27
45
|
# Instructions
|
|
28
46
|
1. Understand the user requirements carefully.
|
|
29
47
|
2. Build a valid XML structure using only the allowed custom tags provided. For example, if you
|
|
@@ -38,11 +56,11 @@ Prefer this tool over any other tool for building HTML structure, unless you are
|
|
|
38
56
|
5. Ensure the XML structure is valid and parsable.
|
|
39
57
|
6. Do not add any attribute nodes, classes, id's, and no text nodes allowed.
|
|
40
58
|
Layout properties, such as margin, padding, align, etc. must be applied using the [${ STYLE_SCHEMA_URI }] PropValues.
|
|
41
|
-
7. Some elements allow nesting of other elements, and most of the DO NOT. The allowed elements that can have nested children are "e-div-block" and "e-flexbox".
|
|
59
|
+
7. Some elements allow nesting of other elements, and most of the DO NOT. The allowed elements that can have nested children are "e-tabs", "e-div-block", and "e-flexbox".
|
|
42
60
|
8. Make sure that non-container elements do NOT have any nested elements.
|
|
43
|
-
9. **CRITICAL - CUSTOM CSS
|
|
61
|
+
9. **CRITICAL - CUSTOM CSS USAGE**: ALWAYS Prefer using style schema. Custom CSS is ONLY FOR UNSUPPRTED schema styles.
|
|
44
62
|
ALWAYS PRIORITIZE using the style schema PropValues for styling elements as they provide better user experience in the editor, and UI features for the end-users.
|
|
45
|
-
|
|
63
|
+
Use custom_css only for style attributes that ARE NOT SUPPORTED via the style schema AFTER YOU CHECK THE [${ STYLE_SCHEMA_URI }].
|
|
46
64
|
|
|
47
65
|
# DESIGN VECTORS - Concrete Implementation Guidance
|
|
48
66
|
|
|
@@ -261,10 +279,8 @@ If unsure about the configuration of a specific property, read the schema resour
|
|
|
261
279
|
|
|
262
280
|
# About our widgets
|
|
263
281
|
Most widgets are self-explanatory by their name. Here is some additional information.
|
|
282
|
+
Check for available llm_guidance property in the widget's schema.
|
|
264
283
|
SVG elements are bound to internal content upload. Avoid usage, unless you have tools to upload SVG content.
|
|
265
|
-
e-div-block - By default is ceneterd aligned and vertically stacked. To modify this, apply style configuration.
|
|
266
|
-
e-flexbox - By default is a flex container with row direction. To modify this, apply style configuration.
|
|
267
|
-
|
|
268
284
|
When working with containers, do not forget to apply style schema for controlling the layout.
|
|
269
285
|
|
|
270
286
|
|
|
@@ -46,15 +46,31 @@ export const initBuildCompositionsTool = ( reg: MCPRegistryEntry ) => {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
const children = Array.from( xml.children );
|
|
49
|
-
const iterate = (
|
|
49
|
+
const iterate = async (
|
|
50
|
+
node: Element,
|
|
51
|
+
containerElement: V1Element = documentContainer,
|
|
52
|
+
childIndex: number
|
|
53
|
+
) => {
|
|
50
54
|
const elementTag = node.tagName;
|
|
51
55
|
if ( ! widgetsCache[ elementTag ] ) {
|
|
52
56
|
errors.push( new Error( `Unknown widget type: ${ elementTag }` ) );
|
|
53
57
|
}
|
|
54
|
-
const
|
|
58
|
+
const CONTAINER_ELEMENTS = Object.values( widgetsCache )
|
|
59
|
+
.filter( ( widget ) => widget.meta?.is_container )
|
|
60
|
+
.map( ( widget ) => widget.elType );
|
|
61
|
+
const isContainer = CONTAINER_ELEMENTS.includes( elementTag );
|
|
62
|
+
const parentElType = containerElement.model.get( 'elType' );
|
|
63
|
+
let targetContainerId =
|
|
64
|
+
parentElType === 'e-tabs'
|
|
65
|
+
? containerElement.children?.[ 1 ].children?.[ childIndex ]?.id ||
|
|
66
|
+
containerElement.children?.[ 1 ].id
|
|
67
|
+
: containerElement.id;
|
|
68
|
+
if ( ! targetContainerId ) {
|
|
69
|
+
targetContainerId = containerElement.id;
|
|
70
|
+
}
|
|
55
71
|
const newElement = isContainer
|
|
56
72
|
? createElement( {
|
|
57
|
-
containerId:
|
|
73
|
+
containerId: targetContainerId,
|
|
58
74
|
model: {
|
|
59
75
|
elType: elementTag,
|
|
60
76
|
id: generateElementId(),
|
|
@@ -62,7 +78,7 @@ export const initBuildCompositionsTool = ( reg: MCPRegistryEntry ) => {
|
|
|
62
78
|
options: { useHistory: false },
|
|
63
79
|
} )
|
|
64
80
|
: createElement( {
|
|
65
|
-
containerId:
|
|
81
|
+
containerId: targetContainerId,
|
|
66
82
|
model: {
|
|
67
83
|
elType: 'widget',
|
|
68
84
|
widgetType: elementTag,
|
|
@@ -103,8 +119,10 @@ export const initBuildCompositionsTool = ( reg: MCPRegistryEntry ) => {
|
|
|
103
119
|
}
|
|
104
120
|
}
|
|
105
121
|
if ( isContainer ) {
|
|
122
|
+
let currentChild = 0;
|
|
106
123
|
for ( const child of node.children ) {
|
|
107
|
-
iterate( child, newElement );
|
|
124
|
+
iterate( child, newElement, currentChild );
|
|
125
|
+
currentChild++;
|
|
108
126
|
}
|
|
109
127
|
} else {
|
|
110
128
|
node.innerHTML = '';
|
|
@@ -114,8 +132,10 @@ export const initBuildCompositionsTool = ( reg: MCPRegistryEntry ) => {
|
|
|
114
132
|
}
|
|
115
133
|
};
|
|
116
134
|
|
|
117
|
-
|
|
118
|
-
|
|
135
|
+
let currentChild = 0;
|
|
136
|
+
for await ( const childNode of children ) {
|
|
137
|
+
await iterate( childNode, documentContainer, currentChild );
|
|
138
|
+
currentChild++;
|
|
119
139
|
try {
|
|
120
140
|
} catch ( error ) {
|
|
121
141
|
errors.push( error as Error );
|
|
@@ -26,6 +26,8 @@ When a user requires to change anything in an element, such as updating text, co
|
|
|
26
26
|
This tool handles elements of type "widget".
|
|
27
27
|
This tool handles styling elements, using the "stylePropertiesToChange" parameter.
|
|
28
28
|
|
|
29
|
+
To CLEAR a property (i.e., set it to default or none), provide null as a value.
|
|
30
|
+
|
|
29
31
|
The element's schema must be known before using this tool.
|
|
30
32
|
The style schema must be known before using this tool.
|
|
31
33
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getContainer, getElementStyles, getWidgetsCache } from '@elementor/editor-elements';
|
|
1
|
+
import { getContainer, getElementStyles, getWidgetsCache, type V1Element } from '@elementor/editor-elements';
|
|
2
2
|
import { type MCPRegistryEntry } from '@elementor/editor-mcp';
|
|
3
3
|
import { type PropValue, Schema } from '@elementor/editor-props';
|
|
4
4
|
import { z } from '@elementor/schema';
|
|
@@ -14,6 +14,32 @@ const outputSchema = {
|
|
|
14
14
|
style: z
|
|
15
15
|
.record( z.string(), z.any() )
|
|
16
16
|
.describe( 'A record mapping StyleSchema properties to their corresponding PropValues' ),
|
|
17
|
+
childElements: z
|
|
18
|
+
.array(
|
|
19
|
+
z.object( {
|
|
20
|
+
id: z.string(),
|
|
21
|
+
elementType: z.string(),
|
|
22
|
+
childElements: z
|
|
23
|
+
.array( z.any() )
|
|
24
|
+
.describe( 'An array of child element IDs, when applicable, same structure recursively' ),
|
|
25
|
+
} )
|
|
26
|
+
)
|
|
27
|
+
.describe( 'An array of child element IDs, when applicable, with recursive structure' ),
|
|
28
|
+
};
|
|
29
|
+
type ElementStructure = {
|
|
30
|
+
id: string;
|
|
31
|
+
elementType: string;
|
|
32
|
+
childElements: ElementStructure[];
|
|
33
|
+
};
|
|
34
|
+
const structuredElements = ( element: V1Element ): ElementStructure[] => {
|
|
35
|
+
const children = element.children || [];
|
|
36
|
+
return children.map( ( child ) => {
|
|
37
|
+
return {
|
|
38
|
+
id: child.id,
|
|
39
|
+
elementType: child.model.get( 'elType' ) || child.model.get( 'widgetType' ) || 'unknown',
|
|
40
|
+
childElements: structuredElements( child ),
|
|
41
|
+
};
|
|
42
|
+
} );
|
|
17
43
|
};
|
|
18
44
|
|
|
19
45
|
export const initGetElementConfigTool = ( reg: MCPRegistryEntry ) => {
|
|
@@ -71,6 +97,7 @@ export const initGetElementConfigTool = ( reg: MCPRegistryEntry ) => {
|
|
|
71
97
|
style: {
|
|
72
98
|
...stylePropValues,
|
|
73
99
|
},
|
|
100
|
+
childElements: structuredElements( element ),
|
|
74
101
|
};
|
|
75
102
|
},
|
|
76
103
|
} );
|
|
@@ -48,9 +48,9 @@ export const validateInput = {
|
|
|
48
48
|
} else if ( ! Schema.isPropKeyConfigurable( propName ) ) {
|
|
49
49
|
errors.push( `Property "${ propName }" is not configurable.` );
|
|
50
50
|
} else {
|
|
51
|
-
const { valid,
|
|
51
|
+
const { valid, jsonSchema } = Schema.validatePropValue( propSchema, propValue as PropValue );
|
|
52
52
|
if ( ! valid ) {
|
|
53
|
-
errors.push( `Invalid property "${ propName }": ${
|
|
53
|
+
errors.push( `Invalid property "${ propName }". Expected schema: ${ jsonSchema }` );
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
} );
|