@elementor/editor-canvas 3.35.0-355 → 3.35.0-357

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 CHANGED
@@ -5,6 +5,7 @@ import { Props, PropTypeKey, PropsSchema, AnyTransformable } from '@elementor/ed
5
5
 
6
6
  declare const BREAKPOINTS_SCHEMA_URI = "elementor://breakpoints/list";
7
7
 
8
+ declare const WIDGET_SCHEMA_URI = "elementor://widgets/schema/{widgetType}";
8
9
  declare const STYLE_SCHEMA_URI = "elementor://styles/schema/{category}";
9
10
 
10
11
  declare function init(): void;
@@ -190,6 +191,8 @@ declare const endDragElementFromPanel: () => void;
190
191
 
191
192
  declare function getCanvasIframeDocument(): Document | null | undefined;
192
193
 
194
+ declare const DOCUMENT_STRUCTURE_URI = "elementor://document/structure";
195
+
193
196
  declare function createTransformer<TValue = never>(cb: TValue extends AnyTransformable ? 'Transformable values are invalid, use the actual value instead.' : UnbrandedTransformer<TValue>): Transformer<NoInfer<TValue>>;
194
197
 
195
- export { type AnyTransformer, BREAKPOINTS_SCHEMA_URI, type BackboneModel, type CreateTemplatedElementTypeOptions, type ElementModel, ElementType, ElementView, type LegacyWindow, type PropsResolver, STYLE_SCHEMA_URI, createPropsResolver, createTemplatedElementView, createTransformer, createTransformersRegistry, endDragElementFromPanel, getCanvasIframeDocument, init, registerElementType, settingsTransformersRegistry, startDragElementFromPanel, styleTransformersRegistry };
198
+ export { type AnyTransformer, BREAKPOINTS_SCHEMA_URI, type BackboneModel, type CreateTemplatedElementTypeOptions, DOCUMENT_STRUCTURE_URI, type ElementModel, ElementType, ElementView, type LegacyWindow, type PropsResolver, STYLE_SCHEMA_URI, WIDGET_SCHEMA_URI, createPropsResolver, createTemplatedElementView, createTransformer, createTransformersRegistry, endDragElementFromPanel, getCanvasIframeDocument, init, registerElementType, settingsTransformersRegistry, startDragElementFromPanel, styleTransformersRegistry };
package/dist/index.d.ts CHANGED
@@ -5,6 +5,7 @@ import { Props, PropTypeKey, PropsSchema, AnyTransformable } from '@elementor/ed
5
5
 
6
6
  declare const BREAKPOINTS_SCHEMA_URI = "elementor://breakpoints/list";
7
7
 
8
+ declare const WIDGET_SCHEMA_URI = "elementor://widgets/schema/{widgetType}";
8
9
  declare const STYLE_SCHEMA_URI = "elementor://styles/schema/{category}";
9
10
 
10
11
  declare function init(): void;
@@ -190,6 +191,8 @@ declare const endDragElementFromPanel: () => void;
190
191
 
191
192
  declare function getCanvasIframeDocument(): Document | null | undefined;
192
193
 
194
+ declare const DOCUMENT_STRUCTURE_URI = "elementor://document/structure";
195
+
193
196
  declare function createTransformer<TValue = never>(cb: TValue extends AnyTransformable ? 'Transformable values are invalid, use the actual value instead.' : UnbrandedTransformer<TValue>): Transformer<NoInfer<TValue>>;
194
197
 
