@elementor/editor-canvas 4.3.0-998 → 4.3.0-beta1
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 +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +452 -408
- package/dist/index.mjs +434 -386
- package/package.json +20 -20
- package/src/init-settings-transformers.ts +4 -0
- package/src/init-style-transformers.ts +2 -2
- package/src/init.tsx +5 -4
- package/src/legacy/__tests__/create-templated-element-type.test.ts +50 -0
- package/src/legacy/__tests__/list-type.test.ts +89 -0
- package/src/legacy/create-nested-templated-element-type.ts +3 -1
- package/src/legacy/create-templated-element-type.ts +5 -2
- package/src/legacy/list-type.ts +63 -0
- package/src/legacy/replacements/inline-editing/__tests__/inline-editing-eligibility.test.ts +7 -7
- package/src/legacy/replacements/inline-editing/inline-editing-elements.tsx +22 -9
- package/src/legacy/replacements/inline-editing/inline-editing-eligibility.ts +12 -3
- package/src/legacy/tabs-model-extensions.ts +2 -5
- package/src/legacy/twig-rendering-utils.ts +11 -2
- package/src/legacy/types.ts +4 -0
- package/src/mcp/canvas-mcp.ts +2 -6
- package/src/mcp/mcp-description.ts +18 -30
- package/src/mcp/resources/__tests__/available-widgets-resource.test.ts +22 -13
- package/src/mcp/resources/__tests__/dynamic-tags-resource.test.ts +22 -30
- package/src/mcp/resources/__tests__/widgets-schema-resource.test.ts +11 -6
- package/src/mcp/resources/available-widgets-resource.ts +13 -10
- package/src/mcp/resources/dynamic-tags-resource.ts +6 -15
- package/src/mcp/resources/widgets-schema-resource.ts +8 -5
- package/src/mcp/tools/configure-element/__tests__/tool.test.ts +130 -0
- package/src/mcp/tools/configure-element/prompt.ts +3 -6
- package/src/mcp/tools/configure-element/schema.ts +6 -0
- package/src/mcp/tools/configure-element/tool.ts +11 -1
- package/src/mcp/tools/get-page-structure/tool.ts +73 -0
- package/src/mcp/utils/__tests__/do-update-element-property.test.ts +27 -1
- package/src/mcp/utils/do-update-element-property.ts +18 -6
- package/src/mcp/utils/get-mcp-error-message.ts +16 -0
- package/src/renderers/__tests__/compute-html-tag.test.ts +55 -0
- package/src/renderers/__tests__/create-dom-renderer.test.ts +60 -0
- package/src/renderers/__tests__/fixtures/html-tag-computer-cases.json +87 -0
- package/src/renderers/compute-html-tag.ts +73 -0
- package/src/renderers/create-dom-renderer.ts +13 -22
- package/src/transformers/settings/escaped-html-transformer.ts +6 -0
- package/src/transformers/shared/__tests__/icon-transformer.test.ts +74 -0
- package/src/transformers/shared/icon-transformer.ts +122 -0
- package/src/transformers/shared/process-svg-content.ts +26 -0
- package/src/transformers/shared/svg-src-transformer.ts +1 -26
- package/src/utils/__tests__/sanitize-escaped-html.test.ts +105 -0
- package/src/utils/sanitize-escaped-html.ts +32 -0
- package/src/mcp/tools/build-composition/tool.ts +0 -133
- package/src/mcp/tools/create-element/tool.ts +0 -61
- package/src/mcp/tools/get-element-config/tool.ts +0 -114
package/dist/index.js
CHANGED
|
@@ -81,10 +81,10 @@ var BEST_PRACTICES_FULL_URI = `${CANVAS_SERVER_NAME}_${BEST_PRACTICES_URI}`;
|
|
|
81
81
|
var MCP_PROXY_URL = "elementor/v1/mcp-proxy";
|
|
82
82
|
var listWidgetTypes = async () => {
|
|
83
83
|
const { data } = await (0, import_http_client.httpService)().post(MCP_PROXY_URL, {
|
|
84
|
-
tool: "list-
|
|
85
|
-
input: {}
|
|
84
|
+
tool: "list-widget-schemas",
|
|
85
|
+
input: { summary: true }
|
|
86
86
|
});
|
|
87
|
-
return (data.data ?? []).map((widget) => widget.type);
|
|
87
|
+
return (data.data?.widgets ?? []).map((widget) => widget.type);
|
|
88
88
|
};
|
|
89
89
|
var fetchWidgetSchema = async (widgetType) => {
|
|
90
90
|
const { data } = await (0, import_http_client.httpService)().post(MCP_PROXY_URL, {
|
|
@@ -116,13 +116,13 @@ var initWidgetsSchemaResource = (reg) => {
|
|
|
116
116
|
if (!widgetType) {
|
|
117
117
|
throw new Error("No widget type provided.");
|
|
118
118
|
}
|
|
119
|
-
const
|
|
119
|
+
const schema = await fetchWidgetSchema(widgetType);
|
|
120
120
|
return {
|
|
121
121
|
contents: [
|
|
122
122
|
{
|
|
123
123
|
uri: uri.toString(),
|
|
124
124
|
mimeType: "application/json",
|
|
125
|
-
text: JSON.stringify(
|
|
125
|
+
text: JSON.stringify(schema)
|
|
126
126
|
}
|
|
127
127
|
]
|
|
128
128
|
};
|
|
@@ -1310,10 +1310,10 @@ var getMultiPropsValue = (multiProps) => {
|
|
|
1310
1310
|
// src/renderers/create-props-resolver.ts
|
|
1311
1311
|
var TRANSFORM_DEPTH_LIMIT = 3;
|
|
1312
1312
|
function createPropsResolver({ transformers, schema: initialSchema, onPropResolve }) {
|
|
1313
|
-
async function resolve({ props, schema
|
|
1314
|
-
|
|
1313
|
+
async function resolve({ props, schema, signal, renderContext }) {
|
|
1314
|
+
schema = schema ?? initialSchema;
|
|
1315
1315
|
const promises = Promise.all(
|
|
1316
|
-
Object.entries(
|
|
1316
|
+
Object.entries(schema).map(async ([key, type]) => {
|
|
1317
1317
|
const value = props[key] ?? type.default;
|
|
1318
1318
|
const transformed = await transform({ value, key, type, signal, renderContext });
|
|
1319
1319
|
onPropResolve?.({ key, value: transformed, propValue: value, propType: type });
|
|
@@ -2037,6 +2037,40 @@ var dateTimeTransformer = createTransformer((values) => {
|
|
|
2037
2037
|
}).join(" ");
|
|
2038
2038
|
});
|
|
2039
2039
|
|
|
2040
|
+
// src/utils/sanitize-escaped-html.ts
|
|
2041
|
+
var import_dompurify = __toESM(require("dompurify"));
|
|
2042
|
+
var ALLOWED_NON_OPERATIONAL_ATTRS = [
|
|
2043
|
+
"href",
|
|
2044
|
+
"target",
|
|
2045
|
+
"class",
|
|
2046
|
+
"id",
|
|
2047
|
+
"style",
|
|
2048
|
+
"title",
|
|
2049
|
+
"lang",
|
|
2050
|
+
"dir",
|
|
2051
|
+
"role"
|
|
2052
|
+
];
|
|
2053
|
+
function getAllowedHtmlWrapperTags() {
|
|
2054
|
+
return window.elementorCommon?.config?.allowedHTMLWrapperTags ?? [];
|
|
2055
|
+
}
|
|
2056
|
+
function sanitizeEscapedHtml(value) {
|
|
2057
|
+
if (!value) {
|
|
2058
|
+
return "";
|
|
2059
|
+
}
|
|
2060
|
+
const allowedTags = [...getAllowedHtmlWrapperTags()];
|
|
2061
|
+
return import_dompurify.default.sanitize(value, {
|
|
2062
|
+
ALLOWED_TAGS: allowedTags,
|
|
2063
|
+
ALLOWED_ATTR: [...ALLOWED_NON_OPERATIONAL_ATTRS],
|
|
2064
|
+
ALLOW_DATA_ATTR: true,
|
|
2065
|
+
ALLOW_ARIA_ATTR: true
|
|
2066
|
+
});
|
|
2067
|
+
}
|
|
2068
|
+
|
|
2069
|
+
// src/transformers/settings/escaped-html-transformer.ts
|
|
2070
|
+
var escapedHtmlTransformer = createTransformer((value) => {
|
|
2071
|
+
return sanitizeEscapedHtml(value);
|
|
2072
|
+
});
|
|
2073
|
+
|
|
2040
2074
|
// src/transformers/settings/html-v2-transformer.ts
|
|
2041
2075
|
var htmlV2Transformer = createTransformer((value) => {
|
|
2042
2076
|
return value?.content ?? "";
|
|
@@ -2073,6 +2107,102 @@ var timeRangeTransformer = createTransformer((value) => {
|
|
|
2073
2107
|
};
|
|
2074
2108
|
});
|
|
2075
2109
|
|
|
2110
|
+
// src/transformers/shared/process-svg-content.ts
|
|
2111
|
+
var import_dompurify2 = __toESM(require("dompurify"));
|
|
2112
|
+
var SVG_INLINE_STYLES = "width: 100%; height: 100%; overflow: unset;";
|
|
2113
|
+
function processSvgContent(svgText) {
|
|
2114
|
+
const sanitized = import_dompurify2.default.sanitize(svgText, {
|
|
2115
|
+
USE_PROFILES: { svg: true, svgFilters: true }
|
|
2116
|
+
});
|
|
2117
|
+
const parser = new DOMParser();
|
|
2118
|
+
const doc = parser.parseFromString(sanitized, "image/svg+xml");
|
|
2119
|
+
const svgElement = doc.querySelector("svg");
|
|
2120
|
+
if (!svgElement) {
|
|
2121
|
+
return null;
|
|
2122
|
+
}
|
|
2123
|
+
svgElement.setAttribute("fill", "currentColor");
|
|
2124
|
+
const existingStyle = svgElement.getAttribute("style") ?? "";
|
|
2125
|
+
const trimmed = existingStyle.trim();
|
|
2126
|
+
const merged = trimmed ? `${trimmed.replace(/;$/, "")}; ${SVG_INLINE_STYLES}` : SVG_INLINE_STYLES;
|
|
2127
|
+
svgElement.setAttribute("style", merged);
|
|
2128
|
+
return svgElement.outerHTML;
|
|
2129
|
+
}
|
|
2130
|
+
|
|
2131
|
+
// src/transformers/shared/icon-transformer.ts
|
|
2132
|
+
var FONT_AWESOME_JSON = {
|
|
2133
|
+
width: 0,
|
|
2134
|
+
height: 1,
|
|
2135
|
+
path: 4
|
|
2136
|
+
};
|
|
2137
|
+
var fontAwesomeJsonCache = /* @__PURE__ */ new Map();
|
|
2138
|
+
var iconTransformer = createTransformer(async (value, { signal }) => {
|
|
2139
|
+
const iconValue = typeof value.value === "string" ? value.value : null;
|
|
2140
|
+
const library = typeof value.library === "string" ? value.library : null;
|
|
2141
|
+
if (!iconValue || !library) {
|
|
2142
|
+
return { html: null, url: null };
|
|
2143
|
+
}
|
|
2144
|
+
const iconName = getFontAwesomeIconName(iconValue);
|
|
2145
|
+
const jsonFileName = getFontAwesomeJsonFileName(library);
|
|
2146
|
+
if (!iconName || !jsonFileName) {
|
|
2147
|
+
return { html: null, url: null };
|
|
2148
|
+
}
|
|
2149
|
+
const icons = await fetchFontAwesomeIcons(jsonFileName, signal);
|
|
2150
|
+
const iconData = icons?.[iconName];
|
|
2151
|
+
if (!iconData) {
|
|
2152
|
+
return { html: null, url: null };
|
|
2153
|
+
}
|
|
2154
|
+
const svgText = buildFontAwesomeSvg(iconData);
|
|
2155
|
+
const html = processSvgContent(svgText);
|
|
2156
|
+
return { html, url: null };
|
|
2157
|
+
});
|
|
2158
|
+
function getFontAwesomeIconName(iconValue) {
|
|
2159
|
+
const match = iconValue.match(/^fa\S*\s+fa-(.+)$/);
|
|
2160
|
+
return match?.[1] ?? null;
|
|
2161
|
+
}
|
|
2162
|
+
function getFontAwesomeJsonFileName(library) {
|
|
2163
|
+
if (!library.startsWith("fa-")) {
|
|
2164
|
+
return null;
|
|
2165
|
+
}
|
|
2166
|
+
return library.replace(/^fa-/, "");
|
|
2167
|
+
}
|
|
2168
|
+
function getAssetsBaseUrl() {
|
|
2169
|
+
const assetsUrl = window.elementorCommon?.config?.urls?.assets;
|
|
2170
|
+
return typeof assetsUrl === "string" && assetsUrl !== "" ? assetsUrl : null;
|
|
2171
|
+
}
|
|
2172
|
+
async function fetchFontAwesomeIcons(jsonFileName, signal) {
|
|
2173
|
+
const cached = fontAwesomeJsonCache.get(jsonFileName);
|
|
2174
|
+
if (cached) {
|
|
2175
|
+
return cached;
|
|
2176
|
+
}
|
|
2177
|
+
const icons = await loadFontAwesomeIcons(jsonFileName, signal);
|
|
2178
|
+
if (icons) {
|
|
2179
|
+
fontAwesomeJsonCache.set(jsonFileName, icons);
|
|
2180
|
+
}
|
|
2181
|
+
return icons;
|
|
2182
|
+
}
|
|
2183
|
+
async function loadFontAwesomeIcons(jsonFileName, signal) {
|
|
2184
|
+
const assetsUrl = getAssetsBaseUrl();
|
|
2185
|
+
if (!assetsUrl) {
|
|
2186
|
+
return null;
|
|
2187
|
+
}
|
|
2188
|
+
try {
|
|
2189
|
+
const response = await fetch(`${assetsUrl}lib/font-awesome/json/${jsonFileName}.json`, { signal });
|
|
2190
|
+
if (!response.ok) {
|
|
2191
|
+
return null;
|
|
2192
|
+
}
|
|
2193
|
+
const data = await response.json();
|
|
2194
|
+
return data.icons ?? null;
|
|
2195
|
+
} catch {
|
|
2196
|
+
return null;
|
|
2197
|
+
}
|
|
2198
|
+
}
|
|
2199
|
+
function buildFontAwesomeSvg(iconData) {
|
|
2200
|
+
const width = iconData[FONT_AWESOME_JSON.width];
|
|
2201
|
+
const height = iconData[FONT_AWESOME_JSON.height];
|
|
2202
|
+
const path = iconData[FONT_AWESOME_JSON.path];
|
|
2203
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}"><path d="${path}"></path></svg>`;
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2076
2206
|
// src/transformers/shared/image-src-transformer.ts
|
|
2077
2207
|
var imageSrcTransformer = createTransformer((value) => ({
|
|
2078
2208
|
id: value.id ?? null,
|
|
@@ -2114,26 +2244,7 @@ var plainTransformer = createTransformer((value) => {
|
|
|
2114
2244
|
});
|
|
2115
2245
|
|
|
2116
2246
|
// src/transformers/shared/svg-src-transformer.ts
|
|
2117
|
-
var import_dompurify = __toESM(require("dompurify"));
|
|
2118
2247
|
var import_wp_media2 = require("@elementor/wp-media");
|
|
2119
|
-
var SVG_INLINE_STYLES = "width: 100%; height: 100%; overflow: unset;";
|
|
2120
|
-
function processSvgContent(svgText) {
|
|
2121
|
-
const sanitized = import_dompurify.default.sanitize(svgText, {
|
|
2122
|
-
USE_PROFILES: { svg: true, svgFilters: true }
|
|
2123
|
-
});
|
|
2124
|
-
const parser = new DOMParser();
|
|
2125
|
-
const doc = parser.parseFromString(sanitized, "image/svg+xml");
|
|
2126
|
-
const svgElement = doc.querySelector("svg");
|
|
2127
|
-
if (!svgElement) {
|
|
2128
|
-
return null;
|
|
2129
|
-
}
|
|
2130
|
-
svgElement.setAttribute("fill", "currentColor");
|
|
2131
|
-
const existingStyle = svgElement.getAttribute("style") ?? "";
|
|
2132
|
-
const trimmed = existingStyle.trim();
|
|
2133
|
-
const merged = trimmed ? `${trimmed.replace(/;$/, "")}; ${SVG_INLINE_STYLES}` : SVG_INLINE_STYLES;
|
|
2134
|
-
svgElement.setAttribute("style", merged);
|
|
2135
|
-
return svgElement.outerHTML;
|
|
2136
|
-
}
|
|
2137
2248
|
async function fetchSvgContent(url, signal) {
|
|
2138
2249
|
try {
|
|
2139
2250
|
const response = await fetch(url, { signal });
|
|
@@ -2189,7 +2300,7 @@ var videoSrcTransformer = createTransformer(async (value) => {
|
|
|
2189
2300
|
|
|
2190
2301
|
// src/init-settings-transformers.ts
|
|
2191
2302
|
function initSettingsTransformers() {
|
|
2192
|
-
settingsTransformersRegistry.register("classes", createClassesTransformer()).register("link", linkTransformer).register("query", queryTransformer).register("image", imageTransformer).register("image-src", imageSrcTransformer).register("svg-src", svgSrcTransformer).register("video-src", videoSrcTransformer).register("attributes", attributesTransformer).register("date-time", dateTimeTransformer).register("html-v2", htmlV2Transformer).register("html-v3", htmlV3Transformer).register("date-range", dateRangeTransformer).register("time-range", timeRangeTransformer).registerFallback(plainTransformer);
|
|
2303
|
+
settingsTransformersRegistry.register("classes", createClassesTransformer()).register("link", linkTransformer).register("query", queryTransformer).register("image", imageTransformer).register("image-src", imageSrcTransformer).register("svg-src", svgSrcTransformer).register("icon", iconTransformer).register("video-src", videoSrcTransformer).register("attributes", attributesTransformer).register("date-time", dateTimeTransformer).register("html-v2", htmlV2Transformer).register("html-v3", htmlV3Transformer).register("escaped-html", escapedHtmlTransformer).register("date-range", dateRangeTransformer).register("time-range", timeRangeTransformer).registerFallback(plainTransformer);
|
|
2193
2304
|
}
|
|
2194
2305
|
|
|
2195
2306
|
// src/transformers/styles/background-color-overlay-transformer.ts
|
|
@@ -2466,11 +2577,11 @@ function getVal2(val) {
|
|
|
2466
2577
|
var transformOriginTransformer = createTransformer((value) => {
|
|
2467
2578
|
const x = getVal2(value.x);
|
|
2468
2579
|
const y = getVal2(value.y);
|
|
2469
|
-
const
|
|
2470
|
-
if (x === DEFAULT_XY && y === DEFAULT_XY &&
|
|
2580
|
+
const z3 = getVal2(value.z);
|
|
2581
|
+
if (x === DEFAULT_XY && y === DEFAULT_XY && z3 === DEFAULT_Z) {
|
|
2471
2582
|
return null;
|
|
2472
2583
|
}
|
|
2473
|
-
return `${x} ${y} ${
|
|
2584
|
+
return `${x} ${y} ${z3}`;
|
|
2474
2585
|
});
|
|
2475
2586
|
|
|
2476
2587
|
// src/transformers/styles/transform-rotate-transformer.ts
|
|
@@ -2548,13 +2659,13 @@ function initStyleTransformers() {
|
|
|
2548
2659
|
"layout-direction",
|
|
2549
2660
|
createMultiPropsTransformer(["row", "column"], ({ propKey, key }) => `${key}-${propKey}`)
|
|
2550
2661
|
).register("flex", flexTransformer).register(
|
|
2551
|
-
"border-width",
|
|
2662
|
+
"border-width-v2",
|
|
2552
2663
|
createMultiPropsTransformer(
|
|
2553
2664
|
["block-start", "block-end", "inline-start", "inline-end"],
|
|
2554
2665
|
({ key }) => `border-${key}-width`
|
|
2555
2666
|
)
|
|
2556
2667
|
).register(
|
|
2557
|
-
"border-radius",
|
|
2668
|
+
"border-radius-v2",
|
|
2558
2669
|
createMultiPropsTransformer(
|
|
2559
2670
|
["start-start", "start-end", "end-start", "end-end"],
|
|
2560
2671
|
({ key }) => `border-${key}-radius`
|
|
@@ -2578,28 +2689,13 @@ function createDomRenderer() {
|
|
|
2578
2689
|
render: environment.render
|
|
2579
2690
|
};
|
|
2580
2691
|
}
|
|
2692
|
+
function getAllowedHtmlWrapperTags2() {
|
|
2693
|
+
return window.elementorCommon?.config?.allowedHTMLWrapperTags ?? [];
|
|
2694
|
+
}
|
|
2581
2695
|
function escapeHtmlTag(value) {
|
|
2582
|
-
const allowedTags =
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
"aside",
|
|
2586
|
-
"button",
|
|
2587
|
-
"div",
|
|
2588
|
-
"footer",
|
|
2589
|
-
"h1",
|
|
2590
|
-
"h2",
|
|
2591
|
-
"h3",
|
|
2592
|
-
"h4",
|
|
2593
|
-
"h5",
|
|
2594
|
-
"h6",
|
|
2595
|
-
"header",
|
|
2596
|
-
"main",
|
|
2597
|
-
"nav",
|
|
2598
|
-
"p",
|
|
2599
|
-
"section",
|
|
2600
|
-
"span"
|
|
2601
|
-
];
|
|
2602
|
-
return allowedTags.includes(value) ? value : "div";
|
|
2696
|
+
const allowedTags = getAllowedHtmlWrapperTags2();
|
|
2697
|
+
const normalizedTag = value?.toLowerCase?.() ?? "";
|
|
2698
|
+
return allowedTags.includes(normalizedTag) ? value : "div";
|
|
2603
2699
|
}
|
|
2604
2700
|
function escapeURL(value) {
|
|
2605
2701
|
const allowedProtocols = ["http:", "https:", "mailto:", "tel:"];
|
|
@@ -2694,6 +2790,52 @@ function createElementViewClassDeclaration() {
|
|
|
2694
2790
|
// src/legacy/create-nested-templated-element-type.ts
|
|
2695
2791
|
var import_editor_elements6 = require("@elementor/editor-elements");
|
|
2696
2792
|
|
|
2793
|
+
// src/renderers/compute-html-tag.ts
|
|
2794
|
+
var DEFAULT_LINK_TAG = "a";
|
|
2795
|
+
function computeHtmlTag(settings, defaultTag, options = {}) {
|
|
2796
|
+
const followLink = options.followLink ?? true;
|
|
2797
|
+
if (followLink && settingsHaveActiveLink(settings)) {
|
|
2798
|
+
const link = settings.link;
|
|
2799
|
+
return extractLinkHtmlTag(isRecord(link) ? link : {});
|
|
2800
|
+
}
|
|
2801
|
+
const settingsTag = extractHtmlTagValue(settings.tag);
|
|
2802
|
+
if (null !== settingsTag && "" !== settingsTag) {
|
|
2803
|
+
return settingsTag;
|
|
2804
|
+
}
|
|
2805
|
+
return defaultTag;
|
|
2806
|
+
}
|
|
2807
|
+
function settingsHaveActiveLink(settings) {
|
|
2808
|
+
const link = settings.link;
|
|
2809
|
+
if (!isRecord(link)) {
|
|
2810
|
+
return false;
|
|
2811
|
+
}
|
|
2812
|
+
const href = extractHtmlTagValue(link.href);
|
|
2813
|
+
if (null !== href && "" !== href) {
|
|
2814
|
+
return true;
|
|
2815
|
+
}
|
|
2816
|
+
const attributes = link.attributes;
|
|
2817
|
+
return typeof attributes === "string" && "" !== attributes;
|
|
2818
|
+
}
|
|
2819
|
+
function extractLinkHtmlTag(link) {
|
|
2820
|
+
const tag = extractHtmlTagValue(link.tag);
|
|
2821
|
+
if (null !== tag && "" !== tag) {
|
|
2822
|
+
return tag;
|
|
2823
|
+
}
|
|
2824
|
+
return DEFAULT_LINK_TAG;
|
|
2825
|
+
}
|
|
2826
|
+
function extractHtmlTagValue(value) {
|
|
2827
|
+
if (isRecord(value) && typeof value.value === "string") {
|
|
2828
|
+
return value.value;
|
|
2829
|
+
}
|
|
2830
|
+
if (typeof value === "string") {
|
|
2831
|
+
return value;
|
|
2832
|
+
}
|
|
2833
|
+
return null;
|
|
2834
|
+
}
|
|
2835
|
+
function isRecord(value) {
|
|
2836
|
+
return typeof value === "object" && null !== value && !Array.isArray(value);
|
|
2837
|
+
}
|
|
2838
|
+
|
|
2697
2839
|
// src/legacy/create-pending-element.ts
|
|
2698
2840
|
var import_editor_elements5 = require("@elementor/editor-elements");
|
|
2699
2841
|
function createPendingElement(wrapperView, data, options = {}) {
|
|
@@ -2754,7 +2896,13 @@ function setupTwigRenderer({ renderer, element }) {
|
|
|
2754
2896
|
transformers: settingsTransformersRegistry,
|
|
2755
2897
|
schema: element.atomic_props_schema
|
|
2756
2898
|
});
|
|
2757
|
-
return {
|
|
2899
|
+
return {
|
|
2900
|
+
templateKey,
|
|
2901
|
+
baseStylesDictionary,
|
|
2902
|
+
resolveProps,
|
|
2903
|
+
defaultHtmlTag: element.default_html_tag ?? "div",
|
|
2904
|
+
htmlTagFollowsLink: element.html_tag_follows_link ?? true
|
|
2905
|
+
};
|
|
2758
2906
|
}
|
|
2759
2907
|
function createBeforeRender(view) {
|
|
2760
2908
|
view._ensureViewIsIntact();
|
|
@@ -2794,7 +2942,7 @@ function createTemplatedElementView({
|
|
|
2794
2942
|
element
|
|
2795
2943
|
}) {
|
|
2796
2944
|
const BaseView = createElementViewClassDeclaration();
|
|
2797
|
-
const { templateKey, baseStylesDictionary, resolveProps } = setupTwigRenderer({
|
|
2945
|
+
const { templateKey, baseStylesDictionary, resolveProps, defaultHtmlTag, htmlTagFollowsLink } = setupTwigRenderer({
|
|
2798
2946
|
type,
|
|
2799
2947
|
renderer,
|
|
2800
2948
|
element
|
|
@@ -2864,6 +3012,7 @@ function createTemplatedElementView({
|
|
|
2864
3012
|
interaction_id: this.getInteractionId(),
|
|
2865
3013
|
type,
|
|
2866
3014
|
settings,
|
|
3015
|
+
tag: computeHtmlTag(settings, defaultHtmlTag, { followLink: htmlTagFollowsLink }),
|
|
2867
3016
|
base_styles: baseStylesDictionary,
|
|
2868
3017
|
...this.getResolverRenderContext?.() ?? {}
|
|
2869
3018
|
};
|
|
@@ -2953,7 +3102,7 @@ function createNestedTemplatedElementView({
|
|
|
2953
3102
|
element
|
|
2954
3103
|
}) {
|
|
2955
3104
|
const legacyWindow = window;
|
|
2956
|
-
const { templateKey, baseStylesDictionary, resolveProps } = setupTwigRenderer({
|
|
3105
|
+
const { templateKey, baseStylesDictionary, resolveProps, defaultHtmlTag, htmlTagFollowsLink } = setupTwigRenderer({
|
|
2957
3106
|
type,
|
|
2958
3107
|
renderer,
|
|
2959
3108
|
element
|
|
@@ -3028,6 +3177,7 @@ function createNestedTemplatedElementView({
|
|
|
3028
3177
|
interaction_id: this.getInteractionId(),
|
|
3029
3178
|
type,
|
|
3030
3179
|
settings: resolvedSettings,
|
|
3180
|
+
tag: computeHtmlTag(resolvedSettings, defaultHtmlTag, { followLink: htmlTagFollowsLink }),
|
|
3031
3181
|
base_styles: baseStylesDictionary,
|
|
3032
3182
|
editor_attributes: buildEditorAttributes(model),
|
|
3033
3183
|
editor_classes: buildEditorClasses(model),
|
|
@@ -3531,7 +3681,7 @@ var import_editor_props3 = require("@elementor/editor-props");
|
|
|
3531
3681
|
var hasKey = (propType) => {
|
|
3532
3682
|
return "key" in propType;
|
|
3533
3683
|
};
|
|
3534
|
-
var TEXT_PROP_TYPE_KEYS = /* @__PURE__ */ new Set([import_editor_props3.htmlV3PropTypeUtil.key, import_editor_props3.stringPropTypeUtil.key]);
|
|
3684
|
+
var TEXT_PROP_TYPE_KEYS = /* @__PURE__ */ new Set([import_editor_props3.escapedHtmlPropTypeUtil.key, import_editor_props3.htmlV3PropTypeUtil.key, import_editor_props3.stringPropTypeUtil.key]);
|
|
3535
3685
|
var isCoreTextPropTypeKey = (key) => {
|
|
3536
3686
|
return TEXT_PROP_TYPE_KEYS.has(key);
|
|
3537
3687
|
};
|
|
@@ -3551,7 +3701,7 @@ var isInlineEditingAllowed = ({ rawValue, propTypeFromSchema }) => {
|
|
|
3551
3701
|
if (rawValue === null || rawValue === void 0) {
|
|
3552
3702
|
return isAllowedBySchema(propTypeFromSchema);
|
|
3553
3703
|
}
|
|
3554
|
-
return import_editor_props3.htmlV3PropTypeUtil.isValid(rawValue) || import_editor_props3.stringPropTypeUtil.isValid(rawValue);
|
|
3704
|
+
return import_editor_props3.escapedHtmlPropTypeUtil.isValid(rawValue) || import_editor_props3.htmlV3PropTypeUtil.isValid(rawValue) || import_editor_props3.stringPropTypeUtil.isValid(rawValue);
|
|
3555
3705
|
};
|
|
3556
3706
|
|
|
3557
3707
|
// src/legacy/replacements/inline-editing/inline-editing-elements.tsx
|
|
@@ -3636,17 +3786,26 @@ var InlineEditingReplacement = class extends ReplacementBase {
|
|
|
3636
3786
|
}
|
|
3637
3787
|
getExtractedContentValue() {
|
|
3638
3788
|
const propValue = this.getInlineEditablePropValue();
|
|
3789
|
+
if (import_editor_props4.escapedHtmlPropTypeUtil.isValid(propValue)) {
|
|
3790
|
+
return import_editor_props4.escapedHtmlPropTypeUtil.extract(propValue) ?? "";
|
|
3791
|
+
}
|
|
3639
3792
|
const extracted = import_editor_props4.htmlV3PropTypeUtil.extract(propValue);
|
|
3640
3793
|
return import_editor_props4.stringPropTypeUtil.extract(extracted?.content ?? null) ?? "";
|
|
3641
3794
|
}
|
|
3795
|
+
createContentPropValue(value) {
|
|
3796
|
+
const content = value || "";
|
|
3797
|
+
const propTypeKey = this.getInlineEditablePropTypeKey();
|
|
3798
|
+
if (propTypeKey === import_editor_props4.htmlV3PropTypeUtil.key) {
|
|
3799
|
+
return import_editor_props4.htmlV3PropTypeUtil.create({
|
|
3800
|
+
content: import_editor_props4.stringPropTypeUtil.create(content),
|
|
3801
|
+
children: []
|
|
3802
|
+
});
|
|
3803
|
+
}
|
|
3804
|
+
return import_editor_props4.escapedHtmlPropTypeUtil.create(content);
|
|
3805
|
+
}
|
|
3642
3806
|
setContentValue(value) {
|
|
3643
3807
|
const settingKey = this.getInlineEditablePropertyName();
|
|
3644
|
-
const
|
|
3645
|
-
const parsed = (0, import_editor_props4.parseHtmlChildren)(html);
|
|
3646
|
-
const valueToSave = import_editor_props4.htmlV3PropTypeUtil.create({
|
|
3647
|
-
content: parsed.content ? import_editor_props4.stringPropTypeUtil.create(parsed.content) : null,
|
|
3648
|
-
children: parsed.children
|
|
3649
|
-
});
|
|
3808
|
+
const valueToSave = this.createContentPropValue(value);
|
|
3650
3809
|
(0, import_editor_v1_adapters13.undoable)(
|
|
3651
3810
|
{
|
|
3652
3811
|
do: () => {
|
|
@@ -3675,7 +3834,7 @@ var InlineEditingReplacement = class extends ReplacementBase {
|
|
|
3675
3834
|
return null;
|
|
3676
3835
|
}
|
|
3677
3836
|
if (propType.kind === "union") {
|
|
3678
|
-
const textKeys = [import_editor_props4.htmlV3PropTypeUtil.key, import_editor_props4.stringPropTypeUtil.key];
|
|
3837
|
+
const textKeys = [import_editor_props4.escapedHtmlPropTypeUtil.key, import_editor_props4.htmlV3PropTypeUtil.key, import_editor_props4.stringPropTypeUtil.key];
|
|
3679
3838
|
for (const key of textKeys) {
|
|
3680
3839
|
if (propType.prop_types[key]) {
|
|
3681
3840
|
return key;
|
|
@@ -3930,6 +4089,52 @@ function createNestedTemplatedType(type, renderer, element) {
|
|
|
3930
4089
|
});
|
|
3931
4090
|
}
|
|
3932
4091
|
|
|
4092
|
+
// src/legacy/list-type.ts
|
|
4093
|
+
var LIST_TYPE = "e-list";
|
|
4094
|
+
function initListType() {
|
|
4095
|
+
registerElementType(
|
|
4096
|
+
LIST_TYPE,
|
|
4097
|
+
(options) => createListType(options)
|
|
4098
|
+
);
|
|
4099
|
+
}
|
|
4100
|
+
function createListType(options) {
|
|
4101
|
+
const BaseType = createNestedTemplatedElementType(options);
|
|
4102
|
+
let ListView = null;
|
|
4103
|
+
return class extends BaseType {
|
|
4104
|
+
getView() {
|
|
4105
|
+
if (!ListView) {
|
|
4106
|
+
ListView = createListView(options);
|
|
4107
|
+
}
|
|
4108
|
+
return ListView;
|
|
4109
|
+
}
|
|
4110
|
+
};
|
|
4111
|
+
}
|
|
4112
|
+
function createListView(options) {
|
|
4113
|
+
const BaseView = createNestedTemplatedElementView(options);
|
|
4114
|
+
return BaseView.extend({
|
|
4115
|
+
getRenderContext() {
|
|
4116
|
+
const parentContext = this._parent?.getRenderContext?.();
|
|
4117
|
+
const settings = this.model.get("settings");
|
|
4118
|
+
const showMarkersProp = settings?.get?.("show_markers");
|
|
4119
|
+
const showMarkers = showMarkersProp?.value ?? showMarkersProp ?? true;
|
|
4120
|
+
return {
|
|
4121
|
+
...parentContext,
|
|
4122
|
+
show_markers: showMarkers
|
|
4123
|
+
};
|
|
4124
|
+
},
|
|
4125
|
+
getResolverRenderContext() {
|
|
4126
|
+
const parentContext = this._parent?.getResolverRenderContext?.();
|
|
4127
|
+
const settings = this.model.get("settings");
|
|
4128
|
+
const showMarkersProp = settings?.get?.("show_markers");
|
|
4129
|
+
const showMarkers = showMarkersProp?.value ?? showMarkersProp ?? true;
|
|
4130
|
+
return {
|
|
4131
|
+
...parentContext,
|
|
4132
|
+
show_markers: showMarkers
|
|
4133
|
+
};
|
|
4134
|
+
}
|
|
4135
|
+
});
|
|
4136
|
+
}
|
|
4137
|
+
|
|
3933
4138
|
// src/legacy/tabs-model-extensions.ts
|
|
3934
4139
|
var import_editor_props5 = require("@elementor/editor-props");
|
|
3935
4140
|
var tabModelExtensions = {
|
|
@@ -3947,10 +4152,7 @@ var tabModelExtensions = {
|
|
|
3947
4152
|
...paragraphElement,
|
|
3948
4153
|
settings: {
|
|
3949
4154
|
...paragraphElement.settings,
|
|
3950
|
-
paragraph: import_editor_props5.
|
|
3951
|
-
content: import_editor_props5.stringPropTypeUtil.create(`Tab ${position}`),
|
|
3952
|
-
children: []
|
|
3953
|
-
})
|
|
4155
|
+
paragraph: import_editor_props5.escapedHtmlPropTypeUtil.create(`Tab ${position}`)
|
|
3954
4156
|
}
|
|
3955
4157
|
};
|
|
3956
4158
|
return [updatedParagraph, ...elements.slice(1)];
|
|
@@ -3961,22 +4163,22 @@ function initTabsModelExtensions() {
|
|
|
3961
4163
|
}
|
|
3962
4164
|
|
|
3963
4165
|
// src/mcp/canvas-mcp.ts
|
|
3964
|
-
var
|
|
4166
|
+
var import_editor_props8 = require("@elementor/editor-props");
|
|
3965
4167
|
|
|
3966
4168
|
// src/mcp/resources/available-widgets-resource.ts
|
|
3967
4169
|
var import_http_client3 = require("@elementor/http-client");
|
|
3968
4170
|
var MCP_PROXY_URL2 = "elementor/v1/mcp-proxy";
|
|
3969
4171
|
var AVAILABLE_WIDGETS_URI = "elementor://context/available-widgets";
|
|
3970
4172
|
var AVAILABLE_WIDGETS_URI_V4 = "elementor://context/available-widgets/v4";
|
|
3971
|
-
var fetchWidgets = async (
|
|
4173
|
+
var fetchWidgets = async () => {
|
|
3972
4174
|
const { data } = await (0, import_http_client3.httpService)().post(MCP_PROXY_URL2, {
|
|
3973
|
-
tool: "list-
|
|
3974
|
-
input:
|
|
4175
|
+
tool: "list-widget-schemas",
|
|
4176
|
+
input: { summary: true }
|
|
3975
4177
|
});
|
|
3976
|
-
return data.data ?? [];
|
|
4178
|
+
return data.data?.widgets ?? [];
|
|
3977
4179
|
};
|
|
3978
|
-
var buildContents = async (uri
|
|
3979
|
-
const widgets = await fetchWidgets(
|
|
4180
|
+
var buildContents = async (uri) => {
|
|
4181
|
+
const widgets = await fetchWidgets();
|
|
3980
4182
|
return {
|
|
3981
4183
|
contents: [
|
|
3982
4184
|
{
|
|
@@ -3995,13 +4197,13 @@ var initAvailableWidgetsResource = (reg) => {
|
|
|
3995
4197
|
{
|
|
3996
4198
|
description: "All registered v4 version widgets"
|
|
3997
4199
|
},
|
|
3998
|
-
async () => buildContents(AVAILABLE_WIDGETS_URI_V4
|
|
4200
|
+
async () => buildContents(AVAILABLE_WIDGETS_URI_V4)
|
|
3999
4201
|
);
|
|
4000
4202
|
resource(
|
|
4001
4203
|
"available-widgets",
|
|
4002
4204
|
AVAILABLE_WIDGETS_URI,
|
|
4003
4205
|
{
|
|
4004
|
-
description: "All registered widget types with
|
|
4206
|
+
description: "All registered v4 widget types with description."
|
|
4005
4207
|
},
|
|
4006
4208
|
async () => buildContents(AVAILABLE_WIDGETS_URI)
|
|
4007
4209
|
);
|
|
@@ -4134,11 +4336,10 @@ var import_http_client5 = require("@elementor/http-client");
|
|
|
4134
4336
|
var DYNAMIC_TAGS_URI = "elementor://dynamic-tags";
|
|
4135
4337
|
var MCP_PROXY_URL4 = "elementor/v1/mcp-proxy";
|
|
4136
4338
|
var fetchDynamicTags = async () => {
|
|
4137
|
-
const { data } = await (0, import_http_client5.httpService)().
|
|
4138
|
-
|
|
4139
|
-
input: {}
|
|
4339
|
+
const { data } = await (0, import_http_client5.httpService)().get(MCP_PROXY_URL4, {
|
|
4340
|
+
params: { uri: DYNAMIC_TAGS_URI }
|
|
4140
4341
|
});
|
|
4141
|
-
return data.data ?? [];
|
|
4342
|
+
return data.data ?? "[]";
|
|
4142
4343
|
};
|
|
4143
4344
|
var initDynamicTagsResource = (reg) => {
|
|
4144
4345
|
const { resource } = reg;
|
|
@@ -4150,13 +4351,12 @@ var initDynamicTagsResource = (reg) => {
|
|
|
4150
4351
|
mimeType: "application/json"
|
|
4151
4352
|
},
|
|
4152
4353
|
async (uri) => {
|
|
4153
|
-
const tags = await fetchDynamicTags();
|
|
4154
4354
|
return {
|
|
4155
4355
|
contents: [
|
|
4156
4356
|
{
|
|
4157
4357
|
uri: uri.href,
|
|
4158
4358
|
mimeType: "application/json",
|
|
4159
|
-
text:
|
|
4359
|
+
text: await fetchDynamicTags()
|
|
4160
4360
|
}
|
|
4161
4361
|
]
|
|
4162
4362
|
};
|
|
@@ -4479,104 +4679,13 @@ function getElementDisplayName(container) {
|
|
|
4479
4679
|
}
|
|
4480
4680
|
}
|
|
4481
4681
|
|
|
4482
|
-
// src/mcp/tools/build-composition/tool.ts
|
|
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
|
-
}
|
|
4572
|
-
|
|
4573
4682
|
// src/mcp/tools/configure-element/tool.ts
|
|
4574
|
-
var
|
|
4683
|
+
var import_editor_elements13 = require("@elementor/editor-elements");
|
|
4575
4684
|
var import_editor_mcp3 = require("@elementor/editor-mcp");
|
|
4576
4685
|
var import_editor_props7 = require("@elementor/editor-props");
|
|
4577
4686
|
|
|
4578
4687
|
// src/mcp/utils/do-update-element-property.ts
|
|
4579
|
-
var
|
|
4688
|
+
var import_editor_elements12 = require("@elementor/editor-elements");
|
|
4580
4689
|
var import_editor_props6 = require("@elementor/editor-props");
|
|
4581
4690
|
var import_editor_styles4 = require("@elementor/editor-styles");
|
|
4582
4691
|
var import_editor_v1_adapters20 = require("@elementor/editor-v1-adapters");
|
|
@@ -4596,10 +4705,10 @@ var readStoredCustomCssText = (raw) => {
|
|
|
4596
4705
|
};
|
|
4597
4706
|
|
|
4598
4707
|
// src/mcp/utils/resolve-canonical-prop-name.ts
|
|
4599
|
-
var
|
|
4600
|
-
function buildAliasToCanonicalMap(
|
|
4708
|
+
var import_editor_elements11 = require("@elementor/editor-elements");
|
|
4709
|
+
function buildAliasToCanonicalMap(schema) {
|
|
4601
4710
|
const aliasToCanonical = {};
|
|
4602
|
-
for (const [canonical, propType] of Object.entries(
|
|
4711
|
+
for (const [canonical, propType] of Object.entries(schema)) {
|
|
4603
4712
|
const aliases = propType.meta?.aliases;
|
|
4604
4713
|
if (!Array.isArray(aliases)) {
|
|
4605
4714
|
continue;
|
|
@@ -4613,26 +4722,26 @@ function buildAliasToCanonicalMap(schema2) {
|
|
|
4613
4722
|
return aliasToCanonical;
|
|
4614
4723
|
}
|
|
4615
4724
|
function resolveCanonicalPropName(elementType, propertyName) {
|
|
4616
|
-
const
|
|
4617
|
-
if (!
|
|
4725
|
+
const schema = (0, import_editor_elements11.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
|
|
4726
|
+
if (!schema || schema[propertyName]) {
|
|
4618
4727
|
return propertyName;
|
|
4619
4728
|
}
|
|
4620
|
-
return buildAliasToCanonicalMap(
|
|
4729
|
+
return buildAliasToCanonicalMap(schema)[propertyName] ?? propertyName;
|
|
4621
4730
|
}
|
|
4622
4731
|
function resolveCanonicalPropKeys(elementType, props) {
|
|
4623
|
-
const
|
|
4624
|
-
if (!
|
|
4732
|
+
const schema = (0, import_editor_elements11.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
|
|
4733
|
+
if (!schema) {
|
|
4625
4734
|
return { ...props };
|
|
4626
4735
|
}
|
|
4627
|
-
const aliasToCanonical = buildAliasToCanonicalMap(
|
|
4736
|
+
const aliasToCanonical = buildAliasToCanonicalMap(schema);
|
|
4628
4737
|
const resolved = {};
|
|
4629
4738
|
for (const [key, value] of Object.entries(props)) {
|
|
4630
|
-
if (
|
|
4739
|
+
if (schema[key]) {
|
|
4631
4740
|
resolved[key] = value;
|
|
4632
4741
|
}
|
|
4633
4742
|
}
|
|
4634
4743
|
for (const [key, value] of Object.entries(props)) {
|
|
4635
|
-
if (
|
|
4744
|
+
if (schema[key]) {
|
|
4636
4745
|
continue;
|
|
4637
4746
|
}
|
|
4638
4747
|
const canonical = aliasToCanonical[key];
|
|
@@ -4680,9 +4789,9 @@ var dynamicTagLLMResolver = (value) => {
|
|
|
4680
4789
|
}
|
|
4681
4790
|
};
|
|
4682
4791
|
};
|
|
4683
|
-
var buildStrictSettings = (
|
|
4792
|
+
var buildStrictSettings = (schema, provided) => {
|
|
4684
4793
|
const settings = {};
|
|
4685
|
-
for (const [key, propType] of Object.entries(
|
|
4794
|
+
for (const [key, propType] of Object.entries(schema)) {
|
|
4686
4795
|
if (OMITTED_DYNAMIC_SETTING_KEYS.includes(key)) {
|
|
4687
4796
|
continue;
|
|
4688
4797
|
}
|
|
@@ -4714,6 +4823,20 @@ var LOCAL_STYLE_META = {
|
|
|
4714
4823
|
breakpoint: "desktop",
|
|
4715
4824
|
state: null
|
|
4716
4825
|
};
|
|
4826
|
+
var UnsupportedPropertyError = class extends Error {
|
|
4827
|
+
elementType;
|
|
4828
|
+
propertyName;
|
|
4829
|
+
constructor(elementType, propertyName, availableProperties) {
|
|
4830
|
+
super(
|
|
4831
|
+
`Property "${propertyName}" does not exist on element type "${elementType}". Available properties are: ${availableProperties.join(
|
|
4832
|
+
", "
|
|
4833
|
+
)}`
|
|
4834
|
+
);
|
|
4835
|
+
this.name = "UnsupportedPropertyError";
|
|
4836
|
+
this.elementType = elementType;
|
|
4837
|
+
this.propertyName = propertyName;
|
|
4838
|
+
}
|
|
4839
|
+
};
|
|
4717
4840
|
function resolvePropValue(value, forceKey) {
|
|
4718
4841
|
const Utils = window.elementorV2.editorVariables.Utils;
|
|
4719
4842
|
return import_editor_props6.Schema.adjustLlmPropValueSchema(value, {
|
|
@@ -4728,7 +4851,7 @@ var doUpdateElementProperty = (params) => {
|
|
|
4728
4851
|
const { elementId, propertyValue, elementType, customCssWriteMode = "replace" } = params;
|
|
4729
4852
|
const propertyName = params.propertyName === "_styles" ? params.propertyName : resolveCanonicalPropName(elementType, params.propertyName);
|
|
4730
4853
|
if (propertyName === "_styles") {
|
|
4731
|
-
const elementStyles = (0,
|
|
4854
|
+
const elementStyles = (0, import_editor_elements12.getElementStyles)(elementId) || {};
|
|
4732
4855
|
const propertyMapValue = propertyValue;
|
|
4733
4856
|
const styleSchema = (0, import_editor_styles4.getStylesSchema)();
|
|
4734
4857
|
const transformedStyleValues = Object.fromEntries(
|
|
@@ -4785,7 +4908,7 @@ var doUpdateElementProperty = (params) => {
|
|
|
4785
4908
|
});
|
|
4786
4909
|
delete transformedStyleValues.custom_css;
|
|
4787
4910
|
if (!localStyle) {
|
|
4788
|
-
(0,
|
|
4911
|
+
(0, import_editor_elements12.createElementStyle)({
|
|
4789
4912
|
elementId,
|
|
4790
4913
|
...typeof customCss !== "undefined" ? { custom_css: customCss } : {},
|
|
4791
4914
|
classesProp: "classes",
|
|
@@ -4799,7 +4922,7 @@ var doUpdateElementProperty = (params) => {
|
|
|
4799
4922
|
}
|
|
4800
4923
|
});
|
|
4801
4924
|
} else {
|
|
4802
|
-
(0,
|
|
4925
|
+
(0, import_editor_elements12.updateElementStyle)({
|
|
4803
4926
|
elementId,
|
|
4804
4927
|
styleId: localStyle.id,
|
|
4805
4928
|
meta: {
|
|
@@ -4814,17 +4937,12 @@ var doUpdateElementProperty = (params) => {
|
|
|
4814
4937
|
}
|
|
4815
4938
|
return;
|
|
4816
4939
|
}
|
|
4817
|
-
const elementPropSchema = (0,
|
|
4940
|
+
const elementPropSchema = (0, import_editor_elements12.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
|
|
4818
4941
|
if (!elementPropSchema) {
|
|
4819
4942
|
throw new Error(`No prop schema found for element type: ${elementType}`);
|
|
4820
4943
|
}
|
|
4821
4944
|
if (!elementPropSchema[propertyName]) {
|
|
4822
|
-
|
|
4823
|
-
throw new Error(
|
|
4824
|
-
`Property "${propertyName}" does not exist on element type "${elementType}". Available properties are: ${propertyNames.join(
|
|
4825
|
-
", "
|
|
4826
|
-
)}`
|
|
4827
|
-
);
|
|
4945
|
+
throw new UnsupportedPropertyError(elementType, propertyName, Object.keys(elementPropSchema));
|
|
4828
4946
|
}
|
|
4829
4947
|
const propKey = elementPropSchema[propertyName].key;
|
|
4830
4948
|
const value = resolvePropValue(propertyValue, propKey);
|
|
@@ -4837,7 +4955,7 @@ var doUpdateElementProperty = (params) => {
|
|
|
4837
4955
|
Expected Schema: ${jsonSchema}`
|
|
4838
4956
|
);
|
|
4839
4957
|
}
|
|
4840
|
-
(0,
|
|
4958
|
+
(0, import_editor_elements12.updateElementSettings)({
|
|
4841
4959
|
id: elementId,
|
|
4842
4960
|
props: {
|
|
4843
4961
|
[propertyName]: value
|
|
@@ -4894,8 +5012,6 @@ For all non-primitive entries in \`propertiesToChange\`, provide the schema \`ke
|
|
|
4894
5012
|
|
|
4895
5013
|
Use the EXACT PropType schema given, and ALWAYS include the \`key\` from the schema for every property you are changing in \`propertiesToChange\`.
|
|
4896
5014
|
|
|
4897
|
-
Check \`llm_guidance.default_settings\` in the widget schema \u2014 include a key in \`propertiesToChange\` only when the user explicitly asks to change it.
|
|
4898
|
-
|
|
4899
5015
|
# Dynamic tags
|
|
4900
5016
|
A value can be made dynamic wherever its schema exposes a variant with "$$type": "dynamic". This may be the property root OR a NESTED field: for example an image is made dynamic on its "src" (the root stays "image"), NOT on the whole "image" value.
|
|
4901
5017
|
Put the dynamic object EXACTLY at the node whose schema offers the "dynamic" variant, in place of the static variant. The variant's "name" enumerates the tags allowed at that node.
|
|
@@ -4922,7 +5038,7 @@ Do NOT send "group" (it is resolved automatically). Use { "settings": {} } only
|
|
|
4922
5038
|
);
|
|
4923
5039
|
configureElementToolPrompt.parameter(
|
|
4924
5040
|
"style",
|
|
4925
|
-
'A flat map of raw CSS declarations (property \u2192 value), e.g. { "line-height": "1.25rem", "color": "var(--primary-text, #000)" }. Set a value to null to reset that property to its default. OPTIONAL.'
|
|
5041
|
+
'A flat map of raw CSS declarations (property \u2192 value), e.g. { "line-height": "1.25rem", "color": "var(--primary-text, #000)" }. font-family must be a single Google Font name or a var(--label) \u2014 no fallback stacks. Set a value to null to reset that property to its default. OPTIONAL.'
|
|
4926
5042
|
);
|
|
4927
5043
|
configureElementToolPrompt.example(`
|
|
4928
5044
|
\`\`\`json
|
|
@@ -4954,36 +5070,39 @@ Do NOT send "group" (it is resolved automatically). Use { "settings": {} } only
|
|
|
4954
5070
|
V4 only: If MCP fails, give manual steps using V4 UI.
|
|
4955
5071
|
|
|
4956
5072
|
V4 Editor structure:
|
|
4957
|
-
Panel tabs: General (\u2192 Settings section: ID, Tag, Link), Style, Interactions.
|
|
5073
|
+
Panel tabs: General (\u2192 Settings section: ID, Tag, and Link where the widget supports it), Style, Interactions.
|
|
4958
5074
|
NO Advanced tab. Never mention Advanced tab.
|
|
5075
|
+
Note: \`link\` is valid only when the element's PropType schema (which you must already have) includes a \`link\` property. Sending \`link\` to a widget whose schema lacks it is skipped and reported in the response \`warnings\` (other changes still apply) and the link is lost.
|
|
4959
5076
|
`);
|
|
4960
5077
|
return configureElementToolPrompt.prompt();
|
|
4961
5078
|
};
|
|
4962
|
-
var CONFIGURE_ELEMENT_GUIDE_TEXT = generatePrompt();
|
|
4963
5079
|
|
|
4964
5080
|
// src/mcp/tools/configure-element/schema.ts
|
|
4965
|
-
var
|
|
5081
|
+
var import_schema = require("@elementor/schema");
|
|
4966
5082
|
var inputSchema = {
|
|
4967
|
-
propertiesToChange:
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
5083
|
+
propertiesToChange: import_schema.z.record(
|
|
5084
|
+
import_schema.z.string().describe("The property name."),
|
|
5085
|
+
import_schema.z.any().describe(`PropValue, refer to [${WIDGET_SCHEMA_URI}] by correct type, as appears in elementType`),
|
|
5086
|
+
import_schema.z.any()
|
|
4971
5087
|
).describe("An object record containing property names and their new values to be set on the element"),
|
|
4972
|
-
style:
|
|
4973
|
-
|
|
4974
|
-
|
|
5088
|
+
style: import_schema.z.record(
|
|
5089
|
+
import_schema.z.string().describe('A CSS property name, e.g. "color", "margin-top".'),
|
|
5090
|
+
import_schema.z.string().nullable().describe(
|
|
4975
5091
|
'A CSS value, e.g. "red", "10px", "1px solid #000". Use null to reset the property to its default.'
|
|
4976
5092
|
)
|
|
4977
5093
|
).describe(
|
|
4978
5094
|
"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."
|
|
4979
5095
|
).default({}),
|
|
4980
|
-
elementType:
|
|
4981
|
-
elementId:
|
|
5096
|
+
elementType: import_schema.z.string().describe("The type of the element to retrieve the schema"),
|
|
5097
|
+
elementId: import_schema.z.string().describe("The unique id of the element to configure")
|
|
4982
5098
|
};
|
|
4983
5099
|
var outputSchema = {
|
|
4984
|
-
success:
|
|
5100
|
+
success: import_schema.z.boolean().describe(
|
|
4985
5101
|
"Whether the configuration change was successful, only if propertyName and propertyValue are provided"
|
|
4986
|
-
)
|
|
5102
|
+
),
|
|
5103
|
+
warnings: import_schema.z.string().describe(
|
|
5104
|
+
'Non-fatal notices. Present when some props were skipped because they are not in the element schema (e.g. a "link" on a widget with no link prop). Other changes were still applied.'
|
|
5105
|
+
).optional()
|
|
4987
5106
|
};
|
|
4988
5107
|
|
|
4989
5108
|
// src/mcp/tools/configure-element/tool.ts
|
|
@@ -5012,13 +5131,13 @@ var initConfigureElementTool = (reg) => {
|
|
|
5012
5131
|
{ description: "Dynamic tags catalog", uri: DYNAMIC_TAGS_URI }
|
|
5013
5132
|
],
|
|
5014
5133
|
handler: async ({ elementId, propertiesToChange, elementType, style }) => {
|
|
5015
|
-
const widgetData = (0,
|
|
5134
|
+
const widgetData = (0, import_editor_elements13.getWidgetsCache)()?.[elementType];
|
|
5016
5135
|
if (!widgetData) {
|
|
5017
5136
|
throw new Error(
|
|
5018
5137
|
`Unknown element type: ${elementType}. Check the available-widgets resource for valid types.`
|
|
5019
5138
|
);
|
|
5020
5139
|
}
|
|
5021
|
-
const container = (0,
|
|
5140
|
+
const container = (0, import_editor_elements13.getContainer)(elementId);
|
|
5022
5141
|
if (!container) {
|
|
5023
5142
|
throw new Error(`Element with id ${elementId} not found`);
|
|
5024
5143
|
}
|
|
@@ -5033,6 +5152,7 @@ var initConfigureElementTool = (reg) => {
|
|
|
5033
5152
|
}
|
|
5034
5153
|
const propertiesToUpdate = resolveCanonicalPropKeys(elementType, propertiesToChange);
|
|
5035
5154
|
const toUpdate = Object.entries(propertiesToUpdate);
|
|
5155
|
+
const skippedProps = [];
|
|
5036
5156
|
for (const [propertyName, propertyValue] of toUpdate) {
|
|
5037
5157
|
if (!import_editor_props7.Schema.isPropKeyConfigurable(propertyName)) {
|
|
5038
5158
|
throw new Error(`Not allowed to update ${propertyName}`);
|
|
@@ -5045,6 +5165,10 @@ var initConfigureElementTool = (reg) => {
|
|
|
5045
5165
|
propertyValue
|
|
5046
5166
|
});
|
|
5047
5167
|
} catch (error) {
|
|
5168
|
+
if (error instanceof UnsupportedPropertyError) {
|
|
5169
|
+
skippedProps.push(error.propertyName);
|
|
5170
|
+
continue;
|
|
5171
|
+
}
|
|
5048
5172
|
const errorMessage = createUpdateErrorMessage({
|
|
5049
5173
|
propertyName,
|
|
5050
5174
|
elementId,
|
|
@@ -5057,7 +5181,10 @@ var initConfigureElementTool = (reg) => {
|
|
|
5057
5181
|
}
|
|
5058
5182
|
await applyStyleFromCss({ elementId, elementType, style });
|
|
5059
5183
|
return {
|
|
5060
|
-
success: true
|
|
5184
|
+
success: true,
|
|
5185
|
+
warnings: skippedProps.length ? `Skipped unsupported props (not in the "${elementType}" schema; other changes were applied): ${skippedProps.join(
|
|
5186
|
+
", "
|
|
5187
|
+
)}.` : void 0
|
|
5061
5188
|
};
|
|
5062
5189
|
}
|
|
5063
5190
|
});
|
|
@@ -5109,143 +5236,74 @@ Provide styling as raw CSS via the "style" parameter (a flat map of CSS property
|
|
|
5109
5236
|
}`;
|
|
5110
5237
|
}
|
|
5111
5238
|
|
|
5112
|
-
// src/mcp/tools/
|
|
5113
|
-
var
|
|
5239
|
+
// src/mcp/tools/get-page-structure/tool.ts
|
|
5240
|
+
var import_editor_documents2 = require("@elementor/editor-documents");
|
|
5114
5241
|
var import_http_client7 = require("@elementor/http-client");
|
|
5115
|
-
var
|
|
5116
|
-
|
|
5117
|
-
|
|
5242
|
+
var import_schema3 = require("@elementor/schema");
|
|
5243
|
+
|
|
5244
|
+
// src/mcp/utils/get-mcp-error-message.ts
|
|
5245
|
+
var import_http_client6 = require("@elementor/http-client");
|
|
5246
|
+
function getMcpErrorMessage(error, toolName) {
|
|
5247
|
+
if (error instanceof import_http_client6.AxiosError) {
|
|
5248
|
+
const data = error.response?.data;
|
|
5249
|
+
if (data?.message) {
|
|
5250
|
+
return data.code ? `${data.code}: ${data.message}` : data.message;
|
|
5251
|
+
}
|
|
5252
|
+
}
|
|
5253
|
+
if (error instanceof Error) {
|
|
5254
|
+
return error.message;
|
|
5255
|
+
}
|
|
5256
|
+
return `${toolName} failed with an unknown error.`;
|
|
5257
|
+
}
|
|
5258
|
+
|
|
5259
|
+
// src/mcp/tools/get-page-structure/tool.ts
|
|
5260
|
+
var MCP_PROXY_URL5 = "elementor/v1/mcp-proxy";
|
|
5261
|
+
var initGetPageStructureTool = (reg) => {
|
|
5118
5262
|
const { addTool } = reg;
|
|
5119
5263
|
addTool({
|
|
5120
|
-
name: "
|
|
5121
|
-
description: "
|
|
5264
|
+
name: "get-page-structure",
|
|
5265
|
+
description: "Returns a lean Elementor element tree skeleton (id, elType, widgetType, title, nested elements) for a post or page. If no postId is provided, uses the currently open document. Optionally scope to a subtree with elementId. Set includeContent=true (requires elementId) to also return each node's settings and styles.",
|
|
5122
5266
|
schema: {
|
|
5123
|
-
|
|
5124
|
-
|
|
5267
|
+
postId: import_schema3.z.number().optional().describe(
|
|
5268
|
+
"WordPress post ID of the Elementor document. If omitted, uses the currently open document."
|
|
5269
|
+
),
|
|
5270
|
+
elementId: import_schema3.z.string().optional().describe("If provided, returns only the subtree rooted at that element id."),
|
|
5271
|
+
includeContent: import_schema3.z.boolean().optional().describe(
|
|
5272
|
+
"If true, includes each node's settings and styles (same shape build-composition accepts as input). Requires elementId."
|
|
5273
|
+
)
|
|
5125
5274
|
},
|
|
5126
5275
|
outputSchema: {
|
|
5127
|
-
|
|
5128
|
-
|
|
5129
|
-
|
|
5276
|
+
elements: import_schema3.z.array(import_schema3.z.any()).describe(
|
|
5277
|
+
"Skeleton of Elementor elements (id, elType, widgetType, title, nested elements). When includeContent is true, each node also includes settings and styles."
|
|
5278
|
+
)
|
|
5130
5279
|
},
|
|
5131
|
-
handler: async ({
|
|
5132
|
-
const
|
|
5133
|
-
if (!
|
|
5134
|
-
throw new Error("No active document found.");
|
|
5135
|
-
}
|
|
5136
|
-
const { data } = await (0, import_http_client7.httpService)().post(MCP_PROXY_URL6, {
|
|
5137
|
-
tool: "create-element",
|
|
5138
|
-
input: {
|
|
5139
|
-
parent_id: parentId ?? "document",
|
|
5140
|
-
element: { type: elementType },
|
|
5141
|
-
post_id: document2.id
|
|
5142
|
-
}
|
|
5143
|
-
});
|
|
5144
|
-
return {
|
|
5145
|
-
elementId: data.data.element_id,
|
|
5146
|
-
previewUrl: data.data.preview_url,
|
|
5147
|
-
version: data.data.version
|
|
5148
|
-
};
|
|
5149
|
-
}
|
|
5150
|
-
});
|
|
5151
|
-
};
|
|
5152
|
-
|
|
5153
|
-
// src/mcp/tools/get-element-config/tool.ts
|
|
5154
|
-
var import_editor_elements15 = require("@elementor/editor-elements");
|
|
5155
|
-
var import_editor_props8 = require("@elementor/editor-props");
|
|
5156
|
-
var import_schema5 = require("@elementor/schema");
|
|
5157
|
-
var schema = {
|
|
5158
|
-
elementId: import_schema5.z.string()
|
|
5159
|
-
};
|
|
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")
|
|
5168
|
-
})
|
|
5169
|
-
).describe("An array of child element IDs, when applicable, with recursive structure")
|
|
5170
|
-
};
|
|
5171
|
-
var structuredElements = (element) => {
|
|
5172
|
-
const children = element.children || [];
|
|
5173
|
-
return children.map((child) => {
|
|
5174
|
-
return {
|
|
5175
|
-
id: child.id,
|
|
5176
|
-
elementType: child.model.get("elType") || child.model.get("widgetType") || "unknown",
|
|
5177
|
-
childElements: structuredElements(child)
|
|
5178
|
-
};
|
|
5179
|
-
});
|
|
5180
|
-
};
|
|
5181
|
-
var initGetElementConfigTool = (reg) => {
|
|
5182
|
-
const { addTool } = reg;
|
|
5183
|
-
addTool({
|
|
5184
|
-
name: "get-element-configuration-values",
|
|
5185
|
-
description: "Retrieve the element's configuration PropValues for a specific element by unique ID.",
|
|
5186
|
-
schema,
|
|
5187
|
-
outputSchema: outputSchema2,
|
|
5188
|
-
handler: async ({ elementId }) => {
|
|
5189
|
-
const element = (0, import_editor_elements15.getContainer)(elementId);
|
|
5190
|
-
if (!element) {
|
|
5191
|
-
throw new Error(`Element with ID ${elementId} not found.`);
|
|
5192
|
-
}
|
|
5193
|
-
const elementType = element.model.get("widgetType") || element.model.get("elType") || "";
|
|
5194
|
-
const widgetData = (0, import_editor_elements15.getWidgetsCache)()?.[elementType];
|
|
5195
|
-
if (!widgetData) {
|
|
5196
|
-
throw new Error(
|
|
5197
|
-
`Unknown element type: ${elementType}. Check the available-widgets resource for valid types.`
|
|
5198
|
-
);
|
|
5199
|
-
}
|
|
5200
|
-
if (!widgetData.atomic_props_schema) {
|
|
5201
|
-
throw new Error(
|
|
5202
|
-
`This tool does not support V3 elements. Please use the elementor-v3-mcp tools instead for element type: ${elementType}`
|
|
5203
|
-
);
|
|
5204
|
-
}
|
|
5205
|
-
const elementRawSettings = element.settings;
|
|
5206
|
-
const propSchema = (0, import_editor_elements15.getWidgetsCache)()?.[elementType]?.atomic_props_schema;
|
|
5207
|
-
if (!elementRawSettings || !propSchema) {
|
|
5208
|
-
throw new Error(`No settings or prop schema found for element ID: ${elementId}`);
|
|
5280
|
+
handler: async ({ postId, elementId, includeContent }) => {
|
|
5281
|
+
const resolvedPostId = postId ?? (0, import_editor_documents2.getCurrentDocument)()?.id;
|
|
5282
|
+
if (!resolvedPostId) {
|
|
5283
|
+
throw new Error("No post ID provided and no active document found.");
|
|
5209
5284
|
}
|
|
5210
|
-
|
|
5211
|
-
|
|
5212
|
-
|
|
5213
|
-
|
|
5214
|
-
|
|
5215
|
-
|
|
5216
|
-
|
|
5217
|
-
if (localStyle) {
|
|
5218
|
-
const defaultVariant = localStyle.variants.find(
|
|
5219
|
-
(variant) => variant.meta.breakpoint === "desktop" && !variant.meta.state
|
|
5220
|
-
);
|
|
5221
|
-
if (defaultVariant) {
|
|
5222
|
-
const styleProps = defaultVariant.props || {};
|
|
5223
|
-
Object.keys(styleProps).forEach((stylePropName) => {
|
|
5224
|
-
if (typeof styleProps[stylePropName] !== "undefined") {
|
|
5225
|
-
stylePropValues[stylePropName] = structuredClone(styleProps[stylePropName]);
|
|
5226
|
-
}
|
|
5227
|
-
});
|
|
5228
|
-
if (defaultVariant.custom_css) {
|
|
5229
|
-
stylePropValues.custom_css = atob(defaultVariant.custom_css.raw);
|
|
5285
|
+
try {
|
|
5286
|
+
const { data } = await (0, import_http_client7.httpService)().post(MCP_PROXY_URL5, {
|
|
5287
|
+
tool: "get-page-structure",
|
|
5288
|
+
input: {
|
|
5289
|
+
post_id: resolvedPostId,
|
|
5290
|
+
...elementId ? { element_id: elementId } : {},
|
|
5291
|
+
...includeContent ? { include_content: true } : {}
|
|
5230
5292
|
}
|
|
5231
|
-
}
|
|
5293
|
+
});
|
|
5294
|
+
return {
|
|
5295
|
+
elements: data.data.elements
|
|
5296
|
+
};
|
|
5297
|
+
} catch (error) {
|
|
5298
|
+
throw new Error(getMcpErrorMessage(error, "get-page-structure"));
|
|
5232
5299
|
}
|
|
5233
|
-
return {
|
|
5234
|
-
properties: {
|
|
5235
|
-
...propValues
|
|
5236
|
-
},
|
|
5237
|
-
style: {
|
|
5238
|
-
...stylePropValues
|
|
5239
|
-
},
|
|
5240
|
-
childElements: structuredElements(element)
|
|
5241
|
-
};
|
|
5242
5300
|
}
|
|
5243
5301
|
});
|
|
5244
5302
|
};
|
|
5245
5303
|
|
|
5246
5304
|
// src/mcp/canvas-mcp.ts
|
|
5247
5305
|
var initCanvasMcp = (reg) => {
|
|
5248
|
-
|
|
5306
|
+
import_editor_props8.Schema.setDynamicTagNamesResolver(getDynamicTagNamesByCategories);
|
|
5249
5307
|
initWidgetsSchemaResource(reg);
|
|
5250
5308
|
initAvailableWidgetsResource(reg);
|
|
5251
5309
|
initDocumentStructureResource(reg);
|
|
@@ -5254,17 +5312,15 @@ var initCanvasMcp = (reg) => {
|
|
|
5254
5312
|
initEditorStateResource(reg);
|
|
5255
5313
|
initGeneralContextResource(reg);
|
|
5256
5314
|
initBestPracticesResource(reg);
|
|
5257
|
-
initGetElementConfigTool(reg);
|
|
5258
5315
|
initConfigureElementTool(reg);
|
|
5259
|
-
|
|
5260
|
-
initBuildCompositionTool(reg);
|
|
5316
|
+
initGetPageStructureTool(reg);
|
|
5261
5317
|
initBreakpointsResource(reg);
|
|
5262
5318
|
};
|
|
5263
5319
|
|
|
5264
5320
|
// src/mcp/mcp-description.ts
|
|
5265
5321
|
var ELEMENT_SCHEMA_URI = WIDGET_SCHEMA_URI.replace("{widgetType}", "element-schema");
|
|
5266
5322
|
var mcpDescription = `Elementor Canvas MCP
|
|
5267
|
-
This MCP enables
|
|
5323
|
+
This MCP enables configuration and styling of existing V4 elements on the Elementor canvas using the configure-element tool.
|
|
5268
5324
|
|
|
5269
5325
|
# Core Concepts
|
|
5270
5326
|
|
|
@@ -5283,66 +5339,54 @@ The \`$$type\` defines how Elementor interprets the value. Providing the correct
|
|
|
5283
5339
|
- **Global Classes**: Reusable style sets that can be applied to elements (\`elementor://global-classes\`)
|
|
5284
5340
|
- **Widget Schemas**: Configuration options for each widget type (\`${WIDGET_SCHEMA_URI}\`)
|
|
5285
5341
|
|
|
5286
|
-
#
|
|
5342
|
+
# Configuring Elements with configure-element
|
|
5287
5343
|
|
|
5288
|
-
The \`
|
|
5344
|
+
The \`configure-element\` tool updates settings and styles on existing V4 elements. Read the configure-element guide resource before use.
|
|
5289
5345
|
|
|
5290
5346
|
## Complete Workflow
|
|
5291
5347
|
|
|
5292
5348
|
### 1. Parse User Requirements
|
|
5293
|
-
Understand what needs to
|
|
5349
|
+
Understand what needs to change: content, settings, or styling on existing elements.
|
|
5294
5350
|
|
|
5295
5351
|
### 2. Check Global Resources FIRST
|
|
5296
|
-
Always check existing resources before
|
|
5352
|
+
Always check existing resources before styling:
|
|
5297
5353
|
- List \`elementor://global-variables\` for available variables (colors, sizes, fonts)
|
|
5298
5354
|
- List \`elementor://global-classes\` for available style sets
|
|
5299
5355
|
- **Always prefer using existing global resources over creating inline styles**
|
|
5300
5356
|
|
|
5301
5357
|
### 3. Retrieve Widget Schemas
|
|
5302
|
-
For each
|
|
5358
|
+
For each element you will configure:
|
|
5303
5359
|
- List \`${WIDGET_SCHEMA_URI}\` to see available widgets
|
|
5304
5360
|
- Retrieve configuration schema from \`${ELEMENT_SCHEMA_URI}\` for each widget
|
|
5305
|
-
- Check the \`llm_guidance\` property for container nesting, \`default_styles\`, and \`default_settings\`
|
|
5361
|
+
- Check the \`llm_guidance\` property for container nesting, \`default_styles\`, and \`default_settings\`
|
|
5306
5362
|
|
|
5307
|
-
### 4.
|
|
5308
|
-
|
|
5309
|
-
- Each element must have a unique \`configuration-id\` attribute
|
|
5310
|
-
- No text nodes, classes, or IDs in XML - structure only
|
|
5311
|
-
- Example:
|
|
5312
|
-
\`\`\`xml
|
|
5313
|
-
<e-container configuration-id="container-1">
|
|
5314
|
-
<e-heading configuration-id="heading-1" />
|
|
5315
|
-
<e-text configuration-id="text-1" />
|
|
5316
|
-
</e-container>
|
|
5317
|
-
\`\`\`
|
|
5363
|
+
### 4. Get Current Element State
|
|
5364
|
+
Use page structure and element configuration resources to find element IDs and current values.
|
|
5318
5365
|
|
|
5319
|
-
### 5. Create
|
|
5320
|
-
Map
|
|
5366
|
+
### 5. Create propertiesToChange
|
|
5367
|
+
Map property names to PropValues using the widget schema:
|
|
5321
5368
|
- Use correct \`$$type\` matching the widget's schema
|
|
5322
5369
|
- Use global variables in PropValues where applicable
|
|
5323
5370
|
- Example:
|
|
5324
5371
|
\`\`\`json
|
|
5325
5372
|
{
|
|
5326
|
-
"
|
|
5327
|
-
|
|
5328
|
-
"tag": { "$$type": "string", "value": "h1" }
|
|
5329
|
-
}
|
|
5373
|
+
"text": { "$$type": "string", "value": "Welcome" },
|
|
5374
|
+
"tag": { "$$type": "string", "value": "h1" }
|
|
5330
5375
|
}
|
|
5331
5376
|
\`\`\`
|
|
5332
5377
|
|
|
5333
5378
|
### 6. Create style
|
|
5334
|
-
|
|
5379
|
+
Provide raw CSS declarations (property \u2192 value strings). The server converts them to native styles and stores any unconvertible declarations as the element custom CSS.
|
|
5335
5380
|
- Example:
|
|
5336
5381
|
\`\`\`json
|
|
5337
5382
|
{
|
|
5338
|
-
"
|
|
5339
|
-
|
|
5383
|
+
"color": "#1a1a1a",
|
|
5384
|
+
"font-size": "2rem"
|
|
5340
5385
|
}
|
|
5341
5386
|
\`\`\`
|
|
5342
5387
|
|
|
5343
|
-
### 7. Execute
|
|
5344
|
-
Call the tool with
|
|
5345
|
-
At the response you will also find llm_instructions for you to do afterwards, read and follow them!
|
|
5388
|
+
### 7. Execute configure-element
|
|
5389
|
+
Call the tool with elementId, elementType, propertiesToChange, and style as needed.
|
|
5346
5390
|
|
|
5347
5391
|
## Key Points
|
|
5348
5392
|
|
|
@@ -5370,7 +5414,7 @@ Note: The "size" property controls image resolution/loading, not visual size. Se
|
|
|
5370
5414
|
`;
|
|
5371
5415
|
|
|
5372
5416
|
// src/prevent-link-in-link-commands.ts
|
|
5373
|
-
var
|
|
5417
|
+
var import_editor_elements14 = require("@elementor/editor-elements");
|
|
5374
5418
|
var import_editor_notifications3 = require("@elementor/editor-notifications");
|
|
5375
5419
|
var import_editor_v1_adapters21 = require("@elementor/editor-v1-adapters");
|
|
5376
5420
|
var import_i18n4 = require("@wordpress/i18n");
|
|
@@ -5441,25 +5485,25 @@ function shouldBlock(sourceElements, targetElements) {
|
|
|
5441
5485
|
return false;
|
|
5442
5486
|
}
|
|
5443
5487
|
const isSourceContainsAnAnchor = sourceElements.some((src) => {
|
|
5444
|
-
return src?.id ? (0,
|
|
5488
|
+
return src?.id ? (0, import_editor_elements14.isElementAnchored)(src.id) || !!(0, import_editor_elements14.getAnchoredDescendantId)(src.id) : false;
|
|
5445
5489
|
});
|
|
5446
5490
|
if (!isSourceContainsAnAnchor) {
|
|
5447
5491
|
return false;
|
|
5448
5492
|
}
|
|
5449
5493
|
const isTargetContainsAnAnchor = targetElements.some((target) => {
|
|
5450
|
-
return target?.id ? (0,
|
|
5494
|
+
return target?.id ? (0, import_editor_elements14.isElementAnchored)(target.id) || !!(0, import_editor_elements14.getAnchoredAncestorId)(target.id) : false;
|
|
5451
5495
|
});
|
|
5452
5496
|
return isTargetContainsAnAnchor;
|
|
5453
5497
|
}
|
|
5454
5498
|
|
|
5455
5499
|
// src/style-commands/paste-style.ts
|
|
5456
|
-
var
|
|
5457
|
-
var
|
|
5500
|
+
var import_editor_elements17 = require("@elementor/editor-elements");
|
|
5501
|
+
var import_editor_props10 = require("@elementor/editor-props");
|
|
5458
5502
|
var import_editor_v1_adapters23 = require("@elementor/editor-v1-adapters");
|
|
5459
5503
|
|
|
5460
5504
|
// src/utils/command-utils.ts
|
|
5461
|
-
var
|
|
5462
|
-
var
|
|
5505
|
+
var import_editor_elements15 = require("@elementor/editor-elements");
|
|
5506
|
+
var import_editor_props9 = require("@elementor/editor-props");
|
|
5463
5507
|
var import_i18n5 = require("@wordpress/i18n");
|
|
5464
5508
|
function hasAtomicWidgets(args) {
|
|
5465
5509
|
const { containers = [args.container] } = args;
|
|
@@ -5477,13 +5521,13 @@ function getClassesProp(container) {
|
|
|
5477
5521
|
return null;
|
|
5478
5522
|
}
|
|
5479
5523
|
const [propKey] = Object.entries(propsSchema).find(
|
|
5480
|
-
([, propType]) => propType.kind === "plain" && propType.key ===
|
|
5524
|
+
([, propType]) => propType.kind === "plain" && propType.key === import_editor_props9.CLASSES_PROP_KEY
|
|
5481
5525
|
) ?? [];
|
|
5482
5526
|
return propKey ?? null;
|
|
5483
5527
|
}
|
|
5484
5528
|
function getContainerSchema(container) {
|
|
5485
5529
|
const type = container?.model.get("widgetType") || container?.model.get("elType");
|
|
5486
|
-
const widgetsCache = (0,
|
|
5530
|
+
const widgetsCache = (0, import_editor_elements15.getWidgetsCache)();
|
|
5487
5531
|
const elementType = widgetsCache?.[type];
|
|
5488
5532
|
return elementType?.atomic_props_schema ?? null;
|
|
5489
5533
|
}
|
|
@@ -5496,11 +5540,11 @@ function getClipboardElements(storageKey = "clipboard") {
|
|
|
5496
5540
|
}
|
|
5497
5541
|
}
|
|
5498
5542
|
function getTitleForContainers(containers) {
|
|
5499
|
-
return containers.length > 1 ? (0, import_i18n5.__)("Elements", "elementor") : (0,
|
|
5543
|
+
return containers.length > 1 ? (0, import_i18n5.__)("Elements", "elementor") : (0, import_editor_elements15.getElementLabel)(containers[0].id);
|
|
5500
5544
|
}
|
|
5501
5545
|
|
|
5502
5546
|
// src/style-commands/undoable-actions/paste-element-style.ts
|
|
5503
|
-
var
|
|
5547
|
+
var import_editor_elements16 = require("@elementor/editor-elements");
|
|
5504
5548
|
var import_editor_styles_repository4 = require("@elementor/editor-styles-repository");
|
|
5505
5549
|
var import_editor_v1_adapters22 = require("@elementor/editor-v1-adapters");
|
|
5506
5550
|
var import_i18n6 = require("@wordpress/i18n");
|
|
@@ -5513,7 +5557,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
|
|
|
5513
5557
|
if (!classesProp) {
|
|
5514
5558
|
return null;
|
|
5515
5559
|
}
|
|
5516
|
-
const originalStyles = (0,
|
|
5560
|
+
const originalStyles = (0, import_editor_elements16.getElementStyles)(container.id);
|
|
5517
5561
|
const [styleId, styleDef] = Object.entries(originalStyles ?? {})[0] ?? [];
|
|
5518
5562
|
const originalStyle = Object.keys(styleDef ?? {}).length ? styleDef : null;
|
|
5519
5563
|
const revertData = {
|
|
@@ -5522,7 +5566,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
|
|
|
5522
5566
|
};
|
|
5523
5567
|
if (styleId) {
|
|
5524
5568
|
newStyle.variants.forEach(({ meta, props, custom_css: customCss }) => {
|
|
5525
|
-
(0,
|
|
5569
|
+
(0, import_editor_elements16.updateElementStyle)({
|
|
5526
5570
|
elementId,
|
|
5527
5571
|
styleId,
|
|
5528
5572
|
meta,
|
|
@@ -5533,7 +5577,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
|
|
|
5533
5577
|
} else {
|
|
5534
5578
|
const [firstVariant] = newStyle.variants;
|
|
5535
5579
|
const additionalVariants = newStyle.variants.slice(1);
|
|
5536
|
-
revertData.styleId = (0,
|
|
5580
|
+
revertData.styleId = (0, import_editor_elements16.createElementStyle)({
|
|
5537
5581
|
elementId,
|
|
5538
5582
|
classesProp,
|
|
5539
5583
|
label: import_editor_styles_repository4.ELEMENTS_STYLES_RESERVED_LABEL,
|
|
@@ -5551,7 +5595,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
|
|
|
5551
5595
|
return;
|
|
5552
5596
|
}
|
|
5553
5597
|
if (!revertData.originalStyle) {
|
|
5554
|
-
(0,
|
|
5598
|
+
(0, import_editor_elements16.deleteElementStyle)(container.id, revertData.styleId);
|
|
5555
5599
|
return;
|
|
5556
5600
|
}
|
|
5557
5601
|
const classesProp = getClassesProp(container);
|
|
@@ -5560,7 +5604,7 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters22.undoable)(
|
|
|
5560
5604
|
}
|
|
5561
5605
|
const [firstVariant] = revertData.originalStyle.variants;
|
|
5562
5606
|
const additionalVariants = revertData.originalStyle.variants.slice(1);
|
|
5563
|
-
(0,
|
|
5607
|
+
(0, import_editor_elements16.createElementStyle)({
|
|
5564
5608
|
elementId: container.id,
|
|
5565
5609
|
classesProp,
|
|
5566
5610
|
label: import_editor_styles_repository4.ELEMENTS_STYLES_RESERVED_LABEL,
|
|
@@ -5597,7 +5641,7 @@ function pasteStyles(args, pasteLocalStyle) {
|
|
|
5597
5641
|
}
|
|
5598
5642
|
const clipboardElements = getClipboardElements(storageKey);
|
|
5599
5643
|
const [clipboardElement] = clipboardElements ?? [];
|
|
5600
|
-
const clipboardContainer = (0,
|
|
5644
|
+
const clipboardContainer = (0, import_editor_elements17.getContainer)(clipboardElement.id);
|
|
5601
5645
|
if (!clipboardElement || !clipboardContainer || !isAtomicWidget(clipboardContainer)) {
|
|
5602
5646
|
return;
|
|
5603
5647
|
}
|
|
@@ -5616,7 +5660,7 @@ function getClassesWithoutLocalStyle(clipboardContainer, style) {
|
|
|
5616
5660
|
if (!classesProp) {
|
|
5617
5661
|
return [];
|
|
5618
5662
|
}
|
|
5619
|
-
const classesSetting = (0,
|
|
5663
|
+
const classesSetting = (0, import_editor_elements17.getElementSetting)(clipboardContainer.id, classesProp);
|
|
5620
5664
|
return classesSetting?.value.filter((styleId) => styleId !== style?.id) ?? [];
|
|
5621
5665
|
}
|
|
5622
5666
|
function pasteClasses(containers, classes) {
|
|
@@ -5625,10 +5669,10 @@ function pasteClasses(containers, classes) {
|
|
|
5625
5669
|
if (!classesProp) {
|
|
5626
5670
|
return;
|
|
5627
5671
|
}
|
|
5628
|
-
const classesSetting = (0,
|
|
5629
|
-
const currentClasses =
|
|
5630
|
-
const newClasses =
|
|
5631
|
-
(0,
|
|
5672
|
+
const classesSetting = (0, import_editor_elements17.getElementSetting)(container.id, classesProp);
|
|
5673
|
+
const currentClasses = import_editor_props10.classesPropTypeUtil.extract(classesSetting) ?? [];
|
|
5674
|
+
const newClasses = import_editor_props10.classesPropTypeUtil.create(Array.from(/* @__PURE__ */ new Set([...classes, ...currentClasses])));
|
|
5675
|
+
(0, import_editor_elements17.updateElementSettings)({
|
|
5632
5676
|
id: container.id,
|
|
5633
5677
|
props: { [classesProp]: newClasses }
|
|
5634
5678
|
});
|
|
@@ -5639,7 +5683,7 @@ function pasteClasses(containers, classes) {
|
|
|
5639
5683
|
var import_editor_v1_adapters25 = require("@elementor/editor-v1-adapters");
|
|
5640
5684
|
|
|
5641
5685
|
// src/style-commands/undoable-actions/reset-element-style.ts
|
|
5642
|
-
var
|
|
5686
|
+
var import_editor_elements18 = require("@elementor/editor-elements");
|
|
5643
5687
|
var import_editor_styles_repository5 = require("@elementor/editor-styles-repository");
|
|
5644
5688
|
var import_editor_v1_adapters24 = require("@elementor/editor-v1-adapters");
|
|
5645
5689
|
var import_i18n7 = require("@wordpress/i18n");
|
|
@@ -5648,9 +5692,9 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters24.undoable)(
|
|
|
5648
5692
|
do: ({ containers }) => {
|
|
5649
5693
|
return containers.map((container) => {
|
|
5650
5694
|
const elementId = container.model.get("id");
|
|
5651
|
-
const containerStyles = (0,
|
|
5695
|
+
const containerStyles = (0, import_editor_elements18.getElementStyles)(elementId);
|
|
5652
5696
|
Object.keys(containerStyles ?? {}).forEach(
|
|
5653
|
-
(styleId) => (0,
|
|
5697
|
+
(styleId) => (0, import_editor_elements18.deleteElementStyle)(elementId, styleId)
|
|
5654
5698
|
);
|
|
5655
5699
|
return containerStyles;
|
|
5656
5700
|
});
|
|
@@ -5666,7 +5710,7 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters24.undoable)(
|
|
|
5666
5710
|
Object.entries(containerStyles ?? {}).forEach(([styleId, style]) => {
|
|
5667
5711
|
const [firstVariant] = style.variants;
|
|
5668
5712
|
const additionalVariants = style.variants.slice(1);
|
|
5669
|
-
(0,
|
|
5713
|
+
(0, import_editor_elements18.createElementStyle)({
|
|
5670
5714
|
elementId,
|
|
5671
5715
|
classesProp,
|
|
5672
5716
|
styleId,
|
|
@@ -5740,15 +5784,15 @@ function init() {
|
|
|
5740
5784
|
initCanvasMcp(
|
|
5741
5785
|
(0, import_editor_mcp4.getMCPByDomain)("canvas", {
|
|
5742
5786
|
instructions: `Everything related to V4 ( Atomic ) canvas.
|
|
5743
|
-
# Canvas workflow
|
|
5744
|
-
- Configure
|
|
5745
|
-
-
|
|
5746
|
-
- Get and retrieve element configuration values
|
|
5787
|
+
# Canvas workflow
|
|
5788
|
+
- Configure element settings and styles with configure-element
|
|
5789
|
+
- Get page structure and element configuration values
|
|
5747
5790
|
`,
|
|
5748
5791
|
docs: mcpDescription
|
|
5749
5792
|
})
|
|
5750
5793
|
);
|
|
5751
5794
|
initTabsModelExtensions();
|
|
5795
|
+
initListType();
|
|
5752
5796
|
}
|
|
5753
5797
|
|
|
5754
5798
|
// src/sync/drag-element-from-panel.ts
|
|
@@ -5866,10 +5910,10 @@ function useEscapeOnCanvas(canvasDocument, onEscape) {
|
|
|
5866
5910
|
}
|
|
5867
5911
|
|
|
5868
5912
|
// src/utils/after-render.ts
|
|
5869
|
-
var
|
|
5913
|
+
var import_editor_elements19 = require("@elementor/editor-elements");
|
|
5870
5914
|
function doAfterRender(elementIds, callback) {
|
|
5871
5915
|
const pending = elementIds.map((elementId) => {
|
|
5872
|
-
const view = (0,
|
|
5916
|
+
const view = (0, import_editor_elements19.getContainer)(elementId)?.view;
|
|
5873
5917
|
if (!view || !hasDoAfterRender(view)) {
|
|
5874
5918
|
return void 0;
|
|
5875
5919
|
}
|