@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.
Files changed (46) hide show
  1. package/dist/codemods/add-effect.d.ts +26 -0
  2. package/dist/codemods/add-effect.js +193 -0
  3. package/dist/codemods/format-file-content.js +1 -1
  4. package/dist/codemods/parse-ast.js +4 -1
  5. package/dist/codemods/paste-effects.d.ts +15 -0
  6. package/dist/codemods/paste-effects.js +234 -0
  7. package/dist/codemods/recast-mods.js +178 -31
  8. package/dist/codemods/reorder-effect.d.ts +13 -0
  9. package/dist/codemods/reorder-effect.js +61 -0
  10. package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.d.ts +1 -1
  11. package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.js +7 -55
  12. package/dist/codemods/update-keyframes/update-keyframes.d.ts +15 -6
  13. package/dist/codemods/update-keyframes/update-keyframes.js +152 -26
  14. package/dist/helpers/get-ast-node-path.js +6 -1
  15. package/dist/helpers/import-agnostic-node-path.d.ts +10 -0
  16. package/dist/helpers/import-agnostic-node-path.js +154 -0
  17. package/dist/helpers/imports.d.ts +16 -0
  18. package/dist/helpers/imports.js +145 -0
  19. package/dist/helpers/open-in-editor.d.ts +2 -2
  20. package/dist/helpers/open-in-editor.js +35 -2
  21. package/dist/helpers/resolve-composition-component.d.ts +15 -0
  22. package/dist/helpers/resolve-composition-component.js +332 -31
  23. package/dist/preview-server/api-routes.js +10 -4
  24. package/dist/preview-server/routes/add-effect-keyframe.js +4 -2
  25. package/dist/preview-server/routes/add-effect.d.ts +3 -0
  26. package/dist/preview-server/routes/add-effect.js +68 -0
  27. package/dist/preview-server/routes/add-sequence-keyframe.js +7 -3
  28. package/dist/preview-server/routes/apply-codemod.js +18 -0
  29. package/dist/preview-server/routes/can-update-effect-props.d.ts +3 -2
  30. package/dist/preview-server/routes/can-update-effect-props.js +75 -6
  31. package/dist/preview-server/routes/can-update-sequence-props.d.ts +1 -0
  32. package/dist/preview-server/routes/can-update-sequence-props.js +47 -30
  33. package/dist/preview-server/routes/delete-keyframes.d.ts +13 -0
  34. package/dist/preview-server/routes/delete-keyframes.js +264 -0
  35. package/dist/preview-server/routes/insert-jsx-element.d.ts +3 -0
  36. package/dist/preview-server/routes/insert-jsx-element.js +102 -0
  37. package/dist/preview-server/routes/paste-effects.d.ts +3 -0
  38. package/dist/preview-server/routes/paste-effects.js +78 -0
  39. package/dist/preview-server/routes/reorder-effect.d.ts +3 -0
  40. package/dist/preview-server/routes/reorder-effect.js +67 -0
  41. package/dist/preview-server/routes/save-effect-props.js +1 -0
  42. package/dist/preview-server/routes/subscribe-to-sequence-props.js +2 -1
  43. package/dist/preview-server/sequence-props-watchers.d.ts +2 -1
  44. package/dist/preview-server/sequence-props-watchers.js +22 -2
  45. package/dist/preview-server/undo-stack.d.ts +15 -1
  46. package/package.json +6 -6
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.updateEffectKeyframes = exports.updateEffectKeyframesAst = exports.updateSequenceKeyframes = exports.updateSequenceKeyframesAst = void 0;
37
+ const studio_shared_1 = require("@remotion/studio-shared");
37
38
  const recast = __importStar(require("recast"));
38
39
  const get_ast_node_path_1 = require("../../helpers/get-ast-node-path");
39
40
  const can_update_sequence_props_1 = require("../../preview-server/routes/can-update-sequence-props");
@@ -71,8 +72,7 @@ const getInterpolationExpression = (node) => {
71
72
  }
72
73
  if (node.type !== 'CallExpression' ||
73
74
  node.callee.type !== 'Identifier' ||
74
- (node.callee.name !== 'interpolate' &&
75
- node.callee.name !== 'interpolateColors')) {
75
+ !(0, studio_shared_1.isKeyframeInterpolationFunction)(node.callee.name)) {
76
76
  return null;
77
77
  }
