@remotion/studio-server 4.0.470 → 4.0.472
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/codemods/add-effect.d.ts +26 -0
- package/dist/codemods/add-effect.js +193 -0
- package/dist/codemods/format-file-content.js +1 -1
- package/dist/codemods/parse-ast.js +4 -1
- package/dist/codemods/paste-effects.d.ts +15 -0
- package/dist/codemods/paste-effects.js +234 -0
- package/dist/codemods/recast-mods.js +178 -31
- package/dist/codemods/reorder-effect.d.ts +13 -0
- package/dist/codemods/reorder-effect.js +61 -0
- package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.d.ts +1 -1
- package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.js +7 -55
- package/dist/codemods/update-keyframes/update-keyframes.d.ts +15 -6
- package/dist/codemods/update-keyframes/update-keyframes.js +152 -26
- package/dist/helpers/get-ast-node-path.js +6 -1
- package/dist/helpers/import-agnostic-node-path.d.ts +10 -0
- package/dist/helpers/import-agnostic-node-path.js +154 -0
- package/dist/helpers/imports.d.ts +16 -0
- package/dist/helpers/imports.js +145 -0
- package/dist/helpers/open-in-editor.d.ts +2 -2
- package/dist/helpers/open-in-editor.js +35 -2
- package/dist/helpers/resolve-composition-component.d.ts +15 -0
- package/dist/helpers/resolve-composition-component.js +332 -31
- package/dist/preview-server/api-routes.js +10 -4
- package/dist/preview-server/routes/add-effect-keyframe.js +4 -2
- package/dist/preview-server/routes/add-effect.d.ts +3 -0
- package/dist/preview-server/routes/add-effect.js +68 -0
- package/dist/preview-server/routes/add-sequence-keyframe.js +7 -3
- package/dist/preview-server/routes/apply-codemod.js +18 -0
- package/dist/preview-server/routes/can-update-effect-props.d.ts +3 -2
- package/dist/preview-server/routes/can-update-effect-props.js +75 -6
- package/dist/preview-server/routes/can-update-sequence-props.d.ts +1 -0
- package/dist/preview-server/routes/can-update-sequence-props.js +47 -30
- package/dist/preview-server/routes/delete-keyframes.d.ts +13 -0
- package/dist/preview-server/routes/delete-keyframes.js +264 -0
- package/dist/preview-server/routes/insert-jsx-element.d.ts +3 -0
- package/dist/preview-server/routes/insert-jsx-element.js +102 -0
- package/dist/preview-server/routes/paste-effects.d.ts +3 -0
- package/dist/preview-server/routes/paste-effects.js +78 -0
- package/dist/preview-server/routes/reorder-effect.d.ts +3 -0
- package/dist/preview-server/routes/reorder-effect.js +67 -0
- package/dist/preview-server/routes/save-effect-props.js +1 -0
- package/dist/preview-server/routes/subscribe-to-sequence-props.js +2 -1
- package/dist/preview-server/sequence-props-watchers.d.ts +2 -1
- package/dist/preview-server/sequence-props-watchers.js +22 -2
- package/dist/preview-server/undo-stack.d.ts +15 -1
- package/package.json +6 -6
|
@@ -8,7 +8,7 @@ const applyCodemod = ({ file, codeMod, }) => {
|
|
|
8
8
|
return (0, apply_visual_control_1.applyVisualControl)({ file, transformation: codeMod, changesMade });
|
|
9
9
|
}
|
|
10
10
|
const body = file.program.body.map((node) => {
|
|
11
|
-
return mapAll(node, codeMod, changesMade);
|
|
11
|
+
return mapAll(node, codeMod, changesMade, null);
|
|
12
12
|
});
|
|
13
13
|
return {
|
|
14
14
|
newAst: {
|
|
@@ -22,9 +22,9 @@ const applyCodemod = ({ file, codeMod, }) => {
|
|
|
22
22
|
};
|
|
23
23
|
};
|
|
24
24
|
exports.applyCodemod = applyCodemod;
|
|
25
|
-
const mapAll = (node, transformation, changesMade) => {
|
|
25
|
+
const mapAll = (node, transformation, changesMade, parentFolderName) => {
|
|
26
26
|
if (isRecognizedType(node)) {
|
|
27
|
-
return mapRecognizedType(node, transformation, changesMade);
|
|
27
|
+
return mapRecognizedType(node, transformation, changesMade, parentFolderName);
|
|
28
28
|
}
|
|
29
29
|
return node;
|
|
30
30
|
};
|
|
@@ -40,33 +40,33 @@ const isRecognizedType = (t) => {
|
|
|
40
40
|
t.type === 'ExportNamedDeclaration' ||
|
|
41
41
|
t.type === 'ExportDefaultDeclaration');
|
|
42
42
|
};
|
|
43
|
-
const mapVariableDeclarator = (variableDeclarator, transformation, changesMade) => {
|
|
43
|
+
const mapVariableDeclarator = (variableDeclarator, transformation, changesMade, parentFolderName) => {
|
|
44
44
|
return {
|
|
45
45
|
...variableDeclarator,
|
|
46
46
|
init: variableDeclarator.init
|
|
47
|
-
? mapAll(variableDeclarator.init, transformation, changesMade)
|
|
47
|
+
? mapAll(variableDeclarator.init, transformation, changesMade, parentFolderName)
|
|
48
48
|
: variableDeclarator.init,
|
|
49
49
|
};
|
|
50
50
|
};
|
|
51
|
-
const mapBlockStatement = (blockStatement, transformation, changesMade) => {
|
|
51
|
+
const mapBlockStatement = (blockStatement, transformation, changesMade, parentFolderName) => {
|
|
52
52
|
return {
|
|
53
53
|
...blockStatement,
|
|
54
54
|
body: blockStatement.body.map((a) => {
|
|
55
|
-
return mapAll(a, transformation, changesMade);
|
|
55
|
+
return mapAll(a, transformation, changesMade, parentFolderName);
|
|
56
56
|
}),
|
|
57
57
|
};
|
|
58
58
|
};
|
|
59
|
-
const mapReturnStatement = (statement, transformation, changesMade) => {
|
|
59
|
+
const mapReturnStatement = (statement, transformation, changesMade, parentFolderName) => {
|
|
60
60
|
if (!statement.argument) {
|
|
61
61
|
return statement;
|
|
62
62
|
}
|
|
63
|
-
const replacement = transformLoneJsxElement(statement.argument, transformation, changesMade);
|
|
63
|
+
const replacement = transformLoneJsxElement(statement.argument, transformation, changesMade, parentFolderName);
|
|
64
64
|
if (replacement !== null) {
|
|
65
65
|
return { ...statement, argument: replacement };
|
|
66
66
|
}
|
|
67
67
|
return {
|
|
68
68
|
...statement,
|
|
69
|
-
argument: mapAll(statement.argument, transformation, changesMade),
|
|
69
|
+
argument: mapAll(statement.argument, transformation, changesMade, parentFolderName),
|
|
70
70
|
};
|
|
71
71
|
};
|
|
72
72
|
const nullLiteral = () => ({ type: 'NullLiteral' });
|
|
@@ -86,40 +86,68 @@ const wrapInJsxFragment = (children) => ({
|
|
|
86
86
|
type: 'JSXFragment',
|
|
87
87
|
openingFragment: { type: 'JSXOpeningFragment' },
|
|
88
88
|
closingFragment: { type: 'JSXClosingFragment' },
|
|
89
|
-
children: children.map(
|
|
89
|
+
children: children.map((child) => {
|
|
90
|
+
if (child.type === 'JSXElement' || child.type === 'JSXFragment') {
|
|
91
|
+
return stripParenthesizedExtra(child);
|
|
92
|
+
}
|
|
93
|
+
return child;
|
|
94
|
+
}),
|
|
90
95
|
});
|
|
96
|
+
const isJsxExpression = (child) => {
|
|
97
|
+
return child.type === 'JSXElement' || child.type === 'JSXFragment';
|
|
98
|
+
};
|
|
99
|
+
const isMeaningfulJsxChild = (child) => {
|
|
100
|
+
return child.type !== 'JSXText' || child.value.trim() !== '';
|
|
101
|
+
};
|
|
91
102
|
// When a <Composition> JSX element appears in a position where it cannot
|
|
92
103
|
// simply be removed from a parent's children list (e.g. as the sole return
|
|
93
104
|
// value of a wrapper component or as the concise body of an arrow function),
|
|
94
105
|
// we still want delete/rename/duplicate codemods to work. This helper detects
|
|
95
106
|
// that case and produces a structurally-valid replacement expression.
|
|
96
|
-
const transformLoneJsxElement = (expression, transformation, changesMade) => {
|
|
107
|
+
const transformLoneJsxElement = (expression, transformation, changesMade, parentFolderName) => {
|
|
97
108
|
if (expression.type !== 'JSXElement') {
|
|
98
109
|
return null;
|
|
99
110
|
}
|
|
100
111
|
const compId = getCompositionIdFromJSXElement(expression);
|
|
112
|
+
const folderName = getFolderNameFromJSXElement(expression);
|
|
101
113
|
if (compId === null) {
|
|
102
|
-
|
|
114
|
+
const isFolderMatch = folderName !== null &&
|
|
115
|
+
((transformation.type === 'delete-folder' &&
|
|
116
|
+
folderName === transformation.folderName &&
|
|
117
|
+
parentFolderName === transformation.parentName) ||
|
|
118
|
+
(transformation.type === 'rename-folder' &&
|
|
119
|
+
folderName === transformation.folderName &&
|
|
120
|
+
parentFolderName === transformation.parentName));
|
|
121
|
+
if (!isFolderMatch) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
103
124
|
}
|
|
104
125
|
const isMatch = (transformation.type === 'delete-composition' &&
|
|
105
126
|
compId === transformation.idToDelete) ||
|
|
106
127
|
(transformation.type === 'rename-composition' &&
|
|
107
128
|
compId === transformation.idToRename) ||
|
|
108
129
|
(transformation.type === 'duplicate-composition' &&
|
|
109
|
-
compId === transformation.idToDuplicate)
|
|
130
|
+
compId === transformation.idToDuplicate) ||
|
|
131
|
+
(transformation.type === 'delete-folder' &&
|
|
132
|
+
folderName === transformation.folderName &&
|
|
133
|
+
parentFolderName === transformation.parentName) ||
|
|
134
|
+
(transformation.type === 'rename-folder' &&
|
|
135
|
+
folderName === transformation.folderName &&
|
|
136
|
+
parentFolderName === transformation.parentName);
|
|
110
137
|
if (!isMatch) {
|
|
111
138
|
return null;
|
|
112
139
|
}
|
|
113
|
-
const transformed = mapJsxChild(expression, transformation, changesMade);
|
|
114
|
-
|
|
140
|
+
const transformed = mapJsxChild(expression, transformation, changesMade, parentFolderName);
|
|
141
|
+
const meaningful = transformed.filter(isMeaningfulJsxChild);
|
|
142
|
+
if (meaningful.length === 0) {
|
|
115
143
|
return nullLiteral();
|
|
116
144
|
}
|
|
117
|
-
if (
|
|
118
|
-
return
|
|
145
|
+
if (meaningful.length === 1 && isJsxExpression(meaningful[0])) {
|
|
146
|
+
return meaningful[0];
|
|
119
147
|
}
|
|
120
148
|
return wrapInJsxFragment(transformed);
|
|
121
149
|
};
|
|
122
|
-
const mapJsxElementOrFragment = (jsxFragment, transformation, changesMade) => {
|
|
150
|
+
const mapJsxElementOrFragment = (jsxFragment, transformation, changesMade, parentFolderName) => {
|
|
123
151
|
return {
|
|
124
152
|
...jsxFragment,
|
|
125
153
|
children: jsxFragment.children
|
|
@@ -127,13 +155,17 @@ const mapJsxElementOrFragment = (jsxFragment, transformation, changesMade) => {
|
|
|
127
155
|
if (c.type !== 'JSXElement') {
|
|
128
156
|
return c;
|
|
129
157
|
}
|
|
130
|
-
return mapJsxChild(c, transformation, changesMade);
|
|
158
|
+
return mapJsxChild(c, transformation, changesMade, parentFolderName);
|
|
131
159
|
})
|
|
132
160
|
.flat(1),
|
|
133
161
|
};
|
|
134
162
|
};
|
|
135
|
-
const
|
|
163
|
+
const getChildFolderParentName = ({ folderName, parentFolderName, }) => {
|
|
164
|
+
return [parentFolderName, folderName].filter(Boolean).join('/');
|
|
165
|
+
};
|
|
166
|
+
const mapJsxChild = (c, transformation, changesMade, parentFolderName) => {
|
|
136
167
|
const compId = getCompositionIdFromJSXElement(c);
|
|
168
|
+
const folderName = getFolderNameFromJSXElement(c);
|
|
137
169
|
if (transformation === null) {
|
|
138
170
|
return [c];
|
|
139
171
|
}
|
|
@@ -175,17 +207,39 @@ const mapJsxChild = (c, transformation, changesMade) => {
|
|
|
175
207
|
});
|
|
176
208
|
return [];
|
|
177
209
|
}
|
|
178
|
-
|
|
210
|
+
if (transformation.type === 'rename-folder' &&
|
|
211
|
+
folderName === transformation.folderName &&
|
|
212
|
+
parentFolderName === transformation.parentName) {
|
|
213
|
+
return [
|
|
214
|
+
changeFolderName({
|
|
215
|
+
jsxElement: c,
|
|
216
|
+
newFolderName: transformation.newName,
|
|
217
|
+
changesMade,
|
|
218
|
+
}),
|
|
219
|
+
];
|
|
220
|
+
}
|
|
221
|
+
if (transformation.type === 'delete-folder' &&
|
|
222
|
+
folderName === transformation.folderName &&
|
|
223
|
+
parentFolderName === transformation.parentName) {
|
|
224
|
+
changesMade.push({
|
|
225
|
+
description: 'Deleted folder',
|
|
226
|
+
});
|
|
227
|
+
return c.children;
|
|
228
|
+
}
|
|
229
|
+
const childParentFolderName = folderName
|
|
230
|
+
? getChildFolderParentName({ folderName, parentFolderName })
|
|
231
|
+
: parentFolderName;
|
|
232
|
+
return [mapAll(c, transformation, changesMade, childParentFolderName)];
|
|
179
233
|
};
|
|
180
|
-
const mapRecognizedType = (expression, transformation, changesMade) => {
|
|
234
|
+
const mapRecognizedType = (expression, transformation, changesMade, parentFolderName) => {
|
|
181
235
|
if (expression.type === 'JSXFragment' || expression.type === 'JSXElement') {
|
|
182
|
-
return mapJsxElementOrFragment(expression, transformation, changesMade);
|
|
236
|
+
return mapJsxElementOrFragment(expression, transformation, changesMade, parentFolderName);
|
|
183
237
|
}
|
|
184
238
|
if (expression.type === 'ArrowFunctionExpression' ||
|
|
185
239
|
expression.type === 'FunctionExpression') {
|
|
186
240
|
if (expression.type === 'ArrowFunctionExpression' &&
|
|
187
241
|
expression.body.type === 'JSXElement') {
|
|
188
|
-
const replacement = transformLoneJsxElement(expression.body, transformation, changesMade);
|
|
242
|
+
const replacement = transformLoneJsxElement(expression.body, transformation, changesMade, parentFolderName);
|
|
189
243
|
if (replacement !== null) {
|
|
190
244
|
return {
|
|
191
245
|
...expression,
|
|
@@ -195,19 +249,19 @@ const mapRecognizedType = (expression, transformation, changesMade) => {
|
|
|
195
249
|
}
|
|
196
250
|
return {
|
|
197
251
|
...expression,
|
|
198
|
-
body: mapAll(expression.body, transformation, changesMade),
|
|
252
|
+
body: mapAll(expression.body, transformation, changesMade, parentFolderName),
|
|
199
253
|
};
|
|
200
254
|
}
|
|
201
255
|
if (expression.type === 'VariableDeclaration') {
|
|
202
256
|
const declarations = expression.declarations.map((d) => {
|
|
203
|
-
return mapVariableDeclarator(d, transformation, changesMade);
|
|
257
|
+
return mapVariableDeclarator(d, transformation, changesMade, parentFolderName);
|
|
204
258
|
});
|
|
205
259
|
return { ...expression, declarations };
|
|
206
260
|
}
|
|
207
261
|
if (expression.type === 'FunctionDeclaration') {
|
|
208
262
|
return {
|
|
209
263
|
...expression,
|
|
210
|
-
body: mapBlockStatement(expression.body, transformation, changesMade),
|
|
264
|
+
body: mapBlockStatement(expression.body, transformation, changesMade, parentFolderName),
|
|
211
265
|
};
|
|
212
266
|
}
|
|
213
267
|
if (expression.type === 'ExportNamedDeclaration' ||
|
|
@@ -217,14 +271,14 @@ const mapRecognizedType = (expression, transformation, changesMade) => {
|
|
|
217
271
|
}
|
|
218
272
|
return {
|
|
219
273
|
...expression,
|
|
220
|
-
declaration: mapAll(expression.declaration, transformation, changesMade),
|
|
274
|
+
declaration: mapAll(expression.declaration, transformation, changesMade, parentFolderName),
|
|
221
275
|
};
|
|
222
276
|
}
|
|
223
277
|
if (expression.type === 'ReturnStatement') {
|
|
224
|
-
return mapReturnStatement(expression, transformation, changesMade);
|
|
278
|
+
return mapReturnStatement(expression, transformation, changesMade, parentFolderName);
|
|
225
279
|
}
|
|
226
280
|
if (expression.type === 'BlockStatement') {
|
|
227
|
-
return mapBlockStatement(expression, transformation, changesMade);
|
|
281
|
+
return mapBlockStatement(expression, transformation, changesMade, parentFolderName);
|
|
228
282
|
}
|
|
229
283
|
return expression;
|
|
230
284
|
};
|
|
@@ -266,6 +320,99 @@ const getCompositionIdFromJSXElement = (jsxElement) => {
|
|
|
266
320
|
.filter(Boolean);
|
|
267
321
|
return id[0];
|
|
268
322
|
};
|
|
323
|
+
const getFolderNameFromJSXElement = (jsxElement) => {
|
|
324
|
+
if (jsxElement.type !== 'JSXElement') {
|
|
325
|
+
return null;
|
|
326
|
+
}
|
|
327
|
+
const { openingElement } = jsxElement;
|
|
328
|
+
const { name } = openingElement;
|
|
329
|
+
if (name.type !== 'JSXIdentifier') {
|
|
330
|
+
return null;
|
|
331
|
+
}
|
|
332
|
+
if (name.name !== 'Folder') {
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
const folderName = openingElement.attributes
|
|
336
|
+
.map((attribute) => {
|
|
337
|
+
if (attribute.type === 'JSXSpreadAttribute') {
|
|
338
|
+
return null;
|
|
339
|
+
}
|
|
340
|
+
if (attribute.name.type === 'JSXNamespacedName') {
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
if (attribute.name.name !== 'name') {
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
if (!attribute.value) {
|
|
347
|
+
return null;
|
|
348
|
+
}
|
|
349
|
+
if (attribute.value.type === 'StringLiteral') {
|
|
350
|
+
return attribute.value.value;
|
|
351
|
+
}
|
|
352
|
+
if (attribute.value.type === 'JSXExpressionContainer' &&
|
|
353
|
+
attribute.value.expression.type === 'StringLiteral') {
|
|
354
|
+
return attribute.value.expression.value;
|
|
355
|
+
}
|
|
356
|
+
return null;
|
|
357
|
+
})
|
|
358
|
+
.filter(Boolean);
|
|
359
|
+
return folderName[0];
|
|
360
|
+
};
|
|
361
|
+
const changeFolderName = ({ jsxElement, newFolderName, changesMade, }) => {
|
|
362
|
+
const { openingElement } = jsxElement;
|
|
363
|
+
const { name } = openingElement;
|
|
364
|
+
if (name.type !== 'JSXIdentifier') {
|
|
365
|
+
return jsxElement;
|
|
366
|
+
}
|
|
367
|
+
if (name.name !== 'Folder') {
|
|
368
|
+
return jsxElement;
|
|
369
|
+
}
|
|
370
|
+
const attributes = openingElement.attributes.map((attribute) => {
|
|
371
|
+
if (attribute.type === 'JSXSpreadAttribute') {
|
|
372
|
+
return attribute;
|
|
373
|
+
}
|
|
374
|
+
if (attribute.name.type === 'JSXNamespacedName') {
|
|
375
|
+
return attribute;
|
|
376
|
+
}
|
|
377
|
+
if (attribute.name.name === 'name' &&
|
|
378
|
+
attribute.value &&
|
|
379
|
+
attribute.value.type === 'StringLiteral') {
|
|
380
|
+
changesMade.push({
|
|
381
|
+
description: 'Replaced folder name',
|
|
382
|
+
});
|
|
383
|
+
return {
|
|
384
|
+
...attribute,
|
|
385
|
+
value: { ...attribute.value, value: newFolderName },
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
if (attribute.name.name === 'name' &&
|
|
389
|
+
attribute.value &&
|
|
390
|
+
attribute.value.type === 'JSXExpressionContainer' &&
|
|
391
|
+
attribute.value.expression.type === 'StringLiteral') {
|
|
392
|
+
changesMade.push({
|
|
393
|
+
description: 'Replaced folder name',
|
|
394
|
+
});
|
|
395
|
+
return {
|
|
396
|
+
...attribute,
|
|
397
|
+
value: {
|
|
398
|
+
...attribute.value,
|
|
399
|
+
expression: {
|
|
400
|
+
...attribute.value.expression,
|
|
401
|
+
value: newFolderName,
|
|
402
|
+
},
|
|
403
|
+
},
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
return attribute;
|
|
407
|
+
});
|
|
408
|
+
return {
|
|
409
|
+
...jsxElement,
|
|
410
|
+
openingElement: {
|
|
411
|
+
...jsxElement.openingElement,
|
|
412
|
+
attributes,
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
};
|
|
269
416
|
const changeComposition = ({ jsxElement, newCompositionId, newCompositionFps, newCompositionDurationInFrames, newCompositionHeight, newCompositionWidth, changesMade, newTagToUse, }) => {
|
|
270
417
|
const { openingElement } = jsxElement;
|
|
271
418
|
const { name } = openingElement;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SequenceNodePath } from 'remotion';
|
|
2
|
+
export declare const reorderEffect: ({ input, sequenceNodePath, fromIndex, toIndex, prettierConfigOverride, }: {
|
|
3
|
+
input: string;
|
|
4
|
+
sequenceNodePath: SequenceNodePath;
|
|
5
|
+
fromIndex: number;
|
|
6
|
+
toIndex: number;
|
|
7
|
+
prettierConfigOverride?: Record<string, unknown> | null | undefined;
|
|
8
|
+
}) => Promise<{
|
|
9
|
+
output: string;
|
|
10
|
+
formatted: boolean;
|
|
11
|
+
effectLabel: string;
|
|
12
|
+
logLine: number;
|
|
13
|
+
}>;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.reorderEffect = void 0;
|
|
4
|
+
const can_update_sequence_props_1 = require("../preview-server/routes/can-update-sequence-props");
|
|
5
|
+
const format_file_content_1 = require("./format-file-content");
|
|
6
|
+
const parse_ast_1 = require("./parse-ast");
|
|
7
|
+
const update_effect_props_1 = require("./update-effect-props/update-effect-props");
|
|
8
|
+
const getEffectsArray = (attr) => {
|
|
9
|
+
if (!attr.value || attr.value.type !== 'JSXExpressionContainer') {
|
|
10
|
+
throw new Error('Cannot reorder effect: effects prop is not an array');
|
|
11
|
+
}
|
|
12
|
+
const expr = attr.value.expression;
|
|
13
|
+
if (expr.type !== 'ArrayExpression') {
|
|
14
|
+
throw new Error('Cannot reorder effect: effects prop is not an array');
|
|
15
|
+
}
|
|
16
|
+
return expr;
|
|
17
|
+
};
|
|
18
|
+
const reorderEffect = async ({ input, sequenceNodePath, fromIndex, toIndex, prettierConfigOverride, }) => {
|
|
19
|
+
var _a, _b;
|
|
20
|
+
var _c, _d, _e;
|
|
21
|
+
const ast = (0, parse_ast_1.parseAst)(input);
|
|
22
|
+
const jsx = (0, can_update_sequence_props_1.findJsxElementAtNodePath)(ast, sequenceNodePath);
|
|
23
|
+
if (!jsx) {
|
|
24
|
+
throw new Error('Could not find a JSX element at the specified location to reorder effect');
|
|
25
|
+
}
|
|
26
|
+
const attr = (0, update_effect_props_1.findEffectsAttr)((_c = jsx.attributes) !== null && _c !== void 0 ? _c : []);
|
|
27
|
+
if (!attr) {
|
|
28
|
+
throw new Error('Could not find effects on the target JSX element');
|
|
29
|
+
}
|
|
30
|
+
const effectsArray = getEffectsArray(attr);
|
|
31
|
+
const elements = (0, update_effect_props_1.enumerateEffectArrayElements)(effectsArray);
|
|
32
|
+
if (fromIndex < 0 || fromIndex >= elements.length) {
|
|
33
|
+
throw new Error('Cannot reorder effect: source index not-found');
|
|
34
|
+
}
|
|
35
|
+
if (toIndex < 0 || toIndex >= elements.length) {
|
|
36
|
+
throw new Error('Cannot reorder effect: target index not-found');
|
|
37
|
+
}
|
|
38
|
+
const target = elements[fromIndex];
|
|
39
|
+
if (target.kind !== 'call') {
|
|
40
|
+
throw new Error('Cannot reorder effect: source effect is not-call-expression');
|
|
41
|
+
}
|
|
42
|
+
if (fromIndex !== toIndex) {
|
|
43
|
+
const [moved] = effectsArray.elements.splice(fromIndex, 1);
|
|
44
|
+
if (!moved) {
|
|
45
|
+
throw new Error('Cannot reorder effect: source effect is not-call-expression');
|
|
46
|
+
}
|
|
47
|
+
effectsArray.elements.splice(toIndex, 0, moved);
|
|
48
|
+
}
|
|
49
|
+
const finalFile = (0, parse_ast_1.serializeAst)(ast);
|
|
50
|
+
const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
|
|
51
|
+
input: finalFile,
|
|
52
|
+
prettierConfigOverride,
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
output,
|
|
56
|
+
formatted,
|
|
57
|
+
effectLabel: `${target.callee}()`,
|
|
58
|
+
logLine: (_e = (_d = (_a = target.node.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _d !== void 0 ? _d : (_b = jsx.loc) === null || _b === void 0 ? void 0 : _b.start.line) !== null && _e !== void 0 ? _e : 1,
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
exports.reorderEffect = reorderEffect;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { File } from '@babel/types';
|
|
2
2
|
export declare const findEnclosingFunctionPath: (path: import("ast-types/lib/node-path").NodePath<N, V>) => import("ast-types/lib/node-path").NodePath<N, V> | null;
|
|
3
3
|
export declare const ensureRemotionImports: (ast: File, names: ReadonlySet<string>) => void;
|
|
4
|
-
export declare const ensureUseCurrentFrameHook: (functionPath: import("ast-types/lib/node-path").NodePath<N, V
|
|
4
|
+
export declare const ensureUseCurrentFrameHook: (functionPath: import("ast-types/lib/node-path").NodePath<N, V>, hookName?: string) => void;
|
|
@@ -35,6 +35,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.ensureUseCurrentFrameHook = exports.ensureRemotionImports = exports.findEnclosingFunctionPath = void 0;
|
|
37
37
|
const recast = __importStar(require("recast"));
|
|
38
|
+
const imports_1 = require("../../helpers/imports");
|
|
38
39
|
const b = recast.types.builders;
|
|
39
40
|
const n = recast.types.namedTypes;
|
|
40
41
|
const isFunctionNode = (value) => {
|
|
@@ -53,60 +54,11 @@ const findEnclosingFunctionPath = (path) => {
|
|
|
53
54
|
return null;
|
|
54
55
|
};
|
|
55
56
|
exports.findEnclosingFunctionPath = findEnclosingFunctionPath;
|
|
56
|
-
const findRemotionImport = (ast) => {
|
|
57
|
-
for (const stmt of ast.program.body) {
|
|
58
|
-
if (stmt.type === 'ImportDeclaration' &&
|
|
59
|
-
stmt.source.type === 'StringLiteral' &&
|
|
60
|
-
stmt.source.value === 'remotion') {
|
|
61
|
-
return stmt;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return null;
|
|
65
|
-
};
|
|
66
|
-
const insertImportDeclaration = (ast, importDecl) => {
|
|
67
|
-
const { body } = ast.program;
|
|
68
|
-
let lastImportIndex = -1;
|
|
69
|
-
for (let i = 0; i < body.length; i++) {
|
|
70
|
-
if (body[i].type === 'ImportDeclaration') {
|
|
71
|
-
lastImportIndex = i;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
body.splice(lastImportIndex + 1, 0, importDecl);
|
|
75
|
-
};
|
|
76
57
|
const ensureRemotionImports = (ast, names) => {
|
|
77
|
-
|
|
78
|
-
if (names.size === 0) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
let remotionImport = findRemotionImport(ast);
|
|
82
|
-
if (!remotionImport) {
|
|
83
|
-
remotionImport = b.importDeclaration([], b.stringLiteral('remotion'));
|
|
84
|
-
insertImportDeclaration(ast, remotionImport);
|
|
85
|
-
}
|
|
86
|
-
const existingNames = new Set();
|
|
87
|
-
for (const specifier of (_a = remotionImport.specifiers) !== null && _a !== void 0 ? _a : []) {
|
|
88
|
-
if (specifier.type !== 'ImportSpecifier') {
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
const { imported } = specifier;
|
|
92
|
-
if (imported.type === 'Identifier') {
|
|
93
|
-
existingNames.add(imported.name);
|
|
94
|
-
}
|
|
95
|
-
else if (imported.type === 'StringLiteral') {
|
|
96
|
-
existingNames.add(imported.value);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
for (const name of names) {
|
|
100
|
-
if (existingNames.has(name)) {
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
remotionImport.specifiers = (_b = remotionImport.specifiers) !== null && _b !== void 0 ? _b : [];
|
|
104
|
-
remotionImport.specifiers.push(b.importSpecifier(b.identifier(name)));
|
|
105
|
-
existingNames.add(name);
|
|
106
|
-
}
|
|
58
|
+
(0, imports_1.ensureNamedImports)({ ast, importedNames: names, sourcePath: 'remotion' });
|
|
107
59
|
};
|
|
108
60
|
exports.ensureRemotionImports = ensureRemotionImports;
|
|
109
|
-
const componentBodyHasFrameDeclaration = (body) => {
|
|
61
|
+
const componentBodyHasFrameDeclaration = ({ body, hookName, }) => {
|
|
110
62
|
if (!n.BlockStatement.check(body)) {
|
|
111
63
|
return false;
|
|
112
64
|
}
|
|
@@ -123,14 +75,14 @@ const componentBodyHasFrameDeclaration = (body) => {
|
|
|
123
75
|
decl.init &&
|
|
124
76
|
decl.init.type === 'CallExpression' &&
|
|
125
77
|
decl.init.callee.type === 'Identifier' &&
|
|
126
|
-
decl.init.callee.name ===
|
|
78
|
+
decl.init.callee.name === hookName) {
|
|
127
79
|
return true;
|
|
128
80
|
}
|
|
129
81
|
}
|
|
130
82
|
}
|
|
131
83
|
return false;
|
|
132
84
|
};
|
|
133
|
-
const ensureUseCurrentFrameHook = (functionPath) => {
|
|
85
|
+
const ensureUseCurrentFrameHook = (functionPath, hookName = 'useCurrentFrame') => {
|
|
134
86
|
const fn = functionPath.value;
|
|
135
87
|
if (!n.BlockStatement.check(fn.body)) {
|
|
136
88
|
// Arrow function with expression body: wrap the expression in a block so
|
|
@@ -140,12 +92,12 @@ const ensureUseCurrentFrameHook = (functionPath) => {
|
|
|
140
92
|
b.returnStatement(expression),
|
|
141
93
|
]);
|
|
142
94
|
}
|
|
143
|
-
if (componentBodyHasFrameDeclaration(fn.body)) {
|
|
95
|
+
if (componentBodyHasFrameDeclaration({ body: fn.body, hookName })) {
|
|
144
96
|
return;
|
|
145
97
|
}
|
|
146
98
|
const block = fn.body;
|
|
147
99
|
const frameDecl = b.variableDeclaration('const', [
|
|
148
|
-
b.variableDeclarator(b.identifier('frame'), b.callExpression(b.identifier(
|
|
100
|
+
b.variableDeclarator(b.identifier('frame'), b.callExpression(b.identifier(hookName), [])),
|
|
149
101
|
]);
|
|
150
102
|
block.body.unshift(frameDecl);
|
|
151
103
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type KeyframeInterpolationFunction } from '@remotion/studio-shared';
|
|
2
|
+
import type { SequenceNodePath, SequenceSchema } from 'remotion';
|
|
2
3
|
export type KeyframeOperation = {
|
|
3
4
|
type: 'add';
|
|
4
5
|
frame: number;
|
|
@@ -16,23 +17,26 @@ export type EffectKeyframeUpdate = {
|
|
|
16
17
|
operation: KeyframeOperation;
|
|
17
18
|
};
|
|
18
19
|
export type IntroducedKeyframeIdentifiers = {
|
|
19
|
-
calleeName:
|
|
20
|
+
calleeName: KeyframeInterpolationFunction | null;
|
|
20
21
|
needsFrameHook: boolean;
|
|
21
22
|
};
|
|
22
|
-
export declare const updateSequenceKeyframesAst: ({ input, nodePath, updates, }: {
|
|
23
|
+
export declare const updateSequenceKeyframesAst: ({ input, nodePath, updates, schema, }: {
|
|
23
24
|
input: string;
|
|
24
25
|
nodePath: SequenceNodePath;
|
|
25
26
|
updates: SequenceKeyframeUpdate[];
|
|
27
|
+
schema?: SequenceSchema | undefined;
|
|
26
28
|
}) => {
|
|
27
29
|
serialized: string;
|
|
28
30
|
oldValueStrings: string[];
|
|
29
31
|
newValueStrings: string[];
|
|
30
32
|
logLine: number;
|
|
33
|
+
updatedNodePath: SequenceNodePath;
|
|
31
34
|
};
|
|
32
|
-
export declare const updateSequenceKeyframes: ({ input, nodePath, updates, prettierConfigOverride, }: {
|
|
35
|
+
export declare const updateSequenceKeyframes: ({ input, nodePath, updates, schema, prettierConfigOverride, }: {
|
|
33
36
|
input: string;
|
|
34
37
|
nodePath: SequenceNodePath;
|
|
35
38
|
updates: SequenceKeyframeUpdate[];
|
|
39
|
+
schema?: SequenceSchema | undefined;
|
|
36
40
|
prettierConfigOverride?: Record<string, unknown> | null | undefined;
|
|
37
41
|
}) => Promise<{
|
|
38
42
|
output: string;
|
|
@@ -40,24 +44,28 @@ export declare const updateSequenceKeyframes: ({ input, nodePath, updates, prett
|
|
|
40
44
|
oldValueStrings: string[];
|
|
41
45
|
newValueStrings: string[];
|
|
42
46
|
logLine: number;
|
|
47
|
+
updatedNodePath: SequenceNodePath;
|
|
43
48
|
}>;
|
|
44
|
-
export declare const updateEffectKeyframesAst: ({ input, sequenceNodePath, effectIndex, updates, }: {
|
|
49
|
+
export declare const updateEffectKeyframesAst: ({ input, sequenceNodePath, effectIndex, updates, schema, }: {
|
|
45
50
|
input: string;
|
|
46
51
|
sequenceNodePath: SequenceNodePath;
|
|
47
52
|
effectIndex: number;
|
|
48
53
|
updates: EffectKeyframeUpdate[];
|
|
54
|
+
schema?: SequenceSchema | undefined;
|
|
49
55
|
}) => {
|
|
50
56
|
serialized: string;
|
|
51
57
|
oldValueStrings: string[];
|
|
52
58
|
newValueStrings: string[];
|
|
53
59
|
logLine: number;
|
|
54
60
|
effectCallee: string;
|
|
61
|
+
updatedSequenceNodePath: SequenceNodePath;
|
|
55
62
|
};
|
|
56
|
-
export declare const updateEffectKeyframes: ({ input, sequenceNodePath, effectIndex, updates, prettierConfigOverride, }: {
|
|
63
|
+
export declare const updateEffectKeyframes: ({ input, sequenceNodePath, effectIndex, updates, schema, prettierConfigOverride, }: {
|
|
57
64
|
input: string;
|
|
58
65
|
sequenceNodePath: SequenceNodePath;
|
|
59
66
|
effectIndex: number;
|
|
60
67
|
updates: EffectKeyframeUpdate[];
|
|
68
|
+
schema?: SequenceSchema | undefined;
|
|
61
69
|
prettierConfigOverride?: Record<string, unknown> | null | undefined;
|
|
62
70
|
}) => Promise<{
|
|
63
71
|
output: string;
|
|
@@ -66,4 +74,5 @@ export declare const updateEffectKeyframes: ({ input, sequenceNodePath, effectIn
|
|
|
66
74
|
newValueStrings: string[];
|
|
67
75
|
logLine: number;
|
|
68
76
|
effectCallee: string;
|
|
77
|
+
updatedSequenceNodePath: SequenceNodePath;
|
|
69
78
|
}>;
|