@elementor/editor-canvas 4.0.0-621 → 4.0.0-manual
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 +203 -182
- package/dist/index.mjs +166 -145
- package/package.json +18 -18
- package/src/composition-builder/composition-builder.ts +31 -2
- package/src/mcp/canvas-mcp.ts +8 -1
- package/src/mcp/resources/best-practices.ts +159 -0
- package/src/mcp/resources/widgets-schema-resource.ts +7 -1
- package/src/mcp/tools/build-composition/prompt.ts +110 -134
- package/src/mcp/tools/build-composition/schema.ts +8 -1
- package/src/mcp/tools/build-composition/tool.ts +4 -4
package/dist/index.mjs
CHANGED
|
@@ -59,7 +59,13 @@ Prefer using "em" and "rem" values for text-related sizes, padding and spacing.
|
|
|
59
59
|
This flexboxes are by default "flex" with "stretch" alignment. To ensure proper layout, define the "justify-content" and "align-items" as in the schema.
|
|
60
60
|
|
|
61
61
|
When applicable for styles, apply style PropValues using the ${STYLE_SCHEMA_URI}.
|
|
62
|
-
The css string must follow standard CSS syntax, with properties and values separated by semicolons, no selectors, or nesting rules allowed
|
|
62
|
+
The css string must follow standard CSS syntax, with properties and values separated by semicolons, no selectors, or nesting rules allowed.
|
|
63
|
+
|
|
64
|
+
** CRITICAL - VARIABLES **
|
|
65
|
+
When using global variables, ensure that the variables are defined in the ${"elementor://global-variables"} resource.
|
|
66
|
+
Variables from the user context ARE NOT SUPPORTED AND WILL RESOLVE IN ERROR.
|
|
67
|
+
|
|
68
|
+
`
|
|
63
69
|
}
|
|
64
70
|
]
|
|
65
71
|
};
|
|
@@ -3197,6 +3203,7 @@ var validateInput = {
|
|
|
3197
3203
|
var CompositionBuilder = class _CompositionBuilder {
|
|
3198
3204
|
elementConfig = {};
|
|
3199
3205
|
elementStylesConfig = {};
|
|
3206
|
+
elementCusomCSS = {};
|
|
3200
3207
|
rootContainers = [];
|
|
3201
3208
|
containerElements = [];
|
|
3202
3209
|
api = {
|
|
@@ -3220,11 +3227,12 @@ var CompositionBuilder = class _CompositionBuilder {
|
|
|
3220
3227
|
});
|
|
3221
3228
|
}
|
|
3222
3229
|
constructor(opts) {
|
|
3223
|
-
const { api = {}, elementConfig = {}, stylesConfig = {}, xml } = opts;
|
|
3230
|
+
const { api = {}, elementConfig = {}, stylesConfig = {}, customCSS = {}, xml } = opts;
|
|
3224
3231
|
this.xml = xml;
|
|
3225
3232
|
Object.assign(this.api, api);
|
|
3226
3233
|
this.setElementConfig(elementConfig);
|
|
3227
3234
|
this.setStylesConfig(stylesConfig);
|
|
3235
|
+
this.setCustomCSS(customCSS);
|
|
3228
3236
|
}
|
|
3229
3237
|
setElementConfig(config) {
|
|
3230
3238
|
this.elementConfig = config;
|
|
@@ -3232,6 +3240,9 @@ var CompositionBuilder = class _CompositionBuilder {
|
|
|
3232
3240
|
setStylesConfig(config) {
|
|
3233
3241
|
this.elementStylesConfig = config;
|
|
3234
3242
|
}
|
|
3243
|
+
setCustomCSS(config) {
|
|
3244
|
+
this.elementCusomCSS = config;
|
|
3245
|
+
}
|
|
3235
3246
|
getXML() {
|
|
3236
3247
|
return this.xml;
|
|
3237
3248
|
}
|
|
@@ -3247,7 +3258,10 @@ var CompositionBuilder = class _CompositionBuilder {
|
|
|
3247
3258
|
container: targetContainer,
|
|
3248
3259
|
model: {
|
|
3249
3260
|
elType: elementTag,
|
|
3250
|
-
id: generateElementId()
|
|
3261
|
+
id: generateElementId(),
|
|
3262
|
+
editor_settings: {
|
|
3263
|
+
title: node.getAttribute("configuration-id") ?? void 0
|
|
3264
|
+
}
|
|
3251
3265
|
},
|
|
3252
3266
|
options: { useHistory: false }
|
|
3253
3267
|
}) : this.api.createElement({
|
|
@@ -3255,7 +3269,10 @@ var CompositionBuilder = class _CompositionBuilder {
|
|
|
3255
3269
|
model: {
|
|
3256
3270
|
elType: "widget",
|
|
3257
3271
|
widgetType: elementTag,
|
|
3258
|
-
id: generateElementId()
|
|
3272
|
+
id: generateElementId(),
|
|
3273
|
+
editor_settings: {
|
|
3274
|
+
title: node.getAttribute("configuration-id") ?? void 0
|
|
3275
|
+
}
|
|
3259
3276
|
},
|
|
3260
3277
|
options: { useHistory: false }
|
|
3261
3278
|
});
|
|
@@ -3296,9 +3313,9 @@ var CompositionBuilder = class _CompositionBuilder {
|
|
|
3296
3313
|
applyStyles() {
|
|
3297
3314
|
const errors = [];
|
|
3298
3315
|
const invalidStyles = {};
|
|
3299
|
-
const validStylesPropValues = {};
|
|
3300
3316
|
for (const [styleId, styleConfig] of Object.entries(this.elementStylesConfig)) {
|
|
3301
3317
|
const { element, node } = this.matchNodeByConfigId(styleId);
|
|
3318
|
+
const validStylesPropValues = {};
|
|
3302
3319
|
for (const [styleName, stylePropValue] of Object.entries(styleConfig)) {
|
|
3303
3320
|
const { valid, errors: validationErrors } = validateInput.validateStyles({
|
|
3304
3321
|
[styleName]: stylePropValue
|
|
@@ -3312,14 +3329,30 @@ var CompositionBuilder = class _CompositionBuilder {
|
|
|
3312
3329
|
} else {
|
|
3313
3330
|
validStylesPropValues[styleName] = stylePropValue;
|
|
3314
3331
|
}
|
|
3332
|
+
}
|
|
3333
|
+
if (Object.keys(validStylesPropValues).length === 0) {
|
|
3334
|
+
continue;
|
|
3335
|
+
}
|
|
3336
|
+
try {
|
|
3315
3337
|
this.api.doUpdateElementProperty({
|
|
3316
3338
|
elementId: element.id,
|
|
3317
3339
|
propertyName: "_styles",
|
|
3318
3340
|
propertyValue: validStylesPropValues,
|
|
3319
3341
|
elementType: node.tagName
|
|
3320
3342
|
});
|
|
3343
|
+
} catch (error) {
|
|
3344
|
+
errors.push(String(error));
|
|
3321
3345
|
}
|
|
3322
3346
|
}
|
|
3347
|
+
for (const [customCSSId, customCSS] of Object.entries(this.elementCusomCSS)) {
|
|
3348
|
+
const { element, node } = this.matchNodeByConfigId(customCSSId);
|
|
3349
|
+
this.api.doUpdateElementProperty({
|
|
3350
|
+
elementId: element.id,
|
|
3351
|
+
propertyName: "_styles",
|
|
3352
|
+
propertyValue: { custom_css: customCSS },
|
|
3353
|
+
elementType: node.tagName
|
|
3354
|
+
});
|
|
3355
|
+
}
|
|
3323
3356
|
return {
|
|
3324
3357
|
errors,
|
|
3325
3358
|
invalidStyles
|
|
@@ -3381,162 +3414,141 @@ import { toolPrompts } from "@elementor/editor-mcp";
|
|
|
3381
3414
|
var generatePrompt = () => {
|
|
3382
3415
|
const buildCompositionsToolPrompt = toolPrompts("build-compositions");
|
|
3383
3416
|
buildCompositionsToolPrompt.description(`
|
|
3384
|
-
#
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
4. Build valid XML with minimal inline styles (layout/positioning only)
|
|
3398
|
-
5. Avoid duplicating styles that should be global classes
|
|
3399
|
-
|
|
3400
|
-
## Phase 3: Apply Classes
|
|
3401
|
-
6. Use "apply-global-class" tool to apply global classes to elements
|
|
3402
|
-
|
|
3403
|
-
# CORE INSTRUCTIONS
|
|
3404
|
-
|
|
3405
|
-
**Structure:**
|
|
3406
|
-
- Build valid XML using allowed widget tags (e.g., \`<e-button configuration-id="btn1"></e-button>\`)
|
|
3407
|
-
- Containers only: "e-flexbox", "e-div-block", "e-tabs"
|
|
3408
|
-
- Every element MUST have unique "configuration-id" attribute
|
|
3417
|
+
# RESOURCES (Read before use)
|
|
3418
|
+
- [elementor://global-classes] - Check FIRST for reusable classes
|
|
3419
|
+
- [elementor://global-variables] - ONLY use variables defined here
|
|
3420
|
+
|
|
3421
|
+
# WORKFLOW
|
|
3422
|
+
1. Check/create global classes via "create-global-class" tool
|
|
3423
|
+
2. Build composition (THIS TOOL) - minimal inline styles
|
|
3424
|
+
3. Apply classes via "apply-global-class" tool
|
|
3425
|
+
|
|
3426
|
+
# XML STRUCTURE
|
|
3427
|
+
- Use widget tags: \`<e-button configuration-id="btn1"></e-button>\`
|
|
3428
|
+
- Containers: "e-flexbox", "e-div-block", "e-tabs"
|
|
3429
|
+
- Every element needs unique "configuration-id"
|
|
3409
3430
|
- No attributes, classes, IDs, or text nodes in XML
|
|
3410
3431
|
|
|
3411
|
-
|
|
3412
|
-
- Map
|
|
3413
|
-
-
|
|
3414
|
-
-
|
|
3415
|
-
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
**
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
-
|
|
3460
|
-
-
|
|
3461
|
-
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
-
|
|
3466
|
-
-
|
|
3467
|
-
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
-
|
|
3475
|
-
-
|
|
3476
|
-
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3432
|
+
# CONFIGURATION
|
|
3433
|
+
- Map configuration-id \u2192 elementConfig (props) + stylesConfig (layout only)
|
|
3434
|
+
- All PropValues require \`$$type\` matching schema
|
|
3435
|
+
- NO LINKS in configuration
|
|
3436
|
+
- Retry on errors up to 10x
|
|
3437
|
+
|
|
3438
|
+
Note about configuration ids: These names are visible to the end-user, make sure they make sense, related and relevant.
|
|
3439
|
+
|
|
3440
|
+
# DESIGN PHILOSOPHY: CONTEXT-DRIVEN CREATIVITY
|
|
3441
|
+
|
|
3442
|
+
**Use the user's context aggressively.** Business type, brand personality, target audience, and purpose should drive every design decision. A law firm needs gravitas; a children's app needs playfulness. Don't default to generic.
|
|
3443
|
+
|
|
3444
|
+
## SIZING: DEFAULT IS NO SIZE (CRITICAL)
|
|
3445
|
+
|
|
3446
|
+
**DO NOT specify height or width unless you have a specific visual reason.**
|
|
3447
|
+
|
|
3448
|
+
Flexbox and CSS already handle sizing automatically:
|
|
3449
|
+
- Containers grow to fit their content
|
|
3450
|
+
- Flex children distribute space via flex properties, not width/height
|
|
3451
|
+
- Text elements size to their content
|
|
3452
|
+
|
|
3453
|
+
WHEN TO SPECIFY SIZE:
|
|
3454
|
+
- min-height on ROOT section for viewport-spanning hero (use min-height, NOT height)
|
|
3455
|
+
- max-width for contained content areas (e.g., max-width: 60rem)
|
|
3456
|
+
- Explicit aspect ratios for media containers
|
|
3457
|
+
|
|
3458
|
+
NEVER SPECIFY:
|
|
3459
|
+
- height on nested containers (causes overflow)
|
|
3460
|
+
- width on flex children (use flex-basis or gap instead)
|
|
3461
|
+
- 100vh on anything except root-level sections
|
|
3462
|
+
- Any size "just to be safe" - if unsure, OMIT IT
|
|
3463
|
+
|
|
3464
|
+
vh units are VIEWPORT-relative. Nested 100vh inside 100vh = 200vh overflow.
|
|
3465
|
+
|
|
3466
|
+
GOOD: \`<e-flexbox>content naturally sizes</e-flexbox>\`
|
|
3467
|
+
BAD: \`<e-flexbox style="height:100vh"><e-div-block style="height:100vh">overflow</e-div-block></e-flexbox>\`
|
|
3468
|
+
|
|
3469
|
+
## Layout Variety (Break the Template)
|
|
3470
|
+
- AVOID: Full-width 100vh hero \u2192 three columns \u2192 testimonials \u2192 CTA (every AI does this)
|
|
3471
|
+
- VARY heights: Use auto-height sections with generous padding (6rem+). Let content breathe
|
|
3472
|
+
- VARY widths: Not everything spans full width. Use contained sections (max-width: 960px) mixed with edge-to-edge
|
|
3473
|
+
- ASYMMETRIC grids: 2:1, 1:3, offset layouts. Avoid equal column widths
|
|
3474
|
+
- Negative space as design element: Large margins create focus and sophistication
|
|
3475
|
+
- Break alignment intentionally: Offset headings, overlapping elements, broken grids
|
|
3476
|
+
|
|
3477
|
+
## Visual Depth & Effects
|
|
3478
|
+
- Layer elements: Overlapping cards, text over images, floating elements
|
|
3479
|
+
- Subtle shadows with color tint (not pure black): \`box-shadow: 0 20px 60px rgba(<brand-color-here>, 0.15)\`
|
|
3480
|
+
- Gradient overlays on images for text readability
|
|
3481
|
+
- Border radius variation: Mix sharp (0) and soft (1rem+) corners purposefully
|
|
3482
|
+
- Backdrop blur for glassmorphism where appropriate
|
|
3483
|
+
- Micro-interactions via CSS: hover transforms, transitions (0.3s ease)
|
|
3484
|
+
|
|
3485
|
+
## Typography with Character
|
|
3486
|
+
- Display fonts for headlines (from user's brand or contextually appropriate)
|
|
3487
|
+
- Size contrast: 4rem+ headlines vs 1rem body. Make hierarchy unmistakable
|
|
3488
|
+
- Letter-spacing: Tight for large headlines (-0.02em), loose for small caps (0.1em)
|
|
3489
|
+
- Line-height: Tight for headlines (1.1), generous for body (1.6-1.8)
|
|
3490
|
+
- Text decoration: Underlines, highlights, gradient text for emphasis
|
|
3491
|
+
|
|
3492
|
+
## Color with Purpose
|
|
3493
|
+
- Extract palette from user context (brand colors, industry norms, mood)
|
|
3494
|
+
- 60-30-10 rule: dominant, secondary, accent
|
|
3495
|
+
- Tinted neutrals over pure grays: warm (#faf8f5, #2d2a26) or cool (#f5f7fa, #1e2430)
|
|
3496
|
+
- Color blocking: Large colored sections create visual rhythm
|
|
3497
|
+
- Gradient directions: Diagonal (135deg, 225deg) feel more dynamic than vertical
|
|
3498
|
+
|
|
3499
|
+
## Spacing Strategy
|
|
3500
|
+
- Section padding: 6rem-10rem vertical, creating breathing room
|
|
3501
|
+
- Rhythm variation: Tight groups (2rem) with generous gaps between (6rem)
|
|
3502
|
+
- Use rem/em exclusively for responsive scaling
|
|
3503
|
+
- Generous padding on CTAs: min 1rem 2.5rem
|
|
3504
|
+
|
|
3505
|
+
# HARD CONSTRAINTS
|
|
3506
|
+
- Variables ONLY from [elementor://global-variables] (others throw errors)
|
|
3507
|
+
- Avoid SVG widgets unless assets are pre-uploaded
|
|
3508
|
+
- Check \`llm_guidance\` in widget schemas
|
|
3509
|
+
|
|
3510
|
+
# PARAMETERS
|
|
3479
3511
|
- **xmlStructure**: Valid XML with configuration-id attributes
|
|
3480
|
-
- **elementConfig**:
|
|
3481
|
-
- **stylesConfig**:
|
|
3512
|
+
- **elementConfig**: configuration-id \u2192 widget PropValues
|
|
3513
|
+
- **stylesConfig**: configuration-id \u2192 style PropValues (layout only)
|
|
3514
|
+
- **customCSS**: configuration-id \u2192 CSS rules (no selectors, semicolon-separated)
|
|
3482
3515
|
`);
|
|
3483
3516
|
buildCompositionsToolPrompt.example(`
|
|
3484
|
-
|
|
3517
|
+
Section with heading + button (NO explicit heights - content sizes naturally):
|
|
3485
3518
|
{
|
|
3486
|
-
xmlStructure: "<e-flexbox configuration-id="
|
|
3519
|
+
xmlStructure: "<e-flexbox configuration-id="Main Section"><e-heading configuration-id="Section Title"></e-heading><e-button configuration-id="Call to Action"></e-button></e-flexbox>",
|
|
3487
3520
|
elementConfig: {
|
|
3488
|
-
"
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3492
|
-
},
|
|
3521
|
+
"section1": { "tag": { "$$type": "string", "value": "section" } }
|
|
3522
|
+
},
|
|
3523
|
+
customCSS: {
|
|
3524
|
+
"Section Title": "padding: 6rem 4rem; background: linear-gradient(135deg, #faf8f5 0%, #f0ebe4 100%);"
|
|
3493
3525
|
},
|
|
3494
3526
|
stylesConfig: {
|
|
3495
|
-
"
|
|
3496
|
-
"font-size": {
|
|
3497
|
-
|
|
3498
|
-
"value": {
|
|
3499
|
-
"size": { "$$type": "number", "value": 24 },
|
|
3500
|
-
"unit": { "$$type": "string", "value": "px" }
|
|
3501
|
-
}
|
|
3502
|
-
},
|
|
3503
|
-
"color": {
|
|
3504
|
-
"$$type": "color",
|
|
3505
|
-
"value": { "$$type": "string", "value": "#333" }
|
|
3506
|
-
}
|
|
3527
|
+
"Section Title": {
|
|
3528
|
+
"font-size": { "$$type": "size", "value": { "size": { "$$type": "number", "value": 3.5 }, "unit": { "$$type": "string", "value": "rem" } } },
|
|
3529
|
+
"color": { "$$type": "color", "value": { "$$type": "string", "value": "#2d2a26" } }
|
|
3507
3530
|
}
|
|
3508
|
-
}
|
|
3531
|
+
}
|
|
3509
3532
|
}
|
|
3533
|
+
Note: No height/width specified on any element - flexbox handles layout automatically.
|
|
3510
3534
|
`);
|
|
3511
3535
|
buildCompositionsToolPrompt.parameter(
|
|
3512
3536
|
"xmlStructure",
|
|
3513
|
-
|
|
3514
|
-
);
|
|
3515
|
-
buildCompositionsToolPrompt.parameter(
|
|
3516
|
-
"elementConfig",
|
|
3517
|
-
`**MANDATORY** A record mapping configuration IDs to their corresponding configuration objects, defining the PropValues for each element created.`
|
|
3537
|
+
`Valid XML structure with custom elementor tags and configuration-id attributes.`
|
|
3518
3538
|
);
|
|
3539
|
+
buildCompositionsToolPrompt.parameter("elementConfig", `Record mapping configuration IDs to widget PropValues.`);
|
|
3519
3540
|
buildCompositionsToolPrompt.parameter(
|
|
3520
3541
|
"stylesConfig",
|
|
3521
|
-
|
|
3522
|
-
);
|
|
3523
|
-
buildCompositionsToolPrompt.instruction(
|
|
3524
|
-
`You will be provided the XML structure with element IDs. These IDs represent the actual elementor widgets created on the page/post.
|
|
3525
|
-
You should use these IDs as reference for further configuration, styling or changing elements later on.`
|
|
3542
|
+
`Record mapping configuration IDs to style PropValues (layout/positioning only).`
|
|
3526
3543
|
);
|
|
3527
3544
|
buildCompositionsToolPrompt.instruction(
|
|
3528
|
-
|
|
3529
|
-
1. FIRST: Create reusable global classes for typography, colors, spacing patterns using "create-global-class" tool
|
|
3530
|
-
2. SECOND: Use THIS tool with minimal inline styles (only layout & unique properties)
|
|
3531
|
-
3. THIRD: Apply global classes to elements using "apply-global-class" tool
|
|
3532
|
-
|
|
3533
|
-
This ensures maximum reusability and consistency across your design system. ALWAYS check [elementor://global-classes] for existing classes before creating new ones.`
|
|
3545
|
+
`Element IDs in the returned XML represent actual widgets. Use these IDs for subsequent styling or configuration changes.`
|
|
3534
3546
|
);
|
|
3535
3547
|
return buildCompositionsToolPrompt.prompt();
|
|
3536
3548
|
};
|
|
3537
3549
|
|
|
3538
3550
|
// src/mcp/tools/build-composition/schema.ts
|
|
3539
|
-
import { z } from "@elementor/
|
|
3551
|
+
import { zod as z } from "@elementor/editor-mcp";
|
|
3540
3552
|
var inputSchema = {
|
|
3541
3553
|
xmlStructure: z.string().describe("The XML structure representing the composition to be built"),
|
|
3542
3554
|
elementConfig: z.record(
|
|
@@ -3554,7 +3566,11 @@ var inputSchema = {
|
|
|
3554
3566
|
)
|
|
3555
3567
|
).describe(
|
|
3556
3568
|
`A record mapping element IDs to their styles configuration objects. Use the actual styles schema from [${STYLE_SCHEMA_URI}].`
|
|
3557
|
-
).default({})
|
|
3569
|
+
).default({}),
|
|
3570
|
+
customCSS: z.record(
|
|
3571
|
+
z.string().describe("The configuration id"),
|
|
3572
|
+
z.string().describe("The custom CSS for the element. MANDATORY")
|
|
3573
|
+
).describe("A record mapping element IDs to their custom CSS.").default({})
|
|
3558
3574
|
};
|
|
3559
3575
|
var outputSchema = {
|
|
3560
3576
|
errors: z.string().describe("Error message if the composition building failed").optional(),
|
|
@@ -3583,7 +3599,7 @@ var initBuildCompositionsTool = (reg) => {
|
|
|
3583
3599
|
hints: [{ name: "claude-sonnet-4-5" }]
|
|
3584
3600
|
},
|
|
3585
3601
|
handler: async (params) => {
|
|
3586
|
-
const { xmlStructure, elementConfig, stylesConfig } = params;
|
|
3602
|
+
const { xmlStructure, elementConfig, stylesConfig, customCSS } = params;
|
|
3587
3603
|
let generatedXML = "";
|
|
3588
3604
|
const errors = [];
|
|
3589
3605
|
const rootContainers = [];
|
|
@@ -3595,17 +3611,18 @@ var initBuildCompositionsTool = (reg) => {
|
|
|
3595
3611
|
});
|
|
3596
3612
|
compositionBuilder.setElementConfig(elementConfig);
|
|
3597
3613
|
compositionBuilder.setStylesConfig(stylesConfig);
|
|
3614
|
+
compositionBuilder.setCustomCSS(customCSS);
|
|
3598
3615
|
const {
|
|
3599
3616
|
configErrors,
|
|
3600
3617
|
invalidStyles,
|
|
3601
3618
|
rootContainers: generatedRootContainers
|
|
3602
3619
|
} = compositionBuilder.build(documentContainer);
|
|
3620
|
+
rootContainers.push(...generatedRootContainers);
|
|
3603
3621
|
generatedXML = new XMLSerializer().serializeToString(compositionBuilder.getXML());
|
|
3604
3622
|
if (configErrors.length) {
|
|
3605
3623
|
errors.push(...configErrors.map((e) => new Error(e)));
|
|
3606
3624
|
throw new Error("Configuration errors occurred during composition building.");
|
|
3607
3625
|
}
|
|
3608
|
-
rootContainers.push(...generatedRootContainers);
|
|
3609
3626
|
Object.entries(invalidStyles).forEach(([elementId, rawCssRules]) => {
|
|
3610
3627
|
const customCss = {
|
|
3611
3628
|
value: rawCssRules.join(";\n")
|
|
@@ -3654,10 +3671,7 @@ var initBuildCompositionsTool = (reg) => {
|
|
|
3654
3671
|
|
|
3655
3672
|
${errorMessages.join(
|
|
3656
3673
|
"\n\n"
|
|
3657
|
-
)}
|
|
3658
|
-
|
|
3659
|
-
"Missing $$type" errors indicate that the configuration objects are invalid. Try again and apply **ALL** object entries with correct $$type.
|
|
3660
|
-
Now that you have these errors, fix them and try again. Errors regarding configuration objects, please check against the PropType schemas`;
|
|
3674
|
+
)}`;
|
|
3661
3675
|
throw new Error(errorText);
|
|
3662
3676
|
}
|
|
3663
3677
|
return {
|
|
@@ -3986,7 +4000,14 @@ var initGetElementConfigTool = (reg) => {
|
|
|
3986
4000
|
var initCanvasMcp = (reg) => {
|
|
3987
4001
|
const { setMCPDescription } = reg;
|
|
3988
4002
|
setMCPDescription(
|
|
3989
|
-
|
|
4003
|
+
`Everything related to creative design, layout, styling and building the pages, specifically element of type "widget".
|
|
4004
|
+
# Canvas workflow for new compositions
|
|
4005
|
+
- Check existing global variables
|
|
4006
|
+
- Check existing global classes
|
|
4007
|
+
- Create missing global variables
|
|
4008
|
+
- Create reusable global classes
|
|
4009
|
+
- Build valid XML with minimal inline styles (layout/positioning only)
|
|
4010
|
+
- Apply global classes to elements`
|
|
3990
4011
|
);
|
|
3991
4012
|
initWidgetsSchemaResource(reg);
|
|
3992
4013
|
initDocumentStructureResource(reg);
|
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.0.0-
|
|
4
|
+
"version": "4.0.0-manual",
|
|
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": "4.0.0-
|
|
41
|
-
"@elementor/editor-controls": "4.0.0-
|
|
42
|
-
"@elementor/editor-documents": "4.0.0-
|
|
43
|
-
"@elementor/editor-elements": "4.0.0-
|
|
44
|
-
"@elementor/editor-interactions": "4.0.0-
|
|
45
|
-
"@elementor/editor-mcp": "4.0.0-
|
|
46
|
-
"@elementor/editor-notifications": "4.0.0-
|
|
47
|
-
"@elementor/editor-props": "4.0.0-
|
|
48
|
-
"@elementor/editor-responsive": "4.0.0-
|
|
49
|
-
"@elementor/editor-styles": "4.0.0-
|
|
50
|
-
"@elementor/editor-styles-repository": "4.0.0-
|
|
51
|
-
"@elementor/editor-ui": "4.0.0-
|
|
52
|
-
"@elementor/editor-v1-adapters": "4.0.0-
|
|
53
|
-
"@elementor/schema": "4.0.0-
|
|
54
|
-
"@elementor/twing": "4.0.0-
|
|
40
|
+
"@elementor/editor": "4.0.0-manual",
|
|
41
|
+
"@elementor/editor-controls": "4.0.0-manual",
|
|
42
|
+
"@elementor/editor-documents": "4.0.0-manual",
|
|
43
|
+
"@elementor/editor-elements": "4.0.0-manual",
|
|
44
|
+
"@elementor/editor-interactions": "4.0.0-manual",
|
|
45
|
+
"@elementor/editor-mcp": "4.0.0-manual",
|
|
46
|
+
"@elementor/editor-notifications": "4.0.0-manual",
|
|
47
|
+
"@elementor/editor-props": "4.0.0-manual",
|
|
48
|
+
"@elementor/editor-responsive": "4.0.0-manual",
|
|
49
|
+
"@elementor/editor-styles": "4.0.0-manual",
|
|
50
|
+
"@elementor/editor-styles-repository": "4.0.0-manual",
|
|
51
|
+
"@elementor/editor-ui": "4.0.0-manual",
|
|
52
|
+
"@elementor/editor-v1-adapters": "4.0.0-manual",
|
|
53
|
+
"@elementor/schema": "4.0.0-manual",
|
|
54
|
+
"@elementor/twing": "4.0.0-manual",
|
|
55
55
|
"@elementor/ui": "1.36.17",
|
|
56
|
-
"@elementor/utils": "4.0.0-
|
|
57
|
-
"@elementor/wp-media": "4.0.0-
|
|
56
|
+
"@elementor/utils": "4.0.0-manual",
|
|
57
|
+
"@elementor/wp-media": "4.0.0-manual",
|
|
58
58
|
"@floating-ui/react": "^0.27.5",
|
|
59
59
|
"@wordpress/i18n": "^5.13.0"
|
|
60
60
|
},
|
|
@@ -26,11 +26,13 @@ type CtorOptions = {
|
|
|
26
26
|
api?: Partial< API >;
|
|
27
27
|
elementConfig?: AnyConfig;
|
|
28
28
|
stylesConfig?: AnyConfig;
|
|
29
|
+
customCSS?: Record< string, string >;
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
export class CompositionBuilder {
|
|
32
33
|
private elementConfig: Record< string, Record< string, AnyValue > > = {};
|
|
33
34
|
private elementStylesConfig: Record< string, Record< string, AnyValue > > = {};
|
|
35
|
+
private elementCusomCSS: Record< string, string > = {};
|
|
34
36
|
private rootContainers: V1Element[] = [];
|
|
35
37
|
private containerElements: string[] = [];
|
|
36
38
|
private api: API = {
|
|
@@ -56,11 +58,12 @@ export class CompositionBuilder {
|
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
constructor( opts: CtorOptions ) {
|
|
59
|
-
const { api = {}, elementConfig = {}, stylesConfig = {}, xml } = opts;
|
|
61
|
+
const { api = {}, elementConfig = {}, stylesConfig = {}, customCSS = {}, xml } = opts;
|
|
60
62
|
this.xml = xml;
|
|
61
63
|
Object.assign( this.api, api );
|
|
62
64
|
this.setElementConfig( elementConfig );
|
|
63
65
|
this.setStylesConfig( stylesConfig );
|
|
66
|
+
this.setCustomCSS( customCSS );
|
|
64
67
|
}
|
|
65
68
|
|
|
66
69
|
setElementConfig( config: Record< string, Record< string, AnyValue > > ) {
|
|
@@ -71,6 +74,10 @@ export class CompositionBuilder {
|
|
|
71
74
|
this.elementStylesConfig = config;
|
|
72
75
|
}
|
|
73
76
|
|
|
77
|
+
setCustomCSS( config: Record< string, string > ) {
|
|
78
|
+
this.elementCusomCSS = config;
|
|
79
|
+
}
|
|
80
|
+
|
|
74
81
|
getXML() {
|
|
75
82
|
return this.xml;
|
|
76
83
|
}
|
|
@@ -92,6 +99,9 @@ export class CompositionBuilder {
|
|
|
92
99
|
model: {
|
|
93
100
|
elType: elementTag,
|
|
94
101
|
id: generateElementId(),
|
|
102
|
+
editor_settings: {
|
|
103
|
+
title: node.getAttribute( 'configuration-id' ) ?? undefined,
|
|
104
|
+
},
|
|
95
105
|
},
|
|
96
106
|
options: { useHistory: false },
|
|
97
107
|
} )
|
|
@@ -101,6 +111,9 @@ export class CompositionBuilder {
|
|
|
101
111
|
elType: 'widget',
|
|
102
112
|
widgetType: elementTag,
|
|
103
113
|
id: generateElementId(),
|
|
114
|
+
editor_settings: {
|
|
115
|
+
title: node.getAttribute( 'configuration-id' ) ?? undefined,
|
|
116
|
+
},
|
|
104
117
|
},
|
|
105
118
|
options: { useHistory: false },
|
|
106
119
|
} );
|
|
@@ -144,9 +157,9 @@ export class CompositionBuilder {
|
|
|
144
157
|
applyStyles() {
|
|
145
158
|
const errors: string[] = [];
|
|
146
159
|
const invalidStyles: Record< string, string[] > = {};
|
|
147
|
-
const validStylesPropValues: Record< string, AnyValue > = {};
|
|
148
160
|
for ( const [ styleId, styleConfig ] of Object.entries( this.elementStylesConfig ) ) {
|
|
149
161
|
const { element, node } = this.matchNodeByConfigId( styleId );
|
|
162
|
+
const validStylesPropValues: Record< string, AnyValue > = {};
|
|
150
163
|
for ( const [ styleName, stylePropValue ] of Object.entries( styleConfig ) ) {
|
|
151
164
|
const { valid, errors: validationErrors } = validateInput.validateStyles( {
|
|
152
165
|
[ styleName ]: stylePropValue,
|
|
@@ -160,14 +173,30 @@ export class CompositionBuilder {
|
|
|
160
173
|
} else {
|
|
161
174
|
validStylesPropValues[ styleName ] = stylePropValue;
|
|
162
175
|
}
|
|
176
|
+
}
|
|
177
|
+
if ( Object.keys( validStylesPropValues ).length === 0 ) {
|
|
178
|
+
continue;
|
|
179
|
+
}
|
|
180
|
+
try {
|
|
163
181
|
this.api.doUpdateElementProperty( {
|
|
164
182
|
elementId: element.id,
|
|
165
183
|
propertyName: '_styles',
|
|
166
184
|
propertyValue: validStylesPropValues,
|
|
167
185
|
elementType: node.tagName,
|
|
168
186
|
} );
|
|
187
|
+
} catch ( error ) {
|
|
188
|
+
errors.push( String( error ) );
|
|
169
189
|
}
|
|
170
190
|
}
|
|
191
|
+
for ( const [ customCSSId, customCSS ] of Object.entries( this.elementCusomCSS ) ) {
|
|
192
|
+
const { element, node } = this.matchNodeByConfigId( customCSSId );
|
|
193
|
+
this.api.doUpdateElementProperty( {
|
|
194
|
+
elementId: element.id,
|
|
195
|
+
propertyName: '_styles',
|
|
196
|
+
propertyValue: { custom_css: customCSS },
|
|
197
|
+
elementType: node.tagName,
|
|
198
|
+
} );
|
|
199
|
+
}
|
|
171
200
|
return {
|
|
172
201
|
errors,
|
|
173
202
|
invalidStyles,
|
package/src/mcp/canvas-mcp.ts
CHANGED
|
@@ -10,7 +10,14 @@ import { initGetElementConfigTool } from './tools/get-element-config/tool';
|
|
|
10
10
|
export const initCanvasMcp = ( reg: MCPRegistryEntry ) => {
|
|
11
11
|
const { setMCPDescription } = reg;
|
|
12
12
|
setMCPDescription(
|
|
13
|
-
|
|
13
|
+
`Everything related to creative design, layout, styling and building the pages, specifically element of type "widget".
|
|
14
|
+
# Canvas workflow for new compositions
|
|
15
|
+
- Check existing global variables
|
|
16
|
+
- Check existing global classes
|
|
17
|
+
- Create missing global variables
|
|
18
|
+
- Create reusable global classes
|
|
19
|
+
- Build valid XML with minimal inline styles (layout/positioning only)
|
|
20
|
+
- Apply global classes to elements`
|
|
14
21
|
);
|
|
15
22
|
initWidgetsSchemaResource( reg );
|
|
16
23
|
initDocumentStructureResource( reg );
|