78
78
  const frameArg = getSupportedCallArgument(node.arguments[0]);
@@ -124,14 +124,23 @@ const getInterpolationExpression = (node) => {
124
124
  keyframes,
125
125
  };
126
126
  };
127
- const getInterpolationCalleeForValues = ({ staticValue, newValue, }) => {
128
- return b.identifier(typeof staticValue === 'string' && typeof newValue === 'string'
129
- ? 'interpolateColors'
130
- : 'interpolate');
127
+ const getInterpolationCalleeForValues = ({ schema, key, staticValue, newValue, }) => {
128
+ return b.identifier((0, studio_shared_1.getKeyframeInterpolationFunction)({
129
+ schema,
130
+ key,
131
+ staticValue,
132
+ newValue,
133
+ }));
131
134
  };
132
135
  const createFrameExpression = (frame) => {
133
136
  return (0, update_nested_prop_1.parseValueExpression)(frame);
134
137
  };
138
+ const createClampOptionsExpression = () => {
139
+ return b.objectExpression([
140
+ b.objectProperty(b.identifier('extrapolateLeft'), b.stringLiteral('clamp')),
141
+ b.objectProperty(b.identifier('extrapolateRight'), b.stringLiteral('clamp')),
142
+ ]);
143
+ };
135
144
  const createInterpolateExpression = ({ callee, input, extraArgs, keyframes, }) => {
136
145
  const sortedKeyframes = [...keyframes].sort((first, second) => first.frame - second.frame);
137
146
  return b.callExpression(callee, [
@@ -145,10 +154,21 @@ const noIntroducedIdentifiers = {
145
154
  calleeName: null,
146
155
  needsFrameHook: false,
147
156
  };
148
- const addKeyframe = ({ expression, frame, value, }) => {
157
+ const addKeyframe = ({ expression, key, frame, value, schema, }) => {
158
+ if (!(0, studio_shared_1.isSchemaFieldKeyframable)({ schema, key })) {
159
+ throw new Error(`Cannot add keyframe: "${key}" is not keyframable`);
160
+ }
149
161
  const existing = getInterpolationExpression(expression);
150
162
  const newOutput = (0, update_nested_prop_1.parseValueExpression)(value);
151
163
  if (existing) {
164
+ const existingCalleeName = existing.callee.type === 'Identifier'
165
+ ? existing.callee.name
166
+ : 'interpolate';
167
+ const schemaCalleeName = (0, studio_shared_1.getKeyframeInterpolationFunctionForSchemaField)({
168
+ schema,
169
+ key,
170
+ });
171
+ const nextCalleeName = schemaCalleeName !== null && schemaCalleeName !== void 0 ? schemaCalleeName : existingCalleeName;
152
172
  const existingIndex = existing.keyframes.findIndex((keyframe) => keyframe.frame === frame);
153
173
  const nextKeyframes = existingIndex === -1
154
174
  ? [...existing.keyframes, { frame, output: newOutput, value }]
@@ -157,34 +177,38 @@ const addKeyframe = ({ expression, frame, value, }) => {
157
177
  : keyframe);
158
178
  return {
159
179
  expression: createInterpolateExpression({
160
- callee: existing.callee,
180
+ callee: b.identifier(nextCalleeName),
161
181
  input: existing.input,
162
182
  extraArgs: existing.extraArgs,
163
183
  keyframes: nextKeyframes,
164
184
  }),
165
- introduced: noIntroducedIdentifiers,
185
+ introduced: {
186
+ calleeName: schemaCalleeName && schemaCalleeName !== existingCalleeName
187
+ ? schemaCalleeName
188
+ : null,
189
+ needsFrameHook: false,
190
+ },
166
191
  };
167
192
  }
168
193
  if (!(0, can_update_sequence_props_1.isStaticValue)(expression)) {
169
194
  throw new Error('Cannot add keyframe to computed expression');
170
195
  }
171
196
  const staticValue = (0, can_update_sequence_props_1.extractStaticValue)(expression);
172
- const staticOutput = (0, update_nested_prop_1.parseValueExpression)(staticValue);
173
- const keyframes = frame === 0
174
- ? [{ frame, output: newOutput, value }]
175
- : [
176
- { frame: 0, output: staticOutput, value: staticValue },
177
- { frame, output: newOutput, value },
178
- ];
197
+ const keyframes = [{ frame, output: newOutput, value }];
179
198
  const callee = getInterpolationCalleeForValues({
199
+ schema,
200
+ key,
180
201
  staticValue,
181
202
  newValue: value,
182
203
  });
204
+ const extraArgs = callee.type === 'Identifier' && callee.name === 'interpolateColors'
205
+ ? []
206
+ : [createClampOptionsExpression()];
183
207
  return {
184
208
  expression: createInterpolateExpression({
185
209
  callee,
186
210
  input: b.identifier('frame'),
187
- extraArgs: [],
211
+ extraArgs,
188
212
  keyframes,
189
213
  }),
190
214
  introduced: {
@@ -205,6 +229,9 @@ const removeKeyframe = ({ expression, frame, }) => {
205
229
  throw new Error(`Cannot remove keyframe at frame ${frame}: not found`);
206
230
  }
207
231
  const nextKeyframes = existing.keyframes.filter((_keyframe, index) => index !== keyframeIndex);
232
+ if (nextKeyframes.length === 0) {
233
+ return existing.keyframes[keyframeIndex].output;
234
+ }
208
235
  return createInterpolateExpression({
209
236
  callee: existing.callee,
210
237
  input: existing.input,
@@ -212,12 +239,14 @@ const removeKeyframe = ({ expression, frame, }) => {
212
239
  keyframes: nextKeyframes,
213
240
  });
214
241
  };
215
- const applyKeyframeOperation = ({ expression, operation, }) => {
242
+ const applyKeyframeOperation = ({ expression, key, operation, schema, }) => {
216
243
  if (operation.type === 'add') {
217
244
  return addKeyframe({
218
245
  expression,
246
+ key,
219
247
  frame: operation.frame,
220
248
  value: operation.value,
249
+ schema,
221
250
  });
222
251
  }
223
252
  return {
@@ -270,6 +299,30 @@ const findObjectProperty = (objExpr, propertyName) => {
270
299
  : objExpr.properties[propIndex],
271
300
  };
272
301
  };
302
+ const findFieldInSchema = (schema, key) => {
303
+ if (key in schema) {
304
+ return schema[key];
305
+ }
306
+ for (const field of Object.values(schema)) {
307
+ if (field.type !== 'enum') {
308
+ continue;
309
+ }
310
+ for (const variant of Object.values(field.variants)) {
311
+ const found = findFieldInSchema(variant, key);
312
+ if (found) {
313
+ return found;
314
+ }
315
+ }
316
+ }
317
+ return undefined;
318
+ };
319
+ const getInitialValueForMissingProp = ({ schema, key, newValue, }) => {
320
+ const field = schema ? findFieldInSchema(schema, key) : undefined;
321
+ if (field && field.type !== 'hidden' && field.default !== undefined) {
322
+ return field.default;
323
+ }
324
+ return newValue;
325
+ };
273
326
  const getObjectExpression = (attr) => {
274
327
  if (!attr.value || attr.value.type !== 'JSXExpressionContainer') {
275
328
  return null;
@@ -279,11 +332,31 @@ const getObjectExpression = (attr) => {
279
332
  }
280
333
  return attr.value.expression;
281
334
  };
282
- const getSequenceWritableProp = ({ attributes, key, }) => {
335
+ const createJsxExpressionAttribute = (key, expression) => {
336
+ return b.jsxAttribute(b.jsxIdentifier(key), b.jsxExpressionContainer(expression));
337
+ };
338
+ const createObjectProperty = (key, value) => b.objectProperty(b.identifier(key), value);
339
+ const createObjectExpressionAttribute = ({ parentKey, childKey, expression, }) => {
340
+ return createJsxExpressionAttribute(parentKey, b.objectExpression([
341
+ createObjectProperty(childKey, expression),
342
+ ]));
343
+ };
344
+ const createMissingPropExpression = (missingPropInitialValue) => {
345
+ return (0, update_nested_prop_1.parseValueExpression)(missingPropInitialValue.value);
346
+ };
347
+ const getSequenceWritableProp = ({ attributes, key, missingPropInitialValue, }) => {
283
348
  const dotIndex = key.indexOf('.');
284
349
  if (dotIndex === -1) {
285
350
  const { attr: topLevelAttr } = findJsxAttribute(attributes, key);
286
351
  if (!topLevelAttr) {
352
+ if (missingPropInitialValue) {
353
+ return {
354
+ expression: createMissingPropExpression(missingPropInitialValue),
355
+ setExpression: (nextExpression) => {
356
+ attributes.push(createJsxExpressionAttribute(key, nextExpression));
357
+ },
358
+ };
359
+ }
287
360
  throw new Error(`Cannot update keyframes: "${key}" is not set`);
288
361
  }
289
362
  const expression = getExpressionFromJsxAttribute(topLevelAttr);
@@ -301,6 +374,18 @@ const getSequenceWritableProp = ({ attributes, key, }) => {
301
374
  const childKey = key.slice(dotIndex + 1);
302
375
  const { attr: parentAttr } = findJsxAttribute(attributes, parentKey);
303
376
  if (!parentAttr) {
377
+ if (missingPropInitialValue) {
378
+ return {
379
+ expression: createMissingPropExpression(missingPropInitialValue),
380
+ setExpression: (nextExpression) => {
381
+ attributes.push(createObjectExpressionAttribute({
382
+ parentKey,
383
+ childKey,
384
+ expression: nextExpression,
385
+ }));
386
+ },
387
+ };
388
+ }
304
389
  throw new Error(`Cannot update keyframes: "${parentKey}" is not set`);
305
390
  }
306
391
  const objExpr = getObjectExpression(parentAttr);
@@ -309,6 +394,14 @@ const getSequenceWritableProp = ({ attributes, key, }) => {
309
394
  }
310
395
  const { prop } = findObjectProperty(objExpr, childKey);
311
396
  if (!prop) {
397
+ if (missingPropInitialValue) {
398
+ return {
399
+ expression: createMissingPropExpression(missingPropInitialValue),
400
+ setExpression: (nextExpression) => {
401
+ objExpr.properties.push(createObjectProperty(childKey, nextExpression));
402
+ },
403
+ };
404
+ }
312
405
  throw new Error(`Cannot update keyframes: "${key}" is not set`);
313
406
  }
314
407
  return {
@@ -318,7 +411,7 @@ const getSequenceWritableProp = ({ attributes, key, }) => {
318
411
  },
319
412
  };
320
413
  };
321
- const updateSequenceKeyframesAst = ({ input, nodePath, updates, }) => {
414
+ const updateSequenceKeyframesAst = ({ input, nodePath, updates, schema, }) => {
322
415
  var _a;
323
416
  var _b;
324
417
  const ast = (0, parse_ast_1.parseAst)(input);
@@ -338,11 +431,22 @@ const updateSequenceKeyframesAst = ({ input, nodePath, updates, }) => {
338
431
  const prop = getSequenceWritableProp({
339
432
  attributes: node.attributes,
340
433
  key: update.key,
434
+ missingPropInitialValue: update.operation.type === 'add'
435
+ ? {
436
+ value: getInitialValueForMissingProp({
437
+ schema: schema !== null && schema !== void 0 ? schema : null,
438
+ key: update.key,
439
+ newValue: update.operation.value,
440
+ }),
441
+ }
442
+ : null,
341
443
  });
342
444
  oldValueStrings.push(recast.print(prop.expression).code);
343
445
  const { expression: nextExpression, introduced } = applyKeyframeOperation({
344
446
  expression: prop.expression,
447
+ key: update.key,
345
448
  operation: update.operation,
449
+ schema: schema !== null && schema !== void 0 ? schema : null,
346
450
  });
347
451
  newValueStrings.push(recast.print(nextExpression).code);
348
452
  prop.setExpression(nextExpression);
@@ -361,28 +465,41 @@ const updateSequenceKeyframesAst = ({ input, nodePath, updates, }) => {
361
465
  }
362
466
  }
363
467
  (0, ensure_imports_and_frame_hook_1.ensureRemotionImports)(ast, requiredImports);
468
+ const updatedNodePath = (0, can_update_sequence_props_1.findNodePathForJsxElement)(ast, node);
469
+ if (!updatedNodePath) {
470
+ throw new Error('Could not find updated JSX element location after updating keyframes');
471
+ }
364
472
  return {
365
473
  serialized: (0, parse_ast_1.serializeAst)(ast),
366
474
  oldValueStrings,
367
475
  newValueStrings,
368
476
  logLine: (_b = (_a = node.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _b !== void 0 ? _b : 1,
477
+ updatedNodePath,
369
478
  };
370
479
  };
371
480
  exports.updateSequenceKeyframesAst = updateSequenceKeyframesAst;
372
- const updateSequenceKeyframes = async ({ input, nodePath, updates, prettierConfigOverride, }) => {
373
- const { serialized, oldValueStrings, newValueStrings, logLine } = (0, exports.updateSequenceKeyframesAst)({
481
+ const updateSequenceKeyframes = async ({ input, nodePath, updates, schema, prettierConfigOverride, }) => {
482
+ const { serialized, oldValueStrings, newValueStrings, logLine, updatedNodePath, } = (0, exports.updateSequenceKeyframesAst)({
374
483
  input,
375
484
  nodePath,
376
485
  updates,
486
+ schema,
377
487
  });
378
488
  const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
379
489
  input: serialized,
380
490
  prettierConfigOverride,
381
491
  });
382
- return { output, formatted, oldValueStrings, newValueStrings, logLine };
492
+ return {
493
+ output,
494
+ formatted,
495
+ oldValueStrings,
496
+ newValueStrings,
497
+ logLine,
498
+ updatedNodePath,
499
+ };
383
500
  };
384
501
  exports.updateSequenceKeyframes = updateSequenceKeyframes;
385
- const updateEffectKeyframesAst = ({ input, sequenceNodePath, effectIndex, updates, }) => {
502
+ const updateEffectKeyframesAst = ({ input, sequenceNodePath, effectIndex, updates, schema, }) => {
386
503
  var _a, _b;
387
504
  var _c, _d, _e;
388
505
  const ast = (0, parse_ast_1.parseAst)(input);
@@ -417,7 +534,9 @@ const updateEffectKeyframesAst = ({ input, sequenceNodePath, effectIndex, update
417
534
  oldValueStrings.push(recast.print(prop.value).code);
418
535
  const { expression: nextExpression, introduced } = applyKeyframeOperation({
419
536
  expression: prop.value,
537
+ key: update.key,
420
538
  operation: update.operation,
539
+ schema: schema !== null && schema !== void 0 ? schema : null,
421
540
  });
422
541
  newValueStrings.push(recast.print(nextExpression).code);
423
542
  prop.value = nextExpression;
@@ -436,21 +555,27 @@ const updateEffectKeyframesAst = ({ input, sequenceNodePath, effectIndex, update
436
555
  }
437
556
  }
438
557
  (0, ensure_imports_and_frame_hook_1.ensureRemotionImports)(ast, requiredImports);
558
+ const updatedSequenceNodePath = (0, can_update_sequence_props_1.findNodePathForJsxElement)(ast, jsx);
559
+ if (!updatedSequenceNodePath) {
560
+ throw new Error('Could not find updated JSX element location after updating effect keyframes');
561
+ }
439
562
  return {
440
563
  serialized: (0, parse_ast_1.serializeAst)(ast),
441
564
  oldValueStrings,
442
565
  newValueStrings,
443
566
  logLine: (_e = (_d = (_a = call.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,
444
567
  effectCallee,
568
+ updatedSequenceNodePath,
445
569
  };
446
570
  };
447
571
  exports.updateEffectKeyframesAst = updateEffectKeyframesAst;
448
- const updateEffectKeyframes = async ({ input, sequenceNodePath, effectIndex, updates, prettierConfigOverride, }) => {
449
- const { serialized, oldValueStrings, newValueStrings, logLine, effectCallee } = (0, exports.updateEffectKeyframesAst)({
572
+ const updateEffectKeyframes = async ({ input, sequenceNodePath, effectIndex, updates, schema, prettierConfigOverride, }) => {
573
+ const { serialized, oldValueStrings, newValueStrings, logLine, effectCallee, updatedSequenceNodePath, } = (0, exports.updateEffectKeyframesAst)({
450
574
  input,
451
575
  sequenceNodePath,
452
576
  effectIndex,
453
577
  updates,
578
+ schema,
454
579
  });
455
580
  const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
456
581
  input: serialized,
@@ -463,6 +588,7 @@ const updateEffectKeyframes = async ({ input, sequenceNodePath, effectIndex, upd
463
588
  newValueStrings,
464
589
  logLine,
465
590
  effectCallee,
591
+ updatedSequenceNodePath,
466
592
  };
467
593
  };
468
594
  exports.updateEffectKeyframes = updateEffectKeyframes;
@@ -35,9 +35,14 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.getAstNodePath = void 0;
37
37
  const recast = __importStar(require("recast"));
38
+ const import_agnostic_node_path_1 = require("./import-agnostic-node-path");
38
39
  const getAstNodePath = (ast, nodePath) => {
40
+ const resolvedNodePath = (0, import_agnostic_node_path_1.fromImportAgnosticNodePath)({ ast, nodePath });
41
+ if (!resolvedNodePath) {
42
+ return null;
43
+ }
39
44
  let current = new recast.types.NodePath(ast);
40
- for (const segment of nodePath) {
45
+ for (const segment of resolvedNodePath) {
41
46
  current = current.get(segment);
42
47
  if (current.value === null || current.value === undefined) {
43
48
  return null;
@@ -0,0 +1,10 @@
1
+ import type { File } from '@babel/types';
2
+ import type { SequenceNodePath } from 'remotion';
3
+ export declare const toImportAgnosticNodePath: ({ ast, nodePath, }: {
4
+ ast: File;
5
+ nodePath: SequenceNodePath;
6
+ }) => SequenceNodePath;
7
+ export declare const fromImportAgnosticNodePath: ({ ast, nodePath, }: {
8
+ ast: File;
9
+ nodePath: SequenceNodePath;
10
+ }) => SequenceNodePath | null;
@@ -0,0 +1,154 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fromImportAgnosticNodePath = exports.toImportAgnosticNodePath = void 0;
4
+ const getActualIndex = ({ items, agnosticIndex, shouldIgnore, context, }) => {
5
+ let seenIncludedNodes = 0;
6
+ for (let i = 0; i < items.length; i++) {
7
+ if (shouldIgnore(items[i], context)) {
8
+ continue;
9
+ }
10
+ if (seenIncludedNodes === agnosticIndex) {
11
+ return i;
12
+ }
13
+ seenIncludedNodes++;
14
+ }
15
+ return null;
16
+ };
17
+ const getAgnosticIndex = ({ items, actualIndex, shouldIgnore, context, }) => {
18
+ if (actualIndex < 0 || actualIndex >= items.length) {
19
+ return null;
20
+ }
21
+ let seenIncludedNodes = 0;
22
+ for (let i = 0; i <= actualIndex; i++) {
23
+ if (shouldIgnore(items[i], context)) {
24
+ continue;
25
+ }
26
+ if (i === actualIndex) {
27
+ return seenIncludedNodes;
28
+ }
29
+ seenIncludedNodes++;
30
+ }
31
+ return null;
32
+ };
33
+ const getUseCurrentFrameLocalNames = (ast) => {
34
+ var _a;
35
+ var _b;
36
+ const names = new Set(['useCurrentFrame']);
37
+ for (const statement of ast.program.body) {
38
+ if (statement.type !== 'ImportDeclaration' ||
39
+ statement.source.value !== 'remotion') {
40
+ continue;
41
+ }
42
+ for (const specifier of statement.specifiers) {
43
+ if (specifier.type === 'ImportSpecifier' &&
44
+ specifier.imported.type === 'Identifier' &&
45
+ specifier.imported.name === 'useCurrentFrame') {
46
+ names.add((_b = (_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : 'useCurrentFrame');
47
+ }
48
+ }
49
+ }
50
+ return names;
51
+ };
52
+ const isUseCurrentFrameCall = (node, useCurrentFrameLocalNames) => {
53
+ return ((node === null || node === void 0 ? void 0 : node.type) === 'CallExpression' &&
54
+ node.callee.type === 'Identifier' &&
55
+ useCurrentFrameLocalNames.has(node.callee.name));
56
+ };
57
+ const isUseCurrentFrameStatement = (node, useCurrentFrameLocalNames) => {
58
+ if (node.type === 'ExpressionStatement') {
59
+ return isUseCurrentFrameCall(node.expression, useCurrentFrameLocalNames);
60
+ }
61
+ if (node.type !== 'VariableDeclaration' || node.declarations.length !== 1) {
62
+ return false;
63
+ }
64
+ return isUseCurrentFrameCall(node.declarations[0].init, useCurrentFrameLocalNames);
65
+ };
66
+ const getIgnoredNodePredicate = (ast) => {
67
+ const useCurrentFrameLocalNames = getUseCurrentFrameLocalNames(ast);
68
+ return (node, { parent, property }) => {
69
+ if (parent.type === 'Program' &&
70
+ property === 'body' &&
71
+ node.type === 'ImportDeclaration') {
72
+ return true;
73
+ }
74
+ if (parent.type === 'BlockStatement' && property === 'body') {
75
+ return isUseCurrentFrameStatement(node, useCurrentFrameLocalNames);
76
+ }
77
+ return false;
78
+ };
79
+ };
80
+ const getChild = (value, segment) => {
81
+ var _a, _b;
82
+ if (value === null || value === undefined) {
83
+ return null;
84
+ }
85
+ if (Array.isArray(value)) {
86
+ return (_a = value[segment]) !== null && _a !== void 0 ? _a : null;
87
+ }
88
+ if (typeof value !== 'object') {
89
+ return null;
90
+ }
91
+ return (_b = value[segment]) !== null && _b !== void 0 ? _b : null;
92
+ };
93
+ const transformNodePathIndices = ({ ast, nodePath, direction, }) => {
94
+ const shouldIgnore = getIgnoredNodePredicate(ast);
95
+ const transformed = [];
96
+ let current = ast;
97
+ let arrayContext = null;
98
+ for (const segment of nodePath) {
99
+ if (typeof segment === 'string') {
100
+ const parent = current;
101
+ current = getChild(current, segment);
102
+ if (Array.isArray(current) &&
103
+ parent &&
104
+ typeof parent === 'object' &&
105
+ 'type' in parent) {
106
+ arrayContext = { parent: parent, property: segment };
107
+ }
108
+ else {
109
+ arrayContext = null;
110
+ }
111
+ transformed.push(segment);
112
+ continue;
113
+ }
114
+ if (!Array.isArray(current) || !arrayContext) {
115
+ current = getChild(current, segment);
116
+ transformed.push(segment);
117
+ continue;
118
+ }
119
+ const mappedIndex = direction === 'to-agnostic'
120
+ ? getAgnosticIndex({
121
+ items: current,
122
+ actualIndex: segment,
123
+ shouldIgnore,
124
+ context: arrayContext,
125
+ })
126
+ : getActualIndex({
127
+ items: current,
128
+ agnosticIndex: segment,
129
+ shouldIgnore,
130
+ context: arrayContext,
131
+ });
132
+ if (mappedIndex === null) {
133
+ if (direction === 'from-agnostic') {
134
+ return null;
135
+ }
136
+ current = getChild(current, segment);
137
+ transformed.push(segment);
138
+ continue;
139
+ }
140
+ current = getChild(current, direction === 'to-agnostic' ? segment : mappedIndex);
141
+ arrayContext = null;
142
+ transformed.push(mappedIndex);
143
+ }
144
+ return transformed;
145
+ };
146
+ const toImportAgnosticNodePath = ({ ast, nodePath, }) => {
147
+ var _a;
148
+ return ((_a = transformNodePathIndices({ ast, nodePath, direction: 'to-agnostic' })) !== null && _a !== void 0 ? _a : nodePath);
149
+ };
150
+ exports.toImportAgnosticNodePath = toImportAgnosticNodePath;
151
+ const fromImportAgnosticNodePath = ({ ast, nodePath, }) => {
152
+ return transformNodePathIndices({ ast, nodePath, direction: 'from-agnostic' });
153
+ };
154
+ exports.fromImportAgnosticNodePath = fromImportAgnosticNodePath;
@@ -0,0 +1,16 @@
1
+ import type { File, ImportDeclaration, ImportSpecifier } from '@babel/types';
2
+ export declare const getImportedName: (specifier: ImportSpecifier) => string;
3
+ export declare const findImportDeclaration: (ast: File, sourcePath: string) => ImportDeclaration | null;
4
+ export declare const insertImportDeclaration: (ast: File, importDeclaration: ImportDeclaration) => void;
5
+ export declare const normalizeImportSpacing: (input: string) => string;
6
+ export declare const ensureNamedImport: ({ ast, importedName, sourcePath, localName, }: {
7
+ ast: File;
8
+ importedName: string;
9
+ sourcePath: string;
10
+ localName: string;
11
+ }) => string;
12
+ export declare const ensureNamedImports: ({ ast, importedNames, sourcePath, }: {
13
+ ast: File;
14
+ importedNames: ReadonlySet<string>;
15
+ sourcePath: string;
16
+ }) => void;