@remotion/studio-server 4.0.484 → 4.0.486

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.
Files changed (41) hide show
  1. package/dist/codemods/duplicate-composition.js +8 -0
  2. package/dist/codemods/recast-mods.js +246 -5
  3. package/dist/codemods/split-jsx-sequence.d.ts +14 -0
  4. package/dist/codemods/split-jsx-sequence.js +345 -0
  5. package/dist/codemods/update-sequence-props/update-sequence-props.d.ts +3 -1
  6. package/dist/codemods/update-sequence-props/update-sequence-props.js +406 -9
  7. package/dist/helpers/import-agnostic-node-path.js +30 -4
  8. package/dist/helpers/resolve-composition-component.d.ts +1 -0
  9. package/dist/helpers/resolve-composition-component.js +206 -9
  10. package/dist/preview-server/api-routes.js +2 -0
  11. package/dist/preview-server/routes/add-effect-keyframe.js +2 -2
  12. package/dist/preview-server/routes/add-effect.js +56 -53
  13. package/dist/preview-server/routes/add-keyframes.js +2 -2
  14. package/dist/preview-server/routes/add-sequence-keyframe.js +2 -2
  15. package/dist/preview-server/routes/apply-codemod.js +123 -101
  16. package/dist/preview-server/routes/apply-visual-control-change.js +83 -80
  17. package/dist/preview-server/routes/can-update-sequence-props.d.ts +13 -1
  18. package/dist/preview-server/routes/can-update-sequence-props.js +101 -7
  19. package/dist/preview-server/routes/delete-effect.js +83 -80
  20. package/dist/preview-server/routes/delete-jsx-node.js +74 -71
  21. package/dist/preview-server/routes/delete-keyframes.js +2 -2
  22. package/dist/preview-server/routes/duplicate-effect.js +77 -74
  23. package/dist/preview-server/routes/duplicate-jsx-node.js +53 -50
  24. package/dist/preview-server/routes/insert-element.js +2 -2
  25. package/dist/preview-server/routes/insert-jsx-element.js +53 -4
  26. package/dist/preview-server/routes/move-keyframes.js +2 -2
  27. package/dist/preview-server/routes/paste-effects.js +59 -56
  28. package/dist/preview-server/routes/reorder-effect.js +55 -52
  29. package/dist/preview-server/routes/reorder-sequence.js +55 -52
  30. package/dist/preview-server/routes/save-effect-props.js +2 -2
  31. package/dist/preview-server/routes/save-sequence-props.d.ts +3 -1
  32. package/dist/preview-server/routes/save-sequence-props.js +208 -24
  33. package/dist/preview-server/routes/source-file-write-queue.d.ts +1 -0
  34. package/dist/preview-server/routes/source-file-write-queue.js +11 -0
  35. package/dist/preview-server/routes/split-jsx-sequence.d.ts +3 -0
  36. package/dist/preview-server/routes/split-jsx-sequence.js +66 -0
  37. package/dist/preview-server/routes/update-default-props.js +58 -55
  38. package/dist/preview-server/routes/update-effect-keyframe-settings.js +2 -2
  39. package/dist/preview-server/routes/update-sequence-keyframe-settings.js +2 -2
  40. package/dist/preview-server/undo-stack.d.ts +7 -1
  41. package/package.json +6 -6
@@ -94,6 +94,14 @@ const parseAndApplyCodemod = ({ input, codeMod, }) => {
94
94
  localName: codeMod.componentName,
95
95
  });
96
96
  }
97
+ if (codeMod.type === 'new-folder') {
98
+ (0, imports_1.ensureNamedImport)({
99
+ ast: newAst,
100
+ importedName: 'Folder',
101
+ sourcePath: 'remotion',
102
+ localName: 'Folder',
103
+ });
104
+ }
97
105
  const output = (0, parse_ast_1.serializeAst)(newAst);
98
106
  return { changesMade, newContents: output };
99
107
  };