195
- export { type AnyTransformer, BREAKPOINTS_SCHEMA_URI, type BackboneModel, type CreateTemplatedElementTypeOptions, type ElementModel, ElementType, ElementView, type LegacyWindow, type PropsResolver, STYLE_SCHEMA_URI, createPropsResolver, createTemplatedElementView, createTransformer, createTransformersRegistry, endDragElementFromPanel, getCanvasIframeDocument, init, registerElementType, settingsTransformersRegistry, startDragElementFromPanel, styleTransformersRegistry };
198
+ export { type AnyTransformer, BREAKPOINTS_SCHEMA_URI, type BackboneModel, type CreateTemplatedElementTypeOptions, DOCUMENT_STRUCTURE_URI, type ElementModel, ElementType, ElementView, type LegacyWindow, type PropsResolver, STYLE_SCHEMA_URI, WIDGET_SCHEMA_URI, createPropsResolver, createTemplatedElementView, createTransformer, createTransformersRegistry, endDragElementFromPanel, getCanvasIframeDocument, init, registerElementType, settingsTransformersRegistry, startDragElementFromPanel, styleTransformersRegistry };
package/dist/index.js CHANGED
@@ -31,7 +31,9 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  BREAKPOINTS_SCHEMA_URI: () => BREAKPOINTS_SCHEMA_URI,
34
+ DOCUMENT_STRUCTURE_URI: () => DOCUMENT_STRUCTURE_URI,
34
35
  STYLE_SCHEMA_URI: () => STYLE_SCHEMA_URI,
36
+ WIDGET_SCHEMA_URI: () => WIDGET_SCHEMA_URI,
35
37
  createPropsResolver: () => createPropsResolver,
36
38
  createTemplatedElementView: () => createTemplatedElementView,
37
39
  createTransformer: () => createTransformer,
@@ -1943,6 +1945,81 @@ function initLegacyViews() {
1943
1945
  });
1944
1946
  }
1945
1947
 
1948
+ // src/mcp/resources/document-structure-resource.ts
1949
+ var import_editor_v1_adapters10 = require("@elementor/editor-v1-adapters");
1950
+ var DOCUMENT_STRUCTURE_URI = "elementor://document/structure";
1951
+ var initDocumentStructureResource = (reg) => {
1952
+ const { mcpServer, sendResourceUpdated } = reg;
1953
+ let currentDocumentStructure = null;
1954
+ const updateDocumentStructure = () => {
1955
+ const structure = getDocumentStructure();
1956
+ const newStructure = JSON.stringify(structure, null, 2);
1957
+ if (newStructure !== currentDocumentStructure) {
1958
+ currentDocumentStructure = newStructure;
1959
+ sendResourceUpdated({ uri: DOCUMENT_STRUCTURE_URI });
1960
+ }
1961
+ };
1962
+ (0, import_editor_v1_adapters10.__privateListenTo)(
1963
+ [
1964
+ (0, import_editor_v1_adapters10.commandEndEvent)("document/elements/create"),
1965
+ (0, import_editor_v1_adapters10.commandEndEvent)("document/elements/delete"),
1966
+ (0, import_editor_v1_adapters10.commandEndEvent)("document/elements/move"),
1967
+ (0, import_editor_v1_adapters10.commandEndEvent)("document/elements/copy"),
1968
+ (0, import_editor_v1_adapters10.commandEndEvent)("document/elements/paste"),
1969
+ (0, import_editor_v1_adapters10.commandEndEvent)("editor/documents/attach-preview")
1970
+ ],
1971
+ updateDocumentStructure
1972
+ );
1973
+ updateDocumentStructure();
1974
+ mcpServer.resource("document-structure", DOCUMENT_STRUCTURE_URI, async () => {
1975
+ const structure = getDocumentStructure();
1976
+ return {
1977
+ contents: [
1978
+ {
1979
+ uri: DOCUMENT_STRUCTURE_URI,
1980
+ text: JSON.stringify(structure, null, 2)
1981
+ }
1982
+ ]
1983
+ };
1984
+ });
1985
+ };
1986
+ function getDocumentStructure() {
1987
+ const extendedWindow = window;
1988
+ const document2 = extendedWindow.elementor?.documents?.getCurrent?.();
1989
+ if (!document2) {
1990
+ return { error: "No active document found" };
1991
+ }
1992
+ const containers = document2.container?.children || [];
1993
+ const elements = containers.map(
1994
+ (container) => extractElementData(container)
1995
+ );
1996
+ return {
1997
+ documentId: document2.id,
1998
+ documentType: document2.config.type,
1999
+ title: document2.config.settings?.post_title || "Untitled",
2000
+ elements: elements.filter((el) => el !== null)
2001
+ };
2002
+ }
2003
+ function extractElementData(element) {
2004
+ if (!element || !element.model) {
2005
+ return null;
2006
+ }
2007
+ const model = element.model.attributes;
2008
+ const result = {
2009
+ id: model.id,
2010
+ elType: model.elType,
2011
+ widgetType: model.widgetType || void 0
2012
+ };
2013
+ const title = model.title || element.model?.editor_settings?.title;
2014
+ if (title) {
2015
+ result.title = title;
2016
+ }
2017
+ if (element.children && element.children.length > 0) {
2018
+ result.children = element.children.map((child) => extractElementData(child)).filter((child) => child !== null);
2019
+ }
2020
+ return result;
2021
+ }
2022
+
1946
2023
  // src/mcp/tools/build-composition/tool.ts
