PluginProbe ʕ •ᴥ•ʔ
Elementor Website Builder – more than just a page builder / 4.1.0-dev3
Elementor Website Builder – more than just a page builder v4.1.0-dev3
4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.22.0-dev1 4.0.0-beta3 3.22.0-dev2 4.0.0-beta4 3.22.0-dev3 4.0.0-beta5 3.22.0-dev4 4.0.0-dev1 3.22.0-dev5 4.0.0-dev2 3.22.0-dev6 4.0.0-dev3 3.22.1 4.0.0-dev4 3.22.2 4.0.0-dev5 3.22.3 4.0.1 3.23.0 4.0.2 3.23.0-beta1 3.23.0-beta2 3.23.0-beta3 3.23.0-beta4 3.23.0-beta5 3.23.0-beta6 3.23.0-dev1 3.23.0-dev2 3.23.0-dev3 3.23.0-dev4 3.23.0-dev5 3.23.0-dev6 3.23.1 3.23.2 3.23.3 3.23.4 3.24.0 3.24.0-beta1 3.24.0-beta2 3.24.0-beta3 3.24.0-dev1 3.24.0-dev2 3.24.0-dev3 3.24.1 3.24.2 3.24.3 3.24.4 3.24.5 3.24.6 3.24.7 3.24.8 3.25.0 3.25.0-beta1 3.25.0-beta2 3.25.0-beta3 3.25.0-dev1 3.25.0-dev2 3.25.0-dev3 3.25.1 3.25.10 3.25.11 3.25.2 3.25.3 3.25.4 3.25.5 3.25.6 3.25.7 3.25.8 3.25.9 3.26.0 3.26.0-beta1 3.26.0-beta2 3.26.0-beta3 3.26.0-beta4 3.26.0-beta5 3.26.0-dev1 3.26.0-dev2 3.26.0-dev3 3.26.0-dev4 3.26.0-dev5 3.26.1 3.26.2 3.26.3 3.26.4 3.26.5 3.27.0 3.27.0-beta1 3.27.0-beta2 3.27.0-dev1 3.27.0-dev2 3.27.1 3.27.2 3.27.3 3.27.4 3.27.5 3.27.6 3.27.7 3.28.0 3.28.0-beta1 3.28.0-beta2 3.28.0-beta3 3.28.0-dev1 3.28.0-dev2 3.28.0-dev3 3.28.1 3.28.2 3.28.3 3.28.4 3.29.0 3.29.0-beta1 trunk 3.29.0-beta2 3.0.0 3.29.0-beta3 3.0.1 3.29.0-beta4 3.0.10 3.29.0-dev1 3.0.11 3.29.0-dev2 3.0.12 3.29.0-dev3 3.0.13 3.29.0-dev4 3.0.14 3.29.1 3.0.15 3.29.2 3.0.16 3.3.0 3.0.2 3.3.1 3.0.3 3.30.0 3.0.4 3.30.0-beta1 3.0.5 3.30.0-beta2 3.0.6 3.30.0-beta3 3.0.7 3.30.0-dev1 3.0.8 3.30.0-dev2 3.0.8.1 3.30.0-dev3 3.0.9 3.30.1 3.1.0 3.30.2 3.1.0-beta1 3.30.3 3.1.0-beta2 3.30.4 3.1.0-beta3 3.31.0 3.1.0-beta4 3.31.0-beta1 3.1.0-dev1 3.31.0-beta2 3.1.0-dev2 3.31.0-dev1 3.1.0-dev3 3.31.0-dev2 3.1.1 3.31.1 3.1.2 3.31.2 3.1.3 3.31.3 3.1.4 3.31.4 3.10.0 3.31.5 3.10.0-dev1 3.32.0 3.10.1 3.32.0-beta1 3.10.2 3.32.0-beta2 3.11.0 3.32.0-beta3 3.11.0-beta1 3.32.0-dev1 3.11.0-beta2 3.32.0-dev2 3.11.0-beta3 3.32.0-dev3 3.11.0-dev1 3.32.1 3.11.0-dev2 3.32.2 3.11.0-dev3 3.32.3 3.11.1 3.32.4 3.11.2 3.32.5 3.11.3 3.33.0 3.11.4 3.33.0-beta1 3.11.5 3.33.0-beta2 3.12.0 3.33.0-beta3 3.12.1 3.33.0-beta4 3.12.2 3.33.0-dev1 3.13.0 3.33.0-dev2 3.13.0-beta1 3.33.0-dev3 3.13.0-beta2 3.33.0-dev4 3.13.0-beta3 3.33.1 3.13.0-dev3 3.33.2 3.13.0-dev4 3.33.3 3.13.1 3.33.4 3.13.2 3.33.5 3.13.3 3.33.6 3.13.4 3.34.0 3.14.0 3.34.0-beta1 3.14.0-beta1 3.34.0-beta2 3.14.0-beta2 3.34.0-beta3 3.14.0-beta3 3.34.0-dev1 3.14.0-beta4 3.34.0-dev2 3.14.0-beta5 3.34.1 3.14.1 3.34.2 3.15.0 3.34.3 3.15.1 3.34.4 3.15.2 3.35.0 3.15.3 3.35.0-beta1 3.16.0 3.35.0-beta2 3.16.0-beta3 3.35.0-beta3 3.16.0-beta4 3.35.0-beta4 3.16.0-dev1 3.35.0-dev1 3.16.0-dev2 3.35.0-dev2 3.16.1 3.35.0-dev3 3.16.2 3.35.0-dev4 3.16.3 3.35.1 3.16.4 3.35.2 3.16.5 3.35.3 3.16.6 3.35.4 3.17.0 3.35.5 3.17.0-dev2 3.35.6 3.17.0-dev3 3.35.7 3.17.0-dev4 3.35.8 3.17.1 3.35.9 3.17.2 3.4.0 3.17.3 3.4.0-dev7 3.18.0 3.4.0-dev8 3.18.0-beta1 3.4.0-dev9 3.18.0-beta2 3.4.1 3.18.0-beta3 3.4.2 3.18.0-beta4 3.4.3 3.18.0-dev1 3.4.4 3.18.1 3.4.5 3.18.2 3.4.6 3.18.3 3.4.7 3.19.0 3.4.8 3.19.0-beta1 3.5.0 3.19.0-beta2 3.5.0-beta1 3.19.0-beta3 3.5.0-beta2 3.19.0-beta4 3.5.0-beta3 3.19.0-beta5 3.5.0-beta4 3.19.0-beta6 3.5.0-beta5 3.19.0-dev1 3.5.0-beta7 3.19.0-dev2 3.5.0-beta8 3.19.0-dev3 3.5.0-dev8 3.19.0-dev4 3.5.0-dev9 3.19.0-dev5 3.5.1 3.19.0-dev6 3.5.2 3.19.1 3.5.3 3.19.2 3.5.4 3.19.3 3.5.5 3.19.4 3.5.6 3.2.0 3.6.0 3.2.1 3.6.0-beta1 3.2.2 3.6.0-beta2 3.2.3 3.6.0-beta3 3.2.4 3.6.0-beta4 3.2.5 3.6.0-beta5 3.20.0 3.6.0-dev1 3.20.0-beta1 3.6.0-dev10 3.20.0-beta2 3.6.1 3.20.0-beta3 3.6.2 3.20.0-beta4 3.6.3 3.20.0-dev1 3.6.4 3.20.0-dev2 3.6.5 3.20.0-dev3 3.6.6 3.20.0-dev4 3.6.7 3.20.1 3.6.8 3.20.2 3.7.0 3.20.3 3.7.0-beta1 3.20.4 3.7.0-beta2 3.21.0 3.7.0-beta3 3.21.0-beta1 3.7.0-beta4 3.21.0-beta2 3.7.0-dev1 3.21.0-beta3 3.7.1 3.21.0-dev1 3.7.2 3.21.0-dev2 3.7.3 3.21.0-dev3 3.7.4 3.21.1 3.7.5 3.21.2 3.7.6 3.21.3 3.7.7 3.21.4 3.7.8 3.21.5 3.8.0 3.21.6 3.8.0-beta1 3.21.7 3.8.0-beta2 3.21.8 3.8.0-beta3 3.22.0 3.8.1 3.22.0-beta1 3.9.0 3.22.0-beta2 3.9.1 3.22.0-beta3 3.9.2 3.22.0-beta4 4.0.0 3.22.0-beta5 4.0.0-beta1 3.22.0-beta6 4.0.0-beta2
elementor / migrations / README.md
elementor / migrations Last commit date
operations 2 weeks ago README.md 2 weeks ago manifest.json 2 weeks ago
README.md
440 lines
1 # Prop Type Migrations
2
3 ## System Overview
4 This is a **prop type migration system**, not a general data migration system.
5
6 **Trigger**: Migrations run when it finds a mismatch between data prop type, and actual schema (code) (e.g., `string``string-v2`). Without a type change, there's no trigger and no migration.
7
8 **Scope**: Having mismatch of type (e.g., `string``string-v2`) will find all instances of mismatch, and send the object to run migration script on.
9
10 See [](#migration-scopeMigration Scope](#migration-scope](#migration-scope) for details.
11
12 ## Appendix
13 - [](#structureStructure](#structure](#structure)
14 - [](https://elementor.atlassian.net/wiki/spaces/UE/pages/1999110146/Prop+Types+Migration+Schema+Design+InvestigationLanguage Design](https://elementor.atlassian.net/wiki/spaces/UE/pages/1999110146/Prop+Types+Migration+Schema+Design+Investigation](https://elementor.atlassian.net/wiki/spaces/UE/pages/1999110146/Prop+Types+Migration+Schema+Design+Investigation)
15 - [](#pathsPaths](#paths](#paths)
16 - [](#conditionsConditions](#conditions](#conditions)
17 - [](#functionsFunctions](#functions](#functions)
18 - [](#examplesExamples](#examples](#examples)
19
20 ## Structure
21 ### Manifest
22 Manifest describes the different migrations, it can contain widget key migrations and prop-type migrations
23 ```json
24 {
25 "widgetKeys": {
26 "e-logo": [
27 { "from": "svg", "to": "icon" }
28 ]
29 },
30 "propTypes": {
31 "string-to-html": {
32 "fromType": "string",
33 "toType": "html",
34 "url": "string-to-html.json"
35 }
36 }
37 }
38 ```
39 ### Prop Type Migrations
40 Prop type migrations are a set of operations, **up** for upgrade and reverse **down** for downgrade.
41 Prop type migrations support wildcard paths and conditions (see below)
42 ```json
43 {
44 "up": [
45 {
46 "op": {
47 "fn": "set",
48 "path": "$$type",
49 "value": "html"
50 }
51 }
52 ],
53 "down": [
54 {
55 "op": {
56 "fn": "set",
57 "path": "$$type",
58 "value": "string"
59 }
60 }
61 ]
62 }
63 ```
64
65 ## Paths
66 Path parameter works with wildcard, starting from the **root of the prop object**.
67
68 **Important**: For **prop type migrations** (the primary use case), paths always start at the prop root—not the widget or document root. For example:
69 - `$$type` refers to the type field at the prop root
70 - `value.nested` refers to `propObject.value.nested`
71 - Wildcards like `value.*` or `value.items[*]` match children within the prop
72
73 **Widget key migrations** (rare) start at the widget/element root instead. See [](#migration-scopeMigration Scope](#migration-scope](#migration-scope) for details.
74
75 ## Conditions
76 Conditions check whether to run the migration or not, with many helper functions such as `exists`, conditions can be compounded by `AND` and `OR`.
77 Full list can be found [](https://elementor.atlassian.net/wiki/spaces/UE/pages/1999110146/Prop+Types+Migration+Schema+Design+Investigation#Available-Conditionshere](https://elementor.atlassian.net/wiki/spaces/UE/pages/1999110146/Prop+Types+Migration+Schema+Design+Investigation#Available-Conditions](https://elementor.atlassian.net/wiki/spaces/UE/pages/1999110146/Prop+Types+Migration+Schema+Design+Investigation#Available-Conditions)
78
79 ## Important Notes
80
81 ### Data Transformations
82 **Migrations do NOT support value transformations.** Migrations are purely structural - they create or update, but can't activate any functions on the data.
83
84 Handle transformations in transformer code
85 - Migrations change structure: `{ "color": "#fff" }``{ "color": { "$$type": "color", "value": "#fff" } }`
86 - Transformers can take current values, and transform them `{ "oldColor": "#fff", "newColor": {} }` -> `{ "oldColor": "#fff", "newColor": { "gradient": "something", "value": "#fff" }}`
87
88 ### Migration Scope
89 - **Prop Type Migrations**: Operate on a single prop instance, paths start at prop root
90 - **Widget Key Migrations**: Operate on entire widget element, paths start at element root
91 - Migrations run **before** validation and transformation in the data processing pipeline
92
93 **Example widget:**
94
95 ```json
96 {
97 "id": "heading-1",
98 "elType": "widget",
99 "widgetType": "e-heading",
100 "settings": {
101 "title": {
102 "$$type": "string",
103 "value": "Hello"
104 },
105 "tag": {
106 "$$type": "string",
107 "value": "h2"
108 }
109 }
110 }
111 ```
112
113 **Prop Type Migration** (e.g., `title` migrating from `string``string-v2`):
114 - Operates on **just the prop object**:
115 ```json
116 {
117 "$$type": "string",
118 "value": "Hello"
119 }
120 ```
121 - Paths are relative to prop root: `$$type`, `value`
122
123 **Widget Key Migration** (e.g., renaming `tag``htmlTag`):
124 - Operates on **the entire widget/element**
125 - Paths are relative to widget **settings** root: `tag`, `title.value`
126
127 ### Performance Considerations
128 - Migration state is cached per document with version + manifest hash
129 - Cache clears on Elementor version change, manifest change, or feature flag toggle
130
131 ## Functions
132 ### Set
133 `set` creates or updates data, it can update key / value or both. Full Documentation [](https://elementor.atlassian.net/wiki/spaces/UE/pages/1999110146/Prop+Types+Migration+Schema+Design+Investigation#sethere](https://elementor.atlassian.net/wiki/spaces/UE/pages/1999110146/Prop+Types+Migration+Schema+Design+Investigation#set](https://elementor.atlassian.net/wiki/spaces/UE/pages/1999110146/Prop+Types+Migration+Schema+Design+Investigation#set)
134 Params:
135 - key (optional)
136 - value (optional)
137 - merge **default** true - attempts to deep merge objects instead of replace
138
139 #### Usage
140 Replaces nested key and value
141 ```json
142 { "op": { "fn": "set", "path": "value.*.nested", "value": ["a"], "key": "nested2" } }
143 ```
144 Appends to array
145 ```json
146 { "op": { "fn": "set", "path": "value.*.nested.[]", "value": "a" } }
147 ```
148 Creates empty object at path
149 ```json
150 { "op": { "fn": "set", "path": "value.*.nested.[*]" } }
151 ```
152
153 ### Delete
154 `delete` removes keys/values at specified path. Full Documentation [](https://elementor.atlassian.net/wiki/spaces/UE/pages/1999110146/Prop+Types+Migration+Schema+Design+Investigation#deletehere](https://elementor.atlassian.net/wiki/spaces/UE/pages/1999110146/Prop+Types+Migration+Schema+Design+Investigation#delete](https://elementor.atlassian.net/wiki/spaces/UE/pages/1999110146/Prop+Types+Migration+Schema+Design+Investigation#delete)
155 Params:
156 - clean **default** true - deletes empty parent paths until reaching an object that has siblings
157
158 #### Usage
159 Delete specific nested key
160 ```json
161 { "op": { "fn": "delete", "path": "value.deprecated" } }
162 ```
163 Delete all matching wildcard paths
164 ```json
165 { "op": { "fn": "delete", "path": "value.items[*].legacy" } }
166 ```
167 Delete without cleaning empty parents
168 ```json
169 { "op": { "fn": "delete", "path": "value.old", "clean": false } }
170 ```
171
172 ### Move
173 `move` relocates values from one path to another. Full Documentation [](https://elementor.atlassian.net/wiki/spaces/UE/pages/1999110146/Prop+Types+Migration+Schema+Design+Investigation#movehere](https://elementor.atlassian.net/wiki/spaces/UE/pages/1999110146/Prop+Types+Migration+Schema+Design+Investigation#move](https://elementor.atlassian.net/wiki/spaces/UE/pages/1999110146/Prop+Types+Migration+Schema+Design+Investigation#move)
174 Params:
175 - src - Source path
176 - dest - Destination path
177 - clean **default** true - deletes source path after move (will delete empty paths until reaching an object that has siblings)
178
179 #### Usage
180 Move simple value to new location
181 ```json
182 { "op": { "fn": "move", "src": "value.oldField", "dest": "value.nested.newField" } }
183 ```
184 Move without cleaning source
185 ```json
186 { "op": { "fn": "move", "src": "value.data", "dest": "value.backup", "clean": false } }
187 ```
188 Move nested object structure
189 ```json
190 { "op": { "fn": "move", "src": "value.settings", "dest": "value.config.settings" } }
191 ```
192
193 ## Examples
194
195 ### Widget Key Migration: Rename Settings Key
196
197 **Context**: Rename a widget settings key from `tag``htmlTag`. Paths start at **widget settings root**.
198
199 ```json
200 //manifest.json
201 {
202 "widgetKeys": {
203 "e-heading": [
204 { "from": "tag", "to": "htmlTag" }
205 ],
206 "propTypes": {}
207 }
208 ```
209
210 **Before**:
211 ```json
212 {
213 "id": "heading-1",
214 "elType": "widget",
215 "widgetType": "e-heading",
216 "settings": {
217 "tag": {
218 "$$type": "string",
219 "value": "h2"
220 },
221 "title": {
222 "$$type": "string",
223 "value": "Hello"
224 }
225 }
226 }
227 ```
228
229 **After**:
230 ```json
231 {
232 "id": "heading-1",
233 "elType": "widget",
234 "widgetType": "e-heading",
235 "settings": {
236 "htmlTag": {
237 "$$type": "string",
238 "value": "h2"
239 },
240 "title": {
241 "$$type": "string",
242 "value": "Hello"
243 }
244 }
245 }
246 ```
247
248 ### Prop Type Migration: Change Type
249
250 **Context**: Migrate `string` `html` type. Paths start at **prop root**.
251
252 ```json
253 {
254 "up": [
255 { "op": { "fn": "set", "path": "$$type", "value": "html" } }
256 ],
257 "down": [
258 { "op": { "fn": "set", "path": "$$type", "value": "string" } }
259 ]
260 }
261 ```
262
263 **Before**: `{ "$$type": "string", "value": "Hello" }`
264 **After**: `{ "$$type": "html", "value": "Hello" }`
265
266 ### Prop Type Migration: Rename Keys (Simple and Wildcard)
267
268 **Context**: Rename keys using `key` parameter, with and without wildcards. Paths start at **prop root**.
269
270 **Simple key rename:**
271 ```json
272 {
273 "up": [
274 { "op": { "fn": "set", "path": "value.oldName", "key": "newName" } }
275 ],
276 "down": [
277 { "op": { "fn": "set", "path": "value.newName", "key": "oldName" } }
278 ]
279 }
280 ```
281
282 **Wildcard key rename across multiple objects:**
283 ```json
284 {
285 "up": [
286 {
287 "op": { "fn": "set", "path": "value.*.oldName", "key": "newName" },
288 "condition": { "fn": "exists", "path": "value.*.oldName" }
289 }
290 ],
291 "down": [
292 {
293 "op": { "fn": "set", "path": "value.*.newName", "key": "oldName" },
294 "condition": { "fn": "exists", "path": "value.*.newName" }
295 }
296 ]
297 }
298 ```
299
300 **Before** (wildcard example):
301 ```json
302 {
303 "$$type": "responsive",
304 "value": {
305 "desktop": { "oldName": "value1" },
306 "tablet": { "oldName": "value2" },
307 "mobile": { "oldName": "value3" }
308 }
309 }
310 ```
311
312 **After**:
313 ```json
314 {
315 "$$type": "responsive",
316 "value": {
317 "desktop": { "newName": "value1" },
318 "tablet": { "newName": "value2" },
319 "mobile": { "newName": "value3" }
320 }
321 }
322 ```
323
324 ### Prop Type Migration: Wildcards with Array Items
325
326 **Context**: Update all color types in a gradient using array wildcards `[*]`. Paths start at **prop root**.
327
328 ```json
329 {
330 "up": [
331 {
332 "op": { "fn": "set", "path": "value.stops[*].color.$$type", "value": "color" },
333 "condition": { "fn": "equals", "path": "value.stops[*].color.$$type", "value": "string" }
334 }
335 ],
336 "down": [
337 {
338 "op": { "fn": "set", "path": "value.stops[*].color.$$type", "value": "string" },
339 "condition": { "fn": "equals", "path": "value.stops[*].color.$$type", "value": "color" }
340 }
341 ]
342 }
343 ```
344
345 **Before**:
346 ```json
347 {
348 "$$type": "gradient",
349 "value": {
350 "stops": [
351 { "position": 0, "color": { "$$type": "string", "value": "#ff0000" } },
352 { "position": 50, "color": { "$$type": "string", "value": "#00ff00" } },
353 { "position": 100, "color": { "$$type": "string", "value": "#0000ff" } }
354 ]
355 }
356 }
357 ```
358
359 **After**:
360 ```json
361 {
362 "$$type": "gradient",
363 "value": {
364 "stops": [
365 { "position": 0, "color": { "$$type": "color", "value": "#ff0000" } },
366 { "position": 50, "color": { "$$type": "color", "value": "#00ff00" } },
367 { "position": 100, "color": { "$$type": "color", "value": "#0000ff" } }
368 ]
369 }
370 }
371 ```
372
373 ### Prop Type Migration: Compound Conditions (AND/OR)
374
375 **Context**: Use `and`/`or` conditions to selectively migrate items. Paths start at **prop root**.
376
377 ```json
378 {
379 "up": [
380 {
381 "op": { "fn": "set", "path": "value.items[*].type", "value": "enhanced" },
382 "condition": {
383 "fn": "and",
384 "conditions": [
385 { "fn": "equals", "path": "value.items[*].type", "value": "legacy" },
386 { "fn": "exists", "path": "value.items[*].data" }
387 ]
388 }
389 },
390 {
391 "op": { "fn": "set", "path": "value.items[*].migrated", "value": true },
392 "condition": {
393 "fn": "or",
394 "conditions": [
395 { "fn": "equals", "path": "value.items[*].type", "value": "enhanced" },
396 { "fn": "not_exists", "path": "value.items[*].migrated" }
397 ]
398 }
399 }
400 ],
401 "down": [
402 {
403 "op": { "fn": "set", "path": "value.items[*].type", "value": "legacy" },
404 "condition": { "fn": "equals", "path": "value.items[*].type", "value": "enhanced" }
405 },
406 {
407 "op": { "fn": "delete", "path": "value.items[*].migrated" }
408 }
409 ]
410 }
411 ```
412
413 **Before**:
414 ```json
415 {
416 "$$type": "list",
417 "value": {
418 "items": [
419 { "type": "legacy", "data": { "content": "Item 1" } },
420 { "type": "legacy", "data": { "content": "Item 2" } },
421 { "type": "new", "data": { "content": "Item 3" } }
422 ]
423 }
424 }
425 ```
426
427 **After**:
428 ```json
429 {
430 "$$type": "list",
431 "value": {
432 "items": [
433 { "type": "enhanced", "data": { "content": "Item 1" } },
434 { "type": "enhanced", "data": { "content": "Item 2" } },
435 { "type": "new", "data": { "content": "Item 3" } }
436 ]
437 }
438 }
439 ```
440