@@ -36,12 +36,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.applyCodemod = void 0;
37
37
  const recast = __importStar(require("recast"));
38
38
  const apply_visual_control_1 = require("./apply-visual-control");
39
+ const delete_jsx_node_1 = require("./delete-jsx-node");
39
40
  const b = recast.types.builders;
40
41
  const applyCodemod = ({ file, codeMod, }) => {
41
42
  const changesMade = [];
42
43
  if (codeMod.type === 'apply-visual-control') {
43
44
  return (0, apply_visual_control_1.applyVisualControl)({ file, transformation: codeMod, changesMade });
44
45
  }
46
+ if (codeMod.type === 'move-composition-to-folder') {
47
+ return moveCompositionToFolder({
48
+ file,
49
+ transformation: codeMod,
50
+ changesMade,
51
+ });
52
+ }
45
53
  const body = file.program.body.map((node) => {
46
54
  return mapAll(node, codeMod, changesMade, null);
47
55
  });
@@ -96,6 +104,7 @@ const mapReturnStatement = (statement, transformation, changesMade, parentFolder
96
104
  return statement;
97
105
  }
98
106
  if (transformation.type === 'new-composition' &&
107
+ transformation.folderName === null &&
99
108
  (statement.argument.type === 'JSXElement' ||
100
109
  statement.argument.type === 'JSXFragment')) {
101
110
  return {
@@ -103,6 +112,15 @@ const mapReturnStatement = (statement, transformation, changesMade, parentFolder
103
112
  argument: addNewCompositionToRootJsx(statement.argument, transformation, changesMade),
104
113
  };
105
114
  }
115
+ if (transformation.type === 'new-folder' &&
116
+ transformation.parentName === null &&
117
+ (statement.argument.type === 'JSXElement' ||
118
+ statement.argument.type === 'JSXFragment')) {
119
+ return {
120
+ ...statement,
121
+ argument: addNewFolderToRootJsx(statement.argument, transformation, changesMade),
122
+ };
123
+ }
106
124
  const replacement = transformLoneJsxElement(statement.argument, transformation, changesMade, parentFolderName);
107
125
  if (replacement !== null) {
108
126
  return { ...statement, argument: replacement };
@@ -176,6 +194,19 @@ const newCompositionElement = (transformation) => {
176
194
  children: [],
177
195
  };
178
196
  };
197
+ const newFolderElement = (transformation) => {
198
+ return {
199
+ type: 'JSXElement',
200
+ openingElement: {
201
+ type: 'JSXOpeningElement',
202
+ name: jsxId('Folder'),
203
+ attributes: [jsxAttributeWithString('name', transformation.folderName)],
204
+ selfClosing: true,
205
+ },
206
+ closingElement: null,
207
+ children: [],
208
+ };
209
+ };
179
210
  const addNewCompositionToRootJsx = (root, transformation, changesMade) => {
180
211
  if (changesMade.length > 0) {
181
212
  return root;
@@ -191,6 +222,185 @@ const addNewCompositionToRootJsx = (root, transformation, changesMade) => {
191
222
  }
192
223
  return wrapInJsxFragment([root, newCompositionElement(transformation)]);
193
224
  };
225
+ const addNewFolderToRootJsx = (root, transformation, changesMade) => {
226
+ if (changesMade.length > 0) {
227
+ return root;
228
+ }
229
+ changesMade.push({
230
+ description: 'Added new folder',
231
+ });
232
+ if (root.type === 'JSXFragment') {
233
+ return {
234
+ ...root,
235
+ children: [...root.children, newFolderElement(transformation)],
236
+ };
237
+ }
238
+ return wrapInJsxFragment([root, newFolderElement(transformation)]);
239
+ };
240
+ const addNewCompositionToFolder = (folderElement, transformation, changesMade) => {
241
+ var _a;
242
+ if (changesMade.length > 0) {
243
+ return folderElement;
244
+ }
245
+ changesMade.push({
246
+ description: 'Added new composition',
247
+ });
248
+ return {
249
+ ...folderElement,
250
+ openingElement: {
251
+ ...folderElement.openingElement,
252
+ selfClosing: false,
253
+ },
254
+ closingElement: (_a = folderElement.closingElement) !== null && _a !== void 0 ? _a : {
255
+ type: 'JSXClosingElement',
256
+ name: folderElement.openingElement.name,
257
+ },
258
+ children: [
259
+ ...folderElement.children,
260
+ newCompositionElement(transformation),
261
+ ],
262
+ };
263
+ };
264
+ const addNewFolderToFolder = (folderElement, transformation, changesMade) => {
265
+ var _a;
266
+ if (changesMade.length > 0) {
267
+ return folderElement;
268
+ }
269
+ changesMade.push({
270
+ description: 'Added new folder',
271
+ });
272
+ return {
273
+ ...folderElement,
274
+ openingElement: {
275
+ ...folderElement.openingElement,
276
+ selfClosing: false,
277
+ },
278
+ closingElement: (_a = folderElement.closingElement) !== null && _a !== void 0 ? _a : {
279
+ type: 'JSXClosingElement',
280
+ name: folderElement.openingElement.name,
281
+ },
282
+ children: [...folderElement.children, newFolderElement(transformation)],
283
+ };
284
+ };
285
+ const getChildFolderParentName = ({ folderName, parentFolderName, }) => {
286
+ return [parentFolderName, folderName].filter(Boolean).join('/');
287
+ };
288
+ const appendCompositionToFolder = ({ compositionElement, folderElement, }) => {
289
+ var _a;
290
+ folderElement.openingElement.selfClosing = false;
291
+ folderElement.closingElement = (_a = folderElement.closingElement) !== null && _a !== void 0 ? _a : {
292
+ type: 'JSXClosingElement',
293
+ name: folderElement.openingElement.name,
294
+ };
295
+ folderElement.children.push(stripParenthesizedExtra(compositionElement));
296
+ };
297
+ const appendCompositionToRoot = ({ compositionElement, file, }) => {
298
+ let appended = false;
299
+ recast.types.visit(file, {
300
+ visitReturnStatement(astPath) {
301
+ if (appended) {
302
+ return false;
303
+ }
304
+ const { argument } = astPath.node;
305
+ if ((argument === null || argument === void 0 ? void 0 : argument.type) !== 'JSXFragment' && (argument === null || argument === void 0 ? void 0 : argument.type) !== 'JSXElement') {
306
+ this.traverse(astPath);
307
+ return undefined;
308
+ }
309
+ if (argument.type === 'JSXFragment') {
310
+ argument.children.push(stripParenthesizedExtra(compositionElement));
311
+ }
312
+ else {
313
+ astPath.node.argument = wrapInJsxFragment([
314
+ argument,
315
+ compositionElement,
316
+ ]);
317
+ }
318
+ appended = true;
319
+ return false;
320
+ },
321
+ });
322
+ if (!appended) {
323
+ throw new Error('Could not find a root JSX element');
324
+ }
325
+ };
326
+ const moveCompositionToFolder = ({ file, transformation, changesMade, }) => {
327
+ let sourcePath = null;
328
+ let sourceParentFolderName = null;
329
+ let sourceIsDirectJsxChild = false;
330
+ let targetFolder = null;
331
+ const folderStack = [];
332
+ const isDirectJsxChild = (astPath) => {
333
+ var _a;
334
+ const parent = (_a = astPath.parentPath) === null || _a === void 0 ? void 0 : _a.node;
335
+ return (((parent === null || parent === void 0 ? void 0 : parent.type) === 'JSXElement' || (parent === null || parent === void 0 ? void 0 : parent.type) === 'JSXFragment') &&
336
+ parent.children.includes(astPath.node));
337
+ };
338
+ const visitJsxElementWithFolderContext = (astPath) => {
339
+ const node = astPath.node;
340
+ const compositionId = getCompositionIdFromJSXElement(node);
341
+ if (compositionId === transformation.idToMove) {
342
+ sourcePath = astPath;
343
+ sourceParentFolderName = folderStack.join('/') || null;
344
+ sourceIsDirectJsxChild = isDirectJsxChild(astPath);
345
+ }
346
+ const folderName = getFolderNameFromJSXElement(node);
347
+ const parentName = folderStack.join('/') || null;
348
+ if (transformation.folderName !== null &&
349
+ folderName === transformation.folderName &&
350
+ parentName === transformation.parentName) {
351
+ targetFolder = node;
352
+ }
353
+ if (folderName) {
354
+ folderStack.push(folderName);
355
+ }
356
+ for (let i = 0; i < node.children.length; i++) {
357
+ if (node.children[i].type !== 'JSXElement') {
358
+ continue;
359
+ }
360
+ visitJsxElementWithFolderContext(astPath.get('children', i));
361
+ }
362
+ if (folderName) {
363
+ folderStack.pop();
364
+ }
365
+ };
366
+ recast.types.visit(file, {
367
+ visitJSXElement(astPath) {
368
+ visitJsxElementWithFolderContext(astPath);
369
+ return false;
370
+ },
371
+ });
372
+ if (!sourcePath) {
373
+ throw new Error(`Could not find composition "${transformation.idToMove}"`);
374
+ }
375
+ if (!sourceIsDirectJsxChild) {
376
+ throw new Error(`Cannot move composition "${transformation.idToMove}" because it is not a direct JSX child`);
377
+ }
378
+ if (transformation.folderName === null && sourceParentFolderName === null) {
379
+ return { newAst: file, changesMade };
380
+ }
381
+ if (transformation.folderName !== null && !targetFolder) {
382
+ const folderLabel = `${transformation.parentName ? `${transformation.parentName}/` : ''}${transformation.folderName}`;
383
+ throw new Error(`Could not find folder "${folderLabel}"`);
384
+ }
385
+ const compositionElement = sourcePath
386
+ .node;
387
+ (0, delete_jsx_node_1.deleteJsxElementAtPath)(sourcePath);
388
+ if (transformation.folderName === null) {
389
+ appendCompositionToRoot({ compositionElement, file });
390
+ changesMade.push({ description: 'Moved composition to root' });
391
+ }
392
+ else {
393
+ if (targetFolder === null) {
394
+ throw new Error('Could not find target folder');
395
+ }
396
+ appendCompositionToFolder({
397
+ compositionElement,
398
+ folderElement: targetFolder,
399
+ });
400
+ changesMade.push({ description: 'Moved composition into folder' });
401
+ }
402
+ return { newAst: file, changesMade };
403
+ };
194
404
  // When a <Composition> JSX element appears in a position where it cannot
195
405
  // simply be removed from a parent's children list (e.g. as the sole return
196
406
  // value of a wrapper component or as the concise body of an arrow function),
@@ -209,7 +419,13 @@ const transformLoneJsxElement = (expression, transformation, changesMade, parent
209
419
  parentFolderName === transformation.parentName) ||
210
420
  (transformation.type === 'rename-folder' &&
211
421
  folderName === transformation.folderName &&
212
- parentFolderName === transformation.parentName));
422
+ parentFolderName === transformation.parentName) ||
423
+ (transformation.type === 'new-composition' &&
424
+ folderName === transformation.folderName &&
425
+ parentFolderName === transformation.parentName) ||
426
+ (transformation.type === 'new-folder' &&
427
+ getChildFolderParentName({ folderName, parentFolderName }) ===
428
+ transformation.parentName));
213
429
  if (!isFolderMatch) {
214
430
  return null;
215
431
  }
