@elementor/editor-variables 4.3.0-976 → 4.3.0-978
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 +34 -176
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +31 -173
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -15
- package/src/mcp/manage-variable-tool.ts +21 -94
- package/src/mcp/variable-tool-prompt.ts +0 -84
- package/src/mcp/variables-resource.ts +13 -22
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elementor/editor-variables",
|
|
3
|
-
"version": "4.3.0-
|
|
3
|
+
"version": "4.3.0-978",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "Elementor Team",
|
|
6
6
|
"homepage": "https://elementor.com/",
|
|
@@ -39,22 +39,22 @@
|
|
|
39
39
|
"dev": "tsup --config=../../tsup.dev.ts"
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@elementor/editor": "4.3.0-
|
|
43
|
-
"@elementor/editor-canvas": "4.3.0-
|
|
44
|
-
"@elementor/editor-controls": "4.3.0-
|
|
45
|
-
"@elementor/editor-current-user": "4.3.0-
|
|
46
|
-
"@elementor/editor-mcp": "4.3.0-
|
|
47
|
-
"@elementor/editor-panels": "4.3.0-
|
|
48
|
-
"@elementor/editor-props": "4.3.0-
|
|
49
|
-
"@elementor/editor-ui": "4.3.0-
|
|
50
|
-
"@elementor/editor-v1-adapters": "4.3.0-
|
|
51
|
-
"@elementor/menus": "4.3.0-
|
|
52
|
-
"@elementor/http-client": "4.3.0-
|
|
42
|
+
"@elementor/editor": "4.3.0-978",
|
|
43
|
+
"@elementor/editor-canvas": "4.3.0-978",
|
|
44
|
+
"@elementor/editor-controls": "4.3.0-978",
|
|
45
|
+
"@elementor/editor-current-user": "4.3.0-978",
|
|
46
|
+
"@elementor/editor-mcp": "4.3.0-978",
|
|
47
|
+
"@elementor/editor-panels": "4.3.0-978",
|
|
48
|
+
"@elementor/editor-props": "4.3.0-978",
|
|
49
|
+
"@elementor/editor-ui": "4.3.0-978",
|
|
50
|
+
"@elementor/editor-v1-adapters": "4.3.0-978",
|
|
51
|
+
"@elementor/menus": "4.3.0-978",
|
|
52
|
+
"@elementor/http-client": "4.3.0-978",
|
|
53
53
|
"@elementor/icons": "~1.75.1",
|
|
54
|
-
"@elementor/events": "4.3.0-
|
|
55
|
-
"@elementor/schema": "4.3.0-
|
|
54
|
+
"@elementor/events": "4.3.0-978",
|
|
55
|
+
"@elementor/schema": "4.3.0-978",
|
|
56
56
|
"@elementor/ui": "1.37.5",
|
|
57
|
-
"@elementor/utils": "4.3.0-
|
|
57
|
+
"@elementor/utils": "4.3.0-978",
|
|
58
58
|
"@wordpress/i18n": "^5.13.0"
|
|
59
59
|
},
|
|
60
60
|
"peerDependencies": {
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { type MCPRegistryEntry } from '@elementor/editor-mcp';
|
|
2
|
+
import { type HttpResponse, httpService } from '@elementor/http-client';
|
|
2
3
|
import { z } from '@elementor/schema';
|
|
3
4
|
import { isProActive } from '@elementor/utils';
|
|
4
5
|
|
|
5
|
-
import {
|
|
6
|
-
import { getFontConfigs } from '../sync/get-font-configs';
|
|
7
|
-
import { validateLabel } from '../utils/validations';
|
|
8
|
-
import { generateVariablesPrompt, MANAGE_VARIABLES_GUIDE_URI } from './variable-tool-prompt';
|
|
6
|
+
import { MANAGE_VARIABLES_GUIDE_URI } from './variable-tool-prompt';
|
|
9
7
|
import { GLOBAL_VARIABLES_URI } from './variables-resource';
|
|
10
8
|
|
|
9
|
+
const MCP_PROXY_URL = 'elementor/v1/mcp-proxy';
|
|
10
|
+
const TOOL_NAME = 'manage-global-variable';
|
|
11
|
+
|
|
11
12
|
const VARIABLE_TYPES = {
|
|
12
13
|
COLOR: 'global-color-variable',
|
|
13
14
|
FONT: 'global-font-variable',
|
|
@@ -15,36 +16,6 @@ const VARIABLE_TYPES = {
|
|
|
15
16
|
CUSTOM_SIZE: 'global-custom-size-variable',
|
|
16
17
|
} as const;
|
|
17
18
|
|
|
18
|
-
const LENGTH_UNIT_PATTERN = /^(auto|\d+(\.\d+)?(px|rem|em|vh|vw|%|ch|s|ms))$/i;
|
|
19
|
-
const COLOR_PATTERN = /^(#[0-9a-f]{3,8}|rgba?\(|hsl)/i;
|
|
20
|
-
|
|
21
|
-
function validateValueForType( type: string, value: string ): string | null {
|
|
22
|
-
if ( type === VARIABLE_TYPES.FONT && LENGTH_UNIT_PATTERN.test( value.trim() ) ) {
|
|
23
|
-
return `Font variable value must be a font family name (e.g. "Roboto"), not a size value like "${ value }". Use "global-size-variable" or "global-custom-size-variable" for spacing/size values.`;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
if ( type === VARIABLE_TYPES.COLOR && ! COLOR_PATTERN.test( value.trim() ) ) {
|
|
27
|
-
return `Color variable value should be a CSS color (e.g. "#FF0000"), got "${ value }".`;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if ( type === VARIABLE_TYPES.SIZE && ! LENGTH_UNIT_PATTERN.test( value.trim() ) ) {
|
|
31
|
-
return `Size variable value should include a CSS unit (e.g. "16px") or be "auto", got "${ value }".`;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if ( type === VARIABLE_TYPES.FONT && ! isFontAvailable( value ) ) {
|
|
35
|
-
return `Font "${ value }" is not supported in WordPress. Please choose one of the available font families.`;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
return null;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function isFontAvailable( font: string ) {
|
|
42
|
-
const fonts = getFontConfigs();
|
|
43
|
-
const key = font.trim();
|
|
44
|
-
|
|
45
|
-
return !! fonts?.[ key ];
|
|
46
|
-
}
|
|
47
|
-
|
|
48
19
|
export const initManageVariableTool = ( reg: MCPRegistryEntry ) => {
|
|
49
20
|
const { addTool, resource } = reg;
|
|
50
21
|
const RUNTIME_ALLOWED_VARIABLE_TYPES = isProActive()
|
|
@@ -59,13 +30,19 @@ export const initManageVariableTool = ( reg: MCPRegistryEntry ) => {
|
|
|
59
30
|
description: 'Detailed guide for using the manage-global-variable tool',
|
|
60
31
|
mimeType: 'text/plain',
|
|
61
32
|
},
|
|
62
|
-
async ( uri: URL ) =>
|
|
63
|
-
|
|
64
|
-
|
|
33
|
+
async ( uri: URL ) => {
|
|
34
|
+
const { data } = await httpService().get< HttpResponse< string > >( MCP_PROXY_URL, {
|
|
35
|
+
params: { uri: uri.href },
|
|
36
|
+
} );
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
contents: [ { uri: uri.href, mimeType: 'text/plain', text: data.data } ],
|
|
40
|
+
};
|
|
41
|
+
}
|
|
65
42
|
);
|
|
66
43
|
|
|
67
44
|
addTool( {
|
|
68
|
-
name:
|
|
45
|
+
name: TOOL_NAME,
|
|
69
46
|
description:
|
|
70
47
|
'Manage V4 global variables (color, font, size, custom-size). Read the guide resource before use. font = font-famliy, size = measured unit, custom-size = calculated values',
|
|
71
48
|
schema: {
|
|
@@ -96,62 +73,12 @@ export const initManageVariableTool = ( reg: MCPRegistryEntry ) => {
|
|
|
96
73
|
],
|
|
97
74
|
isDestructive: true,
|
|
98
75
|
handler: async ( params ) => {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
throw new Error( `Unknown action ${ params.action }` );
|
|
76
|
+
await httpService().post( MCP_PROXY_URL, {
|
|
77
|
+
tool: TOOL_NAME,
|
|
78
|
+
input: params,
|
|
79
|
+
} );
|
|
80
|
+
|
|
81
|
+
return { status: 'ok' };
|
|
106
82
|
},
|
|
107
83
|
} );
|
|
108
84
|
};
|
|
109
|
-
|
|
110
|
-
type Opts< T extends Record< string, string > > = Partial< T > & {
|
|
111
|
-
[ k: string ]: unknown;
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
function getServiceActions( svc: typeof service ) {
|
|
115
|
-
return {
|
|
116
|
-
create( { type, label, value }: Opts< { type: string; label: string; value: string } > ) {
|
|
117
|
-
if ( ! type || ! label || ! value ) {
|
|
118
|
-
throw new Error( 'Create requires type, label, and value' );
|
|
119
|
-
}
|
|
120
|
-
if ( ( type === VARIABLE_TYPES.SIZE || type === VARIABLE_TYPES.CUSTOM_SIZE ) && ! isProActive() ) {
|
|
121
|
-
throw new Error( 'Creating size variables requires Elementor Pro.' );
|
|
122
|
-
}
|
|
123
|
-
const labelError = validateLabel( label );
|
|
124
|
-
if ( labelError ) {
|
|
125
|
-
throw new Error( labelError );
|
|
126
|
-
}
|
|
127
|
-
const valueError = validateValueForType( type, value );
|
|
128
|
-
if ( valueError ) {
|
|
129
|
-
throw new Error( valueError );
|
|
130
|
-
}
|
|
131
|
-
return svc.create( { type, label, value }, { eventData: { executedBy: 'mcp_tool' } } );
|
|
132
|
-
},
|
|
133
|
-
update( { id, label, value }: Opts< { id: string; label: string; value: string } > ) {
|
|
134
|
-
if ( ! id || ! label || ! value ) {
|
|
135
|
-
throw new Error( 'Update requires id, label, and value' );
|
|
136
|
-
}
|
|
137
|
-
const labelError = validateLabel( label );
|
|
138
|
-
if ( labelError ) {
|
|
139
|
-
throw new Error( labelError );
|
|
140
|
-
}
|
|
141
|
-
const existingVariable = svc.variables()[ id ];
|
|
142
|
-
if ( existingVariable ) {
|
|
143
|
-
const valueError = validateValueForType( existingVariable.type, value );
|
|
144
|
-
if ( valueError ) {
|
|
145
|
-
throw new Error( valueError );
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
return svc.update( id, { label, value }, { eventData: { executedBy: 'mcp_tool' } } );
|
|
149
|
-
},
|
|
150
|
-
delete( { id }: Opts< { id: string } > ) {
|
|
151
|
-
if ( ! id ) {
|
|
152
|
-
throw new Error( 'delete requires id' );
|
|
153
|
-
}
|
|
154
|
-
return svc.delete( id );
|
|
155
|
-
},
|
|
156
|
-
};
|
|
157
|
-
}
|
|
@@ -1,85 +1 @@
|
|
|
1
|
-
import { toolPrompts } from '@elementor/editor-mcp';
|
|
2
|
-
import { isProActive } from '@elementor/utils';
|
|
3
|
-
|
|
4
1
|
export const MANAGE_VARIABLES_GUIDE_URI = 'elementor://variables/tools/manage-global-variable-guide';
|
|
5
|
-
|
|
6
|
-
export const generateVariablesPrompt = () => {
|
|
7
|
-
const prompt = toolPrompts( 'manage-global-variable' );
|
|
8
|
-
const proIsActive = isProActive();
|
|
9
|
-
|
|
10
|
-
const sizeVariableSection = proIsActive
|
|
11
|
-
? `- **global-size-variable** — A simple CSS length with a unit (Elementor Pro). Use this for fixed spacing, font sizes, or layout values. Example: \`16px\`, \`1.5rem\`, \`2em\`, \`10vh\`
|
|
12
|
-
- **global-custom-size-variable** — Any CSS size expression that goes beyond a simple number + unit (Elementor Pro). Use this when the value is a CSS function, a keyword, or a combination of units that \`global-size-variable\` cannot represent. Example: \`auto\`, \`clamp(1rem, 2vw, 2rem)\`, \`calc(100% - 32px)\`, \`min(50vw, 600px)\`, \`300ms\`, \`2ch\`. When in doubt: if the value contains a function call or a keyword, use \`global-custom-size-variable\`.`
|
|
13
|
-
: `- ~~global-size-variable~~ — requires Elementor Pro (not available on this site)
|
|
14
|
-
- ~~global-custom-size-variable~~ — requires Elementor Pro (not available on this site)`;
|
|
15
|
-
|
|
16
|
-
prompt.description( `
|
|
17
|
-
# Purpose
|
|
18
|
-
Create, update, or delete V4 global CSS variables. These are distinct from legacy v3 globals and map 1:1 to \`--css-var: VALUE\`.
|
|
19
|
-
|
|
20
|
-
# Available Types
|
|
21
|
-
- **global-color-variable** — CSS color value. Example: \`#FF0000\`, \`rgba(255,0,0,1)\`, \`hsl(0,100%,50%)\`
|
|
22
|
-
- **global-font-variable** — Font family name ONLY — NOT a size or px value. Example: \`Roboto\`, \`Open Sans\`. NEVER pass px/rem here.
|
|
23
|
-
${ sizeVariableSection }
|
|
24
|
-
|
|
25
|
-
# Naming Rules
|
|
26
|
-
- Labels must be **lowercase**, using only letters (a-z), numbers, digits (0-9), dashes (-), or underscores (_)
|
|
27
|
-
- No spaces, no special characters
|
|
28
|
-
- Example: "Headline Primary" → \`headline-primary\`
|
|
29
|
-
- Labels must be unique — always check [elementor://global-variables] first
|
|
30
|
-
|
|
31
|
-
# Value Rules
|
|
32
|
-
- Provide a **plain CSS value** only — do NOT pass JSON, legacy-globals object structures, or variable references
|
|
33
|
-
- Values are inserted as-is: \`--css-var: <value>\`
|
|
34
|
-
- NEVER store a px/rem value inside a \`global-font-variable\` — use \`global-size-variable\` (Pro) instead
|
|
35
|
-
|
|
36
|
-
# Operations
|
|
37
|
-
- **create** — requires \`type\`, \`label\`, \`value\`. Label must be unique.
|
|
38
|
-
- **update** — requires \`id\`, \`label\`, \`value\`. Get \`id\` from [elementor://global-variables]. When renaming: keep existing value. When changing value: keep exact existing label.
|
|
39
|
-
- **delete** — requires \`id\`. DESTRUCTIVE — always confirm with user before executing.
|
|
40
|
-
` );
|
|
41
|
-
|
|
42
|
-
prompt.parameter( 'action', '"create", "update", or "delete".' );
|
|
43
|
-
prompt.parameter( 'type', 'Variable type. Required for create. See Available Types above.' );
|
|
44
|
-
prompt.parameter( 'label', 'Variable name (lowercase, dash-separated). Required for create/update.' );
|
|
45
|
-
prompt.parameter(
|
|
46
|
-
'value',
|
|
47
|
-
'Plain CSS value matching the variable type. Required for create/update. Do NOT pass JSON.'
|
|
48
|
-
);
|
|
49
|
-
prompt.parameter( 'id', 'Variable ID. Required for update/delete. Obtain from [elementor://global-variables].' );
|
|
50
|
-
|
|
51
|
-
prompt.example( `
|
|
52
|
-
Create a brand color:
|
|
53
|
-
{ "action": "create", "type": "global-color-variable", "label": "brand-primary", "value": "#1A73E8" }
|
|
54
|
-
|
|
55
|
-
Create a heading font:
|
|
56
|
-
{ "action": "create", "type": "global-font-variable", "label": "font-heading", "value": "Playfair Display" }
|
|
57
|
-
|
|
58
|
-
Create a simple spacing size:
|
|
59
|
-
{ "action": "create", "type": "global-size-variable", "label": "spacing-md", "value": "16px" }
|
|
60
|
-
|
|
61
|
-
Create a fluid/responsive size using a CSS function (use global-custom-size-variable, NOT global-size-variable):
|
|
62
|
-
{ "action": "create", "type": "global-custom-size-variable", "label": "spacing-fluid", "value": "clamp(1rem, 2vw, 2rem)" }
|
|
63
|
-
|
|
64
|
-
Create a size that is a keyword:
|
|
65
|
-
{ "action": "create", "type": "global-custom-size-variable", "label": "width-auto", "value": "auto" }
|
|
66
|
-
|
|
67
|
-
Create a size using calc():
|
|
68
|
-
{ "action": "create", "type": "global-custom-size-variable", "label": "sidebar-width", "value": "calc(100% - 32px)" }
|
|
69
|
-
|
|
70
|
-
Update a variable's value (keep exact label):
|
|
71
|
-
{ "action": "update", "id": "abc123", "label": "brand-primary", "value": "#0D47A1" }
|
|
72
|
-
|
|
73
|
-
Rename a variable (keep existing value):
|
|
74
|
-
{ "action": "update", "id": "abc123", "label": "brand-secondary", "value": "#1A73E8" }
|
|
75
|
-
|
|
76
|
-
Delete a variable:
|
|
77
|
-
{ "action": "delete", "id": "abc123" }
|
|
78
|
-
` );
|
|
79
|
-
|
|
80
|
-
prompt.instruction(
|
|
81
|
-
'Always read [elementor://global-variables] before creating to check existing variables and avoid duplicate labels.'
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
return prompt.prompt();
|
|
85
|
-
};
|
|
@@ -1,33 +1,18 @@
|
|
|
1
1
|
import { type MCPRegistryEntry } from '@elementor/editor-mcp';
|
|
2
2
|
import { __privateListenTo as listenTo, commandEndEvent } from '@elementor/editor-v1-adapters';
|
|
3
|
+
import { type HttpResponse, httpService } from '@elementor/http-client';
|
|
3
4
|
|
|
4
|
-
import {
|
|
5
|
-
import { STORAGE_UPDATED_EVENT, type TVariable } from '../storage';
|
|
5
|
+
import { STORAGE_UPDATED_EVENT } from '../storage';
|
|
6
6
|
|
|
7
|
+
const MCP_PROXY_URL = 'elementor/v1/mcp-proxy';
|
|
7
8
|
export const GLOBAL_VARIABLES_URI = 'elementor://global-variables';
|
|
8
9
|
|
|
9
|
-
type GlobalVariablesResourceEntry =
|
|
10
|
-
| ( TVariable & { version: 'v4' } )
|
|
11
|
-
| ( Record< string, unknown > & { version: 'v3' } );
|
|
12
|
-
|
|
13
|
-
const buildGlobalVariablesPayload = async (): Promise< Record< string, GlobalVariablesResourceEntry > > => {
|
|
14
|
-
const merged: Record< string, GlobalVariablesResourceEntry > = {};
|
|
15
|
-
Object.entries( service.variables() ).forEach( ( [ id, variable ] ) => {
|
|
16
|
-
if ( ! variable.deleted ) {
|
|
17
|
-
merged[ id ] = { ...variable, version: 'v4' };
|
|
18
|
-
}
|
|
19
|
-
} );
|
|
20
|
-
return merged;
|
|
21
|
-
};
|
|
22
|
-
|
|
23
10
|
export const initVariablesResource = ( variablesMcpEntry: MCPRegistryEntry, canvasMcpEntry: MCPRegistryEntry ) => {
|
|
24
11
|
[ canvasMcpEntry, variablesMcpEntry ].forEach( ( entry ) => {
|
|
25
12
|
const { resource, sendResourceUpdated } = entry;
|
|
26
13
|
|
|
27
14
|
const notifyGlobalVariablesUpdated = () => {
|
|
28
|
-
sendResourceUpdated( {
|
|
29
|
-
uri: GLOBAL_VARIABLES_URI,
|
|
30
|
-
} );
|
|
15
|
+
sendResourceUpdated( { uri: GLOBAL_VARIABLES_URI } );
|
|
31
16
|
};
|
|
32
17
|
|
|
33
18
|
resource(
|
|
@@ -36,12 +21,18 @@ export const initVariablesResource = ( variablesMcpEntry: MCPRegistryEntry, canv
|
|
|
36
21
|
{
|
|
37
22
|
description: 'Global variables available (v4)',
|
|
38
23
|
},
|
|
39
|
-
async () => {
|
|
40
|
-
const
|
|
24
|
+
async ( uri: URL ) => {
|
|
25
|
+
const { data } = await httpService().get< HttpResponse< Record< string, unknown > > >( MCP_PROXY_URL, {
|
|
26
|
+
params: { uri: uri.href },
|
|
27
|
+
} );
|
|
41
28
|
|
|
42
29
|
return {
|
|
43
30
|
contents: [
|
|
44
|
-
{
|
|
31
|
+
{
|
|
32
|
+
uri: uri.href,
|
|
33
|
+
mimeType: 'application/json',
|
|
34
|
+
text: JSON.stringify( data.data ?? {} ),
|
|
35
|
+
},
|
|
45
36
|
],
|
|
46
37
|
};
|
|
47
38
|
}
|