@elementor/editor-canvas 4.4.0-1145 → 4.4.0-1147
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +47 -58
- package/dist/index.mjs +4 -15
- package/package.json +20 -20
- package/src/mcp/__tests__/canvas-mcp.test.ts +33 -0
- package/src/mcp/canvas-mcp.ts +1 -4
- package/src/mcp/tools/configure-element/__tests__/prompt.test.ts +34 -0
- package/src/mcp/tools/configure-element/prompt.ts +2 -6
- package/src/transformers/shared/__tests__/icon-transformer.test.ts +66 -4
- package/src/transformers/shared/icon-transformer.ts +1 -2
- package/src/mcp/icon-library-experiment.ts +0 -5
package/dist/index.js
CHANGED
|
@@ -2330,7 +2330,6 @@ var svgSrcTransformer = createTransformer(async (value, { signal }) => {
|
|
|
2330
2330
|
var EMPTY_ICON_RESULT = { html: null, url: null };
|
|
2331
2331
|
var ICON_SVG_SIZE = "100%";
|
|
2332
2332
|
var ICON_SVG_OVERFLOW = "visible";
|
|
2333
|
-
var FONT_AWESOME_LIBRARY_PREFIX = "fa-";
|
|
2334
2333
|
var EICONS_LIBRARY = "eicons";
|
|
2335
2334
|
var DEFAULT_SVG_RELATIVE_PATH = "images/default-svg.svg";
|
|
2336
2335
|
var iconTransformer = createTransformer(async (value, { signal }) => {
|
|
@@ -2343,7 +2342,7 @@ var iconTransformer = createTransformer(async (value, { signal }) => {
|
|
|
2343
2342
|
if (fontAwesomeHtml) {
|
|
2344
2343
|
return { html: fontAwesomeHtml, url: null };
|
|
2345
2344
|
}
|
|
2346
|
-
if (
|
|
2345
|
+
if (EICONS_LIBRARY === library) {
|
|
2347
2346
|
return EMPTY_ICON_RESULT;
|
|
2348
2347
|
}
|
|
2349
2348
|
const providerHtml = await resolveProviderSvg(library, iconValue, signal);
|
|
@@ -4345,11 +4344,6 @@ function initTabsModelExtensions() {
|
|
|
4345
4344
|
// src/mcp/canvas-mcp.ts
|
|
4346
4345
|
var import_editor_props8 = require("@elementor/editor-props");
|
|
4347
4346
|
|
|
4348
|
-
// src/mcp/icon-library-experiment.ts
|
|
4349
|
-
var import_editor_v1_adapters18 = require("@elementor/editor-v1-adapters");
|
|
4350
|
-
var ICON_LIBRARY_EXPERIMENT = "e_svg_library";
|
|
4351
|
-
var isIconLibraryActive = () => (0, import_editor_v1_adapters18.isExperimentActive)(ICON_LIBRARY_EXPERIMENT);
|
|
4352
|
-
|
|
4353
4347
|
// src/mcp/resources/available-widgets-resource.ts
|
|
4354
4348
|
var import_http_client3 = require("@elementor/http-client");
|
|
4355
4349
|
var MCP_PROXY_URL2 = "elementor/v1/mcp-proxy";
|
|
@@ -4426,7 +4420,7 @@ var initBestPracticesResource = (reg) => {
|
|
|
4426
4420
|
|
|
4427
4421
|
// src/mcp/resources/document-structure-resource.ts
|
|
4428
4422
|
var import_editor_elements10 = require("@elementor/editor-elements");
|
|
4429
|
-
var
|
|
4423
|
+
var import_editor_v1_adapters18 = require("@elementor/editor-v1-adapters");
|
|
4430
4424
|
var DOCUMENT_STRUCTURE_URI = "elementor://document/structure";
|
|
4431
4425
|
var initDocumentStructureResource = (reg) => {
|
|
4432
4426
|
const { resource, sendResourceUpdated } = reg;
|
|
@@ -4439,15 +4433,15 @@ var initDocumentStructureResource = (reg) => {
|
|
|
4439
4433
|
sendResourceUpdated({ uri: DOCUMENT_STRUCTURE_URI });
|
|
4440
4434
|
}
|
|
4441
4435
|
};
|
|
4442
|
-
(0,
|
|
4436
|
+
(0, import_editor_v1_adapters18.__privateListenTo)(
|
|
4443
4437
|
[
|
|
4444
|
-
(0,
|
|
4445
|
-
(0,
|
|
4446
|
-
(0,
|
|
4447
|
-
(0,
|
|
4448
|
-
(0,
|
|
4449
|
-
(0,
|
|
4450
|
-
(0,
|
|
4438
|
+
(0, import_editor_v1_adapters18.commandEndEvent)("document/elements/create"),
|
|
4439
|
+
(0, import_editor_v1_adapters18.commandEndEvent)("document/elements/delete"),
|
|
4440
|
+
(0, import_editor_v1_adapters18.commandEndEvent)("document/elements/move"),
|
|
4441
|
+
(0, import_editor_v1_adapters18.commandEndEvent)("document/elements/copy"),
|
|
4442
|
+
(0, import_editor_v1_adapters18.commandEndEvent)("document/elements/paste"),
|
|
4443
|
+
(0, import_editor_v1_adapters18.commandEndEvent)("editor/documents/attach-preview"),
|
|
4444
|
+
(0, import_editor_v1_adapters18.commandEndEvent)("editor/documents/switch")
|
|
4451
4445
|
],
|
|
4452
4446
|
updateDocumentStructure
|
|
4453
4447
|
);
|
|
@@ -4550,7 +4544,7 @@ var initDynamicTagsResource = (reg) => {
|
|
|
4550
4544
|
};
|
|
4551
4545
|
|
|
4552
4546
|
// src/mcp/resources/editor-state-resource.ts
|
|
4553
|
-
var
|
|
4547
|
+
var import_editor_v1_adapters19 = require("@elementor/editor-v1-adapters");
|
|
4554
4548
|
var CURRENTLY_VIEWED_SCREEN = "The user is currently viewing the Elementor editor";
|
|
4555
4549
|
var PAGE_CONTENT_CHARACTER_LIMIT = 500;
|
|
4556
4550
|
var PREVIEW_TEXT_NODE_MIN_LENGTH = 2;
|
|
@@ -4571,8 +4565,8 @@ var initEditorStateResource = (reg) => {
|
|
|
4571
4565
|
lastSerializedState = serialized;
|
|
4572
4566
|
sendResourceUpdated({ uri: EDITOR_STATE_URI });
|
|
4573
4567
|
};
|
|
4574
|
-
(0,
|
|
4575
|
-
[(0,
|
|
4568
|
+
(0, import_editor_v1_adapters19.__privateListenTo)(
|
|
4569
|
+
[(0, import_editor_v1_adapters19.commandEndEvent)("editor/documents/switch"), (0, import_editor_v1_adapters19.commandEndEvent)("editor/documents/attach-preview")],
|
|
4576
4570
|
notifyIfChanged
|
|
4577
4571
|
);
|
|
4578
4572
|
lastSerializedState = JSON.stringify(buildState());
|
|
@@ -4646,7 +4640,7 @@ function getPageTitle() {
|
|
|
4646
4640
|
}
|
|
4647
4641
|
|
|
4648
4642
|
// src/mcp/resources/general-context-resource.ts
|
|
4649
|
-
var
|
|
4643
|
+
var import_editor_v1_adapters20 = require("@elementor/editor-v1-adapters");
|
|
4650
4644
|
var GENERAL_CONTEXT_URI = "elementor://context/general";
|
|
4651
4645
|
var initGeneralContextResource = (reg) => {
|
|
4652
4646
|
const { resource, sendResourceUpdated } = reg;
|
|
@@ -4707,11 +4701,11 @@ var initGeneralContextResource = (reg) => {
|
|
|
4707
4701
|
};
|
|
4708
4702
|
}
|
|
4709
4703
|
);
|
|
4710
|
-
(0,
|
|
4704
|
+
(0, import_editor_v1_adapters20.__privateListenTo)(
|
|
4711
4705
|
[
|
|
4712
|
-
(0,
|
|
4713
|
-
(0,
|
|
4714
|
-
(0,
|
|
4706
|
+
(0, import_editor_v1_adapters20.commandEndEvent)("editor/documents/switch"),
|
|
4707
|
+
(0, import_editor_v1_adapters20.commandEndEvent)("editor/documents/attach-preview"),
|
|
4708
|
+
(0, import_editor_v1_adapters20.commandEndEvent)("document/elements/settings")
|
|
4715
4709
|
],
|
|
4716
4710
|
pushUpdateIfChanged
|
|
4717
4711
|
);
|
|
@@ -4720,7 +4714,7 @@ var initGeneralContextResource = (reg) => {
|
|
|
4720
4714
|
|
|
4721
4715
|
// src/mcp/resources/selected-element-resource.ts
|
|
4722
4716
|
var import_editor_elements11 = require("@elementor/editor-elements");
|
|
4723
|
-
var
|
|
4717
|
+
var import_editor_v1_adapters21 = require("@elementor/editor-v1-adapters");
|
|
4724
4718
|
var SELECTED_ELEMENT_URI = "elementor://context/selected-element";
|
|
4725
4719
|
var initSelectedElementResource = (reg) => {
|
|
4726
4720
|
const { resource, sendResourceUpdated } = reg;
|
|
@@ -4751,11 +4745,11 @@ var initSelectedElementResource = (reg) => {
|
|
|
4751
4745
|
}
|
|
4752
4746
|
publishIfChanged(readSelectionFromEditor());
|
|
4753
4747
|
};
|
|
4754
|
-
(0,
|
|
4748
|
+
(0, import_editor_v1_adapters21.__privateListenTo)(
|
|
4755
4749
|
[
|
|
4756
|
-
(0,
|
|
4757
|
-
(0,
|
|
4758
|
-
(0,
|
|
4750
|
+
(0, import_editor_v1_adapters21.commandEndEvent)("document/elements/select"),
|
|
4751
|
+
(0, import_editor_v1_adapters21.commandEndEvent)("document/elements/deselect-all"),
|
|
4752
|
+
(0, import_editor_v1_adapters21.commandEndEvent)("document/elements/settings")
|
|
4759
4753
|
],
|
|
4760
4754
|
onCommand
|
|
4761
4755
|
);
|
|
@@ -4873,7 +4867,7 @@ var import_editor_props7 = require("@elementor/editor-props");
|
|
|
4873
4867
|
var import_editor_elements13 = require("@elementor/editor-elements");
|
|
4874
4868
|
var import_editor_props6 = require("@elementor/editor-props");
|
|
4875
4869
|
var import_editor_styles4 = require("@elementor/editor-styles");
|
|
4876
|
-
var
|
|
4870
|
+
var import_editor_v1_adapters23 = require("@elementor/editor-v1-adapters");
|
|
4877
4871
|
|
|
4878
4872
|
// src/mcp/utils/merge-custom-css.ts
|
|
4879
4873
|
var CUSTOM_CSS_SEPARATOR = "\n";
|
|
@@ -4942,11 +4936,11 @@ function resolveCanonicalPropKeys(elementType, props) {
|
|
|
4942
4936
|
}
|
|
4943
4937
|
|
|
4944
4938
|
// src/mcp/utils/resolve-dynamic-tag.ts
|
|
4945
|
-
var
|
|
4939
|
+
var import_editor_v1_adapters22 = require("@elementor/editor-v1-adapters");
|
|
4946
4940
|
var DYNAMIC_PROP_TYPE_KEY = "dynamic";
|
|
4947
4941
|
var OMITTED_DYNAMIC_SETTING_KEYS = ["fallback"];
|
|
4948
4942
|
var getAtomicDynamicTags = () => {
|
|
4949
|
-
const config = (0,
|
|
4943
|
+
const config = (0, import_editor_v1_adapters22.getElementorConfig)();
|
|
4950
4944
|
return config.atomicDynamicTags?.tags ?? {};
|
|
4951
4945
|
};
|
|
4952
4946
|
var getDynamicTagNamesByCategories = (categories) => {
|
|
@@ -5147,7 +5141,7 @@ Expected Schema: ${jsonSchema}`
|
|
|
5147
5141
|
},
|
|
5148
5142
|
withHistory: false
|
|
5149
5143
|
});
|
|
5150
|
-
(0,
|
|
5144
|
+
(0, import_editor_v1_adapters23.__privateRunCommandSync)("document/save/set-is-modified", { status: true }, { internal: true });
|
|
5151
5145
|
};
|
|
5152
5146
|
|
|
5153
5147
|
// src/mcp/tools/configure-element/prompt.ts
|
|
@@ -5191,7 +5185,6 @@ Setting a Font Awesome icon on an e-svg, after resolving it with \`find-icons\`:
|
|
|
5191
5185
|
`;
|
|
5192
5186
|
var CONFIGURE_ELEMENT_GUIDE_URI = "elementor://canvas/tools/configure-element-guide";
|
|
5193
5187
|
var generatePrompt = () => {
|
|
5194
|
-
const iconLibraryActive = isIconLibraryActive();
|
|
5195
5188
|
const configureElementToolPrompt = (0, import_editor_mcp2.toolPrompts)("configure-element");
|
|
5196
5189
|
configureElementToolPrompt.description(`
|
|
5197
5190
|
Configure an existing element on the page.
|
|
@@ -5250,7 +5243,7 @@ Put the dynamic object EXACTLY at the node whose schema offers the "dynamic" var
|
|
|
5250
5243
|
Image example: { "$$type": "image", "value": { "src": { "$$type": "dynamic", "value": { "name": "<image tag>", "settings": { ... } } } } }
|
|
5251
5244
|
Do NOT send "group" (it is resolved automatically). Use { "settings": {} } only when the tag has no settings.
|
|
5252
5245
|
|
|
5253
|
-
${
|
|
5246
|
+
${ICONS_SECTION}`);
|
|
5254
5247
|
configureElementToolPrompt.parameter("elementId", "The ID of the element to configure. MANDATORY.");
|
|
5255
5248
|
configureElementToolPrompt.parameter(
|
|
5256
5249
|
"elementType",
|
|
@@ -5287,9 +5280,7 @@ ${iconLibraryActive ? ICONS_SECTION : ""}`);
|
|
|
5287
5280
|
};
|
|
5288
5281
|
\`\`\`
|
|
5289
5282
|
`);
|
|
5290
|
-
|
|
5291
|
-
configureElementToolPrompt.example(ICON_EXAMPLE);
|
|
5292
|
-
}
|
|
5283
|
+
configureElementToolPrompt.example(ICON_EXAMPLE);
|
|
5293
5284
|
configureElementToolPrompt.instruction(
|
|
5294
5285
|
"The $$type property is MANDATORY for every value in propertiesToChange; it is not used in the style parameter (raw CSS only)."
|
|
5295
5286
|
);
|
|
@@ -5652,9 +5643,7 @@ var initCanvasMcp = (reg) => {
|
|
|
5652
5643
|
initGeneralContextResource(reg);
|
|
5653
5644
|
initBestPracticesResource(reg);
|
|
5654
5645
|
initConfigureElementTool(reg);
|
|
5655
|
-
|
|
5656
|
-
initFindIconsTool(reg);
|
|
5657
|
-
}
|
|
5646
|
+
initFindIconsTool(reg);
|
|
5658
5647
|
initGetPageStructureTool(reg);
|
|
5659
5648
|
initBreakpointsResource(reg);
|
|
5660
5649
|
};
|
|
@@ -5758,14 +5747,14 @@ Note: The "size" property controls image resolution/loading, not visual size. Se
|
|
|
5758
5747
|
// src/prevent-link-in-link-commands.ts
|
|
5759
5748
|
var import_editor_elements15 = require("@elementor/editor-elements");
|
|
5760
5749
|
var import_editor_notifications6 = require("@elementor/editor-notifications");
|
|
5761
|
-
var
|
|
5750
|
+
var import_editor_v1_adapters24 = require("@elementor/editor-v1-adapters");
|
|
5762
5751
|
var import_i18n7 = require("@wordpress/i18n");
|
|
5763
5752
|
function initLinkInLinkPrevention() {
|
|
5764
|
-
(0,
|
|
5753
|
+
(0, import_editor_v1_adapters24.blockCommand)({
|
|
5765
5754
|
command: "document/elements/paste",
|
|
5766
5755
|
condition: blockLinkInLinkPaste
|
|
5767
5756
|
});
|
|
5768
|
-
(0,
|
|
5757
|
+
(0, import_editor_v1_adapters24.blockCommand)({
|
|
5769
5758
|
command: "document/elements/move",
|
|
5770
5759
|
condition: blockLinkInLinkMove
|
|
5771
5760
|
});
|
|
@@ -5841,7 +5830,7 @@ function shouldBlock(sourceElements, targetElements) {
|
|
|
5841
5830
|
// src/style-commands/paste-style.ts
|
|
5842
5831
|
var import_editor_elements18 = require("@elementor/editor-elements");
|
|
5843
5832
|
var import_editor_props10 = require("@elementor/editor-props");
|
|
5844
|
-
var
|
|
5833
|
+
var import_editor_v1_adapters26 = require("@elementor/editor-v1-adapters");
|
|
5845
5834
|
|
|
5846
5835
|
// src/utils/command-utils.ts
|
|
5847
5836
|
var import_editor_elements16 = require("@elementor/editor-elements");
|
|
@@ -5888,9 +5877,9 @@ function getTitleForContainers(containers) {
|
|
|
5888
5877
|
// src/style-commands/undoable-actions/paste-element-style.ts
|
|
5889
5878
|
var import_editor_elements17 = require("@elementor/editor-elements");
|
|
5890
5879
|
var import_editor_styles_repository4 = require("@elementor/editor-styles-repository");
|
|
5891
|
-
var
|
|
5880
|
+
var import_editor_v1_adapters25 = require("@elementor/editor-v1-adapters");
|
|
5892
5881
|
var import_i18n9 = require("@wordpress/i18n");
|
|
5893
|
-
var undoablePasteElementStyle = () => (0,
|
|
5882
|
+
var undoablePasteElementStyle = () => (0, import_editor_v1_adapters25.undoable)(
|
|
5894
5883
|
{
|
|
5895
5884
|
do: ({ containers, newStyle }) => {
|
|
5896
5885
|
return containers.map((container) => {
|
|
@@ -5966,12 +5955,12 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters26.undoable)(
|
|
|
5966
5955
|
// src/style-commands/paste-style.ts
|
|
5967
5956
|
function initPasteStyleCommand() {
|
|
5968
5957
|
const pasteElementStyleCommand = undoablePasteElementStyle();
|
|
5969
|
-
(0,
|
|
5958
|
+
(0, import_editor_v1_adapters26.blockCommand)({
|
|
5970
5959
|
command: "document/elements/paste-style",
|
|
5971
5960
|
condition: hasAtomicWidgets
|
|
5972
5961
|
});
|
|
5973
|
-
(0,
|
|
5974
|
-
(0,
|
|
5962
|
+
(0, import_editor_v1_adapters26.__privateListenTo)(
|
|
5963
|
+
(0, import_editor_v1_adapters26.commandStartEvent)("document/elements/paste-style"),
|
|
5975
5964
|
(e) => pasteStyles(e.args, pasteElementStyleCommand)
|
|
5976
5965
|
);
|
|
5977
5966
|
}
|
|
@@ -6022,14 +6011,14 @@ function pasteClasses(containers, classes) {
|
|
|
6022
6011
|
}
|
|
6023
6012
|
|
|
6024
6013
|
// src/style-commands/reset-style.ts
|
|
6025
|
-
var
|
|
6014
|
+
var import_editor_v1_adapters28 = require("@elementor/editor-v1-adapters");
|
|
6026
6015
|
|
|
6027
6016
|
// src/style-commands/undoable-actions/reset-element-style.ts
|
|
6028
6017
|
var import_editor_elements19 = require("@elementor/editor-elements");
|
|
6029
6018
|
var import_editor_styles_repository5 = require("@elementor/editor-styles-repository");
|
|
6030
|
-
var
|
|
6019
|
+
var import_editor_v1_adapters27 = require("@elementor/editor-v1-adapters");
|
|
6031
6020
|
var import_i18n10 = require("@wordpress/i18n");
|
|
6032
|
-
var undoableResetElementStyle = () => (0,
|
|
6021
|
+
var undoableResetElementStyle = () => (0, import_editor_v1_adapters27.undoable)(
|
|
6033
6022
|
{
|
|
6034
6023
|
do: ({ containers }) => {
|
|
6035
6024
|
return containers.map((container) => {
|
|
@@ -6073,12 +6062,12 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters28.undoable)(
|
|
|
6073
6062
|
// src/style-commands/reset-style.ts
|
|
6074
6063
|
function initResetStyleCommand() {
|
|
6075
6064
|
const resetElementStyles = undoableResetElementStyle();
|
|
6076
|
-
(0,
|
|
6065
|
+
(0, import_editor_v1_adapters28.blockCommand)({
|
|
6077
6066
|
command: "document/elements/reset-style",
|
|
6078
6067
|
condition: hasAtomicWidgets
|
|
6079
6068
|
});
|
|
6080
|
-
(0,
|
|
6081
|
-
(0,
|
|
6069
|
+
(0, import_editor_v1_adapters28.__privateListenTo)(
|
|
6070
|
+
(0, import_editor_v1_adapters28.commandStartEvent)("document/elements/reset-style"),
|
|
6082
6071
|
(e) => resetStyles(e.args, resetElementStyles)
|
|
6083
6072
|
);
|
|
6084
6073
|
}
|
|
@@ -6230,9 +6219,9 @@ function getRectClipPath(rect, viewport) {
|
|
|
6230
6219
|
}
|
|
6231
6220
|
|
|
6232
6221
|
// src/hooks/use-canvas-document.ts
|
|
6233
|
-
var
|
|
6222
|
+
var import_editor_v1_adapters29 = require("@elementor/editor-v1-adapters");
|
|
6234
6223
|
function useCanvasDocument() {
|
|
6235
|
-
return (0,
|
|
6224
|
+
return (0, import_editor_v1_adapters29.__privateUseListenTo)((0, import_editor_v1_adapters29.commandEndEvent)("editor/documents/attach-preview"), () => (0, import_editor_v1_adapters29.getCanvasIframeDocument)());
|
|
6236
6225
|
}
|
|
6237
6226
|
|
|
6238
6227
|
// src/hooks/use-escape-on-canvas.ts
|
package/dist/index.mjs
CHANGED
|
@@ -2286,7 +2286,6 @@ var svgSrcTransformer = createTransformer(async (value, { signal }) => {
|
|
|
2286
2286
|
var EMPTY_ICON_RESULT = { html: null, url: null };
|
|
2287
2287
|
var ICON_SVG_SIZE = "100%";
|
|
2288
2288
|
var ICON_SVG_OVERFLOW = "visible";
|
|
2289
|
-
var FONT_AWESOME_LIBRARY_PREFIX = "fa-";
|
|
2290
2289
|
var EICONS_LIBRARY = "eicons";
|
|
2291
2290
|
var DEFAULT_SVG_RELATIVE_PATH = "images/default-svg.svg";
|
|
2292
2291
|
var iconTransformer = createTransformer(async (value, { signal }) => {
|
|
@@ -2299,7 +2298,7 @@ var iconTransformer = createTransformer(async (value, { signal }) => {
|
|
|
2299
2298
|
if (fontAwesomeHtml) {
|
|
2300
2299
|
return { html: fontAwesomeHtml, url: null };
|
|
2301
2300
|
}
|
|
2302
|
-
if (
|
|
2301
|
+
if (EICONS_LIBRARY === library) {
|
|
2303
2302
|
return EMPTY_ICON_RESULT;
|
|
2304
2303
|
}
|
|
2305
2304
|
const providerHtml = await resolveProviderSvg(library, iconValue, signal);
|
|
@@ -4315,11 +4314,6 @@ function initTabsModelExtensions() {
|
|
|
4315
4314
|
// src/mcp/canvas-mcp.ts
|
|
4316
4315
|
import { Schema as Schema3 } from "@elementor/editor-props";
|
|
4317
4316
|
|
|
4318
|
-
// src/mcp/icon-library-experiment.ts
|
|
4319
|
-
import { isExperimentActive } from "@elementor/editor-v1-adapters";
|
|
4320
|
-
var ICON_LIBRARY_EXPERIMENT = "e_svg_library";
|
|
4321
|
-
var isIconLibraryActive = () => isExperimentActive(ICON_LIBRARY_EXPERIMENT);
|
|
4322
|
-
|
|
4323
4317
|
// src/mcp/resources/available-widgets-resource.ts
|
|
4324
4318
|
import { httpService as httpService3 } from "@elementor/http-client";
|
|
4325
4319
|
var MCP_PROXY_URL2 = "elementor/v1/mcp-proxy";
|
|
@@ -5172,7 +5166,6 @@ Setting a Font Awesome icon on an e-svg, after resolving it with \`find-icons\`:
|
|
|
5172
5166
|
`;
|
|
5173
5167
|
var CONFIGURE_ELEMENT_GUIDE_URI = "elementor://canvas/tools/configure-element-guide";
|
|
5174
5168
|
var generatePrompt = () => {
|
|
5175
|
-
const iconLibraryActive = isIconLibraryActive();
|
|
5176
5169
|
const configureElementToolPrompt = toolPrompts("configure-element");
|
|
5177
5170
|
configureElementToolPrompt.description(`
|
|
5178
5171
|
Configure an existing element on the page.
|
|
@@ -5231,7 +5224,7 @@ Put the dynamic object EXACTLY at the node whose schema offers the "dynamic" var
|
|
|
5231
5224
|
Image example: { "$$type": "image", "value": { "src": { "$$type": "dynamic", "value": { "name": "<image tag>", "settings": { ... } } } } }
|
|
5232
5225
|
Do NOT send "group" (it is resolved automatically). Use { "settings": {} } only when the tag has no settings.
|
|
5233
5226
|
|
|
5234
|
-
${
|
|
5227
|
+
${ICONS_SECTION}`);
|
|
5235
5228
|
configureElementToolPrompt.parameter("elementId", "The ID of the element to configure. MANDATORY.");
|
|
5236
5229
|
configureElementToolPrompt.parameter(
|
|
5237
5230
|
"elementType",
|
|
@@ -5268,9 +5261,7 @@ ${iconLibraryActive ? ICONS_SECTION : ""}`);
|
|
|
5268
5261
|
};
|
|
5269
5262
|
\`\`\`
|
|
5270
5263
|
`);
|
|
5271
|
-
|
|
5272
|
-
configureElementToolPrompt.example(ICON_EXAMPLE);
|
|
5273
|
-
}
|
|
5264
|
+
configureElementToolPrompt.example(ICON_EXAMPLE);
|
|
5274
5265
|
configureElementToolPrompt.instruction(
|
|
5275
5266
|
"The $$type property is MANDATORY for every value in propertiesToChange; it is not used in the style parameter (raw CSS only)."
|
|
5276
5267
|
);
|
|
@@ -5633,9 +5624,7 @@ var initCanvasMcp = (reg) => {
|
|
|
5633
5624
|
initGeneralContextResource(reg);
|
|
5634
5625
|
initBestPracticesResource(reg);
|
|
5635
5626
|
initConfigureElementTool(reg);
|
|
5636
|
-
|
|
5637
|
-
initFindIconsTool(reg);
|
|
5638
|
-
}
|
|
5627
|
+
initFindIconsTool(reg);
|
|
5639
5628
|
initGetPageStructureTool(reg);
|
|
5640
5629
|
initBreakpointsResource(reg);
|
|
5641
5630
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-canvas",
|
|
3
3
|
"description": "Elementor Editor Canvas",
|
|
4
|
-
"version": "4.4.0-
|
|
4
|
+
"version": "4.4.0-1147",
|
|
5
5
|
"private": false,
|
|
6
6
|
"author": "Elementor Team",
|
|
7
7
|
"homepage": "https://elementor.com/",
|
|
@@ -37,26 +37,26 @@
|
|
|
37
37
|
"react-dom": "^18.3.1"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@elementor/editor": "4.4.0-
|
|
41
|
-
"@elementor/editor-controls": "4.4.0-
|
|
42
|
-
"@elementor/editor-documents": "4.4.0-
|
|
43
|
-
"@elementor/editor-elements": "4.4.0-
|
|
44
|
-
"@elementor/editor-interactions": "4.4.0-
|
|
45
|
-
"@elementor/editor-mcp": "4.4.0-
|
|
46
|
-
"@elementor/editor-notifications": "4.4.0-
|
|
47
|
-
"@elementor/editor-props": "4.4.0-
|
|
48
|
-
"@elementor/editor-responsive": "4.4.0-
|
|
49
|
-
"@elementor/editor-styles": "4.4.0-
|
|
50
|
-
"@elementor/editor-styles-repository": "4.4.0-
|
|
51
|
-
"@elementor/editor-ui": "4.4.0-
|
|
52
|
-
"@elementor/editor-v1-adapters": "4.4.0-
|
|
53
|
-
"@elementor/events": "4.4.0-
|
|
54
|
-
"@elementor/http-client": "4.4.0-
|
|
55
|
-
"@elementor/schema": "4.4.0-
|
|
56
|
-
"@elementor/twing": "4.4.0-
|
|
40
|
+
"@elementor/editor": "4.4.0-1147",
|
|
41
|
+
"@elementor/editor-controls": "4.4.0-1147",
|
|
42
|
+
"@elementor/editor-documents": "4.4.0-1147",
|
|
43
|
+
"@elementor/editor-elements": "4.4.0-1147",
|
|
44
|
+
"@elementor/editor-interactions": "4.4.0-1147",
|
|
45
|
+
"@elementor/editor-mcp": "4.4.0-1147",
|
|
46
|
+
"@elementor/editor-notifications": "4.4.0-1147",
|
|
47
|
+
"@elementor/editor-props": "4.4.0-1147",
|
|
48
|
+
"@elementor/editor-responsive": "4.4.0-1147",
|
|
49
|
+
"@elementor/editor-styles": "4.4.0-1147",
|
|
50
|
+
"@elementor/editor-styles-repository": "4.4.0-1147",
|
|
51
|
+
"@elementor/editor-ui": "4.4.0-1147",
|
|
52
|
+
"@elementor/editor-v1-adapters": "4.4.0-1147",
|
|
53
|
+
"@elementor/events": "4.4.0-1147",
|
|
54
|
+
"@elementor/http-client": "4.4.0-1147",
|
|
55
|
+
"@elementor/schema": "4.4.0-1147",
|
|
56
|
+
"@elementor/twing": "4.4.0-1147",
|
|
57
57
|
"@elementor/ui": "1.41.4",
|
|
58
|
-
"@elementor/utils": "4.4.0-
|
|
59
|
-
"@elementor/wp-media": "4.4.0-
|
|
58
|
+
"@elementor/utils": "4.4.0-1147",
|
|
59
|
+
"@elementor/wp-media": "4.4.0-1147",
|
|
60
60
|
"@floating-ui/react": "^0.27.5",
|
|
61
61
|
"@wordpress/i18n": "^5.13.0",
|
|
62
62
|
"dompurify": "^3.2.6"
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { initCanvasMcp } from '../canvas-mcp';
|
|
2
|
+
import { initFindIconsTool } from '../tools/find-icons/tool';
|
|
3
|
+
|
|
4
|
+
jest.mock( '@elementor/editor-props', () => ( {
|
|
5
|
+
Schema: { setDynamicTagNamesResolver: jest.fn() },
|
|
6
|
+
} ) );
|
|
7
|
+
|
|
8
|
+
jest.mock( '../resources/available-widgets-resource', () => ( { initAvailableWidgetsResource: jest.fn() } ) );
|
|
9
|
+
jest.mock( '../resources/best-practices-resource', () => ( { initBestPracticesResource: jest.fn() } ) );
|
|
10
|
+
jest.mock( '../resources/breakpoints-resource', () => ( { initBreakpointsResource: jest.fn() } ) );
|
|
11
|
+
jest.mock( '../resources/document-structure-resource', () => ( { initDocumentStructureResource: jest.fn() } ) );
|
|
12
|
+
jest.mock( '../resources/dynamic-tags-resource', () => ( { initDynamicTagsResource: jest.fn() } ) );
|
|
13
|
+
jest.mock( '../resources/editor-state-resource', () => ( { initEditorStateResource: jest.fn() } ) );
|
|
14
|
+
jest.mock( '../resources/general-context-resource', () => ( { initGeneralContextResource: jest.fn() } ) );
|
|
15
|
+
jest.mock( '../resources/selected-element-resource', () => ( { initSelectedElementResource: jest.fn() } ) );
|
|
16
|
+
jest.mock( '../resources/widgets-schema-resource', () => ( { initWidgetsSchemaResource: jest.fn() } ) );
|
|
17
|
+
jest.mock( '../tools/configure-element/tool', () => ( { initConfigureElementTool: jest.fn() } ) );
|
|
18
|
+
jest.mock( '../tools/find-icons/tool', () => ( { initFindIconsTool: jest.fn() } ) );
|
|
19
|
+
jest.mock( '../tools/get-page-structure/tool', () => ( { initGetPageStructureTool: jest.fn() } ) );
|
|
20
|
+
jest.mock( '../utils/resolve-dynamic-tag', () => ( { getDynamicTagNamesByCategories: jest.fn() } ) );
|
|
21
|
+
|
|
22
|
+
describe( 'initCanvasMcp', () => {
|
|
23
|
+
it( 'should always register the find-icons tool', () => {
|
|
24
|
+
// Arrange.
|
|
25
|
+
const reg = { addTool: jest.fn() } as never;
|
|
26
|
+
|
|
27
|
+
// Act.
|
|
28
|
+
initCanvasMcp( reg );
|
|
29
|
+
|
|
30
|
+
// Assert.
|
|
31
|
+
expect( initFindIconsTool ).toHaveBeenCalledWith( reg );
|
|
32
|
+
} );
|
|
33
|
+
} );
|
package/src/mcp/canvas-mcp.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { type MCPRegistryEntry } from '@elementor/editor-mcp';
|
|
2
2
|
import { Schema } from '@elementor/editor-props';
|
|
3
3
|
|
|
4
|
-
import { isIconLibraryActive } from './icon-library-experiment';
|
|
5
4
|
import { initAvailableWidgetsResource } from './resources/available-widgets-resource';
|
|
6
5
|
import { initBestPracticesResource } from './resources/best-practices-resource';
|
|
7
6
|
import { initBreakpointsResource } from './resources/breakpoints-resource';
|
|
@@ -30,9 +29,7 @@ export const initCanvasMcp = ( reg: MCPRegistryEntry ) => {
|
|
|
30
29
|
initGeneralContextResource( reg );
|
|
31
30
|
initBestPracticesResource( reg );
|
|
32
31
|
initConfigureElementTool( reg );
|
|
33
|
-
|
|
34
|
-
initFindIconsTool( reg );
|
|
35
|
-
}
|
|
32
|
+
initFindIconsTool( reg );
|
|
36
33
|
initGetPageStructureTool( reg );
|
|
37
34
|
initBreakpointsResource( reg );
|
|
38
35
|
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { generatePrompt } from '../prompt';
|
|
2
|
+
|
|
3
|
+
const mockPromptParts: string[] = [];
|
|
4
|
+
|
|
5
|
+
jest.mock( '@elementor/editor-mcp', () => ( {
|
|
6
|
+
toolPrompts: () => {
|
|
7
|
+
const record = ( ...args: unknown[] ) => {
|
|
8
|
+
mockPromptParts.push( ...args.filter( ( arg ): arg is string => 'string' === typeof arg ) );
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
return {
|
|
12
|
+
description: record,
|
|
13
|
+
parameter: record,
|
|
14
|
+
example: record,
|
|
15
|
+
instruction: record,
|
|
16
|
+
prompt: () => mockPromptParts.join( '\n' ),
|
|
17
|
+
};
|
|
18
|
+
},
|
|
19
|
+
} ) );
|
|
20
|
+
|
|
21
|
+
describe( 'configure-element prompt', () => {
|
|
22
|
+
beforeEach( () => {
|
|
23
|
+
mockPromptParts.length = 0;
|
|
24
|
+
} );
|
|
25
|
+
|
|
26
|
+
it( 'should always point agents at the find-icons tool for the svg property', () => {
|
|
27
|
+
// Act.
|
|
28
|
+
const prompt = generatePrompt();
|
|
29
|
+
|
|
30
|
+
// Assert.
|
|
31
|
+
expect( prompt ).toContain( '# Icons (the `svg` property on e-svg)' );
|
|
32
|
+
expect( prompt ).toContain( 'find-icons' );
|
|
33
|
+
} );
|
|
34
|
+
} );
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { toolPrompts } from '@elementor/editor-mcp';
|
|
2
2
|
|
|
3
|
-
import { isIconLibraryActive } from '../../icon-library-experiment';
|
|
4
3
|
import { DYNAMIC_TAGS_URI } from '../../resources/dynamic-tags-resource';
|
|
5
4
|
import { WIDGET_SCHEMA_URI } from '../../resources/widgets-schema-resource';
|
|
6
5
|
|
|
@@ -46,7 +45,6 @@ Setting a Font Awesome icon on an e-svg, after resolving it with \`find-icons\`:
|
|
|
46
45
|
export const CONFIGURE_ELEMENT_GUIDE_URI = 'elementor://canvas/tools/configure-element-guide';
|
|
47
46
|
|
|
48
47
|
export const generatePrompt = () => {
|
|
49
|
-
const iconLibraryActive = isIconLibraryActive();
|
|
50
48
|
const configureElementToolPrompt = toolPrompts( 'configure-element' );
|
|
51
49
|
|
|
52
50
|
configureElementToolPrompt.description( `
|
|
@@ -106,7 +104,7 @@ Put the dynamic object EXACTLY at the node whose schema offers the "dynamic" var
|
|
|
106
104
|
Image example: { "$$type": "image", "value": { "src": { "$$type": "dynamic", "value": { "name": "<image tag>", "settings": { ... } } } } }
|
|
107
105
|
Do NOT send "group" (it is resolved automatically). Use { "settings": {} } only when the tag has no settings.
|
|
108
106
|
|
|
109
|
-
${
|
|
107
|
+
${ ICONS_SECTION }` );
|
|
110
108
|
|
|
111
109
|
configureElementToolPrompt.parameter( 'elementId', 'The ID of the element to configure. MANDATORY.' );
|
|
112
110
|
|
|
@@ -149,9 +147,7 @@ ${ iconLibraryActive ? ICONS_SECTION : '' }` );
|
|
|
149
147
|
\`\`\`
|
|
150
148
|
` );
|
|
151
149
|
|
|
152
|
-
|
|
153
|
-
configureElementToolPrompt.example( ICON_EXAMPLE );
|
|
154
|
-
}
|
|
150
|
+
configureElementToolPrompt.example( ICON_EXAMPLE );
|
|
155
151
|
|
|
156
152
|
configureElementToolPrompt.instruction(
|
|
157
153
|
'The $$type property is MANDATORY for every value in propertiesToChange; it is not used in the style parameter (raw CSS only).'
|
|
@@ -133,7 +133,7 @@ describe( 'iconTransformer', () => {
|
|
|
133
133
|
expect( html ).toContain( 'M10 10' );
|
|
134
134
|
} );
|
|
135
135
|
|
|
136
|
-
it( '
|
|
136
|
+
it( 'falls back to the default svg when the icon cannot be resolved', async () => {
|
|
137
137
|
// Arrange.
|
|
138
138
|
mockFetch( { icons: {} } );
|
|
139
139
|
|
|
@@ -141,7 +141,7 @@ describe( 'iconTransformer', () => {
|
|
|
141
141
|
const result = await resolveSavedIcon( 'fas fa-missing', 'fa-solid' );
|
|
142
142
|
|
|
143
143
|
// Assert.
|
|
144
|
-
expect( result ).toEqual( { html: null, url:
|
|
144
|
+
expect( result ).toEqual( { html: null, url: 'https://example.com/assets/images/default-svg.svg' } );
|
|
145
145
|
} );
|
|
146
146
|
|
|
147
147
|
it( 'fetches json from the localized font awesome 7 base url', async () => {
|
|
@@ -180,8 +180,70 @@ describe( 'iconTransformer', () => {
|
|
|
180
180
|
const result = await resolveSavedIcon( 'fas fa-star', 'fa-../../wp-config' );
|
|
181
181
|
|
|
182
182
|
// Assert.
|
|
183
|
-
expect( global.fetch ).
|
|
184
|
-
|
|
183
|
+
expect( ( global.fetch as jest.Mock ).mock.calls.map( ( [ url ] ) => String( url ) ) ).toEqual( [
|
|
184
|
+
'https://example.com/assets/images/default-svg.svg',
|
|
185
|
+
] );
|
|
186
|
+
expect( result ).toEqual(
|
|
187
|
+
expect.objectContaining( { url: 'https://example.com/assets/images/default-svg.svg' } )
|
|
188
|
+
);
|
|
189
|
+
} );
|
|
190
|
+
|
|
191
|
+
it( 'asks providers for a font awesome icon missing from the free data', async () => {
|
|
192
|
+
// Arrange.
|
|
193
|
+
mockFetch( { icons: {} } );
|
|
194
|
+
const resolveSvg = jest
|
|
195
|
+
.fn()
|
|
196
|
+
.mockResolvedValue(
|
|
197
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 10"><path d="M2 2h6v6H2z"></path></svg>'
|
|
198
|
+
);
|
|
199
|
+
registerIconLibraryProvider( {
|
|
200
|
+
id: 'test-provider',
|
|
201
|
+
useIcons: () => ( { data: [], isLoading: false } ),
|
|
202
|
+
resolveSvg,
|
|
203
|
+
} );
|
|
204
|
+
|
|
205
|
+
// Act.
|
|
206
|
+
const result = ( await resolveSavedIcon( 'fal fa-star', 'fa-light' ) ) as { html: string; url: string | null };
|
|
207
|
+
|
|
208
|
+
unregisterIconLibraryProvider( 'test-provider' );
|
|
209
|
+
|
|
210
|
+
// Assert.
|
|
211
|
+
expect( resolveSvg ).toHaveBeenCalledWith( 'fa-light', 'fal fa-star', undefined );
|
|
212
|
+
expect( result.html ).toContain( 'M2 2h6v6H2z' );
|
|
213
|
+
expect( result.url ).toBeNull();
|
|
214
|
+
} );
|
|
215
|
+
|
|
216
|
+
it( 'falls back to the default svg for a font awesome icon when no provider resolves it', async () => {
|
|
217
|
+
// Arrange.
|
|
218
|
+
registerIconLibraryProvider( {
|
|
219
|
+
id: 'test-provider',
|
|
220
|
+
useIcons: () => ( { data: [], isLoading: false } ),
|
|
221
|
+
resolveSvg: async () => null,
|
|
222
|
+
} );
|
|
223
|
+
const defaultSvg =
|
|
224
|
+
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 50 50"><path d="M24.9999 4.31543"></path></svg>';
|
|
225
|
+
global.fetch = jest.fn( ( url: string ) =>
|
|
226
|
+
Promise.resolve(
|
|
227
|
+
String( url ).endsWith( '.svg' )
|
|
228
|
+
? {
|
|
229
|
+
ok: true,
|
|
230
|
+
headers: new Headers( { 'content-type': 'image/svg+xml' } ),
|
|
231
|
+
text: () => Promise.resolve( defaultSvg ),
|
|
232
|
+
}
|
|
233
|
+
: { ok: true, json: () => Promise.resolve( { icons: {} } ) }
|
|
234
|
+
)
|
|
235
|
+
) as never;
|
|
236
|
+
|
|
237
|
+
// Act.
|
|
238
|
+
const result = await resolveSavedIcon( 'fa-light fa-star', 'fa-light' );
|
|
239
|
+
|
|
240
|
+
unregisterIconLibraryProvider( 'test-provider' );
|
|
241
|
+
|
|
242
|
+
// Assert.
|
|
243
|
+
expect( result ).toEqual( {
|
|
244
|
+
html: expect.stringContaining( 'M24.9999 4.31543' ),
|
|
245
|
+
url: 'https://example.com/assets/images/default-svg.svg',
|
|
246
|
+
} );
|
|
185
247
|
} );
|
|
186
248
|
|
|
187
249
|
it( 'falls back to the default svg when no provider resolves a non-native library', async () => {
|
|
@@ -13,7 +13,6 @@ import { svgSrcTransformer } from './svg-src-transformer';
|
|
|
13
13
|
const EMPTY_ICON_RESULT = { html: null, url: null };
|
|
14
14
|
const ICON_SVG_SIZE = '100%';
|
|
15
15
|
const ICON_SVG_OVERFLOW = 'visible';
|
|
16
|
-
const FONT_AWESOME_LIBRARY_PREFIX = 'fa-';
|
|
17
16
|
const EICONS_LIBRARY = 'eicons';
|
|
18
17
|
const DEFAULT_SVG_RELATIVE_PATH = 'images/default-svg.svg';
|
|
19
18
|
|
|
@@ -36,7 +35,7 @@ export const iconTransformer = createTransformer( async ( value: IconValue, { si
|
|
|
36
35
|
return { html: fontAwesomeHtml, url: null };
|
|
37
36
|
}
|
|
38
37
|
|
|
39
|
-
if (
|
|
38
|
+
if ( EICONS_LIBRARY === library ) {
|
|
40
39
|
return EMPTY_ICON_RESULT;
|
|
41
40
|
}
|
|
42
41
|
|