@@ -225,7 +441,14 @@ const transformLoneJsxElement = (expression, transformation, changesMade, parent
225
441
  parentFolderName === transformation.parentName) ||
226
442
  (transformation.type === 'rename-folder' &&
227
443
  folderName === transformation.folderName &&
228
- parentFolderName === transformation.parentName);
444
+ parentFolderName === transformation.parentName) ||
445
+ (transformation.type === 'new-composition' &&
446
+ folderName === transformation.folderName &&
447
+ parentFolderName === transformation.parentName) ||
448
+ (transformation.type === 'new-folder' &&
449
+ folderName !== null &&
450
+ getChildFolderParentName({ folderName, parentFolderName }) ===
451
+ transformation.parentName);
229
452
  if (!isMatch) {
230
453
  return null;
231
454
  }
@@ -252,9 +475,6 @@ const mapJsxElementOrFragment = (jsxFragment, transformation, changesMade, paren
252
475
  .flat(1),
253
476
  };
254
477
  };
255
- const getChildFolderParentName = ({ folderName, parentFolderName, }) => {
256
- return [parentFolderName, folderName].filter(Boolean).join('/');
257
- };
258
478
  const mapJsxChild = (c, transformation, changesMade, parentFolderName) => {
259
479
  const compId = getCompositionIdFromJSXElement(c);
260
480
  const folderName = getFolderNameFromJSXElement(c);
@@ -318,6 +538,17 @@ const mapJsxChild = (c, transformation, changesMade, parentFolderName) => {
318
538
  });
