@elementor/editor-canvas 4.3.0-993 → 4.3.0-995
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.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +181 -901
- package/dist/index.mjs +124 -855
- package/package.json +20 -20
- package/src/index.ts +1 -1
- package/src/mcp/canvas-mcp.ts +2 -2
- package/src/mcp/tools/build-composition/tool.ts +107 -218
- package/src/sync/element-added-event.ts +8 -0
- package/src/composition-builder/__tests__/composition-builder.test.ts +0 -352
- package/src/composition-builder/composition-builder.ts +0 -350
- package/src/composition-builder/utils/__tests__/required-children-enforcer.test.ts +0 -79
- package/src/composition-builder/utils/__tests__/required-default-child-tags.test.ts +0 -35
- package/src/composition-builder/utils/required-children-enforcer.ts +0 -56
- package/src/composition-builder/utils/required-default-child-tags.ts +0 -22
- package/src/mcp/tools/build-composition/__tests__/xml-leaf-wrapper.test.ts +0 -117
- package/src/mcp/tools/build-composition/prompt.ts +0 -167
- package/src/mcp/tools/build-composition/schema.ts +0 -42
- package/src/mcp/tools/build-composition/xml-leaf-wrapper.ts +0 -68
- package/src/mcp/utils/__tests__/get-composition-target-container.test.ts +0 -59
- package/src/mcp/utils/get-composition-target-container.ts +0 -15
package/dist/index.js
CHANGED
|
@@ -195,7 +195,7 @@ var convertCssToAtomic = async (style) => {
|
|
|
195
195
|
|
|
196
196
|
// src/init.tsx
|
|
197
197
|
var import_editor = require("@elementor/editor");
|
|
198
|
-
var
|
|
198
|
+
var import_editor_mcp4 = require("@elementor/editor-mcp");
|
|
199
199
|
|
|
200
200
|
// src/components/classes-rename.tsx
|
|
201
201
|
var import_react = require("react");
|
|
@@ -1854,46 +1854,6 @@ function clipboardRootsAreAtomicForms(elements) {
|
|
|
1854
1854
|
}
|
|
1855
1855
|
return elements.every((el) => getClipboardElementType(el) === FORM_ELEMENT_TYPE);
|
|
1856
1856
|
}
|
|
1857
|
-
function hasFormAncestor(node) {
|
|
1858
|
-
return node.closest(FORM_ELEMENT_TYPE) !== null;
|
|
1859
|
-
}
|
|
1860
|
-
function collectFormAncestorErrors(xml) {
|
|
1861
|
-
const errors = [];
|
|
1862
|
-
for (const node of xml.querySelectorAll("*")) {
|
|
1863
|
-
if (!FORM_FIELD_ELEMENT_TYPES.has(node.tagName.toLowerCase())) {
|
|
1864
|
-
continue;
|
|
1865
|
-
}
|
|
1866
|
-
if (hasFormAncestor(node)) {
|
|
1867
|
-
continue;
|
|
1868
|
-
}
|
|
1869
|
-
const id = node.getAttribute("configuration-id");
|
|
1870
|
-
errors.push(
|
|
1871
|
-
`<${node.tagName}${id ? ` configuration-id="${id}"` : ""}> must be nested inside <e-form> (any ancestor depth is allowed).`
|
|
1872
|
-
);
|
|
1873
|
-
}
|
|
1874
|
-
return errors;
|
|
1875
|
-
}
|
|
1876
|
-
function collectSubmitButtonErrors(xml) {
|
|
1877
|
-
const errors = [];
|
|
1878
|
-
for (const form of xml.querySelectorAll("e-form")) {
|
|
1879
|
-
const submitButtons = form.querySelectorAll("e-form-submit-button");
|
|
1880
|
-
if (submitButtons.length === 0) {
|
|
1881
|
-
errors.push(`<e-form> has no <e-form-submit-button>.`);
|
|
1882
|
-
} else if (submitButtons.length > 1) {
|
|
1883
|
-
errors.push(`<e-form> has ${submitButtons.length} submit buttons \u2014 only 1 is allowed.`);
|
|
1884
|
-
}
|
|
1885
|
-
}
|
|
1886
|
-
return errors;
|
|
1887
|
-
}
|
|
1888
|
-
function collectEmptyMessageErrors(xml) {
|
|
1889
|
-
const errors = [];
|
|
1890
|
-
for (const node of xml.querySelectorAll("e-form-success-message, e-form-error-message")) {
|
|
1891
|
-
if (node.children.length === 0) {
|
|
1892
|
-
errors.push(`<${node.tagName}> must have at least one child element (e.g. <e-atomic-paragraph>).`);
|
|
1893
|
-
}
|
|
1894
|
-
}
|
|
1895
|
-
return errors;
|
|
1896
|
-
}
|
|
1897
1857
|
|
|
1898
1858
|
// src/form-structure/enforce-form-ancestor-commands.ts
|
|
1899
1859
|
var FORM_FIELDS_OUTSIDE_ALERT = {
|
|
@@ -4520,15 +4480,103 @@ function getElementDisplayName(container) {
|
|
|
4520
4480
|
}
|
|
4521
4481
|
|
|
4522
4482
|
// src/mcp/tools/build-composition/tool.ts
|
|
4523
|
-
var
|
|
4524
|
-
var
|
|
4525
|
-
var
|
|
4483
|
+
var import_editor_documents2 = require("@elementor/editor-documents");
|
|
4484
|
+
var import_editor_elements11 = require("@elementor/editor-elements");
|
|
4485
|
+
var import_http_client6 = require("@elementor/http-client");
|
|
4486
|
+
var import_schema = require("@elementor/schema");
|
|
4487
|
+
var MCP_PROXY_URL5 = "elementor/v1/mcp-proxy";
|
|
4488
|
+
var initBuildCompositionTool = (reg) => {
|
|
4489
|
+
const { addTool } = reg;
|
|
4490
|
+
addTool({
|
|
4491
|
+
name: "build-composition",
|
|
4492
|
+
description: "Build a V4 element composition on the Elementor canvas via the server-side MCP ability. Pass the raw XML tags directly as xmlStructure \u2014 do NOT wrap the value in <![CDATA[ ... ]]>, code fences, or quotes. The document is saved as a draft. Reload the editor after calling this tool to see the result.",
|
|
4493
|
+
schema: {
|
|
4494
|
+
xmlStructure: import_schema.z.string().describe(
|
|
4495
|
+
'Valid XML structure with custom Elementor widget tags. Every element MUST have a unique configuration-id attribute (e.g. <e-heading configuration-id="hero-title"></e-heading>). No attributes, classes, IDs, or text nodes in XML. Pass raw XML \u2014 do not wrap in CDATA.'
|
|
4496
|
+
),
|
|
4497
|
+
elementConfig: import_schema.z.record(
|
|
4498
|
+
import_schema.z.string().describe("configuration-id"),
|
|
4499
|
+
import_schema.z.record(import_schema.z.string().describe("property name"), import_schema.z.any().describe("PropValue"))
|
|
4500
|
+
).optional().describe("Map configuration-id \u2192 widget PropValues ($$type + value)."),
|
|
4501
|
+
style: import_schema.z.record(
|
|
4502
|
+
import_schema.z.string().describe("configuration-id"),
|
|
4503
|
+
import_schema.z.record(import_schema.z.string().describe("CSS property name"), import_schema.z.string().describe("CSS value"))
|
|
4504
|
+
).optional().describe(
|
|
4505
|
+
"Map configuration-id \u2192 raw CSS declarations (property \u2192 value strings; no selectors). Server converts to native styles; unconvertible declarations become the element custom CSS."
|
|
4506
|
+
),
|
|
4507
|
+
parentId: import_schema.z.string().optional().describe("ID of the parent container. Omit or pass 'document' to insert at document root."),
|
|
4508
|
+
dryRun: import_schema.z.boolean().optional().describe("If true, validate and return the resolved tree without persisting.")
|
|
4509
|
+
},
|
|
4510
|
+
outputSchema: {
|
|
4511
|
+
rootElementIds: import_schema.z.array(import_schema.z.string()),
|
|
4512
|
+
previewUrl: import_schema.z.string(),
|
|
4513
|
+
version: import_schema.z.string(),
|
|
4514
|
+
resolvedXml: import_schema.z.string(),
|
|
4515
|
+
llmInstructions: import_schema.z.string(),
|
|
4516
|
+
warnings: import_schema.z.array(import_schema.z.string()).optional()
|
|
4517
|
+
},
|
|
4518
|
+
handler: async ({ xmlStructure, elementConfig, style, parentId, dryRun }) => {
|
|
4519
|
+
const document2 = (0, import_editor_documents2.getCurrentDocument)();
|
|
4520
|
+
if (!document2?.id) {
|
|
4521
|
+
throw new Error("No active document found.");
|
|
4522
|
+
}
|
|
4523
|
+
try {
|
|
4524
|
+
const { data } = await (0, import_http_client6.httpService)().post(MCP_PROXY_URL5, {
|
|
4525
|
+
tool: "build-composition",
|
|
4526
|
+
input: {
|
|
4527
|
+
post_id: document2.id,
|
|
4528
|
+
xml_structure: xmlStructure,
|
|
4529
|
+
element_config: elementConfig ?? {},
|
|
4530
|
+
style: style ?? {},
|
|
4531
|
+
parent_id: parentId ?? "document",
|
|
4532
|
+
dry_run: dryRun ?? false
|
|
4533
|
+
}
|
|
4534
|
+
});
|
|
4535
|
+
if (!dryRun) {
|
|
4536
|
+
await (0, import_editor_documents2.reloadCurrentDocument)();
|
|
4537
|
+
const [firstRootId] = data.data.root_element_ids;
|
|
4538
|
+
if (firstRootId) {
|
|
4539
|
+
(0, import_editor_elements11.selectElement)(firstRootId);
|
|
4540
|
+
(0, import_editor_elements11.getContainer)(firstRootId)?.view?.el?.scrollIntoView({
|
|
4541
|
+
behavior: "smooth",
|
|
4542
|
+
block: "center"
|
|
4543
|
+
});
|
|
4544
|
+
}
|
|
4545
|
+
}
|
|
4546
|
+
return {
|
|
4547
|
+
rootElementIds: data.data.root_element_ids,
|
|
4548
|
+
previewUrl: data.data.preview_url,
|
|
4549
|
+
version: data.data.version,
|
|
4550
|
+
resolvedXml: data.data.resolved_xml,
|
|
4551
|
+
llmInstructions: data.data.llm_instructions,
|
|
4552
|
+
warnings: data.data.warnings
|
|
4553
|
+
};
|
|
4554
|
+
} catch (error) {
|
|
4555
|
+
throw new Error(getErrorMessage(error));
|
|
4556
|
+
}
|
|
4557
|
+
}
|
|
4558
|
+
});
|
|
4559
|
+
};
|
|
4560
|
+
function getErrorMessage(error) {
|
|
4561
|
+
if (error instanceof import_http_client6.AxiosError) {
|
|
4562
|
+
const data = error.response?.data;
|
|
4563
|
+
if (data?.message) {
|
|
4564
|
+
return data.code ? `${data.code}: ${data.message}` : data.message;
|
|
4565
|
+
}
|
|
4566
|
+
}
|
|
4567
|
+
if (error instanceof Error) {
|
|
4568
|
+
return error.message;
|
|
4569
|
+
}
|
|
4570
|
+
return "build-composition failed with an unknown error.";
|
|
4571
|
+
}
|
|
4526
4572
|
|
|
4527
|
-
// src/
|
|
4528
|
-
var
|
|
4573
|
+
// src/mcp/tools/configure-element/tool.ts
|
|
4574
|
+
var import_editor_elements14 = require("@elementor/editor-elements");
|
|
4575
|
+
var import_editor_mcp3 = require("@elementor/editor-mcp");
|
|
4576
|
+
var import_editor_props7 = require("@elementor/editor-props");
|
|
4529
4577
|
|
|
4530
4578
|
// src/mcp/utils/do-update-element-property.ts
|
|
4531
|
-
var
|
|
4579
|
+
var import_editor_elements13 = require("@elementor/editor-elements");
|
|
4532
4580
|
var import_editor_props6 = require("@elementor/editor-props");
|
|
4533
4581
|
var import_editor_styles4 = require("@elementor/editor-styles");
|
|
4534
4582
|
var import_editor_v1_adapters20 = require("@elementor/editor-v1-adapters");
|
|
@@ -4548,7 +4596,7 @@ var readStoredCustomCssText = (raw) => {
|
|
|
4548
4596
|
};
|
|
4549
4597
|
|
|
4550
4598
|
// src/mcp/utils/resolve-canonical-prop-name.ts
|
|
4551
|
-
var
|
|
4599
|
+
var import_editor_elements12 = require("@elementor/editor-elements");
|
|
4552
4600
|
function buildAliasToCanonicalMap(schema2) {
|
|
4553
4601
|
const aliasToCanonical = {};
|
|
4554
4602
|
for (const [canonical, propType] of Object.entries(schema2)) {
|
|
@@ -4565,14 +4613,14 @@ function buildAliasToCanonicalMap(schema2) {
|
|
|
4565
4613
|
return aliasToCanonical;
|
|
4566
4614
|
}
|
|
4567
4615
|
function resolveCanonicalPropName(elementType, propertyName) {
|
|
4568
|
-
const schema2 = (0,
|
|
4616
|
+
const schema2 = (0, import_editor_elements12.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
|
|
4569
4617
|
if (!schema2 || schema2[propertyName]) {
|
|
4570
4618
|
return propertyName;
|
|
4571
4619
|
}
|
|
4572
4620
|
return buildAliasToCanonicalMap(schema2)[propertyName] ?? propertyName;
|
|
4573
4621
|
}
|
|
4574
4622
|
function resolveCanonicalPropKeys(elementType, props) {
|
|
4575
|
-
const schema2 = (0,
|
|
4623
|
+
const schema2 = (0, import_editor_elements12.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
|
|
4576
4624
|
if (!schema2) {
|
|
4577
4625
|
return { ...props };
|
|
4578
4626
|
}
|
|
@@ -4680,7 +4728,7 @@ var doUpdateElementProperty = (params) => {
|
|
|
4680
4728
|
const { elementId, propertyValue, elementType, customCssWriteMode = "replace" } = params;
|
|
4681
4729
|
const propertyName = params.propertyName === "_styles" ? params.propertyName : resolveCanonicalPropName(elementType, params.propertyName);
|
|
4682
4730
|
if (propertyName === "_styles") {
|
|
4683
|
-
const elementStyles = (0,
|
|
4731
|
+
const elementStyles = (0, import_editor_elements13.getElementStyles)(elementId) || {};
|
|
4684
4732
|
const propertyMapValue = propertyValue;
|
|
4685
4733
|
const styleSchema = (0, import_editor_styles4.getStylesSchema)();
|
|
4686
4734
|
const transformedStyleValues = Object.fromEntries(
|
|
@@ -4737,7 +4785,7 @@ var doUpdateElementProperty = (params) => {
|
|
|
4737
4785
|
});
|
|
4738
4786
|
delete transformedStyleValues.custom_css;
|
|
4739
4787
|
if (!localStyle) {
|
|
4740
|
-
(0,
|
|
4788
|
+
(0, import_editor_elements13.createElementStyle)({
|
|
4741
4789
|
elementId,
|
|
4742
4790
|
...typeof customCss !== "undefined" ? { custom_css: customCss } : {},
|
|
4743
4791
|
classesProp: "classes",
|
|
@@ -4751,7 +4799,7 @@ var doUpdateElementProperty = (params) => {
|
|
|
4751
4799
|
}
|
|
4752
4800
|
});
|
|
4753
4801
|
} else {
|
|
4754
|
-
(0,
|
|
4802
|
+
(0, import_editor_elements13.updateElementStyle)({
|
|
4755
4803
|
elementId,
|
|
4756
4804
|
styleId: localStyle.id,
|
|
4757
4805
|
meta: {
|
|
@@ -4766,7 +4814,7 @@ var doUpdateElementProperty = (params) => {
|
|
|
4766
4814
|
}
|
|
4767
4815
|
return;
|
|
4768
4816
|
}
|
|
4769
|
-
const elementPropSchema = (0,
|
|
4817
|
+
const elementPropSchema = (0, import_editor_elements13.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
|
|
4770
4818
|
if (!elementPropSchema) {
|
|
4771
4819
|
throw new Error(`No prop schema found for element type: ${elementType}`);
|
|
4772
4820
|
}
|
|
@@ -4789,7 +4837,7 @@ var doUpdateElementProperty = (params) => {
|
|
|
4789
4837
|
Expected Schema: ${jsonSchema}`
|
|
4790
4838
|
);
|
|
4791
4839
|
}
|
|
4792
|
-
(0,
|
|
4840
|
+
(0, import_editor_elements13.updateElementSettings)({
|
|
4793
4841
|
id: elementId,
|
|
4794
4842
|
props: {
|
|
4795
4843
|
[propertyName]: value
|
|
@@ -4799,782 +4847,11 @@ Expected Schema: ${jsonSchema}`
|
|
|
4799
4847
|
(0, import_editor_v1_adapters20.__privateRunCommandSync)("document/save/set-is-modified", { status: true }, { internal: true });
|
|
4800
4848
|
};
|
|
4801
4849
|
|
|
4802
|
-
// src/composition-builder/utils/required-default-child-tags.ts
|
|
4803
|
-
function getRequiredDefaultChildTemplates(elementConfig) {
|
|
4804
|
-
const defaultChildren = elementConfig?.default_children;
|
|
4805
|
-
if (!Array.isArray(defaultChildren)) {
|
|
4806
|
-
return [];
|
|
4807
|
-
}
|
|
4808
|
-
return defaultChildren.filter((child) => child?.meta?.required ?? false);
|
|
4809
|
-
}
|
|
4810
|
-
|
|
4811
|
-
// src/composition-builder/utils/required-children-enforcer.ts
|
|
4812
|
-
var REQUIRED_CHILD_SCHEMA_HINT = "Use the widget schema resource; under llm_guidance.required_direct_children for V4 widgets.";
|
|
4813
|
-
var RequiredChildrenEnforcer = class {
|
|
4814
|
-
elementType;
|
|
4815
|
-
requiredTemplates;
|
|
4816
|
-
constructor(elementType, widgetsCache) {
|
|
4817
|
-
this.elementType = elementType;
|
|
4818
|
-
this.requiredTemplates = getRequiredDefaultChildTemplates(widgetsCache[elementType]);
|
|
4819
|
-
}
|
|
4820
|
-
enforce(xml) {
|
|
4821
|
-
if (this.requiredTemplates.length === 0) {
|
|
4822
|
-
return;
|
|
4823
|
-
}
|
|
4824
|
-
const errors = [];
|
|
4825
|
-
for (const rootNode of Array.from(xml.children)) {
|
|
4826
|
-
this.collectMissingRequiredErrors(rootNode, errors);
|
|
4827
|
-
}
|
|
4828
|
-
if (errors.length) {
|
|
4829
|
-
throw new Error(`${errors.join("\n")}
|
|
4830
|
-
${REQUIRED_CHILD_SCHEMA_HINT}`);
|
|
4831
|
-
}
|
|
4832
|
-
}
|
|
4833
|
-
collectMissingRequiredErrors(node, errors) {
|
|
4834
|
-
if (node.tagName === this.elementType) {
|
|
4835
|
-
const existingChildTags = new Set(Array.from(node.children).map((child) => child.tagName));
|
|
4836
|
-
const missingTags = this.requiredTemplates.map((child) => child.widgetType ?? child.elType ?? "").filter((type) => type && !existingChildTags.has(type));
|
|
4837
|
-
if (missingTags.length) {
|
|
4838
|
-
const configurationId = node.getAttribute("configuration-id");
|
|
4839
|
-
const location2 = configurationId ? `<${node.tagName} configuration-id="${configurationId}">` : `<${node.tagName}>`;
|
|
4840
|
-
errors.push(
|
|
4841
|
-
`${location2} Missing required direct child element tag(s): ${missingTags.join(", ")}.`
|
|
4842
|
-
);
|
|
4843
|
-
}
|
|
4844
|
-
}
|
|
4845
|
-
for (const childNode of Array.from(node.children)) {
|
|
4846
|
-
this.collectMissingRequiredErrors(childNode, errors);
|
|
4847
|
-
}
|
|
4848
|
-
}
|
|
4849
|
-
};
|
|
4850
|
-
|
|
4851
|
-
// src/composition-builder/composition-builder.ts
|
|
4852
|
-
var CREATE_ELEMENT_INVALID_CONTAINER_MESSAGE = "createElement did not return an element container with a model.";
|
|
4853
|
-
var CompositionBuilder = class _CompositionBuilder {
|
|
4854
|
-
elementConfig = {};
|
|
4855
|
-
elementStylesConfig = {};
|
|
4856
|
-
elementCustomCSS = {};
|
|
4857
|
-
rootContainers = [];
|
|
4858
|
-
api = {
|
|
4859
|
-
createElement: import_editor_elements13.createElement,
|
|
4860
|
-
deleteElement: import_editor_elements13.deleteElement,
|
|
4861
|
-
getWidgetsCache: import_editor_elements13.getWidgetsCache,
|
|
4862
|
-
generateElementId: import_editor_elements13.generateElementId,
|
|
4863
|
-
getContainer: import_editor_elements13.getContainer,
|
|
4864
|
-
doUpdateElementProperty
|
|
4865
|
-
};
|
|
4866
|
-
xml;
|
|
4867
|
-
static fromXMLString(xmlString, api = {}) {
|
|
4868
|
-
const parser = new DOMParser();
|
|
4869
|
-
const xmlDoc = parser.parseFromString(xmlString, "application/xml");
|
|
4870
|
-
const errorNode = xmlDoc.querySelector("parsererror");
|
|
4871
|
-
if (errorNode) {
|
|
4872
|
-
throw new Error("Failed to parse XML string: " + errorNode.textContent);
|
|
4873
|
-
}
|
|
4874
|
-
return new _CompositionBuilder({
|
|
4875
|
-
xml: xmlDoc,
|
|
4876
|
-
api
|
|
4877
|
-
});
|
|
4878
|
-
}
|
|
4879
|
-
constructor(opts) {
|
|
4880
|
-
const { api = {}, elementConfig = {}, stylesConfig = {}, customCSS = {}, xml } = opts;
|
|
4881
|
-
this.xml = xml;
|
|
4882
|
-
Object.assign(this.api, api);
|
|
4883
|
-
this.setElementConfig(elementConfig);
|
|
4884
|
-
this.setStylesConfig(stylesConfig);
|
|
4885
|
-
this.setCustomCSS(customCSS);
|
|
4886
|
-
}
|
|
4887
|
-
setElementConfig(config) {
|
|
4888
|
-
this.elementConfig = config;
|
|
4889
|
-
}
|
|
4890
|
-
setStylesConfig(config) {
|
|
4891
|
-
this.elementStylesConfig = config;
|
|
4892
|
-
}
|
|
4893
|
-
setCustomCSS(config) {
|
|
4894
|
-
this.elementCustomCSS = config;
|
|
4895
|
-
}
|
|
4896
|
-
getXML() {
|
|
4897
|
-
return this.xml;
|
|
4898
|
-
}
|
|
4899
|
-
buildModelTree(node, widgetsCache) {
|
|
4900
|
-
const elementTag = node.tagName;
|
|
4901
|
-
const isWidget = widgetsCache[elementTag]?.elType === "widget";
|
|
4902
|
-
const id = this.api.generateElementId();
|
|
4903
|
-
const children = Array.from(node.children).map((child) => this.buildModelTree(child, widgetsCache));
|
|
4904
|
-
node.setAttribute("id", id);
|
|
4905
|
-
const base = {
|
|
4906
|
-
id,
|
|
4907
|
-
skipDefaultChildren: true,
|
|
4908
|
-
elements: children,
|
|
4909
|
-
editor_settings: {
|
|
4910
|
-
title: node.getAttribute("configuration-id") ?? void 0
|
|
4911
|
-
},
|
|
4912
|
-
elType: "widget"
|
|
4913
|
-
};
|
|
4914
|
-
if (isWidget) {
|
|
4915
|
-
return { ...base, elType: "widget", widgetType: elementTag };
|
|
4916
|
-
}
|
|
4917
|
-
return { ...base, elType: elementTag };
|
|
4918
|
-
}
|
|
4919
|
-
async awaitViewRender(element) {
|
|
4920
|
-
const view = element.view;
|
|
4921
|
-
if (view?._currentRenderPromise instanceof Promise) {
|
|
4922
|
-
await view._currentRenderPromise;
|
|
4923
|
-
} else {
|
|
4924
|
-
await Promise.resolve();
|
|
4925
|
-
}
|
|
4926
|
-
}
|
|
4927
|
-
validateChildTypes(node, widgetsCache) {
|
|
4928
|
-
const errors = [];
|
|
4929
|
-
const allowedChildTypes = widgetsCache[node.tagName]?.allowed_child_types;
|
|
4930
|
-
if (allowedChildTypes?.length) {
|
|
4931
|
-
for (const child of Array.from(node.children)) {
|
|
4932
|
-
if (!allowedChildTypes.includes(child.tagName)) {
|
|
4933
|
-
errors.push(
|
|
4934
|
-
`"${child.tagName}" is not allowed as a child of "${node.tagName}". Allowed: ${allowedChildTypes.join(", ")}`
|
|
4935
|
-
);
|
|
4936
|
-
}
|
|
4937
|
-
}
|
|
4938
|
-
}
|
|
4939
|
-
for (const child of Array.from(node.children)) {
|
|
4940
|
-
errors.push(...this.validateChildTypes(child, widgetsCache));
|
|
4941
|
-
}
|
|
4942
|
-
return errors;
|
|
4943
|
-
}
|
|
4944
|
-
matchNodeByConfigId(configId) {
|
|
4945
|
-
const node = this.xml.querySelector(`[configuration-id="${configId}"]`);
|
|
4946
|
-
if (!node) {
|
|
4947
|
-
throw new Error(`Configuration id "${configId}" does not have target node.`);
|
|
4948
|
-
}
|
|
4949
|
-
const id = node.getAttribute("id");
|
|
4950
|
-
if (!id) {
|
|
4951
|
-
throw new Error(`Node with configuration id "${configId}" does not have element id.`);
|
|
4952
|
-
}
|
|
4953
|
-
const element = this.api.getContainer(id);
|
|
4954
|
-
if (!element) {
|
|
4955
|
-
throw new Error(`Element with id "${id}" not found but should exist.`);
|
|
4956
|
-
}
|
|
4957
|
-
return {
|
|
4958
|
-
element,
|
|
4959
|
-
node
|
|
4960
|
-
};
|
|
4961
|
-
}
|
|
4962
|
-
async applyProperties() {
|
|
4963
|
-
const configErrors = [];
|
|
4964
|
-
const styleErrors = [];
|
|
4965
|
-
const allConfigIds = /* @__PURE__ */ new Set([
|
|
4966
|
-
...Object.keys(this.elementConfig),
|
|
4967
|
-
...Object.keys(this.elementStylesConfig),
|
|
4968
|
-
...Object.keys(this.elementCustomCSS)
|
|
4969
|
-
]);
|
|
4970
|
-
for (const configId of allConfigIds) {
|
|
4971
|
-
let element, node;
|
|
4972
|
-
try {
|
|
4973
|
-
({ element, node } = this.matchNodeByConfigId(configId));
|
|
4974
|
-
} catch (matchErr) {
|
|
4975
|
-
const msg = matchErr.message;
|
|
4976
|
-
if (this.elementConfig[configId]) {
|
|
4977
|
-
configErrors.push(msg);
|
|
4978
|
-
}
|
|
4979
|
-
if (this.elementStylesConfig[configId] || this.elementCustomCSS[configId]) {
|
|
4980
|
-
styleErrors.push(msg);
|
|
4981
|
-
}
|
|
4982
|
-
continue;
|
|
4983
|
-
}
|
|
4984
|
-
const config = this.elementConfig[configId];
|
|
4985
|
-
if (config) {
|
|
4986
|
-
for (const [propertyName, propertyValue] of Object.entries(config)) {
|
|
4987
|
-
try {
|
|
4988
|
-
this.api.doUpdateElementProperty({
|
|
4989
|
-
elementId: element.id,
|
|
4990
|
-
propertyName,
|
|
4991
|
-
propertyValue,
|
|
4992
|
-
elementType: node.tagName
|
|
4993
|
-
});
|
|
4994
|
-
} catch (error) {
|
|
4995
|
-
configErrors.push(error.message);
|
|
4996
|
-
}
|
|
4997
|
-
}
|
|
4998
|
-
}
|
|
4999
|
-
const styleConfig = this.elementStylesConfig[configId];
|
|
5000
|
-
const hasInvalidStyles = false;
|
|
5001
|
-
if (styleConfig) {
|
|
5002
|
-
const validStylesPropValues = {};
|
|
5003
|
-
for (const [styleName, stylePropValue] of Object.entries(styleConfig)) {
|
|
5004
|
-
if (styleName === "$intention") {
|
|
5005
|
-
continue;
|
|
5006
|
-
} else {
|
|
5007
|
-
validStylesPropValues[styleName] = stylePropValue;
|
|
5008
|
-
}
|
|
5009
|
-
}
|
|
5010
|
-
if (Object.keys(validStylesPropValues).length > 0) {
|
|
5011
|
-
try {
|
|
5012
|
-
this.api.doUpdateElementProperty({
|
|
5013
|
-
elementId: element.id,
|
|
5014
|
-
propertyName: "_styles",
|
|
5015
|
-
propertyValue: validStylesPropValues,
|
|
5016
|
-
elementType: node.tagName
|
|
5017
|
-
});
|
|
5018
|
-
} catch (error) {
|
|
5019
|
-
styleErrors.push(String(error));
|
|
5020
|
-
}
|
|
5021
|
-
}
|
|
5022
|
-
}
|
|
5023
|
-
const intentionCss = typeof styleConfig?.$intention === "string" ? styleConfig.$intention.trim() : "";
|
|
5024
|
-
const fallbackCss = hasInvalidStyles && intentionCss ? intentionCss : "";
|
|
5025
|
-
const mergedCustomCss = mergeCustomCssText(this.elementCustomCSS[configId], fallbackCss);
|
|
5026
|
-
if (mergedCustomCss) {
|
|
5027
|
-
try {
|
|
5028
|
-
this.api.doUpdateElementProperty({
|
|
5029
|
-
elementId: element.id,
|
|
5030
|
-
propertyName: "_styles",
|
|
5031
|
-
propertyValue: { custom_css: mergedCustomCss },
|
|
5032
|
-
elementType: node.tagName
|
|
5033
|
-
});
|
|
5034
|
-
} catch (cssErr) {
|
|
5035
|
-
styleErrors.push(String(cssErr));
|
|
5036
|
-
}
|
|
5037
|
-
}
|
|
5038
|
-
await this.awaitViewRender(element);
|
|
5039
|
-
}
|
|
5040
|
-
return { configErrors, styleErrors };
|
|
5041
|
-
}
|
|
5042
|
-
async build(rootContainer) {
|
|
5043
|
-
const widgetsCache = this.api.getWidgetsCache() || {};
|
|
5044
|
-
new Set(this.xml.querySelectorAll("*")).forEach((node) => {
|
|
5045
|
-
if (!widgetsCache[node.tagName]) {
|
|
5046
|
-
throw new Error(`Unknown widget type: ${node.tagName}`);
|
|
5047
|
-
}
|
|
5048
|
-
});
|
|
5049
|
-
const typesWithRequiredChildren = Object.keys(widgetsCache).filter(
|
|
5050
|
-
(elementType) => getRequiredDefaultChildTemplates(widgetsCache[elementType]).length > 0
|
|
5051
|
-
);
|
|
5052
|
-
typesWithRequiredChildren.forEach((elementType) => {
|
|
5053
|
-
new RequiredChildrenEnforcer(elementType, widgetsCache).enforce(this.xml);
|
|
5054
|
-
});
|
|
5055
|
-
const childTypeErrors = [];
|
|
5056
|
-
for (const rootChild of Array.from(this.xml.children)) {
|
|
5057
|
-
childTypeErrors.push(...this.validateChildTypes(rootChild, widgetsCache));
|
|
5058
|
-
}
|
|
5059
|
-
if (childTypeErrors.length) {
|
|
5060
|
-
throw new Error(`Invalid element structure:
|
|
5061
|
-
${childTypeErrors.join("\n")}`);
|
|
5062
|
-
}
|
|
5063
|
-
const formErrors = [
|
|
5064
|
-
...collectFormAncestorErrors(this.xml),
|
|
5065
|
-
...collectSubmitButtonErrors(this.xml),
|
|
5066
|
-
...collectEmptyMessageErrors(this.xml)
|
|
5067
|
-
];
|
|
5068
|
-
const children = Array.from(this.xml.children);
|
|
5069
|
-
for (const childNode of children) {
|
|
5070
|
-
const modelTree = this.buildModelTree(childNode, widgetsCache);
|
|
5071
|
-
try {
|
|
5072
|
-
const newElement = this.api.createElement({
|
|
5073
|
-
container: rootContainer,
|
|
5074
|
-
model: modelTree,
|
|
5075
|
-
options: { useHistory: false }
|
|
5076
|
-
});
|
|
5077
|
-
if (!newElement?.model) {
|
|
5078
|
-
throw new Error(CREATE_ELEMENT_INVALID_CONTAINER_MESSAGE);
|
|
5079
|
-
}
|
|
5080
|
-
this.rootContainers.push(newElement);
|
|
5081
|
-
await this.awaitViewRender(newElement);
|
|
5082
|
-
} catch (e) {
|
|
5083
|
-
const attempToRestoreInvalidContainer = this.api.getContainer(modelTree.id);
|
|
5084
|
-
if (attempToRestoreInvalidContainer) {
|
|
5085
|
-
this.api.deleteElement({ container: attempToRestoreInvalidContainer });
|
|
5086
|
-
}
|
|
5087
|
-
throw e;
|
|
5088
|
-
}
|
|
5089
|
-
}
|
|
5090
|
-
const { configErrors, styleErrors } = await this.applyProperties();
|
|
5091
|
-
if (typeof window !== "undefined") {
|
|
5092
|
-
const targetWindow = window.top || window;
|
|
5093
|
-
targetWindow.dispatchEvent(
|
|
5094
|
-
new CustomEvent("elementor/composition/built", {
|
|
5095
|
-
detail: { rootContainers: this.rootContainers.map((c) => c.id) }
|
|
5096
|
-
})
|
|
5097
|
-
);
|
|
5098
|
-
}
|
|
5099
|
-
return {
|
|
5100
|
-
configErrors,
|
|
5101
|
-
styleErrors,
|
|
5102
|
-
formErrors,
|
|
5103
|
-
rootContainers: [...this.rootContainers]
|
|
5104
|
-
};
|
|
5105
|
-
}
|
|
5106
|
-
};
|
|
5107
|
-
|
|
5108
|
-
// src/utils/tracking.ts
|
|
5109
|
-
var import_events = require("@elementor/events");
|
|
5110
|
-
var trackCanvasEvent = (data) => {
|
|
5111
|
-
(0, import_events.trackEvent)(data);
|
|
5112
|
-
};
|
|
5113
|
-
|
|
5114
|
-
// src/mcp/utils/element-data-util.ts
|
|
5115
|
-
var import_editor_elements14 = require("@elementor/editor-elements");
|
|
5116
|
-
function hasV3Controls(controls) {
|
|
5117
|
-
return typeof controls === "object" && controls !== null && Object.keys(controls).length > 0;
|
|
5118
|
-
}
|
|
5119
|
-
function isWidgetAvailableForLLM(config) {
|
|
5120
|
-
if (!config) {
|
|
5121
|
-
return false;
|
|
5122
|
-
}
|
|
5123
|
-
if (config.meta?.llm_support === false) {
|
|
5124
|
-
return false;
|
|
5125
|
-
}
|
|
5126
|
-
if (config.title === "Component") {
|
|
5127
|
-
return false;
|
|
5128
|
-
}
|
|
5129
|
-
if (config.atomic_props_schema) {
|
|
5130
|
-
return true;
|
|
5131
|
-
}
|
|
5132
|
-
return hasV3Controls(config.controls);
|
|
5133
|
-
}
|
|
5134
|
-
|
|
5135
|
-
// src/mcp/utils/get-composition-target-container.ts
|
|
5136
|
-
var import_editor_documents2 = require("@elementor/editor-documents");
|
|
5137
|
-
function getCompositionTargetContainer(documentContainer, documentType) {
|
|
5138
|
-
const firstChild = documentContainer.children?.[0];
|
|
5139
|
-
if (documentType === import_editor_documents2.COMPONENT_DOCUMENT_TYPE && firstChild) {
|
|
5140
|
-
return firstChild;
|
|
5141
|
-
}
|
|
5142
|
-
return documentContainer;
|
|
5143
|
-
}
|
|
5144
|
-
|
|
5145
|
-
// src/mcp/tools/build-composition/prompt.ts
|
|
5146
|
-
var import_editor_mcp2 = require("@elementor/editor-mcp");
|
|
5147
|
-
var BUILD_COMPOSITIONS_GUIDE_URI = "elementor://canvas/tools/build-compositions-guide";
|
|
5148
|
-
var generatePrompt = () => {
|
|
5149
|
-
const buildCompositionsToolPrompt = (0, import_editor_mcp2.toolPrompts)("build-compositions");
|
|
5150
|
-
buildCompositionsToolPrompt.description(`
|
|
5151
|
-
# RESOURCES (Read before use)
|
|
5152
|
-
- [elementor://global-classes] - Check FIRST for reusable classes
|
|
5153
|
-
- [elementor://global-variables] - ONLY use variables defined here
|
|
5154
|
-
- [${AVAILABLE_WIDGETS_URI}/v4]
|
|
5155
|
-
|
|
5156
|
-
# TOOL SUPPORT
|
|
5157
|
-
This tool support v4 elements only
|
|
5158
|
-
|
|
5159
|
-
# WORKFLOW
|
|
5160
|
-
1. Check/create global classes via "manage-global-classes" tool
|
|
5161
|
-
2. Build composition (THIS TOOL) - minimal inline styles
|
|
5162
|
-
3. Apply classes via "apply-global-class" tool
|
|
5163
|
-
|
|
5164
|
-
# XML STRUCTURE
|
|
5165
|
-
- Use widget tags: \`<e-button configuration-id="btn1"></e-button>\`
|
|
5166
|
-
- Containers: "e-flexbox", "e-div-block", "e-tabs"
|
|
5167
|
-
- Every element needs unique "configuration-id"
|
|
5168
|
-
- No attributes, classes, IDs, or text nodes in XML
|
|
5169
|
-
|
|
5170
|
-
## NESTED ELEMENTS
|
|
5171
|
-
Some elements have internal tree structures (nesting). When using these elements, you MUST build the FULL tree in XML.
|
|
5172
|
-
- Check \`llm_guidance.nesting\` in widget schemas for structure requirements
|
|
5173
|
-
- \`llm_guidance.required_direct_children\` lists element types that must appear as direct child tags in XML (from widget defaults)
|
|
5174
|
-
- \`allowed_child_types\` lists which element types can be nested inside
|
|
5175
|
-
- \`allowed_parents\` lists which element types this element can be placed inside
|
|
5176
|
-
|
|
5177
|
-
# CONFIGURATION
|
|
5178
|
-
- Map configuration-id \u2192 elementConfig (props) + style (raw CSS declarations)
|
|
5179
|
-
- elementConfig PropValues require \`$$type\` matching schema
|
|
5180
|
-
- style is raw CSS (property \u2192 value strings); the server converts it to native styles and stores any unconvertible declarations as the element custom CSS
|
|
5181
|
-
- NO LINKS in configuration
|
|
5182
|
-
- Retry on errors up to 10x
|
|
5183
|
-
- Check \`llm_guidance.default_settings\` in widget schemas \u2014 omit only keys listed there from elementConfig unless the user explicitly asks to change them
|
|
5184
|
-
|
|
5185
|
-
# DYNAMIC TAGS
|
|
5186
|
-
- A value can be made dynamic wherever its schema exposes a \`"$$type": "dynamic"\` variant. This may be the property root OR a NESTED field (e.g. an image's \`src\`, not the whole \`image\`).
|
|
5187
|
-
- Put the dynamic object EXACTLY at that node, in place of the static variant. The variant's \`name\` lists the allowed tags; read [${DYNAMIC_TAGS_URI}] for each tag's settings schema.
|
|
5188
|
-
- Provide at that node: \`{ "$$type": "dynamic", "value": { "name": "<allowed tag>", "settings": { ... } } }\`
|
|
5189
|
-
- Example (image): \`{ "$$type": "image", "value": { "src": { "$$type": "dynamic", "value": { "name": "<image tag>", "settings": { ... } } } } }\`
|
|
5190
|
-
- Do NOT send \`group\` (it is resolved automatically). Populate \`settings\` strictly per the tag's schema; use \`{}\` only when it has none.
|
|
5191
|
-
|
|
5192
|
-
Note about configuration ids: These names are visible to the end-user, make sure they make sense, related and relevant.
|
|
5193
|
-
|
|
5194
|
-
# DESIGN PHILOSOPHY: CONTEXT-DRIVEN CREATIVITY
|
|
5195
|
-
|
|
5196
|
-
**Use the user's context aggressively.** Business type, brand personality, target audience, and purpose should drive every design decision. A law firm needs gravitas; a children's app needs playfulness. Don't default to generic.
|
|
5197
|
-
|
|
5198
|
-
## SIZING: DEFAULT IS NO SIZE (CRITICAL)
|
|
5199
|
-
|
|
5200
|
-
**DO NOT specify height or width unless you have a specific visual reason.**
|
|
5201
|
-
|
|
5202
|
-
Flexbox and CSS already handle sizing automatically:
|
|
5203
|
-
- Containers grow to fit their content
|
|
5204
|
-
- Flex children distribute space via flex properties, not width/height
|
|
5205
|
-
- Text elements size to their content
|
|
5206
|
-
|
|
5207
|
-
WHEN TO SPECIFY SIZE:
|
|
5208
|
-
- min-height on ROOT section for viewport-spanning hero (use min-height, NOT height)
|
|
5209
|
-
- max-width for contained content areas (e.g., max-width: 60rem)
|
|
5210
|
-
- Explicit aspect ratios for media containers
|
|
5211
|
-
|
|
5212
|
-
NEVER SPECIFY:
|
|
5213
|
-
- height on nested containers (causes overflow)
|
|
5214
|
-
- width on flex children (use flex-basis or gap instead)
|
|
5215
|
-
- 100vh on anything except root-level sections
|
|
5216
|
-
- Any size "just to be safe" - if unsure, OMIT IT
|
|
5217
|
-
|
|
5218
|
-
vh units are VIEWPORT-relative. Nested 100vh inside 100vh = 200vh overflow.
|
|
5219
|
-
|
|
5220
|
-
GOOD: \`<e-flexbox>content naturally sizes</e-flexbox>\`
|
|
5221
|
-
BAD: \`<e-flexbox style="height:100vh"><e-div-block style="height:100vh">overflow</e-div-block></e-flexbox>\`
|
|
5222
|
-
|
|
5223
|
-
## Layout Variety (Break the Template)
|
|
5224
|
-
- AVOID: Full-width 100vh hero \u2192 three columns \u2192 testimonials \u2192 CTA (every AI does this)
|
|
5225
|
-
- VARY heights: Use auto-height sections with generous padding (6rem+). Let content breathe
|
|
5226
|
-
- VARY widths: Not everything spans full width. Use contained sections (max-width: 960px) mixed with edge-to-edge
|
|
5227
|
-
- ASYMMETRIC grids: 2:1, 1:3, offset layouts. Avoid equal column widths
|
|
5228
|
-
- Negative space as design element: Large margins create focus and sophistication
|
|
5229
|
-
- Break alignment intentionally: Offset headings, overlapping elements, broken grids
|
|
5230
|
-
|
|
5231
|
-
## Visual Depth & Effects
|
|
5232
|
-
- Layer elements: Overlapping cards, text over images, floating elements
|
|
5233
|
-
- Subtle shadows with color tint (not pure black): \`box-shadow: 0 20px 60px rgba(<brand-color-here>, 0.15)\`
|
|
5234
|
-
- Gradient overlays on images for text readability
|
|
5235
|
-
- Border radius variation: Mix sharp (0) and soft (1rem+) corners purposefully
|
|
5236
|
-
- Backdrop blur for glassmorphism where appropriate
|
|
5237
|
-
- Micro-interactions via CSS: hover transforms, transitions (0.3s ease)
|
|
5238
|
-
|
|
5239
|
-
## Typography with Character
|
|
5240
|
-
- Display fonts for headlines (from user's brand or contextually appropriate)
|
|
5241
|
-
- Size contrast: 4rem+ headlines vs 1rem body. Make hierarchy unmistakable
|
|
5242
|
-
- Letter-spacing: Tight for large headlines (-0.02em), loose for small caps (0.1em)
|
|
5243
|
-
- Line-height: Tight for headlines (1.1), generous for body (1.6-1.8)
|
|
5244
|
-
- Text decoration: Underlines, highlights, gradient text for emphasis
|
|
5245
|
-
|
|
5246
|
-
## Color with Purpose
|
|
5247
|
-
- Extract palette from user context (brand colors, industry norms, mood)
|
|
5248
|
-
- 60-30-10 rule: dominant, secondary, accent
|
|
5249
|
-
- Tinted neutrals over pure grays: warm (#faf8f5, #2d2a26) or cool (#f5f7fa, #1e2430)
|
|
5250
|
-
- Color blocking: Large colored sections create visual rhythm
|
|
5251
|
-
- Gradient directions: Diagonal (135deg, 225deg) feel more dynamic than vertical
|
|
5252
|
-
|
|
5253
|
-
## Spacing Strategy
|
|
5254
|
-
- Section padding: 6rem-10rem vertical, creating breathing room
|
|
5255
|
-
- Rhythm variation: Tight groups (2rem) with generous gaps between (6rem)
|
|
5256
|
-
- Use rem/em exclusively for responsive scaling
|
|
5257
|
-
- Generous padding on CTAs: min 1rem 2.5rem
|
|
5258
|
-
|
|
5259
|
-
# HARD CONSTRAINTS
|
|
5260
|
-
- Variables ONLY from [elementor://global-variables] (others throw errors)
|
|
5261
|
-
- Avoid SVG widgets unless assets are pre-uploaded
|
|
5262
|
-
- Check \`llm_guidance\` in widget schemas (\`default_styles\`, nesting, required children)
|
|
5263
|
-
|
|
5264
|
-
# PARAMETERS
|
|
5265
|
-
- **xmlStructure**: Valid XML with configuration-id attributes
|
|
5266
|
-
- **elementConfig**: configuration-id \u2192 widget PropValues
|
|
5267
|
-
- **style**: configuration-id \u2192 raw CSS declarations (property \u2192 value strings; no selectors)
|
|
5268
|
-
`);
|
|
5269
|
-
buildCompositionsToolPrompt.example(`
|
|
5270
|
-
Section with heading + button (NO explicit heights - content sizes naturally):
|
|
5271
|
-
{
|
|
5272
|
-
xmlStructure: "<e-flexbox configuration-id="Main Section"><e-heading configuration-id="Section Title"></e-heading><e-button configuration-id="Call to Action"></e-button></e-flexbox>",
|
|
5273
|
-
elementConfig: {
|
|
5274
|
-
"section1": { "tag": { "$$type": "string", "value": "section" } }
|
|
5275
|
-
},
|
|
5276
|
-
style: {
|
|
5277
|
-
"Section Title": {
|
|
5278
|
-
"padding": "6rem 4rem",
|
|
5279
|
-
"background": "linear-gradient(135deg, #faf8f5 0%, #f0ebe4 100%)",
|
|
5280
|
-
"font-size": "3.5rem",
|
|
5281
|
-
"color": "#2d2a26"
|
|
5282
|
-
}
|
|
5283
|
-
}
|
|
5284
|
-
}
|
|
5285
|
-
Note: No height/width specified on any element - flexbox handles layout automatically.
|
|
5286
|
-
`);
|
|
5287
|
-
buildCompositionsToolPrompt.parameter(
|
|
5288
|
-
"xmlStructure",
|
|
5289
|
-
`Valid XML structure with custom elementor tags and configuration-id attributes.`
|
|
5290
|
-
);
|
|
5291
|
-
buildCompositionsToolPrompt.parameter("elementConfig", `Record mapping configuration IDs to widget PropValues.`);
|
|
5292
|
-
buildCompositionsToolPrompt.parameter(
|
|
5293
|
-
"style",
|
|
5294
|
-
`Record mapping configuration IDs to raw CSS declarations (property \u2192 value strings).`
|
|
5295
|
-
);
|
|
5296
|
-
buildCompositionsToolPrompt.instruction(
|
|
5297
|
-
`Element IDs in the returned XML represent actual widgets. Use these IDs for subsequent styling or configuration changes.`
|
|
5298
|
-
);
|
|
5299
|
-
return buildCompositionsToolPrompt.prompt();
|
|
5300
|
-
};
|
|
5301
|
-
|
|
5302
|
-
// src/mcp/tools/build-composition/schema.ts
|
|
5303
|
-
var import_schema = require("@elementor/schema");
|
|
5304
|
-
var inputSchema = {
|
|
5305
|
-
xmlStructure: import_schema.z.string().describe("The XML structure representing the composition to be built"),
|
|
5306
|
-
elementConfig: import_schema.z.record(
|
|
5307
|
-
import_schema.z.string().describe("The configuration id"),
|
|
5308
|
-
import_schema.z.record(
|
|
5309
|
-
import_schema.z.string().describe("property name"),
|
|
5310
|
-
import_schema.z.any().describe(`The PropValue for the property, refer to ${WIDGET_SCHEMA_URI}`)
|
|
5311
|
-
)
|
|
5312
|
-
).describe("A record mapping element IDs to their configuration objects. REQUIRED"),
|
|
5313
|
-
style: import_schema.z.record(
|
|
5314
|
-
import_schema.z.string().describe("The configuration id"),
|
|
5315
|
-
import_schema.z.record(
|
|
5316
|
-
import_schema.z.string().describe('A CSS property name, e.g. "color", "padding".'),
|
|
5317
|
-
import_schema.z.string().describe('A CSS value, e.g. "6rem 4rem", "#2d2a26".')
|
|
5318
|
-
)
|
|
5319
|
-
).describe(
|
|
5320
|
-
"A record mapping element configuration IDs to their raw CSS declarations (property\u2192value). Converted to native styles server-side; any declaration that cannot be converted is stored as the element custom CSS."
|
|
5321
|
-
).default({})
|
|
5322
|
-
};
|
|
5323
|
-
var outputSchema = {
|
|
5324
|
-
errors: import_schema.z.string().describe("Error message if the composition building failed").optional(),
|
|
5325
|
-
xmlStructure: import_schema.z.string().describe(
|
|
5326
|
-
"The built XML structure as a string. Must use this XML after completion of building the composition, it contains real IDs."
|
|
5327
|
-
).optional(),
|
|
5328
|
-
llm_instructions: import_schema.z.string().describe("Instructions what to do next, Important to follow these instructions!").optional()
|
|
5329
|
-
};
|
|
5330
|
-
|
|
5331
|
-
// src/mcp/tools/build-composition/xml-leaf-wrapper.ts
|
|
5332
|
-
var DIV_BLOCK_TAG = "e-div-block";
|
|
5333
|
-
var ZERO_SPACING = {
|
|
5334
|
-
$$type: "size",
|
|
5335
|
-
value: {
|
|
5336
|
-
size: {
|
|
5337
|
-
$$type: "number",
|
|
5338
|
-
value: 0
|
|
5339
|
-
},
|
|
5340
|
-
unit: {
|
|
5341
|
-
$$type: "string",
|
|
5342
|
-
value: "px"
|
|
5343
|
-
}
|
|
5344
|
-
}
|
|
5345
|
-
};
|
|
5346
|
-
function adaptLeafRootParams(params) {
|
|
5347
|
-
const doc = new DOMParser().parseFromString(params.xmlStructure, "application/xml");
|
|
5348
|
-
const rootElement = doc.documentElement;
|
|
5349
|
-
if (!isLeafWidget(rootElement.tagName, params.widgetsCache)) {
|
|
5350
|
-
return params;
|
|
5351
|
-
}
|
|
5352
|
-
const wrapperConfigId = getDivBlockWrapperConfigId(params.widgetsCache);
|
|
5353
|
-
return {
|
|
5354
|
-
...params,
|
|
5355
|
-
xmlStructure: serializeWrapped(doc, rootElement, wrapperConfigId),
|
|
5356
|
-
stylesConfig: {
|
|
5357
|
-
...params.stylesConfig,
|
|
5358
|
-
[wrapperConfigId]: {
|
|
5359
|
-
margin: ZERO_SPACING,
|
|
5360
|
-
padding: ZERO_SPACING,
|
|
5361
|
-
...params.stylesConfig[wrapperConfigId]
|
|
5362
|
-
}
|
|
5363
|
-
}
|
|
5364
|
-
};
|
|
5365
|
-
}
|
|
5366
|
-
function getDivBlockWrapperConfigId(widgetsCache) {
|
|
5367
|
-
return widgetsCache[DIV_BLOCK_TAG]?.title ?? DIV_BLOCK_TAG;
|
|
5368
|
-
}
|
|
5369
|
-
function isLeafWidget(tagName, widgetsCache) {
|
|
5370
|
-
return widgetsCache[tagName]?.elType === "widget";
|
|
5371
|
-
}
|
|
5372
|
-
function serializeWrapped(doc, rootElement, wrapperConfigId) {
|
|
5373
|
-
const wrapper = doc.createElement(DIV_BLOCK_TAG);
|
|
5374
|
-
wrapper.setAttribute("configuration-id", wrapperConfigId);
|
|
5375
|
-
wrapper.appendChild(rootElement.cloneNode(true));
|
|
5376
|
-
const wrappedDoc = new DOMParser().parseFromString(`<${DIV_BLOCK_TAG} />`, "application/xml");
|
|
5377
|
-
wrappedDoc.replaceChild(wrapper, wrappedDoc.documentElement);
|
|
5378
|
-
return new XMLSerializer().serializeToString(wrappedDoc);
|
|
5379
|
-
}
|
|
5380
|
-
|
|
5381
|
-
// src/mcp/tools/build-composition/tool.ts
|
|
5382
|
-
var ELEMENT_ADDED_EVENT = "elementor/canvas/element-added";
|
|
5383
|
-
var initBuildCompositionsTool = (reg) => {
|
|
5384
|
-
const { addTool, resource } = reg;
|
|
5385
|
-
resource(
|
|
5386
|
-
"build-compositions-guide",
|
|
5387
|
-
BUILD_COMPOSITIONS_GUIDE_URI,
|
|
5388
|
-
{
|
|
5389
|
-
title: "Build Compositions Guide",
|
|
5390
|
-
description: "Detailed guide for using the build-compositions tool",
|
|
5391
|
-
mimeType: "text/plain"
|
|
5392
|
-
},
|
|
5393
|
-
async (uri) => ({
|
|
5394
|
-
contents: [{ uri: uri.href, mimeType: "text/plain", text: generatePrompt() }]
|
|
5395
|
-
})
|
|
5396
|
-
);
|
|
5397
|
-
addTool({
|
|
5398
|
-
name: "build-compositions",
|
|
5399
|
-
description: "Build V4 element compositions on the Elementor canvas. Read the guide resource before use.",
|
|
5400
|
-
schema: inputSchema,
|
|
5401
|
-
requiredResources: [
|
|
5402
|
-
{ description: "Build compositions guide", uri: BUILD_COMPOSITIONS_GUIDE_URI },
|
|
5403
|
-
{ description: "Widgets schema", uri: WIDGET_SCHEMA_URI },
|
|
5404
|
-
{ description: "Global Classes", uri: "elementor://global-classes" },
|
|
5405
|
-
{ description: "Global Variables", uri: "elementor://global-variables" },
|
|
5406
|
-
{ description: "Styles best practices", uri: BEST_PRACTICES_URI },
|
|
5407
|
-
{ description: "Available widgets for this tool", uri: AVAILABLE_WIDGETS_URI_V4 },
|
|
5408
|
-
{ description: "Dynamic tags catalog", uri: DYNAMIC_TAGS_URI }
|
|
5409
|
-
],
|
|
5410
|
-
outputSchema,
|
|
5411
|
-
handler: async (rawParams) => {
|
|
5412
|
-
assertCompositionXmlUsesV4WidgetsOnly(rawParams.xmlStructure);
|
|
5413
|
-
const { stylesConfig: convertedStyles, customCSS } = await convertCompositionStyles(rawParams.style);
|
|
5414
|
-
const { xmlStructure, elementConfig, stylesConfig } = adaptLeafRootParams({
|
|
5415
|
-
...rawParams,
|
|
5416
|
-
stylesConfig: convertedStyles,
|
|
5417
|
-
widgetsCache: (0, import_editor_elements15.getWidgetsCache)() ?? {}
|
|
5418
|
-
});
|
|
5419
|
-
let generatedXML = "";
|
|
5420
|
-
const errors = [];
|
|
5421
|
-
const rootContainers = [];
|
|
5422
|
-
const documentContainer = (0, import_editor_elements15.getContainer)("document");
|
|
5423
|
-
const currentDocument = (0, import_editor_documents3.getCurrentDocument)();
|
|
5424
|
-
const targetContainer = getCompositionTargetContainer(documentContainer, currentDocument?.type.value);
|
|
5425
|
-
try {
|
|
5426
|
-
const compositionBuilder = CompositionBuilder.fromXMLString(xmlStructure, {
|
|
5427
|
-
createElement: import_editor_elements15.createElement,
|
|
5428
|
-
deleteElement: import_editor_elements15.deleteElement,
|
|
5429
|
-
getWidgetsCache: import_editor_elements15.getWidgetsCache
|
|
5430
|
-
});
|
|
5431
|
-
compositionBuilder.setElementConfig(elementConfig);
|
|
5432
|
-
compositionBuilder.setStylesConfig(stylesConfig);
|
|
5433
|
-
compositionBuilder.setCustomCSS(customCSS);
|
|
5434
|
-
const {
|
|
5435
|
-
configErrors,
|
|
5436
|
-
formErrors,
|
|
5437
|
-
rootContainers: generatedRootContainers
|
|
5438
|
-
} = await compositionBuilder.build(targetContainer);
|
|
5439
|
-
rootContainers.push(...generatedRootContainers);
|
|
5440
|
-
generatedXML = new XMLSerializer().serializeToString(compositionBuilder.getXML());
|
|
5441
|
-
rootContainers.forEach((container) => {
|
|
5442
|
-
const elementData = container.model?.toJSON();
|
|
5443
|
-
if (elementData) {
|
|
5444
|
-
onElementAdded(elementData);
|
|
5445
|
-
}
|
|
5446
|
-
});
|
|
5447
|
-
Object.values(stylesConfig).forEach((styleValue) => {
|
|
5448
|
-
(0, import_editor_mcp3.dispatchMcpStylesAppliedEvent)({ styleValue });
|
|
5449
|
-
});
|
|
5450
|
-
if (configErrors.length) {
|
|
5451
|
-
errors.push(...configErrors.map((msg) => new Error(msg)));
|
|
5452
|
-
}
|
|
5453
|
-
if (formErrors.length) {
|
|
5454
|
-
errors.push(...formErrors.map((msg) => new Error(msg)));
|
|
5455
|
-
}
|
|
5456
|
-
} catch (error) {
|
|
5457
|
-
errors.push(error);
|
|
5458
|
-
}
|
|
5459
|
-
if (errors.length) {
|
|
5460
|
-
rootContainers.forEach((rootContainer) => {
|
|
5461
|
-
(0, import_editor_elements15.deleteElement)({
|
|
5462
|
-
container: rootContainer,
|
|
5463
|
-
options: { useHistory: false }
|
|
5464
|
-
});
|
|
5465
|
-
});
|
|
5466
|
-
const errorMessages = errors.map((e) => {
|
|
5467
|
-
if (typeof e === "string") {
|
|
5468
|
-
return e;
|
|
5469
|
-
}
|
|
5470
|
-
if (e instanceof Error) {
|
|
5471
|
-
return e.message || String(e);
|
|
5472
|
-
}
|
|
5473
|
-
if (typeof e === "object" && e !== null) {
|
|
5474
|
-
return JSON.stringify(e);
|
|
5475
|
-
}
|
|
5476
|
-
return String(e);
|
|
5477
|
-
}).filter(
|
|
5478
|
-
(msg) => msg && msg.trim() !== "" && msg !== "{}" && msg !== "null" && msg !== "undefined"
|
|
5479
|
-
);
|
|
5480
|
-
if (errorMessages.length === 0) {
|
|
5481
|
-
throw new Error(
|
|
5482
|
-
"Failed to build composition: Unknown error occurred. No error details available."
|
|
5483
|
-
);
|
|
5484
|
-
}
|
|
5485
|
-
const errorText = `Failed to build composition with the following errors:
|
|
5486
|
-
|
|
5487
|
-
${errorMessages.join(
|
|
5488
|
-
"\n\n"
|
|
5489
|
-
)}`;
|
|
5490
|
-
throw new Error(errorText);
|
|
5491
|
-
}
|
|
5492
|
-
return {
|
|
5493
|
-
xmlStructure: generatedXML,
|
|
5494
|
-
errors: errors?.length ? errors.map((e) => typeof e === "string" ? e : e.message).join("\n\n") : void 0,
|
|
5495
|
-
llm_instructions: `The composition was built successfully with element IDs embedded in the XML.
|
|
5496
|
-
|
|
5497
|
-
**CRITICAL NEXT STEPS** (Follow in order):
|
|
5498
|
-
1. **Apply Global Classes**: Use "apply-global-class" tool to apply the global classes you created BEFORE building this composition
|
|
5499
|
-
- Check the created element IDs in the returned XML
|
|
5500
|
-
- Apply semantic classes (heading-primary, button-cta, etc.) to appropriate elements
|
|
5501
|
-
|
|
5502
|
-
2. **Fine-tune if needed**: Use "configure-element" tool only for element-specific adjustments that don't warrant global classes
|
|
5503
|
-
|
|
5504
|
-
Remember: Global classes ensure design consistency and reusability. Don't skip applying them!
|
|
5505
|
-
`
|
|
5506
|
-
};
|
|
5507
|
-
}
|
|
5508
|
-
});
|
|
5509
|
-
};
|
|
5510
|
-
async function convertCompositionStyles(style) {
|
|
5511
|
-
const stylesConfig = {};
|
|
5512
|
-
const customCSS = {};
|
|
5513
|
-
if (!style || Object.keys(style).length === 0) {
|
|
5514
|
-
return { stylesConfig, customCSS };
|
|
5515
|
-
}
|
|
5516
|
-
const results = await convertStyleBlocksToAtomic(style);
|
|
5517
|
-
for (const [configId, { props, customCss }] of Object.entries(results)) {
|
|
5518
|
-
stylesConfig[configId] = props;
|
|
5519
|
-
if (customCss) {
|
|
5520
|
-
customCSS[configId] = customCss;
|
|
5521
|
-
}
|
|
5522
|
-
}
|
|
5523
|
-
return { stylesConfig, customCSS };
|
|
5524
|
-
}
|
|
5525
|
-
function assertCompositionXmlUsesV4WidgetsOnly(xmlStructure) {
|
|
5526
|
-
const doc = new DOMParser().parseFromString(xmlStructure, "application/xml");
|
|
5527
|
-
if (doc.querySelector("parsererror")) {
|
|
5528
|
-
throw new Error("Failed to parse XML string: " + doc);
|
|
5529
|
-
}
|
|
5530
|
-
const widgetsCache = (0, import_editor_elements15.getWidgetsCache)() ?? {};
|
|
5531
|
-
for (const node of doc.querySelectorAll("*")) {
|
|
5532
|
-
const type = node.tagName;
|
|
5533
|
-
const widgetData = widgetsCache[type];
|
|
5534
|
-
if (!widgetData) {
|
|
5535
|
-
continue;
|
|
5536
|
-
}
|
|
5537
|
-
if (widgetData.elType !== "widget") {
|
|
5538
|
-
continue;
|
|
5539
|
-
}
|
|
5540
|
-
if (!isWidgetAvailableForLLM(widgetData) || !widgetData.atomic_props_schema) {
|
|
5541
|
-
throw new Error(`This tool does not support element type: ${type}`);
|
|
5542
|
-
}
|
|
5543
|
-
}
|
|
5544
|
-
}
|
|
5545
|
-
function onElementAdded(element) {
|
|
5546
|
-
const elType = element.elType ?? "";
|
|
5547
|
-
const widgetType = element.widgetType ?? "";
|
|
5548
|
-
const elementName = elType === "widget" ? widgetType : elType;
|
|
5549
|
-
trackCanvasEvent({
|
|
5550
|
-
eventName: "add_element",
|
|
5551
|
-
executed_by: "mcp_tool",
|
|
5552
|
-
element_name: elementName,
|
|
5553
|
-
element_type: elType,
|
|
5554
|
-
widget_type: widgetType
|
|
5555
|
-
});
|
|
5556
|
-
const event = {
|
|
5557
|
-
element,
|
|
5558
|
-
executedBy: "mcp_tool"
|
|
5559
|
-
};
|
|
5560
|
-
window.dispatchEvent(new CustomEvent(ELEMENT_ADDED_EVENT, { detail: event }));
|
|
5561
|
-
if (element.elements?.length) {
|
|
5562
|
-
element.elements?.forEach((childElement) => {
|
|
5563
|
-
onElementAdded(childElement);
|
|
5564
|
-
});
|
|
5565
|
-
}
|
|
5566
|
-
}
|
|
5567
|
-
|
|
5568
|
-
// src/mcp/tools/configure-element/tool.ts
|
|
5569
|
-
var import_editor_elements16 = require("@elementor/editor-elements");
|
|
5570
|
-
var import_editor_mcp5 = require("@elementor/editor-mcp");
|
|
5571
|
-
var import_editor_props7 = require("@elementor/editor-props");
|
|
5572
|
-
|
|
5573
4850
|
// src/mcp/tools/configure-element/prompt.ts
|
|
5574
|
-
var
|
|
4851
|
+
var import_editor_mcp2 = require("@elementor/editor-mcp");
|
|
5575
4852
|
var CONFIGURE_ELEMENT_GUIDE_URI = "elementor://canvas/tools/configure-element-guide";
|
|
5576
|
-
var
|
|
5577
|
-
const configureElementToolPrompt = (0,
|
|
4853
|
+
var generatePrompt = () => {
|
|
4854
|
+
const configureElementToolPrompt = (0, import_editor_mcp2.toolPrompts)("configure-element");
|
|
5578
4855
|
configureElementToolPrompt.description(`
|
|
5579
4856
|
Configure an existing element on the page.
|
|
5580
4857
|
|
|
@@ -5682,29 +4959,29 @@ NO Advanced tab. Never mention Advanced tab.
|
|
|
5682
4959
|
`);
|
|
5683
4960
|
return configureElementToolPrompt.prompt();
|
|
5684
4961
|
};
|
|
5685
|
-
var CONFIGURE_ELEMENT_GUIDE_TEXT =
|
|
4962
|
+
var CONFIGURE_ELEMENT_GUIDE_TEXT = generatePrompt();
|
|
5686
4963
|
|
|
5687
4964
|
// src/mcp/tools/configure-element/schema.ts
|
|
5688
|
-
var
|
|
5689
|
-
var
|
|
5690
|
-
propertiesToChange:
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
4965
|
+
var import_schema2 = require("@elementor/schema");
|
|
4966
|
+
var inputSchema = {
|
|
4967
|
+
propertiesToChange: import_schema2.z.record(
|
|
4968
|
+
import_schema2.z.string().describe("The property name."),
|
|
4969
|
+
import_schema2.z.any().describe(`PropValue, refer to [${WIDGET_SCHEMA_URI}] by correct type, as appears in elementType`),
|
|
4970
|
+
import_schema2.z.any()
|
|
5694
4971
|
).describe("An object record containing property names and their new values to be set on the element"),
|
|
5695
|
-
style:
|
|
5696
|
-
|
|
5697
|
-
|
|
4972
|
+
style: import_schema2.z.record(
|
|
4973
|
+
import_schema2.z.string().describe('A CSS property name, e.g. "color", "margin-top".'),
|
|
4974
|
+
import_schema2.z.string().nullable().describe(
|
|
5698
4975
|
'A CSS value, e.g. "red", "10px", "1px solid #000". Use null to reset the property to its default.'
|
|
5699
4976
|
)
|
|
5700
4977
|
).describe(
|
|
5701
4978
|
"Raw CSS declarations as a flat property\u2192value map. Converted to native styles server-side; any declaration that cannot be converted is stored as the element custom CSS. A null value resets that property to its default."
|
|
5702
4979
|
).default({}),
|
|
5703
|
-
elementType:
|
|
5704
|
-
elementId:
|
|
4980
|
+
elementType: import_schema2.z.string().describe("The type of the element to retrieve the schema"),
|
|
4981
|
+
elementId: import_schema2.z.string().describe("The unique id of the element to configure")
|
|
5705
4982
|
};
|
|
5706
|
-
var
|
|
5707
|
-
success:
|
|
4983
|
+
var outputSchema = {
|
|
4984
|
+
success: import_schema2.z.boolean().describe(
|
|
5708
4985
|
"Whether the configuration change was successful, only if propertyName and propertyValue are provided"
|
|
5709
4986
|
)
|
|
5710
4987
|
};
|
|
@@ -5721,27 +4998,27 @@ var initConfigureElementTool = (reg) => {
|
|
|
5721
4998
|
mimeType: "text/plain"
|
|
5722
4999
|
},
|
|
5723
5000
|
async (uri) => ({
|
|
5724
|
-
contents: [{ uri: uri.href, mimeType: "text/plain", text:
|
|
5001
|
+
contents: [{ uri: uri.href, mimeType: "text/plain", text: generatePrompt() }]
|
|
5725
5002
|
})
|
|
5726
5003
|
);
|
|
5727
5004
|
addTool({
|
|
5728
5005
|
name: "configure-element",
|
|
5729
5006
|
description: "Configure an existing V4 element's properties and styles. Read the guide resource before use.",
|
|
5730
|
-
schema:
|
|
5731
|
-
outputSchema
|
|
5007
|
+
schema: inputSchema,
|
|
5008
|
+
outputSchema,
|
|
5732
5009
|
requiredResources: [
|
|
5733
5010
|
{ description: "Widgets schema", uri: WIDGET_SCHEMA_URI },
|
|
5734
5011
|
{ description: "Configure element guide", uri: CONFIGURE_ELEMENT_GUIDE_URI },
|
|
5735
5012
|
{ description: "Dynamic tags catalog", uri: DYNAMIC_TAGS_URI }
|
|
5736
5013
|
],
|
|
5737
5014
|
handler: async ({ elementId, propertiesToChange, elementType, style }) => {
|
|
5738
|
-
const widgetData = (0,
|
|
5015
|
+
const widgetData = (0, import_editor_elements14.getWidgetsCache)()?.[elementType];
|
|
5739
5016
|
if (!widgetData) {
|
|
5740
5017
|
throw new Error(
|
|
5741
5018
|
`Unknown element type: ${elementType}. Check the available-widgets resource for valid types.`
|
|
5742
5019
|
);
|
|
5743
5020
|
}
|
|
5744
|
-
const container = (0,
|
|
5021
|
+
const container = (0, import_editor_elements14.getContainer)(elementId);
|
|
5745
5022
|
if (!container) {
|
|
5746
5023
|
throw new Error(`Element with id ${elementId} not found`);
|
|
5747
5024
|
}
|
|
@@ -5806,7 +5083,7 @@ async function applyStyleFromCss(opts) {
|
|
|
5806
5083
|
propertyValue: styleValue,
|
|
5807
5084
|
customCssWriteMode: "merge-with-stored"
|
|
5808
5085
|
});
|
|
5809
|
-
(0,
|
|
5086
|
+
(0, import_editor_mcp3.dispatchMcpStylesAppliedEvent)({ styleValue });
|
|
5810
5087
|
} catch (error) {
|
|
5811
5088
|
throw new Error(
|
|
5812
5089
|
createUpdateErrorMessage({
|
|
@@ -5833,30 +5110,30 @@ Provide styling as raw CSS via the "style" parameter (a flat map of CSS property
|
|
|
5833
5110
|
}
|
|
5834
5111
|
|
|
5835
5112
|
// src/mcp/tools/create-element/tool.ts
|
|
5836
|
-
var
|
|
5837
|
-
var
|
|
5838
|
-
var
|
|
5839
|
-
var
|
|
5113
|
+
var import_editor_documents3 = require("@elementor/editor-documents");
|
|
5114
|
+
var import_http_client7 = require("@elementor/http-client");
|
|
5115
|
+
var import_schema4 = require("@elementor/schema");
|
|
5116
|
+
var MCP_PROXY_URL6 = "elementor/v1/mcp-proxy";
|
|
5840
5117
|
var initCreateElementTool = (reg) => {
|
|
5841
5118
|
const { addTool } = reg;
|
|
5842
5119
|
addTool({
|
|
5843
5120
|
name: "create-element",
|
|
5844
5121
|
description: "Insert a new element into the current Elementor document via the server-side MCP ability. The document is saved as a draft. Reload the editor after calling this tool to see the result.",
|
|
5845
5122
|
schema: {
|
|
5846
|
-
elementType:
|
|
5847
|
-
parentId:
|
|
5123
|
+
elementType: import_schema4.z.string().describe("Registry identifier of the element to create, e.g. 'e-heading', 'e-flexbox'."),
|
|
5124
|
+
parentId: import_schema4.z.string().optional().describe("ID of the parent container. Omit or pass 'document' to insert at the document root.")
|
|
5848
5125
|
},
|
|
5849
5126
|
outputSchema: {
|
|
5850
|
-
elementId:
|
|
5851
|
-
previewUrl:
|
|
5852
|
-
version:
|
|
5127
|
+
elementId: import_schema4.z.string(),
|
|
5128
|
+
previewUrl: import_schema4.z.string(),
|
|
5129
|
+
version: import_schema4.z.string()
|
|
5853
5130
|
},
|
|
5854
5131
|
handler: async ({ elementType, parentId }) => {
|
|
5855
|
-
const document2 = (0,
|
|
5132
|
+
const document2 = (0, import_editor_documents3.getCurrentDocument)();
|
|
5856
5133
|
if (!document2?.id) {
|
|
5857
5134
|
throw new Error("No active document found.");
|
|
5858
5135
|
}
|
|
5859
|
-
const { data } = await (0,
|
|
5136
|
+
const { data } = await (0, import_http_client7.httpService)().post(MCP_PROXY_URL6, {
|
|
5860
5137
|
tool: "create-element",
|
|
5861
5138
|
input: {
|
|
5862
5139
|
parent_id: parentId ?? "document",
|
|
@@ -5874,20 +5151,20 @@ var initCreateElementTool = (reg) => {
|
|
|
5874
5151
|
};
|
|
5875
5152
|
|
|
5876
5153
|
// src/mcp/tools/get-element-config/tool.ts
|
|
5877
|
-
var
|
|
5154
|
+
var import_editor_elements15 = require("@elementor/editor-elements");
|
|
5878
5155
|
var import_editor_props8 = require("@elementor/editor-props");
|
|
5879
|
-
var
|
|
5156
|
+
var import_schema5 = require("@elementor/schema");
|
|
5880
5157
|
var schema = {
|
|
5881
|
-
elementId:
|
|
5158
|
+
elementId: import_schema5.z.string()
|
|
5882
5159
|
};
|
|
5883
|
-
var
|
|
5884
|
-
properties:
|
|
5885
|
-
style:
|
|
5886
|
-
childElements:
|
|
5887
|
-
|
|
5888
|
-
id:
|
|
5889
|
-
elementType:
|
|
5890
|
-
childElements:
|
|
5160
|
+
var outputSchema2 = {
|
|
5161
|
+
properties: import_schema5.z.record(import_schema5.z.string(), import_schema5.z.any()).describe("A record mapping PropTypes to their corresponding PropValues"),
|
|
5162
|
+
style: import_schema5.z.record(import_schema5.z.string(), import_schema5.z.any()).describe("A record mapping StyleSchema properties to their corresponding PropValues"),
|
|
5163
|
+
childElements: import_schema5.z.array(
|
|
5164
|
+
import_schema5.z.object({
|
|
5165
|
+
id: import_schema5.z.string(),
|
|
5166
|
+
elementType: import_schema5.z.string(),
|
|
5167
|
+
childElements: import_schema5.z.array(import_schema5.z.any()).describe("An array of child element IDs, when applicable, same structure recursively")
|
|
5891
5168
|
})
|
|
5892
5169
|
).describe("An array of child element IDs, when applicable, with recursive structure")
|
|
5893
5170
|
};
|
|
@@ -5907,14 +5184,14 @@ var initGetElementConfigTool = (reg) => {
|
|
|
5907
5184
|
name: "get-element-configuration-values",
|
|
5908
5185
|
description: "Retrieve the element's configuration PropValues for a specific element by unique ID.",
|
|
5909
5186
|
schema,
|
|
5910
|
-
outputSchema:
|
|
5187
|
+
outputSchema: outputSchema2,
|
|
5911
5188
|
handler: async ({ elementId }) => {
|
|
5912
|
-
const element = (0,
|
|
5189
|
+
const element = (0, import_editor_elements15.getContainer)(elementId);
|
|
5913
5190
|
if (!element) {
|
|
5914
5191
|
throw new Error(`Element with ID ${elementId} not found.`);
|
|
5915
5192
|
}
|
|
5916
5193
|
const elementType = element.model.get("widgetType") || element.model.get("elType") || "";
|
|
5917
|
-
const widgetData = (0,
|
|
5194
|
+
const widgetData = (0, import_editor_elements15.getWidgetsCache)()?.[elementType];
|
|
5918
5195
|
if (!widgetData) {
|
|
5919
5196
|
throw new Error(
|
|
5920
5197
|
`Unknown element type: ${elementType}. Check the available-widgets resource for valid types.`
|
|
@@ -5926,7 +5203,7 @@ var initGetElementConfigTool = (reg) => {
|
|
|
5926
5203
|
);
|
|
5927
5204
|
}
|
|
5928
5205
|
const elementRawSettings = element.settings;
|
|
5929
|
-
const propSchema = (0,
|
|
5206
|
+
const propSchema = (0, import_editor_elements15.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
|
|
5930
5207
|
if (!elementRawSettings || !propSchema) {
|
|
5931
5208
|
throw new Error(`No settings or prop schema found for element ID: ${elementId}`);
|
|
5932
5209
|
}
|
|
@@ -5935,7 +5212,7 @@ var initGetElementConfigTool = (reg) => {
|
|
|
5935
5212
|
import_editor_props8.Schema.configurableKeys(propSchema).forEach((key) => {
|
|
5936
5213
|
propValues[key] = structuredClone(elementRawSettings.get(key));
|
|
5937
5214
|
});
|
|
5938
|
-
const elementStyles = (0,
|
|
5215
|
+
const elementStyles = (0, import_editor_elements15.getElementStyles)(elementId) || {};
|
|
5939
5216
|
const localStyle = Object.values(elementStyles).find((style) => style.label === "local");
|
|
5940
5217
|
if (localStyle) {
|
|
5941
5218
|
const defaultVariant = localStyle.variants.find(
|
|
@@ -5977,10 +5254,10 @@ var initCanvasMcp = (reg) => {
|
|
|
5977
5254
|
initEditorStateResource(reg);
|
|
5978
5255
|
initGeneralContextResource(reg);
|
|
5979
5256
|
initBestPracticesResource(reg);
|
|
5980
|
-
initBuildCompositionsTool(reg);
|
|
5981
5257
|
initGetElementConfigTool(reg);
|
|
5982
5258
|
initConfigureElementTool(reg);
|
|
5983
5259
|
initCreateElementTool(reg);
|
|
5260
|
+
initBuildCompositionTool(reg);
|
|
5984
5261
|
initBreakpointsResource(reg);
|
|
5985
5262
|
};
|
|
5986
5263
|
|
|
@@ -6093,7 +5370,7 @@ Note: The "size" property controls image resolution/loading, not visual size. Se
|
|
|
6093
5370
|
`;
|
|
6094
5371
|
|
|
6095
5372
|
// src/prevent-link-in-link-commands.ts
|
|
6096
|
-
var
|
|
5373
|
+
var import_editor_elements16 = require("@elementor/editor-elements");
|
|
6097
5374
|
var import_editor_notifications3 = require("@elementor/editor-notifications");
|
|
6098
5375
|
var import_editor_v1_adapters21 = require("@elementor/editor-v1-adapters");
|
|
6099
5376
|
var import_i18n4 = require("@wordpress/i18n");
|
|
@@ -6164,24 +5441,24 @@ function shouldBlock(sourceElements, targetElements) {
|
|
|
6164
5441
|
return false;
|
|
6165
5442
|
}
|
|
6166
5443
|
const isSourceContainsAnAnchor = sourceElements.some((src) => {
|
|
6167
|
-
return src?.id ? (0,
|
|
5444
|
+
return src?.id ? (0, import_editor_elements16.isElementAnchored)(src.id) || !!(0, import_editor_elements16.getAnchoredDescendantId)(src.id) : false;
|
|
6168
5445
|
});
|
|
6169
5446
|
if (!isSourceContainsAnAnchor) {
|
|
6170
5447
|
return false;
|
|
6171
5448
|
}
|
|
6172
5449
|
const isTargetContainsAnAnchor = targetElements.some((target) => {
|
|
6173
|
-
return target?.id ? (0,
|
|
5450
|
+
return target?.id ? (0, import_editor_elements16.isElementAnchored)(target.id) || !!(0, import_editor_elements16.getAnchoredAncestorId)(target.id) : false;
|
|
6174
5451
|
});
|
|
6175
5452
|
return isTargetContainsAnAnchor;
|
|
6176
5453
|
}
|
|
6177
5454
|
|
|
6178
5455
|
// src/style-commands/paste-style.ts
|
|
6179
|
-
var
|
|
5456
|
+
var import_editor_elements19 = require("@elementor/editor-elements");
|
|
6180
5457
|
var import_editor_props11 = require("@elementor/editor-props");
|
|
6181
5458
|
var import_editor_v1_adapters23 = require("@elementor/editor-v1-adapters");
|
|
6182
5459
|
|
|
6183
5460
|
// src/utils/command-utils.ts
|
|
6184
|
-
var
|
|
5461
|
+
var import_editor_elements17 = require("@elementor/editor-elements");
|
|
6185
5462
|
var import_editor_props10 = require("@elementor/editor-props");
|
|
6186
5463
|
var import_i18n5 = require("@wordpress/i18n");
|
|
6187
5464
|
function hasAtomicWidgets(args) {
|
|
@@ -6206,7 +5483,7 @@ function getClassesProp(container) {
|
|
|
6206
5483
|
}
|
|
6207
5484
|
function getContainerSchema(container) {
|
|
6208
5485
|
const type = container?.model.get("widgetType") || container?.model.get("elType");
|
|
6209
|
-
const widgetsCache = (0,
|
|
5486
|
+
const widgetsCache = (0, import_editor_elements17.getWidgetsCache)();
|
|
6210
5487
|
const elementType = widgetsCache?.[type];
|
|
6211
5488
|
return elementType?.atomic_props_schema ?? null;
|
|
6212
5489
|
}
|
|
@@ -6219,11 +5496,11 @@ function getClipboardElements(storageKey = "clipboard") {
|
|
|
6219
5496
|
}
|
|
6220
5497
|
}
|
|
6221
5498
|
function getTitleForContainers(containers) {
|
|
6222
|
-
return containers.length > 1 ? (0, import_i18n5.__)("Elements", "elementor") : (0,
|
|
5499
|
+
return containers.length > 1 ? (0, import_i18n5.__)("Elements", "elementor") : (0, import_editor_elements17.getElementLabel)(containers[0].id);
|
|
6223
5500
|
}
|
|
6224
5501
|
|
|
6225
5502
|
// src/style-commands/undoable-actions/paste-element-style.ts
|
|
6226
|
-
var
|
|
5503
|
+
var import_editor_elements18 = require("@elementor/editor-elements");
|
|
6227
5504
|
var import_editor_styles_repository4 = require("@elementor/editor-styles-repository");
|
|
6228
5505
|
var import_editor_v1_adapters22 = require("@elementor/editor-v1-adapters");
|
|
6229
5506
|
var import_i18n6 = require("@wordpress/i18n");
|
|
@@ -6236,7 +5513,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
|
|
|
6236
5513
|
if (!classesProp) {
|
|
6237
5514
|
return null;
|
|
6238
5515
|
}
|
|
6239
|
-
const originalStyles = (0,
|
|
5516
|
+
const originalStyles = (0, import_editor_elements18.getElementStyles)(container.id);
|
|
6240
5517
|
const [styleId, styleDef] = Object.entries(originalStyles ?? {})[0] ?? [];
|
|
6241
5518
|
const originalStyle = Object.keys(styleDef ?? {}).length ? styleDef : null;
|
|
6242
5519
|
const revertData = {
|
|
@@ -6245,7 +5522,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
|
|
|
6245
5522
|
};
|
|
6246
5523
|
if (styleId) {
|
|
6247
5524
|
newStyle.variants.forEach(({ meta, props, custom_css: customCss }) => {
|
|
6248
|
-
(0,
|
|
5525
|
+
(0, import_editor_elements18.updateElementStyle)({
|
|
6249
5526
|
elementId,
|
|
6250
5527
|
styleId,
|
|
6251
5528
|
meta,
|
|
@@ -6256,7 +5533,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
|
|
|
6256
5533
|
} else {
|
|
6257
5534
|
const [firstVariant] = newStyle.variants;
|
|
6258
5535
|
const additionalVariants = newStyle.variants.slice(1);
|
|
6259
|
-
revertData.styleId = (0,
|
|
5536
|
+
revertData.styleId = (0, import_editor_elements18.createElementStyle)({
|
|
6260
5537
|
elementId,
|
|
6261
5538
|
classesProp,
|
|
6262
5539
|
label: import_editor_styles_repository4.ELEMENTS_STYLES_RESERVED_LABEL,
|
|
@@ -6274,7 +5551,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
|
|
|
6274
5551
|
return;
|
|
6275
5552
|
}
|
|
6276
5553
|
if (!revertData.originalStyle) {
|
|
6277
|
-
(0,
|
|
5554
|
+
(0, import_editor_elements18.deleteElementStyle)(container.id, revertData.styleId);
|
|
6278
5555
|
return;
|
|
6279
5556
|
}
|
|
6280
5557
|
const classesProp = getClassesProp(container);
|
|
@@ -6283,7 +5560,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
|
|
|
6283
5560
|
}
|
|
6284
5561
|
const [firstVariant] = revertData.originalStyle.variants;
|
|
6285
5562
|
const additionalVariants = revertData.originalStyle.variants.slice(1);
|
|
6286
|
-
(0,
|
|
5563
|
+
(0, import_editor_elements18.createElementStyle)({
|
|
6287
5564
|
elementId: container.id,
|
|
6288
5565
|
classesProp,
|
|
6289
5566
|
label: import_editor_styles_repository4.ELEMENTS_STYLES_RESERVED_LABEL,
|
|
@@ -6320,7 +5597,7 @@ function pasteStyles(args, pasteLocalStyle) {
|
|
|
6320
5597
|
}
|
|
6321
5598
|
const clipboardElements = getClipboardElements(storageKey);
|
|
6322
5599
|
const [clipboardElement] = clipboardElements ?? [];
|
|
6323
|
-
const clipboardContainer = (0,
|
|
5600
|
+
const clipboardContainer = (0, import_editor_elements19.getContainer)(clipboardElement.id);
|
|
6324
5601
|
if (!clipboardElement || !clipboardContainer || !isAtomicWidget(clipboardContainer)) {
|
|
6325
5602
|
return;
|
|
6326
5603
|
}
|
|
@@ -6339,7 +5616,7 @@ function getClassesWithoutLocalStyle(clipboardContainer, style) {
|
|
|
6339
5616
|
if (!classesProp) {
|
|
6340
5617
|
return [];
|
|
6341
5618
|
}
|
|
6342
|
-
const classesSetting = (0,
|
|
5619
|
+
const classesSetting = (0, import_editor_elements19.getElementSetting)(clipboardContainer.id, classesProp);
|
|
6343
5620
|
return classesSetting?.value.filter((styleId) => styleId !== style?.id) ?? [];
|
|
6344
5621
|
}
|
|
6345
5622
|
function pasteClasses(containers, classes) {
|
|
@@ -6348,10 +5625,10 @@ function pasteClasses(containers, classes) {
|
|
|
6348
5625
|
if (!classesProp) {
|
|
6349
5626
|
return;
|
|
6350
5627
|
}
|
|
6351
|
-
const classesSetting = (0,
|
|
5628
|
+
const classesSetting = (0, import_editor_elements19.getElementSetting)(container.id, classesProp);
|
|
6352
5629
|
const currentClasses = import_editor_props11.classesPropTypeUtil.extract(classesSetting) ?? [];
|
|
6353
5630
|
const newClasses = import_editor_props11.classesPropTypeUtil.create(Array.from(/* @__PURE__ */ new Set([...classes, ...currentClasses])));
|
|
6354
|
-
(0,
|
|
5631
|
+
(0, import_editor_elements19.updateElementSettings)({
|
|
6355
5632
|
id: container.id,
|
|
6356
5633
|
props: { [classesProp]: newClasses }
|
|
6357
5634
|
});
|
|
@@ -6362,7 +5639,7 @@ function pasteClasses(containers, classes) {
|
|
|
6362
5639
|
var import_editor_v1_adapters25 = require("@elementor/editor-v1-adapters");
|
|
6363
5640
|
|
|
6364
5641
|
// src/style-commands/undoable-actions/reset-element-style.ts
|
|
6365
|
-
var
|
|
5642
|
+
var import_editor_elements20 = require("@elementor/editor-elements");
|
|
6366
5643
|
var import_editor_styles_repository5 = require("@elementor/editor-styles-repository");
|
|
6367
5644
|
var import_editor_v1_adapters24 = require("@elementor/editor-v1-adapters");
|
|
6368
5645
|
var import_i18n7 = require("@wordpress/i18n");
|
|
@@ -6371,9 +5648,9 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters24.undoable)(
|
|
|
6371
5648
|
do: ({ containers }) => {
|
|
6372
5649
|
return containers.map((container) => {
|
|
6373
5650
|
const elementId = container.model.get("id");
|
|
6374
|
-
const containerStyles = (0,
|
|
5651
|
+
const containerStyles = (0, import_editor_elements20.getElementStyles)(elementId);
|
|
6375
5652
|
Object.keys(containerStyles ?? {}).forEach(
|
|
6376
|
-
(styleId) => (0,
|
|
5653
|
+
(styleId) => (0, import_editor_elements20.deleteElementStyle)(elementId, styleId)
|
|
6377
5654
|
);
|
|
6378
5655
|
return containerStyles;
|
|
6379
5656
|
});
|
|
@@ -6389,7 +5666,7 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters24.undoable)(
|
|
|
6389
5666
|
Object.entries(containerStyles ?? {}).forEach(([styleId, style]) => {
|
|
6390
5667
|
const [firstVariant] = style.variants;
|
|
6391
5668
|
const additionalVariants = style.variants.slice(1);
|
|
6392
|
-
(0,
|
|
5669
|
+
(0, import_editor_elements20.createElementStyle)({
|
|
6393
5670
|
elementId,
|
|
6394
5671
|
classesProp,
|
|
6395
5672
|
styleId,
|
|
@@ -6461,7 +5738,7 @@ function init() {
|
|
|
6461
5738
|
component: ClassesRename
|
|
6462
5739
|
});
|
|
6463
5740
|
initCanvasMcp(
|
|
6464
|
-
(0,
|
|
5741
|
+
(0, import_editor_mcp4.getMCPByDomain)("canvas", {
|
|
6465
5742
|
instructions: `Everything related to V4 ( Atomic ) canvas.
|
|
6466
5743
|
# Canvas workflow for new compositions
|
|
6467
5744
|
- Configure elements settings and styles
|
|
@@ -6589,10 +5866,10 @@ function useEscapeOnCanvas(canvasDocument, onEscape) {
|
|
|
6589
5866
|
}
|
|
6590
5867
|
|
|
6591
5868
|
// src/utils/after-render.ts
|
|
6592
|
-
var
|
|
5869
|
+
var import_editor_elements21 = require("@elementor/editor-elements");
|
|
6593
5870
|
function doAfterRender(elementIds, callback) {
|
|
6594
5871
|
const pending = elementIds.map((elementId) => {
|
|
6595
|
-
const view = (0,
|
|
5872
|
+
const view = (0, import_editor_elements21.getContainer)(elementId)?.view;
|
|
6596
5873
|
if (!view || !hasDoAfterRender(view)) {
|
|
6597
5874
|
return void 0;
|
|
6598
5875
|
}
|
|
@@ -6607,6 +5884,9 @@ function doAfterRender(elementIds, callback) {
|
|
|
6607
5884
|
function hasDoAfterRender(view) {
|
|
6608
5885
|
return typeof view?._doAfterRender === "function";
|
|
6609
5886
|
}
|
|
5887
|
+
|
|
5888
|
+
// src/sync/element-added-event.ts
|
|
5889
|
+
var ELEMENT_ADDED_EVENT = "elementor/canvas/element-added";
|
|
6610
5890
|
// Annotate the CommonJS export names for ESM import in node:
|
|
6611
5891
|
0 && (module.exports = {
|
|
6612
5892
|
BREAKPOINTS_SCHEMA_FULL_URI,
|