1947
2024
  var import_editor_elements8 = require("@elementor/editor-elements");
1948
2025
 
@@ -2950,6 +3027,7 @@ var initCanvasMcp = (reg) => {
2950
3027
  'Everything related to creative design, layout, styling and building the pages, specifically element of type "widget"'
2951
3028
  );
2952
3029
  initWidgetsSchemaResource(reg);
3030
+ initDocumentStructureResource(reg);
2953
3031
  initBuildCompositionsTool(reg);
2954
3032
  initGetElementConfigTool(reg);
2955
3033
  initConfigureElementTool(reg);
@@ -3085,14 +3163,14 @@ An Example scenario of creating fully styled composition:
3085
3163
  // src/prevent-link-in-link-commands.ts
3086
3164
  var import_editor_elements10 = require("@elementor/editor-elements");
3087
3165
  var import_editor_notifications = require("@elementor/editor-notifications");
3088
- var import_editor_v1_adapters10 = require("@elementor/editor-v1-adapters");
3166
+ var import_editor_v1_adapters11 = require("@elementor/editor-v1-adapters");
3089
3167
  var import_i18n = require("@wordpress/i18n");
3090
3168
  function initLinkInLinkPrevention() {
3091
- (0, import_editor_v1_adapters10.blockCommand)({
3169
+ (0, import_editor_v1_adapters11.blockCommand)({
3092
3170
  command: "document/elements/paste",
3093
3171
  condition: blockLinkInLinkPaste
3094
3172
  });
3095
- (0, import_editor_v1_adapters10.blockCommand)({
3173
+ (0, import_editor_v1_adapters11.blockCommand)({
3096
3174
  command: "document/elements/move",
3097
3175
  condition: blockLinkInLinkMove
3098
3176
  });
@@ -3166,12 +3244,12 @@ function shouldBlock(sourceElements, targetElements) {
3166
3244
  }
3167
3245
 
3168
3246
  // src/style-commands/paste-style.ts
3169
- var import_editor_v1_adapters12 = require("@elementor/editor-v1-adapters");
3247
+ var import_editor_v1_adapters13 = require("@elementor/editor-v1-adapters");
3170
3248
 
3171
3249
  // src/style-commands/undoable-actions/paste-element-style.ts
3172
3250
  var import_editor_elements12 = require("@elementor/editor-elements");
3173
3251
  var import_editor_styles_repository4 = require("@elementor/editor-styles-repository");
3174
- var import_editor_v1_adapters11 = require("@elementor/editor-v1-adapters");
3252
+ var import_editor_v1_adapters12 = require("@elementor/editor-v1-adapters");
3175
3253
  var import_i18n3 = require("@wordpress/i18n");
3176
3254
 
3177
3255
  // src/style-commands/utils.ts
@@ -3217,7 +3295,7 @@ function getTitleForContainers(containers) {
3217
3295
  }
3218
3296
 
3219
3297
  // src/style-commands/undoable-actions/paste-element-style.ts
3220
- var undoablePasteElementStyle = () => (0, import_editor_v1_adapters11.undoable)(
3298
+ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters12.undoable)(
3221
3299
  {
3222
3300
  do: ({ containers, newStyle }) => {
3223
3301
  return containers.map((container) => {
@@ -3293,12 +3371,12 @@ var undoablePasteElementStyle = () => (0, import_editor_v1_adapters11.undoable)(
3293
3371
  // src/style-commands/paste-style.ts
3294
3372
  function initPasteStyleCommand() {
3295
3373
  const pasteElementStyleCommand = undoablePasteElementStyle();
3296
- (0, import_editor_v1_adapters12.blockCommand)({
3374
+ (0, import_editor_v1_adapters13.blockCommand)({
3297
3375
  command: "document/elements/paste-style",
3298
3376
  condition: hasAtomicWidgets
3299
3377
  });
3300
- (0, import_editor_v1_adapters12.__privateListenTo)(
3301
- (0, import_editor_v1_adapters12.commandStartEvent)("document/elements/paste-style"),
3378
+ (0, import_editor_v1_adapters13.__privateListenTo)(
3379
+ (0, import_editor_v1_adapters13.commandStartEvent)("document/elements/paste-style"),
3302
3380
  (e) => pasteStyles(e.args, pasteElementStyleCommand)
3303
3381
  );
3304
3382
  }
@@ -3322,14 +3400,14 @@ function pasteStyles(args, pasteCallback) {
3322
3400
  }
3323
3401
 
3324
3402
  // src/style-commands/reset-style.ts
3325
- var import_editor_v1_adapters14 = require("@elementor/editor-v1-adapters");
3403
+ var import_editor_v1_adapters15 = require("@elementor/editor-v1-adapters");
3326
3404
 
3327
3405
  // src/style-commands/undoable-actions/reset-element-style.ts
3328
3406
  var import_editor_elements13 = require("@elementor/editor-elements");
3329
3407
  var import_editor_styles_repository5 = require("@elementor/editor-styles-repository");
3330
- var import_editor_v1_adapters13 = require("@elementor/editor-v1-adapters");
3408
+ var import_editor_v1_adapters14 = require("@elementor/editor-v1-adapters");
3331
3409
  var import_i18n4 = require("@wordpress/i18n");
3332
- var undoableResetElementStyle = () => (0, import_editor_v1_adapters13.undoable)(
3410
+ var undoableResetElementStyle = () => (0, import_editor_v1_adapters14.undoable)(
3333
3411
  {
3334
3412
  do: ({ containers }) => {
3335
3413
  return containers.map((container) => {
@@ -3373,12 +3451,12 @@ var undoableResetElementStyle = () => (0, import_editor_v1_adapters13.undoable)(
3373
3451
  // src/style-commands/reset-style.ts
3374
3452
  function initResetStyleCommand() {
3375
3453
  const resetElementStyles = undoableResetElementStyle();
3376
- (0, import_editor_v1_adapters14.blockCommand)({
3454
+ (0, import_editor_v1_adapters15.blockCommand)({
3377
3455
  command: "document/elements/reset-style",
3378
3456
  condition: hasAtomicWidgets
3379
3457
  });
3380
- (0, import_editor_v1_adapters14.__privateListenTo)(
3381
- (0, import_editor_v1_adapters14.commandStartEvent)("document/elements/reset-style"),
3458
+ (0, import_editor_v1_adapters15.__privateListenTo)(
3459
+ (0, import_editor_v1_adapters15.commandStartEvent)("document/elements/reset-style"),
3382
3460
  (e) => resetStyles(e.args, resetElementStyles)
3383
3461
  );
3384
3462
  }
@@ -3465,7 +3543,9 @@ var getLegacyPanelElementView = ({ settings, ...rest }) => {
3465
3543
  // Annotate the CommonJS export names for ESM import in node:
3466
3544
  0 && (module.exports = {
3467
3545
  BREAKPOINTS_SCHEMA_URI,
3546
+ DOCUMENT_STRUCTURE_URI,
3468
3547
  STYLE_SCHEMA_URI,
3548
+ WIDGET_SCHEMA_URI,
3469
3549
  createPropsResolver,
3470
3550
  createTemplatedElementView,
3471
3551
  createTransformer,
package/dist/index.mjs CHANGED
@@ -1911,6 +1911,81 @@ function initLegacyViews() {
1911
1911
  });
1912
1912
  }
1913
1913
 
1914
+ // src/mcp/resources/document-structure-resource.ts
1915
+ import { __privateListenTo as listenTo, commandEndEvent as commandEndEvent4 } from "@elementor/editor-v1-adapters";
1916
+ var DOCUMENT_STRUCTURE_URI = "elementor://document/structure";
1917
+ var initDocumentStructureResource = (reg) => {
1918
+ const { mcpServer, sendResourceUpdated } = reg;
1919
+ let currentDocumentStructure = null;
1920
+ const updateDocumentStructure = () => {
1921
+ const structure = getDocumentStructure();
1922
+ const newStructure = JSON.stringify(structure, null, 2);
1923
+ if (newStructure !== currentDocumentStructure) {
1924
+ currentDocumentStructure = newStructure;
1925
+ sendResourceUpdated({ uri: DOCUMENT_STRUCTURE_URI });
1926
+ }
1927
+ };
1928
+ listenTo(
1929
+ [
1930
+ commandEndEvent4("document/elements/create"),
1931
+ commandEndEvent4("document/elements/delete"),
1932
+ commandEndEvent4("document/elements/move"),
1933
+ commandEndEvent4("document/elements/copy"),
1934
+ commandEndEvent4("document/elements/paste"),
1935
+ commandEndEvent4("editor/documents/attach-preview")
1936
+ ],
1937
+ updateDocumentStructure
1938
+ );
1939
+ updateDocumentStructure();
1940
+ mcpServer.resource("document-structure", DOCUMENT_STRUCTURE_URI, async () => {
1941
+ const structure = getDocumentStructure();
1942
+ return {
1943
+ contents: [
1944
+ {
1945
+ uri: DOCUMENT_STRUCTURE_URI,
1946
+ text: JSON.stringify(structure, null, 2)
1947
+ }
1948
+ ]
1949
+ };
1950
+ });
1951
+ };
1952
+ function getDocumentStructure() {
1953
+ const extendedWindow = window;
1954
+ const document2 = extendedWindow.elementor?.documents?.getCurrent?.();
1955
+ if (!document2) {
1956
+ return { error: "No active document found" };
1957
+ }
1958
+ const containers = document2.container?.children || [];
1959
+ const elements = containers.map(
1960
+ (container) => extractElementData(container)
1961
+ );
1962
+ return {
1963
+ documentId: document2.id,
1964
+ documentType: document2.config.type,
1965
+ title: document2.config.settings?.post_title || "Untitled",
1966
+ elements: elements.filter((el) => el !== null)
1967
+ };
1968
+ }
1969
+ function extractElementData(element) {
1970
+ if (!element || !element.model) {
1971
+ return null;
1972
+ }
1973
+ const model = element.model.attributes;
1974
+ const result = {
1975
+ id: model.id,
1976
+ elType: model.elType,
1977
+ widgetType: model.widgetType || void 0
1978
+ };
1979
+ const title = model.title || element.model?.editor_settings?.title;
1980
+ if (title) {
1981
+ result.title = title;
1982
+ }
1983
+ if (element.children && element.children.length > 0) {
1984
+ result.children = element.children.map((child) => extractElementData(child)).filter((child) => child !== null);
1985
+ }
1986
+ return result;
1987
+ }
1988
+
1914
1989
  // src/mcp/tools/build-composition/tool.ts
1915
1990
  import {
1916
1991
  createElement as createElement6,
@@ -2930,6 +3005,7 @@ var initCanvasMcp = (reg) => {
2930
3005
  'Everything related to creative design, layout, styling and building the pages, specifically element of type "widget"'
2931
3006
  );
2932
3007
  initWidgetsSchemaResource(reg);
3008
+ initDocumentStructureResource(reg);
2933
3009
  initBuildCompositionsTool(reg);
2934
3010
  initGetElementConfigTool(reg);
2935
3011
  initConfigureElementTool(reg);
@@ -3151,7 +3227,7 @@ function shouldBlock(sourceElements, targetElements) {
3151
3227
 
3152
3228
  // src/style-commands/paste-style.ts
3153
3229
  import {
3154
- __privateListenTo as listenTo,
3230
+ __privateListenTo as listenTo2,
3155
3231
  blockCommand as blockCommand2,
3156
3232
  commandStartEvent
3157
3233
  } from "@elementor/editor-v1-adapters";
@@ -3290,7 +3366,7 @@ function initPasteStyleCommand() {
3290
3366
  command: "document/elements/paste-style",
3291
3367
  condition: hasAtomicWidgets
3292
3368
  });
3293
- listenTo(
3369
+ listenTo2(
3294
3370
  commandStartEvent("document/elements/paste-style"),
3295
3371
  (e) => pasteStyles(e.args, pasteElementStyleCommand)
3296
3372
  );
@@ -3316,7 +3392,7 @@ function pasteStyles(args, pasteCallback) {
3316
3392
 
3317
3393
  // src/style-commands/reset-style.ts
3318
3394
  import {
3319
- __privateListenTo as listenTo2,
3395
+ __privateListenTo as listenTo3,
3320
3396
  blockCommand as blockCommand3,
3321
3397
  commandStartEvent as commandStartEvent2
3322
3398
  } from "@elementor/editor-v1-adapters";
@@ -3374,7 +3450,7 @@ function initResetStyleCommand() {
3374
3450
  command: "document/elements/reset-style",
3375
3451
  condition: hasAtomicWidgets
3376
3452
  });
3377
- listenTo2(
3453
+ listenTo3(
3378
3454
  commandStartEvent2("document/elements/reset-style"),
3379
3455
  (e) => resetStyles(e.args, resetElementStyles)
3380
3456
  );
@@ -3461,7 +3537,9 @@ var getLegacyPanelElementView = ({ settings, ...rest }) => {
3461
3537
  };
3462
3538
  export {
3463
3539
  BREAKPOINTS_SCHEMA_URI,
3540
+ DOCUMENT_STRUCTURE_URI,
3464
3541
  STYLE_SCHEMA_URI,
3542
+ WIDGET_SCHEMA_URI,
3465
3543
  createPropsResolver,
3466
3544
  createTemplatedElementView,
3467
3545
  createTransformer,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@elementor/editor-canvas",
3
3
  "description": "Elementor Editor Canvas",
4
- "version": "3.35.0-355",
4
+ "version": "3.35.0-357",
5
5
  "private": false,
6
6
  "author": "Elementor Team",
7
7
  "homepage": "https://elementor.com/",
@@ -37,24 +37,24 @@
37
37
  "react-dom": "^18.3.1"
38
38
  },
39
39
  "dependencies": {
40
- "@elementor/editor": "3.35.0-355",
41
- "@elementor/editor-controls": "3.35.0-355",
42
- "@elementor/editor-documents": "3.35.0-355",
43
- "@elementor/editor-elements": "3.35.0-355",
44
- "@elementor/editor-interactions": "3.35.0-355",
45
- "@elementor/editor-mcp": "3.35.0-355",
46
- "@elementor/editor-notifications": "3.35.0-355",
47
- "@elementor/editor-props": "3.35.0-355",
48
- "@elementor/editor-responsive": "3.35.0-355",
49
- "@elementor/editor-styles": "3.35.0-355",
50
- "@elementor/editor-styles-repository": "3.35.0-355",
51
- "@elementor/editor-ui": "3.35.0-355",
52
- "@elementor/editor-v1-adapters": "3.35.0-355",
53
- "@elementor/schema": "3.35.0-355",
54
- "@elementor/twing": "3.35.0-355",
40
+ "@elementor/editor": "3.35.0-357",
41
+ "@elementor/editor-controls": "3.35.0-357",
42
+ "@elementor/editor-documents": "3.35.0-357",
43
+ "@elementor/editor-elements": "3.35.0-357",
44
+ "@elementor/editor-interactions": "3.35.0-357",
45
+ "@elementor/editor-mcp": "3.35.0-357",
46
+ "@elementor/editor-notifications": "3.35.0-357",
47
+ "@elementor/editor-props": "3.35.0-357",
48
+ "@elementor/editor-responsive": "3.35.0-357",
49
+ "@elementor/editor-styles": "3.35.0-357",
50
+ "@elementor/editor-styles-repository": "3.35.0-357",
51
+ "@elementor/editor-ui": "3.35.0-357",
52
+ "@elementor/editor-v1-adapters": "3.35.0-357",
53
+ "@elementor/schema": "3.35.0-357",
54
+ "@elementor/twing": "3.35.0-357",
55
55
  "@elementor/ui": "1.36.17",
56
- "@elementor/utils": "3.35.0-355",
57
- "@elementor/wp-media": "3.35.0-355",
56
+ "@elementor/utils": "3.35.0-357",
57
+ "@elementor/wp-media": "3.35.0-357",
58
58
  "@floating-ui/react": "^0.27.5",
59
59
  "@wordpress/i18n": "^5.13.0"
60
60
  },
package/src/index.ts CHANGED
@@ -14,6 +14,9 @@ export { settingsTransformersRegistry } from './settings-transformers-registry';
14
14
  export { styleTransformersRegistry } from './style-transformers-registry';
15
15
  export { endDragElementFromPanel, startDragElementFromPanel } from './sync/drag-element-from-panel';
16
16
  export { getCanvasIframeDocument } from './sync/get-canvas-iframe-document';
17
+ export { DOCUMENT_STRUCTURE_URI } from './mcp/resources/document-structure-resource';
18
+ export { WIDGET_SCHEMA_URI } from './mcp/resources/widgets-schema-resource';
19
+ export * from './legacy/types';
17
20
  export { createTransformer } from './transformers/create-transformer';
18
21
  export { createTransformersRegistry } from './transformers/create-transformers-registry';
19
22
  export { type AnyTransformer } from './transformers/types';
@@ -1,6 +1,7 @@
1
1
  import { type MCPRegistryEntry } from '@elementor/editor-mcp';
2
2
 
3
3
  import { initBreakpointsResource } from './resources/breakpoints-resource';
4
+ import { initDocumentStructureResource } from './resources/document-structure-resource';
4
5
  import { initWidgetsSchemaResource } from './resources/widgets-schema-resource';
5
6
  import { initBuildCompositionsTool } from './tools/build-composition/tool';
6
7
  import { initConfigureElementTool } from './tools/configure-element/tool';
@@ -12,6 +13,7 @@ export const initCanvasMcp = ( reg: MCPRegistryEntry ) => {
12
13
  'Everything related to creative design, layout, styling and building the pages, specifically element of type "widget"'
13
14
  );
14
15
  initWidgetsSchemaResource( reg );
16
+ initDocumentStructureResource( reg );
15
17
  initBuildCompositionsTool( reg );
16
18
  initGetElementConfigTool( reg );
17
19
  initConfigureElementTool( reg );
@@ -0,0 +1,132 @@
1
+ import { type MCPRegistryEntry } from '@elementor/editor-mcp';
2
+ import { __privateListenTo as listenTo, commandEndEvent } from '@elementor/editor-v1-adapters';
3
+
4
+ type ExtendedWindow = Window & {
5
+ elementor?: {
6
+ documents?: {
7
+ getCurrent?: () => {
8
+ id: number;
9
+ config: {
10
+ type: string;
11
+ settings?: {
12
+ post_title?: string;
13
+ };
14
+ };
15
+ container: {
16
+ children?: ElementorContainer[];
17
+ };
18
+ };
19
+ };
20
+ };
21
+ };
22
+
23
+ type ElementorContainer = {
24
+ id: string;
25
+ model: {
26
+ attributes: {
27
+ id: string;
28
+ elType: string;
29
+ widgetType?: string;
30
+ title?: string;
31
+ };
32
+ editor_settings?: {
33
+ title?: string;
34
+ };
35
+ };
36
+ children?: ElementorContainer[];
37
+ };
38
+
39
+ export const DOCUMENT_STRUCTURE_URI = 'elementor://document/structure';
40
+
41
+ export const initDocumentStructureResource = ( reg: MCPRegistryEntry ) => {
42
+ const { mcpServer, sendResourceUpdated } = reg;
43
+
44
+ let currentDocumentStructure: string | null = null;
45
+
46
+ const updateDocumentStructure = () => {
47
+ const structure = getDocumentStructure();
48
+ const newStructure = JSON.stringify( structure, null, 2 );
49
+
50
+ if ( newStructure !== currentDocumentStructure ) {
51
+ currentDocumentStructure = newStructure;
52
+ sendResourceUpdated( { uri: DOCUMENT_STRUCTURE_URI } );
53
+ }
54
+ };
55
+
56
+ // Listen to document changes
57
+ listenTo(
58
+ [
59
+ commandEndEvent( 'document/elements/create' ),
60
+ commandEndEvent( 'document/elements/delete' ),
61
+ commandEndEvent( 'document/elements/move' ),
62
+ commandEndEvent( 'document/elements/copy' ),
63
+ commandEndEvent( 'document/elements/paste' ),
64
+ commandEndEvent( 'editor/documents/attach-preview' ),
65
+ ],
66
+ updateDocumentStructure
67
+ );
68
+
69
+ // Initialize on load
70
+ updateDocumentStructure();
71
+
72
+ mcpServer.resource( 'document-structure', DOCUMENT_STRUCTURE_URI, async () => {
73
+ const structure = getDocumentStructure();
74
+
75
+ return {
76
+ contents: [
77
+ {
78
+ uri: DOCUMENT_STRUCTURE_URI,
79
+ text: JSON.stringify( structure, null, 2 ),
80
+ },
81
+ ],
82
+ };
83
+ } );
84
+ };
85
+
86
+ function getDocumentStructure() {
87
+ const extendedWindow = window as ExtendedWindow;
88
+ const document = extendedWindow.elementor?.documents?.getCurrent?.();
89
+
90
+ if ( ! document ) {
91
+ return { error: 'No active document found' };
92
+ }
93
+
94
+ const containers = document.container?.children || [];
95
+ const elements = ( containers as ElementorContainer[] ).map( ( container: ElementorContainer ) =>
96
+ extractElementData( container )
97
+ );
98
+
99
+ return {
100
+ documentId: document.id,
101
+ documentType: document.config.type,
102
+ title: document.config.settings?.post_title || 'Untitled',
103
+ elements: elements.filter( ( el: Record< string, unknown > | null ) => el !== null ),
104
+ };
105
+ }
106
+
107
+ function extractElementData( element: ElementorContainer ): Record< string, unknown > | null {
108
+ if ( ! element || ! element.model ) {
109
+ return null;
110
+ }
111
+
112
+ const model = element.model.attributes;
113
+ const result: Record< string, unknown > = {
114
+ id: model.id,
115
+ elType: model.elType,
116
+ widgetType: model.widgetType || undefined,
117
+ };
118
+
119
+ const title = model.title || element.model?.editor_settings?.title;
120
+
121
+ if ( title ) {
122
+ result.title = title;
123
+ }
124
+
125
+ if ( element.children && element.children.length > 0 ) {
126
+ result.children = element.children
127
+ .map( ( child: ElementorContainer ) => extractElementData( child ) )
128
+ .filter( ( child: Record< string, unknown > | null ) => child !== null );
129
+ }
130
+
131
+ return result;
132
+ }