@elementor/editor-props 4.2.0-923 → 4.2.0-925
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 +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +54 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +54 -16
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +2 -0
- package/src/utils/props-to-llm-schema.ts +92 -19
- package/src/utils/test-utils/stubs.ts +167 -0
|
@@ -1,7 +1,25 @@
|
|
|
1
1
|
import { type PropsSchema, type PropType } from '../types';
|
|
2
2
|
import { type JsonSchema7 } from './prop-json-schema';
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
const DYNAMIC_PROP_TYPE_KEY = 'dynamic';
|
|
5
|
+
const OVERRIDABLE_PROP_TYPE_KEY = 'overridable';
|
|
6
|
+
|
|
7
|
+
type DynamicTagNamesResolver = ( categories: string[] ) => string[];
|
|
8
|
+
|
|
9
|
+
// Host (editor-canvas) injects a resolver that maps a prop's accepted categories to the names of the
|
|
10
|
+
// dynamic tags allowed for it. Keeping it injectable preserves this lib's purity: without a host the
|
|
11
|
+
// `name` field stays an open string instead of an enum.
|
|
12
|
+
let dynamicTagNamesResolver: DynamicTagNamesResolver | null = null;
|
|
13
|
+
|
|
14
|
+
export function setDynamicTagNamesResolver( resolver: DynamicTagNamesResolver | null ): void {
|
|
15
|
+
dynamicTagNamesResolver = resolver;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// A dynamic value replaces the value of the exact node it is attached to, which may be a nested
|
|
19
|
+
// field (e.g. an image's `src`) rather than the property root. It is advertised once per branch, at
|
|
20
|
+
// the outermost prop type that supports it, and suppressed for descendants of that node to avoid
|
|
21
|
+
// offering the same dynamic option twice on a single branch.
|
|
22
|
+
export function propTypeToJsonSchema( propType: PropType, suppressDynamic: boolean = false ): JsonSchema7 {
|
|
5
23
|
const description = propType.meta?.description;
|
|
6
24
|
|
|
7
25
|
const schema: JsonSchema7 = {};
|
|
@@ -18,11 +36,11 @@ export function propTypeToJsonSchema( propType: PropType ): JsonSchema7 {
|
|
|
18
36
|
// Handle different kinds of prop types
|
|
19
37
|
switch ( propType.kind ) {
|
|
20
38
|
case 'union':
|
|
21
|
-
return convertUnionPropType( propType, schema );
|
|
39
|
+
return convertUnionPropType( propType, schema, suppressDynamic );
|
|
22
40
|
case 'object':
|
|
23
|
-
return convertObjectPropType( propType, schema );
|
|
41
|
+
return convertObjectPropType( propType, schema, suppressDynamic );
|
|
24
42
|
case 'array':
|
|
25
|
-
return convertArrayPropType( propType, schema );
|
|
43
|
+
return convertArrayPropType( propType, schema, suppressDynamic );
|
|
26
44
|
default:
|
|
27
45
|
return convertPlainPropType( propType, schema );
|
|
28
46
|
}
|
|
@@ -73,24 +91,36 @@ function convertPlainPropType(
|
|
|
73
91
|
}
|
|
74
92
|
|
|
75
93
|
/**
|
|
76
|
-
* Converts a union prop type to JSON Schema (
|
|
94
|
+
* Converts a union prop type to JSON Schema (anyOf).
|
|
77
95
|
*
|
|
78
|
-
* @param propType
|
|
79
|
-
* @param baseSchema
|
|
96
|
+
* @param propType The union prop type to convert
|
|
97
|
+
* @param baseSchema Base schema to extend
|
|
98
|
+
* @param suppressDynamic When true, an ancestor already offered the dynamic option for this branch
|
|
80
99
|
*/
|
|
81
|
-
function convertUnionPropType(
|
|
100
|
+
function convertUnionPropType(
|
|
101
|
+
propType: PropType & { kind: 'union' },
|
|
102
|
+
baseSchema: JsonSchema7,
|
|
103
|
+
suppressDynamic: boolean
|
|
104
|
+
): JsonSchema7 {
|
|
82
105
|
const schema = structuredClone( baseSchema );
|
|
83
106
|
|
|
84
107
|
const propTypes = propType.prop_types || {};
|
|
108
|
+
const offersDynamic = ! suppressDynamic && Boolean( propTypes[ DYNAMIC_PROP_TYPE_KEY ] );
|
|
109
|
+
const suppressNestedDynamic = suppressDynamic || offersDynamic;
|
|
85
110
|
const schemas: JsonSchema7[] = [];
|
|
86
111
|
|
|
87
112
|
// Convert each prop type in the union
|
|
88
113
|
for ( const [ typeKey, subPropType ] of Object.entries( propTypes ) ) {
|
|
89
|
-
if ( typeKey ===
|
|
114
|
+
if ( typeKey === OVERRIDABLE_PROP_TYPE_KEY ) {
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
if ( typeKey === DYNAMIC_PROP_TYPE_KEY ) {
|
|
118
|
+
if ( offersDynamic ) {
|
|
119
|
+
schemas.push( convertDynamicPropType( subPropType ) );
|
|
120
|
+
}
|
|
90
121
|
continue;
|
|
91
122
|
}
|
|
92
|
-
|
|
93
|
-
schemas.push( subSchema );
|
|
123
|
+
schemas.push( propTypeToJsonSchema( subPropType, suppressNestedDynamic ) );
|
|
94
124
|
}
|
|
95
125
|
|
|
96
126
|
if ( schemas.length > 0 ) {
|
|
@@ -104,7 +134,50 @@ function convertUnionPropType( propType: PropType & { kind: 'union' }, baseSchem
|
|
|
104
134
|
return schema;
|
|
105
135
|
}
|
|
106
136
|
|
|
107
|
-
|
|
137
|
+
// Emits a compact representation of the `dynamic` union member. It is offered as one option of THIS
|
|
138
|
+
// node's value (e.g. a property root, or a nested field such as an image's `src`): put the dynamic
|
|
139
|
+
// object exactly here, in place of the sibling static variant. Only `name` is required from the LLM
|
|
140
|
+
// (constrained to the tags allowed here); `group` is filled by the host resolver, and `settings` are
|
|
141
|
+
// described per-tag in the dynamic-tags resource, so the full tag catalog is never inlined.
|
|
142
|
+
function convertDynamicPropType( propType: PropType ): JsonSchema7 {
|
|
143
|
+
const categories = Array.isArray( propType.settings?.categories )
|
|
144
|
+
? ( propType.settings.categories as string[] )
|
|
145
|
+
: [];
|
|
146
|
+
const allowedTagNames = dynamicTagNamesResolver?.( categories ) ?? [];
|
|
147
|
+
|
|
148
|
+
return {
|
|
149
|
+
type: 'object',
|
|
150
|
+
description:
|
|
151
|
+
'Bind THIS value to a dynamic tag instead of a static value (this may be a nested field, ' +
|
|
152
|
+
'e.g. an image\'s "src"). Look up the chosen tag in the "elementor://dynamic-tags" resource ' +
|
|
153
|
+
'and populate "settings" exactly as its schema requires.',
|
|
154
|
+
properties: {
|
|
155
|
+
$$type: { type: 'string', const: DYNAMIC_PROP_TYPE_KEY },
|
|
156
|
+
value: {
|
|
157
|
+
type: 'object',
|
|
158
|
+
properties: {
|
|
159
|
+
name: {
|
|
160
|
+
type: 'string',
|
|
161
|
+
description: 'Dynamic tag name from "elementor://dynamic-tags".',
|
|
162
|
+
...( allowedTagNames.length ? { enum: allowedTagNames } : {} ),
|
|
163
|
+
},
|
|
164
|
+
settings: {
|
|
165
|
+
type: 'object',
|
|
166
|
+
description: "Tag settings matching the chosen tag's schema in the resource.",
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
required: [ 'name' ],
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
required: [ '$$type', 'value' ],
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function convertObjectPropType(
|
|
177
|
+
propType: PropType & { kind: 'object' },
|
|
178
|
+
baseSchema: JsonSchema7,
|
|
179
|
+
suppressDynamic: boolean
|
|
180
|
+
): JsonSchema7 {
|
|
108
181
|
const schema = structuredClone( baseSchema );
|
|
109
182
|
|
|
110
183
|
schema.type = 'object';
|
|
@@ -134,7 +207,7 @@ function convertObjectPropType( propType: PropType & { kind: 'object' }, baseSch
|
|
|
134
207
|
|
|
135
208
|
// Convert each property in the object shape
|
|
136
209
|
for ( const [ key, subPropType ] of Object.entries( shape ) ) {
|
|
137
|
-
const propSchema = propTypeToJsonSchema( subPropType );
|
|
210
|
+
const propSchema = propTypeToJsonSchema( subPropType, suppressDynamic );
|
|
138
211
|
|
|
139
212
|
// Check if this property is required
|
|
140
213
|
if ( subPropType.settings?.required === true ) {
|
|
@@ -157,7 +230,11 @@ function convertObjectPropType( propType: PropType & { kind: 'object' }, baseSch
|
|
|
157
230
|
};
|
|
158
231
|
}
|
|
159
232
|
|
|
160
|
-
function convertArrayPropType(
|
|
233
|
+
function convertArrayPropType(
|
|
234
|
+
propType: PropType & { kind: 'array' },
|
|
235
|
+
baseSchema: JsonSchema7,
|
|
236
|
+
suppressDynamic: boolean
|
|
237
|
+
): JsonSchema7 {
|
|
161
238
|
const schema = structuredClone( baseSchema );
|
|
162
239
|
|
|
163
240
|
schema.type = 'object';
|
|
@@ -166,7 +243,7 @@ function convertArrayPropType( propType: PropType & { kind: 'array' }, baseSchem
|
|
|
166
243
|
const itemPropType = propType.item_prop_type;
|
|
167
244
|
|
|
168
245
|
if ( itemPropType ) {
|
|
169
|
-
items =
|
|
246
|
+
items = propTypeToJsonSchema( itemPropType, suppressDynamic );
|
|
170
247
|
}
|
|
171
248
|
|
|
172
249
|
schema.properties = {
|
|
@@ -182,10 +259,6 @@ function convertArrayPropType( propType: PropType & { kind: 'array' }, baseSchem
|
|
|
182
259
|
return schema;
|
|
183
260
|
}
|
|
184
261
|
|
|
185
|
-
function convertPropTypeToJsonSchema( propType: PropType ): JsonSchema7 {
|
|
186
|
-
return propTypeToJsonSchema( propType );
|
|
187
|
-
}
|
|
188
|
-
|
|
189
262
|
export const nonConfigurablePropKeys = [ '_cssid', 'classes', 'attributes' ] as readonly string[];
|
|
190
263
|
|
|
191
264
|
export function isPropKeyConfigurable( propKey: string, propType?: PropType ): boolean {
|
|
@@ -50,6 +50,173 @@ export const STUBS = {
|
|
|
50
50
|
value: 'rgba(0, 0, 0, 1)',
|
|
51
51
|
},
|
|
52
52
|
},
|
|
53
|
+
dynamicText: {
|
|
54
|
+
kind: 'union',
|
|
55
|
+
default: null,
|
|
56
|
+
meta: {
|
|
57
|
+
description: 'A text value that also supports dynamic tags',
|
|
58
|
+
},
|
|
59
|
+
settings: {},
|
|
60
|
+
prop_types: {
|
|
61
|
+
string: {
|
|
62
|
+
kind: 'string',
|
|
63
|
+
key: 'string',
|
|
64
|
+
default: null,
|
|
65
|
+
meta: {},
|
|
66
|
+
settings: {},
|
|
67
|
+
dependencies: undefined,
|
|
68
|
+
initial_value: null,
|
|
69
|
+
},
|
|
70
|
+
dynamic: {
|
|
71
|
+
kind: 'plain',
|
|
72
|
+
key: 'dynamic',
|
|
73
|
+
default: null,
|
|
74
|
+
meta: {},
|
|
75
|
+
settings: {
|
|
76
|
+
categories: [ 'text' ],
|
|
77
|
+
},
|
|
78
|
+
dependencies: undefined,
|
|
79
|
+
initial_value: null,
|
|
80
|
+
},
|
|
81
|
+
overridable: {
|
|
82
|
+
kind: 'plain',
|
|
83
|
+
key: 'overridable',
|
|
84
|
+
default: null,
|
|
85
|
+
meta: {},
|
|
86
|
+
settings: {},
|
|
87
|
+
dependencies: undefined,
|
|
88
|
+
initial_value: null,
|
|
89
|
+
},
|
|
90
|
+
},
|
|
91
|
+
dependencies: undefined,
|
|
92
|
+
initial_value: null,
|
|
93
|
+
},
|
|
94
|
+
htmlV3Title: {
|
|
95
|
+
kind: 'union',
|
|
96
|
+
default: null,
|
|
97
|
+
meta: {},
|
|
98
|
+
settings: {},
|
|
99
|
+
prop_types: {
|
|
100
|
+
'html-v3': {
|
|
101
|
+
kind: 'object',
|
|
102
|
+
key: 'html-v3',
|
|
103
|
+
default: null,
|
|
104
|
+
meta: {},
|
|
105
|
+
settings: {},
|
|
106
|
+
shape: {
|
|
107
|
+
content: {
|
|
108
|
+
kind: 'union',
|
|
109
|
+
default: null,
|
|
110
|
+
meta: {},
|
|
111
|
+
settings: {},
|
|
112
|
+
prop_types: {
|
|
113
|
+
string: {
|
|
114
|
+
kind: 'string',
|
|
115
|
+
key: 'string',
|
|
116
|
+
default: null,
|
|
117
|
+
meta: {},
|
|
118
|
+
settings: {},
|
|
119
|
+
dependencies: undefined,
|
|
120
|
+
initial_value: null,
|
|
121
|
+
},
|
|
122
|
+
dynamic: {
|
|
123
|
+
kind: 'plain',
|
|
124
|
+
key: 'dynamic',
|
|
125
|
+
default: null,
|
|
126
|
+
meta: {},
|
|
127
|
+
settings: { categories: [ 'text' ] },
|
|
128
|
+
dependencies: undefined,
|
|
129
|
+
initial_value: null,
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
dependencies: undefined,
|
|
133
|
+
initial_value: null,
|
|
134
|
+
},
|
|
135
|
+
},
|
|
136
|
+
dependencies: undefined,
|
|
137
|
+
initial_value: null,
|
|
138
|
+
},
|
|
139
|
+
dynamic: {
|
|
140
|
+
kind: 'plain',
|
|
141
|
+
key: 'dynamic',
|
|
142
|
+
default: null,
|
|
143
|
+
meta: {},
|
|
144
|
+
settings: { categories: [ 'text' ] },
|
|
145
|
+
dependencies: undefined,
|
|
146
|
+
initial_value: null,
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
dependencies: undefined,
|
|
150
|
+
initial_value: null,
|
|
151
|
+
},
|
|
152
|
+
dynamicImage: {
|
|
153
|
+
kind: 'object',
|
|
154
|
+
key: 'image',
|
|
155
|
+
default: null,
|
|
156
|
+
meta: {},
|
|
157
|
+
settings: {},
|
|
158
|
+
shape: {
|
|
159
|
+
src: {
|
|
160
|
+
kind: 'union',
|
|
161
|
+
default: null,
|
|
162
|
+
meta: {},
|
|
163
|
+
settings: {},
|
|
164
|
+
prop_types: {
|
|
165
|
+
'image-src': {
|
|
166
|
+
kind: 'object',
|
|
167
|
+
key: 'image-src',
|
|
168
|
+
default: null,
|
|
169
|
+
meta: {},
|
|
170
|
+
settings: {},
|
|
171
|
+
shape: {
|
|
172
|
+
id: {
|
|
173
|
+
kind: 'number',
|
|
174
|
+
key: 'image-attachment-id',
|
|
175
|
+
default: null,
|
|
176
|
+
meta: {},
|
|
177
|
+
settings: {},
|
|
178
|
+
dependencies: undefined,
|
|
179
|
+
initial_value: null,
|
|
180
|
+
},
|
|
181
|
+
url: {
|
|
182
|
+
kind: 'string',
|
|
183
|
+
key: 'url',
|
|
184
|
+
default: null,
|
|
185
|
+
meta: {},
|
|
186
|
+
settings: {},
|
|
187
|
+
dependencies: undefined,
|
|
188
|
+
initial_value: null,
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
dependencies: undefined,
|
|
192
|
+
initial_value: null,
|
|
193
|
+
},
|
|
194
|
+
dynamic: {
|
|
195
|
+
kind: 'plain',
|
|
196
|
+
key: 'dynamic',
|
|
197
|
+
default: null,
|
|
198
|
+
meta: {},
|
|
199
|
+
settings: { categories: [ 'image' ] },
|
|
200
|
+
dependencies: undefined,
|
|
201
|
+
initial_value: null,
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
dependencies: undefined,
|
|
205
|
+
initial_value: null,
|
|
206
|
+
},
|
|
207
|
+
size: {
|
|
208
|
+
kind: 'string',
|
|
209
|
+
key: 'string',
|
|
210
|
+
default: null,
|
|
211
|
+
meta: {},
|
|
212
|
+
settings: {},
|
|
213
|
+
dependencies: undefined,
|
|
214
|
+
initial_value: null,
|
|
215
|
+
},
|
|
216
|
+
},
|
|
217
|
+
dependencies: undefined,
|
|
218
|
+
initial_value: null,
|
|
219
|
+
},
|
|
53
220
|
alignContent: {
|
|
54
221
|
kind: 'string',
|
|
55
222
|
key: 'string',
|