319
539
  return c.children;
320
540
  }
541
+ if (transformation.type === 'new-composition' &&
542
+ folderName === transformation.folderName &&
543
+ parentFolderName === transformation.parentName) {
544
+ return [addNewCompositionToFolder(c, transformation, changesMade)];
545
+ }
546
+ if (transformation.type === 'new-folder' &&
547
+ folderName !== null &&
548
+ getChildFolderParentName({ folderName, parentFolderName }) ===
549
+ transformation.parentName) {
550
+ return [addNewFolderToFolder(c, transformation, changesMade)];
551
+ }
321
552
  const childParentFolderName = folderName
322
553
  ? getChildFolderParentName({ folderName, parentFolderName })
323
554
  : parentFolderName;
@@ -330,6 +561,7 @@ const mapRecognizedType = (expression, transformation, changesMade, parentFolder
330
561
  if (expression.type === 'ArrowFunctionExpression' ||
331
562
  expression.type === 'FunctionExpression') {
332
563
  if (transformation.type === 'new-composition' &&
564
+ transformation.folderName === null &&
333
565
  (expression.body.type === 'JSXElement' ||
334
566
  expression.body.type === 'JSXFragment')) {
335
567
  return {
@@ -337,6 +569,15 @@ const mapRecognizedType = (expression, transformation, changesMade, parentFolder
337
569
  body: addNewCompositionToRootJsx(expression.body, transformation, changesMade),
338
570
  };
339
571
  }
572
+ if (transformation.type === 'new-folder' &&
573
+ transformation.parentName === null &&
574
+ (expression.body.type === 'JSXElement' ||
575
+ expression.body.type === 'JSXFragment')) {
576
+ return {
577
+ ...expression,
578
+ body: addNewFolderToRootJsx(expression.body, transformation, changesMade),
579
+ };
580
+ }
340
581
  if (expression.type === 'ArrowFunctionExpression' &&
341
582
  expression.body.type === 'JSXElement') {
342
583
  const replacement = transformLoneJsxElement(expression.body, transformation, changesMade, parentFolderName);
@@ -0,0 +1,14 @@
1
+ import type { SequenceNodePath } from 'remotion';
2
+ export declare const getSplitUnsupportedSequenceTagReason: (tagName: string) => string | null;
3
+ export declare const getIsSplittableSequenceTag: (tagName: string) => boolean;
4
+ export declare const splitJsxSequence: ({ input, nodePath, splitFrame, prettierConfigOverride, }: {
5
+ input: string;
6
+ nodePath: SequenceNodePath;
7
+ splitFrame: number;
8
+ prettierConfigOverride?: Record<string, unknown> | null | undefined;
9
+ }) => Promise<{
10
+ output: string;
11
+ formatted: boolean;
12
+ nodeLabel: string;
13
+ logLine: number;
14
+ }>;