@remotion/studio-server 4.0.513 → 4.0.515

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 (67) hide show
  1. package/dist/codemods/delete-jsx-node.d.ts +2 -5
  2. package/dist/codemods/delete-jsx-node.js +23 -341
  3. package/dist/codemods/duplicate-composition.d.ts +1 -9
  4. package/dist/codemods/duplicate-composition.js +3 -49
  5. package/dist/codemods/format-inline-content.d.ts +0 -4
  6. package/dist/codemods/format-inline-content.js +7 -46
  7. package/dist/codemods/recast-mods.js +0 -18
  8. package/dist/codemods/reorder-sequence.d.ts +2 -2
  9. package/dist/codemods/reorder-sequence.js +12 -112
  10. package/dist/codemods/split-jsx-sequence.d.ts +1 -2
  11. package/dist/codemods/split-jsx-sequence.js +11 -298
  12. package/dist/codemods/split-video-from-audio.d.ts +15 -0
  13. package/dist/codemods/split-video-from-audio.js +15 -0
  14. package/dist/codemods/update-default-props.d.ts +2 -6
  15. package/dist/codemods/update-default-props.js +12 -220
  16. package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.d.ts +1 -4
  17. package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.js +5 -102
  18. package/dist/codemods/update-keyframes/update-keyframes.d.ts +8 -93
  19. package/dist/codemods/update-keyframes/update-keyframes.js +11 -1302
  20. package/dist/detect-outdated-remotion-skills.d.ts +7 -0
  21. package/dist/detect-outdated-remotion-skills.js +11 -5
  22. package/dist/helpers/open-file-for-writing-without-symlinks.d.ts +4 -0
  23. package/dist/helpers/open-file-for-writing-without-symlinks.js +52 -0
  24. package/dist/helpers/resolve-composition-component.d.ts +3 -11
  25. package/dist/helpers/resolve-composition-component.js +38 -1495
  26. package/dist/helpers/video-config-values.js +25 -6
  27. package/dist/index.d.ts +3 -2
  28. package/dist/index.js +1 -0
  29. package/dist/max-timeline-tracks.d.ts +2 -1
  30. package/dist/max-timeline-tracks.js +10 -4
  31. package/dist/preview-server/api-routes.js +4 -0
  32. package/dist/preview-server/routes/add-effect.js +1 -1
  33. package/dist/preview-server/routes/apply-codemod.js +3 -3
  34. package/dist/preview-server/routes/apply-visual-control-change.js +3 -3
  35. package/dist/preview-server/routes/can-update-sequence-props.js +107 -24
  36. package/dist/preview-server/routes/delete-effect-keyframe.d.ts +3 -0
  37. package/dist/preview-server/routes/delete-effect-keyframe.js +89 -0
  38. package/dist/preview-server/routes/delete-effect.js +1 -1
  39. package/dist/preview-server/routes/delete-jsx-node.js +1 -1
  40. package/dist/preview-server/routes/delete-sequence-keyframe.d.ts +3 -0
  41. package/dist/preview-server/routes/delete-sequence-keyframe.js +82 -0
  42. package/dist/preview-server/routes/duplicate-effect.js +1 -1
  43. package/dist/preview-server/routes/duplicate-jsx-node.js +1 -1
  44. package/dist/preview-server/routes/element-install-plan.d.ts +1 -1
  45. package/dist/preview-server/routes/insert-element.js +2 -2
  46. package/dist/preview-server/routes/insert-jsx-element.js +1 -1
  47. package/dist/preview-server/routes/install-dependency.js +8 -2
  48. package/dist/preview-server/routes/log-updates/log-effect-update.js +2 -1
  49. package/dist/preview-server/routes/log-updates/log-update.js +2 -1
  50. package/dist/preview-server/routes/paste-effects.js +1 -1
  51. package/dist/preview-server/routes/remotion-skills-info.d.ts +7 -0
  52. package/dist/preview-server/routes/remotion-skills-info.js +24 -0
  53. package/dist/preview-server/routes/reorder-effect.js +1 -1
  54. package/dist/preview-server/routes/reorder-sequence.js +1 -1
  55. package/dist/preview-server/routes/save-props-mutex.d.ts +1 -0
  56. package/dist/preview-server/routes/save-props-mutex.js +11 -0
  57. package/dist/preview-server/routes/source-file-write-queue.d.ts +1 -0
  58. package/dist/preview-server/routes/source-file-write-queue.js +11 -2
  59. package/dist/preview-server/routes/split-jsx-sequence.js +1 -1
  60. package/dist/preview-server/routes/split-video-from-audio.d.ts +3 -0
  61. package/dist/preview-server/routes/split-video-from-audio.js +80 -0
  62. package/dist/preview-server/routes/update-default-props.js +1 -1
  63. package/dist/preview-server/start-server.js +188 -140
  64. package/dist/preview-server/undo-stack.d.ts +3 -52
  65. package/dist/preview-server/update-available.js +4 -4
  66. package/dist/routes.js +36 -5
  67. package/package.json +8 -8
@@ -1,37 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  var __importDefault = (this && this.__importDefault) || function (mod) {
36
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
37
4
  };
@@ -39,1477 +6,53 @@ Object.defineProperty(exports, "__esModule", { value: true });
39
6
  exports.insertJsxElementIntoComposition = exports.resolveCompositionComponent = exports.resolveCompositionComponentWithFile = void 0;
40
7
  const node_fs_1 = __importDefault(require("node:fs"));
41
8
  const node_path_1 = __importDefault(require("node:path"));
42
- const studio_shared_1 = require("@remotion/studio-shared");
43
- const recast = __importStar(require("recast"));
44
- const no_react_1 = require("remotion/no-react");
9
+ const studio_codemods_1 = require("@remotion/studio-codemods");
45
10
  const format_file_content_1 = require("../codemods/format-file-content");
46
- const get_node_path_remappings_1 = require("../codemods/get-node-path-remappings");
47
- const parse_ast_1 = require("../codemods/parse-ast");
48
- const strip_parenthesized_extra_1 = require("../codemods/strip-parenthesized-extra");
49
- const update_nested_prop_1 = require("../codemods/update-nested-prop");
50
- const imports_1 = require("./imports");
51
11
  const svg_to_jsx_1 = require("./svg-to-jsx");
52
- const allowedFileExtensions = new Set(['.tsx', '.ts', '.jsx', '.js']);
53
- const extensionsToProbe = ['.tsx', '.ts', '.jsx', '.js'];
54
- const isInRemotionRoot = ({ remotionRoot, fileName, }) => {
55
- const relativePath = node_path_1.default.relative(remotionRoot, fileName);
56
- return !relativePath.startsWith('..') && !node_path_1.default.isAbsolute(relativePath);
57
- };
58
- const readSourceFile = ({ remotionRoot, fileName, }) => {
59
- const resolved = node_path_1.default.resolve(remotionRoot, fileName);
60
- if (!isInRemotionRoot({ remotionRoot, fileName: resolved })) {
61
- throw new Error(`Not allowed to open ${fileName}`);
62
- }
63
- if (!allowedFileExtensions.has(node_path_1.default.extname(resolved))) {
64
- throw new Error(`Not allowed to open ${fileName}`);
65
- }
66
- return node_fs_1.default.promises.readFile(resolved, 'utf-8');
67
- };
68
- const getAttributeName = (attribute) => {
69
- if (attribute.name.type !== 'JSXIdentifier') {
70
- return null;
71
- }
72
- return attribute.name.name;
73
- };
74
- const findAttribute = (element, name) => {
75
- return element.openingElement.attributes.find((attribute) => {
76
- if (attribute.type !== 'JSXAttribute') {
77
- return false;
78
- }
79
- return getAttributeName(attribute) === name;
80
- });
81
- };
82
- const getStringAttributeValue = (element, name) => {
83
- const attribute = findAttribute(element, name);
84
- if (!(attribute === null || attribute === void 0 ? void 0 : attribute.value)) {
85
- return null;
86
- }
87
- if (attribute.value.type === 'StringLiteral') {
88
- return attribute.value.value;
89
- }
90
- if (attribute.value.type === 'JSXExpressionContainer' &&
91
- attribute.value.expression.type === 'StringLiteral') {
92
- return attribute.value.expression.value;
93
- }
94
- return null;
95
- };
96
- const findCompositionElement = ({ ast, compositionId, }) => {
97
- let found = null;
98
- recast.types.visit(ast, {
99
- visitJSXElement(astPath) {
100
- if (found) {
101
- return false;
102
- }
103
- const node = astPath.node;
104
- const openingName = node.openingElement.name;
105
- if (openingName.type === 'JSXIdentifier' &&
106
- (openingName.name === 'Composition' || openingName.name === 'Still') &&
107
- getStringAttributeValue(node, 'id') === compositionId) {
108
- found = node;
109
- return false;
110
- }
111
- this.traverse(astPath);
112
- return undefined;
113
- },
114
- });
115
- return found;
116
- };
117
- const getComponentIdentifier = (element) => {
118
- const attribute = findAttribute(element, 'component');
119
- if (!(attribute === null || attribute === void 0 ? void 0 : attribute.value) ||
120
- attribute.value.type !== 'JSXExpressionContainer' ||
121
- attribute.value.expression.type !== 'Identifier') {
122
- return null;
123
- }
124
- return attribute.value.expression.name;
125
- };
126
- const isRecord = (value) => {
127
- return typeof value === 'object' && value !== null && !Array.isArray(value);
128
- };
129
- const findDynamicImportPath = (value) => {
130
- if (!isRecord(value)) {
131
- return null;
132
- }
133
- if (value.type === 'CallExpression' &&
134
- isRecord(value.callee) &&
135
- value.callee.type === 'Import' &&
136
- Array.isArray(value.arguments) &&
137
- isRecord(value.arguments[0]) &&
138
- value.arguments[0].type === 'StringLiteral' &&
139
- typeof value.arguments[0].value === 'string') {
140
- return value.arguments[0].value;
141
- }
142
- for (const [key, child] of Object.entries(value)) {
143
- if (key === 'loc' ||
144
- key === 'start' ||
145
- key === 'end' ||
146
- key === 'comments' ||
147
- key === 'leadingComments' ||
148
- key === 'trailingComments' ||
149
- key === 'innerComments' ||
150
- key === 'extra' ||
151
- key === 'original') {
152
- continue;
153
- }
154
- if (Array.isArray(child)) {
155
- for (const item of child) {
156
- const nestedResult = findDynamicImportPath(item);
157
- if (nestedResult) {
158
- return nestedResult;
159
- }
160
- }
161
- continue;
162
- }
163
- const childResult = findDynamicImportPath(child);
164
- if (childResult) {
165
- return childResult;
166
- }
167
- }
168
- return null;
169
- };
170
- const getLazyImportPath = (element) => {
171
- const attribute = findAttribute(element, 'lazyComponent');
172
- if (!(attribute === null || attribute === void 0 ? void 0 : attribute.value) || attribute.value.type !== 'JSXExpressionContainer') {
173
- return null;
174
- }
175
- return findDynamicImportPath(attribute.value.expression);
176
- };
177
- const findImportTarget = ({ ast, componentName, }) => {
178
- let found = null;
179
- recast.types.visit(ast, {
180
- visitImportDeclaration(astPath) {
181
- var _a;
182
- if (found) {
183
- return false;
184
- }
185
- const node = astPath.node;
186
- if (typeof node.source.value !== 'string') {
187
- return false;
188
- }
189
- const matchingSpecifier = (_a = node.specifiers) === null || _a === void 0 ? void 0 : _a.find((specifier) => {
190
- var _a;
191
- return ((_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) === componentName;
192
- });
193
- if (!matchingSpecifier) {
194
- return false;
195
- }
196
- if (matchingSpecifier.type === 'ImportDefaultSpecifier') {
197
- found = {
198
- importPath: node.source.value,
199
- exportName: 'default',
200
- };
201
- return false;
202
- }
203
- if (matchingSpecifier.type === 'ImportSpecifier' &&
204
- matchingSpecifier.imported.type === 'Identifier') {
205
- found = {
206
- importPath: node.source.value,
207
- exportName: matchingSpecifier.imported.name,
208
- };
209
- return false;
210
- }
211
- if (matchingSpecifier.type === 'ImportSpecifier' &&
212
- matchingSpecifier.imported.type === 'StringLiteral') {
213
- found = {
214
- importPath: node.source.value,
215
- exportName: matchingSpecifier.imported.value,
216
- };
217
- return false;
218
- }
219
- return false;
220
- },
221
- });
222
- return found;
223
- };
224
- const getExportedName = (exported) => {
225
- if (!exported) {
226
- return null;
227
- }
228
- if (!isRecord(exported)) {
229
- return null;
230
- }
231
- if (exported.type === 'Identifier' && typeof exported.name === 'string') {
232
- return exported.name;
233
- }
234
- if (exported.type === 'StringLiteral' && typeof exported.value === 'string') {
235
- return exported.value;
236
- }
237
- return null;
238
- };
239
- const getSpecifierLocalName = (specifier) => {
240
- if (specifier.local.type === 'Identifier') {
241
- return specifier.local.name;
242
- }
243
- return null;
244
- };
245
- const findReExportTargets = ({ ast, exportName, }) => {
246
- const targets = [];
247
- recast.types.visit(ast, {
248
- visitExportNamedDeclaration(astPath) {
249
- var _a;
250
- const node = astPath.node;
251
- for (const specifier of node.specifiers) {
252
- if (specifier.type !== 'ExportSpecifier') {
253
- continue;
254
- }
255
- const exportedName = getExportedName(specifier.exported);
256
- if (exportedName !== exportName) {
257
- continue;
258
- }
259
- const localName = getSpecifierLocalName(specifier);
260
- if (!localName) {
261
- continue;
262
- }
263
- // Support barrel files that import a component and export it in a
264
- // separate declaration. See https://github.com/remotion-dev/remotion/issues/9172.
265
- if (typeof ((_a = node.source) === null || _a === void 0 ? void 0 : _a.value) !== 'string') {
266
- const importTarget = findImportTarget({
267
- ast,
268
- componentName: localName,
269
- });
270
- if (importTarget) {
271
- targets.push(importTarget);
272
- }
273
- continue;
274
- }
275
- targets.push({
276
- importPath: node.source.value,
277
- exportName: localName === 'default' ? 'default' : localName,
278
- });
279
- }
280
- return false;
281
- },
282
- visitExportAllDeclaration(astPath) {
283
- const node = astPath.node;
284
- if (typeof node.source.value !== 'string') {
285
- return false;
286
- }
287
- targets.push({
288
- importPath: node.source.value,
289
- exportName,
290
- });
291
- return false;
292
- },
293
- });
294
- return targets;
295
- };
296
- const resolveImportPath = ({ importPath, fromFile, }) => {
297
- if (!importPath.startsWith('.')) {
298
- throw new Error(`Cannot resolve non-relative import ${importPath}`);
299
- }
300
- const basePath = node_path_1.default.resolve(node_path_1.default.dirname(fromFile), importPath);
301
- const candidates = node_path_1.default.extname(basePath)
302
- ? [basePath]
303
- : [
304
- ...extensionsToProbe.map((extension) => `${basePath}${extension}`),
305
- ...extensionsToProbe.map((extension) => node_path_1.default.join(basePath, `index${extension}`)),
306
- ];
307
- const existingFile = candidates.find((candidate) => {
308
- return node_fs_1.default.existsSync(candidate) && node_fs_1.default.statSync(candidate).isFile();
309
- });
310
- if (!existingFile) {
311
- throw new Error(`Could not find imported component file ${importPath}`);
312
- }
313
- return existingFile;
314
- };
315
- const locationFromNode = (node) => {
316
- if (!node.loc) {
317
- return null;
318
- }
319
- return {
320
- line: node.loc.start.line,
321
- column: node.loc.start.column,
322
- };
323
- };
324
- const findLocalSymbolLocation = ({ ast, name, }) => {
325
- let location = null;
326
- // Recast can omit the declaration location for exported functions and
327
- // classes, including components resolved through barrel files. The identifier
328
- // keeps its location. See https://github.com/remotion-dev/remotion/issues/9172.
329
- recast.types.visit(ast, {
330
- visitVariableDeclarator(astPath) {
331
- if (location) {
332
- return false;
333
- }
334
- const { node } = astPath;
335
- if (node.id.type === 'Identifier' && node.id.name === name) {
336
- location = locationFromNode(node.id);
337
- return false;
338
- }
339
- this.traverse(astPath);
340
- return undefined;
341
- },
342
- visitFunctionDeclaration(astPath) {
343
- var _a;
344
- if (location) {
345
- return false;
346
- }
347
- const { node } = astPath;
348
- if (((_a = node.id) === null || _a === void 0 ? void 0 : _a.name) === name) {
349
- location = locationFromNode(node.id);
350
- return false;
351
- }
352
- this.traverse(astPath);
353
- return undefined;
354
- },
355
- visitClassDeclaration(astPath) {
356
- var _a;
357
- if (location) {
358
- return false;
359
- }
360
- const { node } = astPath;
361
- if (((_a = node.id) === null || _a === void 0 ? void 0 : _a.name) === name) {
362
- location = locationFromNode(node.id);
363
- return false;
364
- }
365
- this.traverse(astPath);
366
- return undefined;
367
- },
368
- });
369
- return location;
370
- };
371
- const findDefaultExportLocation = (ast) => {
372
- let location = null;
373
- let exportedIdentifier = null;
374
- recast.types.visit(ast, {
375
- visitExportDefaultDeclaration(astPath) {
376
- var _a;
377
- if (location || exportedIdentifier) {
378
- return false;
379
- }
380
- const { node } = astPath;
381
- if (node.declaration.type === 'Identifier') {
382
- exportedIdentifier = node.declaration.name;
383
- return false;
384
- }
385
- location = (_a = locationFromNode(node.declaration)) !== null && _a !== void 0 ? _a : locationFromNode(node);
386
- return false;
387
- },
388
- });
389
- if (exportedIdentifier) {
390
- return findLocalSymbolLocation({ ast, name: exportedIdentifier });
391
- }
392
- return location;
393
- };
394
- const findLocalComponentDeclaration = ({ ast, name, }) => {
395
- let declaration = null;
396
- recast.types.visit(ast, {
397
- visitVariableDeclarator(astPath) {
398
- if (declaration) {
399
- return false;
400
- }
401
- const { node } = astPath;
402
- if (node.id.type === 'Identifier' && node.id.name === name) {
403
- declaration = node;
404
- return false;
405
- }
406
- this.traverse(astPath);
407
- return undefined;
408
- },
409
- visitFunctionDeclaration(astPath) {
410
- var _a;
411
- if (declaration) {
412
- return false;
413
- }
414
- const { node } = astPath;
415
- if (((_a = node.id) === null || _a === void 0 ? void 0 : _a.name) === name) {
416
- declaration = node;
417
- return false;
418
- }
419
- this.traverse(astPath);
420
- return undefined;
421
- },
422
- visitClassDeclaration(astPath) {
423
- var _a;
424
- if (declaration) {
425
- return false;
426
- }
427
- const { node } = astPath;
428
- if (((_a = node.id) === null || _a === void 0 ? void 0 : _a.name) === name) {
429
- declaration = node;
430
- return false;
431
- }
432
- this.traverse(astPath);
433
- return undefined;
434
- },
435
- });
436
- return declaration;
437
- };
438
- const getTopLevelReturnStatement = (statements) => {
439
- const returnStatements = [];
440
- for (const statement of statements) {
441
- if (recast.types.namedTypes.ReturnStatement.check(statement)) {
442
- returnStatements.push(statement);
443
- }
444
- }
445
- if (returnStatements.length !== 1) {
446
- return null;
447
- }
448
- const singleReturn = returnStatements[0];
449
- const finalStatement = statements.at(-1);
450
- if (singleReturn !== finalStatement) {
451
- return null;
452
- }
453
- return singleReturn;
454
- };
455
- const getReturnedJsxFromFunction = (fn) => {
456
- if (fn.type === 'ArrowFunctionExpression') {
457
- if (fn.body.type === 'JSXElement' || fn.body.type === 'JSXFragment') {
458
- return fn.body;
459
- }
460
- if (fn.body.type !== 'BlockStatement') {
461
- return null;
462
- }
463
- const arrowReturnStatement = getTopLevelReturnStatement(fn.body.body);
464
- if (!(arrowReturnStatement === null || arrowReturnStatement === void 0 ? void 0 : arrowReturnStatement.argument)) {
465
- return null;
466
- }
467
- return arrowReturnStatement.argument.type === 'JSXElement' ||
468
- arrowReturnStatement.argument.type === 'JSXFragment'
469
- ? arrowReturnStatement.argument
470
- : null;
471
- }
472
- if (fn.body.type !== 'BlockStatement') {
473
- return null;
474
- }
475
- const returnStatement = getTopLevelReturnStatement(fn.body.body);
476
- if (!(returnStatement === null || returnStatement === void 0 ? void 0 : returnStatement.argument)) {
477
- return null;
478
- }
479
- return returnStatement.argument.type === 'JSXElement' ||
480
- returnStatement.argument.type === 'JSXFragment'
481
- ? returnStatement.argument
482
- : null;
483
- };
484
- const findRenderMethod = (declaration) => {
485
- const renderMethod = declaration.body.body.find((member) => {
486
- return (member.type === 'ClassMethod' &&
487
- member.kind === 'method' &&
488
- member.key.type === 'Identifier' &&
489
- member.key.name === 'render');
490
- });
491
- return (renderMethod === null || renderMethod === void 0 ? void 0 : renderMethod.type) === 'ClassMethod' ? renderMethod : null;
492
- };
493
- const getComponentRootNode = (declaration) => {
494
- if (declaration.type === 'VariableDeclarator') {
495
- if (!declaration.init ||
496
- (declaration.init.type !== 'ArrowFunctionExpression' &&
497
- declaration.init.type !== 'FunctionExpression')) {
498
- return null;
499
- }
500
- return getReturnedJsxFromFunction(declaration.init);
501
- }
502
- if (declaration.type === 'ArrowFunctionExpression' ||
503
- declaration.type === 'FunctionExpression' ||
504
- declaration.type === 'FunctionDeclaration') {
505
- return getReturnedJsxFromFunction(declaration);
506
- }
507
- if (declaration.type !== 'ClassDeclaration') {
508
- return null;
509
- }
510
- const renderMethod = findRenderMethod(declaration);
511
- if (!renderMethod) {
512
- return null;
513
- }
514
- const returnStatement = getTopLevelReturnStatement(renderMethod.body.body);
515
- if (!(returnStatement === null || returnStatement === void 0 ? void 0 : returnStatement.argument)) {
516
- return null;
517
- }
518
- return returnStatement.argument.type === 'JSXElement' ||
519
- returnStatement.argument.type === 'JSXFragment'
520
- ? returnStatement.argument
521
- : null;
522
- };
523
- const createSequenceElement = () => {
524
- return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier('Sequence'), []), recast.types.builders.jsxClosingElement(recast.types.builders.jsxIdentifier('Sequence')), []);
525
- };
526
- const createSequenceWithChild = ({ child, sequenceLocalName, }) => {
527
- return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(sequenceLocalName), []), recast.types.builders.jsxClosingElement(recast.types.builders.jsxIdentifier(sequenceLocalName)), [child]);
528
- };
529
- const createNumberAttribute = (name, value) => {
530
- return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier(name), recast.types.builders.jsxExpressionContainer(recast.types.builders.numericLiteral(value)));
531
- };
532
- const createStringAttribute = (name, value) => {
533
- return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier(name), recast.types.builders.stringLiteral(value));
534
- };
535
- const createBooleanAttribute = (name, value) => {
536
- return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier(name), recast.types.builders.jsxExpressionContainer(recast.types.builders.booleanLiteral(value)));
537
- };
538
- const translateDecimalPlaces = 1;
539
- const roundTranslateCoordinate = (value) => {
540
- const factor = 10 ** translateDecimalPlaces;
541
- const rounded = Math.round(value * factor) / factor;
542
- return Object.is(rounded, -0) ? 0 : rounded;
543
- };
544
- const formatTranslateValue = ({ x, y }) => `${roundTranslateCoordinate(x)}px ${roundTranslateCoordinate(y)}px`;
545
- const createStyleAttribute = (properties) => {
546
- return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier('style'), recast.types.builders.jsxExpressionContainer(recast.types.builders.objectExpression(properties)));
547
- };
548
- const getPositionStyleProperties = (position) => {
549
- const properties = [
550
- recast.types.builders.objectProperty(recast.types.builders.identifier('position'), recast.types.builders.stringLiteral('absolute')),
551
- ];
552
- if (position) {
553
- properties.push(recast.types.builders.objectProperty(recast.types.builders.identifier('translate'), recast.types.builders.stringLiteral(formatTranslateValue(position))));
554
- }
555
- return properties;
556
- };
557
- const createPositionAbsoluteStyleAttribute = (position) => {
558
- return createStyleAttribute(getPositionStyleProperties(position));
559
- };
560
- const createAssetStyleAttribute = ({ dimensions, position, }) => {
561
- return createStyleAttribute([
562
- ...getPositionStyleProperties(position),
563
- ...(dimensions
564
- ? [
565
- recast.types.builders.objectProperty(recast.types.builders.identifier('width'), recast.types.builders.numericLiteral(dimensions.width)),
566
- recast.types.builders.objectProperty(recast.types.builders.identifier('height'), recast.types.builders.numericLiteral(dimensions.height)),
567
- ]
568
- : []),
569
- ]);
570
- };
571
- const createStaticFileSrcAttribute = ({ staticFileLocalName, src, }) => {
572
- return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier('src'), recast.types.builders.jsxExpressionContainer(recast.types.builders.callExpression(recast.types.builders.identifier(staticFileLocalName), [recast.types.builders.stringLiteral(src)])));
573
- };
574
- const createComponentProp = ({ name, value, }) => {
575
- if (typeof value === 'number') {
576
- return createNumberAttribute(name, value);
577
- }
578
- if (typeof value === 'boolean') {
579
- return createBooleanAttribute(name, value);
580
- }
581
- return createStringAttribute(name, value);
582
- };
583
- const createStringSrcAttribute = (src) => {
584
- return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier('src'), recast.types.builders.stringLiteral(src));
585
- };
586
- const createSolidElement = ({ localName, width, height, position, }) => {
587
- return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
588
- createNumberAttribute('width', width),
589
- createNumberAttribute('height', height),
590
- createStringAttribute('color', 'gray'),
591
- createPositionAbsoluteStyleAttribute(position),
592
- ], true), null, []);
593
- };
594
- const createComponentElement = ({ addPositionStyle, from, localName, props, position, }) => {
595
- return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
596
- ...props.map(createComponentProp),
597
- ...(from === null ? [] : [createNumberAttribute('from', from)]),
598
- ...(addPositionStyle
599
- ? [createPositionAbsoluteStyleAttribute(position)]
600
- : []),
601
- ], true), null, []);
602
- };
603
- const createSequenceWrappedElement = ({ child, dimensions, durationInFrames, from, name, position, sequenceLocalName, }) => {
604
- return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(sequenceLocalName), [
605
- ...(from === null ? [] : [createNumberAttribute('from', from)]),
606
- ...(name === null ? [] : [createStringAttribute('name', name)]),
607
- ...(dimensions !== null
608
- ? [
609
- createNumberAttribute('width', dimensions.width),
610
- createNumberAttribute('height', dimensions.height),
611
- ]
612
- : []),
613
- ...(durationInFrames === null
614
- ? []
615
- : [createNumberAttribute('durationInFrames', durationInFrames)]),
616
- createPositionAbsoluteStyleAttribute(position),
617
- ], false), recast.types.builders.jsxClosingElement(recast.types.builders.jsxIdentifier(sequenceLocalName)), [child]);
618
- };
619
- const createAssetElement = ({ addPositionStyle, durationInFrames, from, localName, staticFileLocalName, src, dimensions, position, }) => {
620
- return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
621
- staticFileLocalName === null
622
- ? createStringSrcAttribute(src)
623
- : createStaticFileSrcAttribute({ staticFileLocalName, src }),
624
- ...(durationInFrames === null
625
- ? []
626
- : [createNumberAttribute('durationInFrames', durationInFrames)]),
627
- ...(from === null ? [] : [createNumberAttribute('from', from)]),
628
- ...(addPositionStyle
629
- ? [createAssetStyleAttribute({ dimensions, position })]
630
- : []),
631
- ], true), null, []);
632
- };
633
- const createSvgElement = async ({ from, interactiveLocalName, markup, position, }) => {
634
- var _a;
635
- var _b;
636
- const svgElement = await (0, svg_to_jsx_1.svgMarkupToJsx)(markup);
637
- const attributes = (_b = svgElement.openingElement.attributes) !== null && _b !== void 0 ? _b : [];
638
- svgElement.openingElement.attributes = attributes;
639
- if (from !== null) {
640
- attributes.push(createNumberAttribute('from', from));
641
- }
642
- const styleAttribute = attributes.find((attribute) => attribute.type === 'JSXAttribute' &&
643
- attribute.name.type === 'JSXIdentifier' &&
644
- attribute.name.name === 'style');
645
- const positionProperties = getPositionStyleProperties(position);
646
- if (styleAttribute === undefined) {
647
- attributes.push(createStyleAttribute(positionProperties));
648
- }
649
- else if (styleAttribute.type === 'JSXAttribute' &&
650
- ((_a = styleAttribute.value) === null || _a === void 0 ? void 0 : _a.type) === 'JSXExpressionContainer' &&
651
- styleAttribute.value.expression.type === 'ObjectExpression') {
652
- styleAttribute.value.expression.properties.push(...positionProperties);
653
- }
654
- else {
655
- throw new Error('Could not convert the root SVG style to JSX');
656
- }
657
- const interactiveSvgName = () => recast.types.builders.jsxMemberExpression(recast.types.builders.jsxIdentifier(interactiveLocalName), recast.types.builders.jsxIdentifier('Svg'));
658
- svgElement.openingElement.name = interactiveSvgName();
659
- if (svgElement.closingElement !== null &&
660
- svgElement.closingElement !== undefined) {
661
- svgElement.closingElement.name = interactiveSvgName();
662
- }
663
- return svgElement;
664
- };
665
- const createFragmentWithElement = (element) => {
666
- return recast.types.builders.jsxFragment(recast.types.builders.jsxOpeningFragment(), recast.types.builders.jsxClosingFragment(), [element]);
667
- };
668
- const replaceNullReturnInFunctionLike = ({ fn, element, }) => {
669
- var _a, _b;
670
- var _c, _d;
671
- if (fn.type === 'ArrowFunctionExpression' && fn.body.type === 'NullLiteral') {
672
- fn.body = createFragmentWithElement(element);
673
- return (_c = (_a = fn.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _c !== void 0 ? _c : 1;
674
- }
675
- if (fn.body.type !== 'BlockStatement') {
676
- return null;
677
- }
678
- const returnStatement = getTopLevelReturnStatement(fn.body.body);
679
- if (!(returnStatement === null || returnStatement === void 0 ? void 0 : returnStatement.argument) ||
680
- returnStatement.argument.type !== 'NullLiteral') {
681
- return null;
682
- }
683
- returnStatement.argument = createFragmentWithElement(element);
684
- return (_d = (_b = returnStatement.loc) === null || _b === void 0 ? void 0 : _b.start.line) !== null && _d !== void 0 ? _d : 1;
685
- };
686
- const addElementToNullComponentReturn = ({ declaration, element, }) => {
687
- var _a;
688
- var _b;
689
- if (declaration.type === 'VariableDeclarator') {
690
- if (!declaration.init ||
691
- (declaration.init.type !== 'ArrowFunctionExpression' &&
692
- declaration.init.type !== 'FunctionExpression')) {
693
- return null;
694
- }
695
- return replaceNullReturnInFunctionLike({ fn: declaration.init, element });
696
- }
697
- if (declaration.type === 'ArrowFunctionExpression' ||
698
- declaration.type === 'FunctionExpression' ||
699
- declaration.type === 'FunctionDeclaration') {
700
- return replaceNullReturnInFunctionLike({ fn: declaration, element });
701
- }
702
- if (declaration.type !== 'ClassDeclaration') {
703
- return null;
704
- }
705
- const renderMethod = findRenderMethod(declaration);
706
- if (!renderMethod) {
707
- return null;
708
- }
709
- const returnStatement = getTopLevelReturnStatement(renderMethod.body.body);
710
- if (!(returnStatement === null || returnStatement === void 0 ? void 0 : returnStatement.argument) ||
711
- returnStatement.argument.type !== 'NullLiteral') {
712
- return null;
713
- }
714
- returnStatement.argument = createFragmentWithElement(element);
715
- return (_b = (_a = returnStatement.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _b !== void 0 ? _b : 1;
716
- };
717
- const declarationBindsName = (declaration, name) => {
718
- var _a;
719
- if (declaration.type === 'FunctionDeclaration' ||
720
- declaration.type === 'ClassDeclaration') {
721
- return ((_a = declaration.id) === null || _a === void 0 ? void 0 : _a.name) === name;
722
- }
723
- return declaration.declarations.some((variableDeclaration) => {
724
- return (variableDeclaration.id.type === 'Identifier' &&
725
- variableDeclaration.id.name === name);
726
- });
727
- };
728
- const hasTopLevelBinding = ({ ast, name }) => {
729
- return ast.program.body.some((node) => {
730
- var _a;
731
- if (node.type === 'FunctionDeclaration' ||
732
- node.type === 'ClassDeclaration' ||
733
- node.type === 'VariableDeclaration') {
734
- return declarationBindsName(node, name);
735
- }
736
- if (node.type === 'ExportNamedDeclaration' &&
737
- node.declaration &&
738
- (node.declaration.type === 'FunctionDeclaration' ||
739
- node.declaration.type === 'ClassDeclaration' ||
740
- node.declaration.type === 'VariableDeclaration')) {
741
- return declarationBindsName(node.declaration, name);
742
- }
743
- if (node.type !== 'ImportDeclaration') {
744
- return false;
745
- }
746
- return (_a = node.specifiers) === null || _a === void 0 ? void 0 : _a.some((specifier) => {
747
- var _a;
748
- return ((_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) === name;
749
- });
750
- });
751
- };
752
- const getAvailableSolidLocalName = (ast) => {
753
- const candidates = ['Solid', 'RemotionSolid'];
754
- const available = candidates.find((candidate) => {
755
- return !hasTopLevelBinding({ ast, name: candidate });
756
- });
757
- if (!available) {
758
- throw new Error('Cannot add <Solid> because Solid is already defined');
759
- }
760
- return available;
761
- };
762
- const ensureSolidImport = (ast) => {
763
- return (0, imports_1.ensureNamedImport)({
764
- ast,
765
- importedName: 'Solid',
766
- sourcePath: 'remotion',
767
- localName: getAvailableSolidLocalName(ast),
768
- });
769
- };
770
- const getAvailableSequenceLocalName = (ast) => {
771
- const candidates = ['Sequence', 'RemotionSequence'];
772
- const available = candidates.find((candidate) => {
773
- return !hasTopLevelBinding({ ast, name: candidate });
774
- });
775
- if (!available) {
776
- throw new Error('Cannot add <Sequence> because Sequence is already defined');
777
- }
778
- return available;
779
- };
780
- const ensureSequenceImport = (ast) => {
781
- return (0, imports_1.ensureNamedImport)({
782
- ast,
783
- importedName: 'Sequence',
784
- sourcePath: 'remotion',
785
- localName: getAvailableSequenceLocalName(ast),
786
- });
787
- };
788
- const ensureInteractiveImport = (ast) => {
789
- var _a;
790
- var _b, _c;
791
- for (const statement of ast.program.body) {
792
- if (statement.type !== 'ImportDeclaration' ||
793
- statement.source.type !== 'StringLiteral' ||
794
- statement.source.value !== 'remotion') {
795
- continue;
796
- }
797
- for (const specifier of (_b = statement.specifiers) !== null && _b !== void 0 ? _b : []) {
798
- if (specifier.type === 'ImportSpecifier' &&
799
- (0, imports_1.getImportedName)(specifier) === 'Interactive') {
800
- return (_c = (_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) !== null && _c !== void 0 ? _c : 'Interactive';
801
- }
802
- }
803
- }
804
- const candidates = ['Interactive', 'RemotionInteractive'];
805
- const localName = candidates.find((candidate) => {
806
- return !hasTopLevelBinding({ ast, name: candidate });
807
- });
808
- if (localName === undefined) {
809
- throw new Error('Cannot add <Interactive.Svg> because Interactive is already defined');
810
- }
811
- return (0, imports_1.ensureNamedImport)({
812
- ast,
813
- importedName: 'Interactive',
814
- sourcePath: 'remotion',
815
- localName,
816
- });
817
- };
818
- const getImportDeclarations = ({ ast, sourcePath, }) => {
819
- return ast.program.body.filter((node) => node.type === 'ImportDeclaration' &&
820
- node.source.type === 'StringLiteral' &&
821
- node.source.value === sourcePath);
822
- };
823
- const importDeclarationHasNamespaceSpecifier = (importDeclaration) => {
824
- var _a;
825
- return (_a = importDeclaration.specifiers) === null || _a === void 0 ? void 0 : _a.some((specifier) => specifier.type === 'ImportNamespaceSpecifier');
826
- };
827
- const hasOfficialLocalImport = ({ ast, importedName, sourcePath, }) => {
828
- return getImportDeclarations({ ast, sourcePath }).some((importDeclaration) => {
829
- var _a;
830
- return (_a = importDeclaration.specifiers) === null || _a === void 0 ? void 0 : _a.some((specifier) => {
831
- var _a;
832
- var _b;
833
- return (specifier.type === 'ImportSpecifier' &&
834
- (0, imports_1.getImportedName)(specifier) === importedName &&
835
- ((_b = (_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : importedName) === importedName);
836
- });
837
- });
838
- };
839
- const addOfficialNamedImport = ({ ast, importedName, sourcePath, }) => {
840
- var _a;
841
- const existingImport = getImportDeclarations({ ast, sourcePath }).find((candidate) => !importDeclarationHasNamespaceSpecifier(candidate));
842
- const importSpecifier = recast.types.builders.importSpecifier(recast.types.builders.identifier(importedName));
843
- if (existingImport) {
844
- existingImport.specifiers = [
845
- ...((_a = existingImport.specifiers) !== null && _a !== void 0 ? _a : []),
846
- importSpecifier,
847
- ];
848
- return;
849
- }
850
- const importDeclaration = recast.types.builders.importDeclaration([importSpecifier], recast.types.builders.stringLiteral(sourcePath));
851
- (0, imports_1.insertImportDeclaration)(ast, importDeclaration);
852
- };
853
- const ensureOfficialNamedImport = ({ ast, importedName, sourcePath, label, }) => {
854
- if (hasOfficialLocalImport({ ast, importedName, sourcePath })) {
855
- return importedName;
856
- }
857
- if (hasTopLevelBinding({ ast, name: importedName })) {
858
- throw new Error(`Cannot add ${label} because ${importedName} is already defined`);
859
- }
860
- addOfficialNamedImport({ ast, importedName, sourcePath });
861
- return importedName;
862
- };
863
- const ensureStaticFileImport = (ast) => {
864
- return ensureOfficialNamedImport({
865
- ast,
866
- importedName: 'staticFile',
867
- sourcePath: 'remotion',
868
- label: 'staticFile()',
869
- });
870
- };
871
- const ensureCanvasImageImport = (ast) => {
872
- return ensureOfficialNamedImport({
873
- ast,
874
- importedName: 'CanvasImage',
875
- sourcePath: 'remotion',
876
- label: '<CanvasImage>',
877
- });
878
- };
879
- const ensureAnimatedImageImport = (ast) => {
880
- return ensureOfficialNamedImport({
881
- ast,
882
- importedName: 'AnimatedImage',
883
- sourcePath: 'remotion',
884
- label: '<AnimatedImage>',
885
- });
886
- };
887
- const ensureVideoImport = (ast) => {
888
- return ensureOfficialNamedImport({
889
- ast,
890
- importedName: 'Video',
891
- sourcePath: '@remotion/media',
892
- label: '<Video>',
893
- });
894
- };
895
- const ensureAudioImport = (ast) => {
896
- return ensureOfficialNamedImport({
897
- ast,
898
- importedName: 'Audio',
899
- sourcePath: '@remotion/media',
900
- label: '<Audio>',
901
- });
902
- };
903
- const ensureGifImport = (ast) => {
904
- return ensureOfficialNamedImport({
905
- ast,
906
- importedName: 'Gif',
907
- sourcePath: '@remotion/gif',
908
- label: '<Gif>',
909
- });
910
- };
911
- const hasComponentLocalImport = ({ ast, importName, importPath, }) => {
912
- var _a;
913
- var _b, _c;
914
- for (const importDeclaration of getImportDeclarations({
915
- ast,
916
- sourcePath: importPath,
917
- })) {
918
- for (const specifier of (_b = importDeclaration.specifiers) !== null && _b !== void 0 ? _b : []) {
919
- if (specifier.type === 'ImportSpecifier' &&
920
- (0, imports_1.getImportedName)(specifier) === importName) {
921
- return (_c = (_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) !== null && _c !== void 0 ? _c : importName;
922
- }
923
- }
924
- }
925
- return null;
926
- };
927
- const ensureComponentImport = ({ ast, componentName, importName, importPath, }) => {
928
- const existingLocalName = hasComponentLocalImport({
929
- ast,
930
- importName,
931
- importPath,
932
- });
933
- if (existingLocalName) {
934
- return existingLocalName;
935
- }
936
- if (hasTopLevelBinding({ ast, name: componentName })) {
937
- throw new Error(`Cannot add <${componentName}> because ${componentName} is already defined`);
938
- }
939
- return (0, imports_1.ensureNamedImport)({
940
- ast,
941
- importedName: importName,
942
- sourcePath: importPath,
943
- localName: componentName,
944
- });
945
- };
946
- const identifierRegex = /^[A-Za-z_$][0-9A-Za-z_$]*$/;
947
- const toPascalCaseIdentifier = (value) => {
948
- var _a;
949
- const words = (_a = value.match(/[a-zA-Z0-9]+/g)) !== null && _a !== void 0 ? _a : [];
950
- const candidate = words
951
- .map((word) => `${word.charAt(0).toUpperCase()}${word.slice(1)}`)
952
- .join('');
953
- if (!candidate) {
954
- return 'CompositionComponent';
955
- }
956
- if (/^[0-9]/.test(candidate)) {
957
- return `Composition${candidate}`;
958
- }
959
- return identifierRegex.test(candidate) ? candidate : 'CompositionComponent';
960
- };
961
- const getAvailableLocalName = ({ ast, baseName, }) => {
962
- if (!hasTopLevelBinding({ ast, name: baseName })) {
963
- return baseName;
964
- }
965
- const suffixed = `${baseName}Composition`;
966
- if (!hasTopLevelBinding({ ast, name: suffixed })) {
967
- return suffixed;
968
- }
969
- for (let i = 2; i < 100; i++) {
970
- const candidate = `${suffixed}${i}`;
971
- if (!hasTopLevelBinding({ ast, name: candidate })) {
972
- return candidate;
973
- }
974
- }
975
- throw new Error(`Cannot find a local name for ${baseName}`);
976
- };
977
- const getImportPathBetweenFiles = ({ fromFile, toFile, }) => {
978
- let relativeImport = node_path_1.default
979
- .relative(node_path_1.default.dirname(fromFile), toFile)
980
- .replaceAll(node_path_1.default.sep, '/')
981
- .replace(/\.(tsx|ts|jsx|js)$/, '');
982
- if (!relativeImport.startsWith('.')) {
983
- relativeImport = `./${relativeImport}`;
984
- }
985
- return relativeImport;
986
- };
987
- const ensureDefaultImport = ({ ast, localName, sourcePath, }) => {
988
- var _a, _b;
989
- var _c;
990
- for (const declaration of getImportDeclarations({ ast, sourcePath })) {
991
- const defaultSpecifier = (_a = declaration.specifiers) === null || _a === void 0 ? void 0 : _a.find((specifier) => specifier.type === 'ImportDefaultSpecifier');
992
- if ((_b = defaultSpecifier === null || defaultSpecifier === void 0 ? void 0 : defaultSpecifier.local) === null || _b === void 0 ? void 0 : _b.name) {
993
- return defaultSpecifier.local.name;
994
- }
995
- }
996
- const importSpecifier = recast.types.builders.importDefaultSpecifier(recast.types.builders.identifier(localName));
997
- const existingImport = getImportDeclarations({ ast, sourcePath }).find((declaration) => {
998
- var _a;
999
- return !((_a = declaration.specifiers) === null || _a === void 0 ? void 0 : _a.some((specifier) => specifier.type === 'ImportNamespaceSpecifier'));
1000
- });
1001
- if (existingImport) {
1002
- existingImport.specifiers = [
1003
- importSpecifier,
1004
- ...((_c = existingImport.specifiers) !== null && _c !== void 0 ? _c : []),
1005
- ];
1006
- return localName;
1007
- }
1008
- const importDeclaration = recast.types.builders.importDeclaration([importSpecifier], recast.types.builders.stringLiteral(sourcePath));
1009
- (0, imports_1.insertImportDeclaration)(ast, importDeclaration);
1010
- return localName;
1011
- };
1012
- const ensureCompositionComponentImport = async ({ ast, compositionFile, compositionId, destinationFileName, remotionRoot, }) => {
1013
- const sourceLocation = await (0, exports.resolveCompositionComponentWithFile)({
1014
- remotionRoot,
1015
- compositionFile,
1016
- compositionId,
1017
- });
1018
- if (sourceLocation.fileName === destinationFileName) {
1019
- if (sourceLocation.exportName === 'default') {
1020
- throw new Error('Cannot insert a composition whose component is a default export in the same file');
1021
- }
1022
- if (!hasTopLevelBinding({ ast, name: sourceLocation.exportName })) {
1023
- throw new Error(`Cannot find component "${sourceLocation.exportName}" in this file`);
1024
- }
1025
- return sourceLocation.exportName;
1026
- }
1027
- const sourcePath = getImportPathBetweenFiles({
1028
- fromFile: destinationFileName,
1029
- toFile: sourceLocation.fileName,
1030
- });
1031
- if (sourceLocation.exportName === 'default') {
1032
- return ensureDefaultImport({
1033
- ast,
1034
- localName: getAvailableLocalName({
1035
- ast,
1036
- baseName: toPascalCaseIdentifier(compositionId),
1037
- }),
1038
- sourcePath,
1039
- });
1040
- }
1041
- return (0, imports_1.ensureNamedImport)({
1042
- ast,
1043
- importedName: sourceLocation.exportName,
1044
- sourcePath,
1045
- localName: getAvailableLocalName({
1046
- ast,
1047
- baseName: sourceLocation.exportName,
1048
- }),
1049
- });
1050
- };
1051
- const parseSerializedCompositionProps = (serializedResolvedPropsWithCustomSchema) => {
1052
- const parsed = JSON.parse(serializedResolvedPropsWithCustomSchema);
1053
- if (!isRecord(parsed)) {
1054
- throw new Error('Resolved composition props must be an object');
1055
- }
1056
- return parsed;
1057
- };
1058
- const containsFileToken = (value) => {
1059
- if (typeof value === 'string') {
1060
- return value.startsWith(no_react_1.NoReactInternals.FILE_TOKEN);
1061
- }
1062
- if (Array.isArray(value)) {
1063
- return value.some(containsFileToken);
1064
- }
1065
- if (isRecord(value)) {
1066
- return Object.values(value).some(containsFileToken);
1067
- }
1068
- return false;
1069
- };
1070
- const createExpressionAttribute = (name, value) => {
1071
- return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier(name), recast.types.builders.jsxExpressionContainer((0, update_nested_prop_1.parseValueExpression)(value)));
1072
- };
1073
- const createCompositionPropAttribute = ({ name, value, }) => {
1074
- if (typeof value === 'string' &&
1075
- !value.startsWith(no_react_1.NoReactInternals.FILE_TOKEN) &&
1076
- !value.startsWith(no_react_1.NoReactInternals.DATE_TOKEN)) {
1077
- return createStringAttribute(name, value);
1078
- }
1079
- return createExpressionAttribute(name, value);
1080
- };
1081
- const createCompositionObjectProperty = ({ name, value, }) => {
1082
- return recast.types.builders.objectProperty(identifierRegex.test(name)
1083
- ? recast.types.builders.identifier(name)
1084
- : recast.types.builders.stringLiteral(name), (0, update_nested_prop_1.parseValueExpression)(value));
1085
- };
1086
- const createCompositionComponentElement = ({ localName, props, }) => {
1087
- const directAttributes = [];
1088
- const spreadProperties = [];
1089
- for (const [name, value] of Object.entries(props)) {
1090
- if (identifierRegex.test(name)) {
1091
- directAttributes.push(createCompositionPropAttribute({ name, value }));
1092
- }
1093
- else {
1094
- spreadProperties.push(createCompositionObjectProperty({ name, value }));
1095
- }
1096
- }
1097
- const attributes = [
1098
- ...directAttributes,
1099
- ...(spreadProperties.length === 0
1100
- ? []
1101
- : [
1102
- recast.types.builders.jsxSpreadAttribute(recast.types.builders.objectExpression(spreadProperties)),
1103
- ]),
1104
- ];
1105
- return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), attributes, true), null, []);
1106
- };
1107
- const addElementToComponentRoot = ({ ast, exportName, element, }) => {
1108
- var _a, _b;
1109
- var _c, _d;
1110
- const declaration = getDeclarationByExportName({ ast, exportName });
1111
- if (!declaration) {
1112
- throw new Error('Could not find composition component declaration');
1113
- }
1114
- const rootNode = getComponentRootNode(declaration);
1115
- if (!rootNode) {
1116
- const insertedAt = addElementToNullComponentReturn({ declaration, element });
1117
- if (insertedAt !== null) {
1118
- return insertedAt;
1119
- }
1120
- throw new Error('Composition component does not return JSX');
1121
- }
1122
- const CANVAS_ROOT_ELEMENTS = [
1123
- 'ThreeCanvas',
1124
- 'RiveCanvas',
1125
- 'SkiaCanvas',
1126
- 'canvas',
1127
- ];
1128
- if (rootNode.type === 'JSXElement' &&
1129
- rootNode.openingElement.name.type === 'JSXIdentifier' &&
1130
- CANVAS_ROOT_ELEMENTS.includes(rootNode.openingElement.name.name)) {
1131
- throw new Error(`Cannot insert a JSX element into a composition whose root element is <${rootNode.openingElement.name.name}>`);
1132
- }
1133
- if (rootNode.type === 'JSXElement') {
1134
- const existingRoot = rootNode.openingElement.selfClosing
1135
- ? createSequenceWithChild({
1136
- child: (0, strip_parenthesized_extra_1.stripParenthesizedExtra)(rootNode),
1137
- sequenceLocalName: ensureSequenceImport(ast),
1138
- })
1139
- : (0, strip_parenthesized_extra_1.stripParenthesizedExtra)(rootNode);
1140
- const fragment = recast.types.builders.jsxFragment(recast.types.builders.jsxOpeningFragment(), recast.types.builders.jsxClosingFragment(), [existingRoot, element]);
1141
- let replaced = false;
1142
- recast.types.visit(ast, {
1143
- visitJSXElement(astPath) {
1144
- if (astPath.node === rootNode) {
1145
- astPath.replace(fragment);
1146
- replaced = true;
1147
- return false;
1148
- }
1149
- this.traverse(astPath);
1150
- },
1151
- });
1152
- if (!replaced) {
1153
- throw new Error('Could not replace composition component root');
1154
- }
1155
- return (_c = (_a = rootNode.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _c !== void 0 ? _c : 1;
1156
- }
1157
- if (!rootNode.children) {
1158
- throw new Error('Composition component root does not accept children');
1159
- }
1160
- rootNode.children.push(element);
1161
- return (_d = (_b = rootNode.loc) === null || _b === void 0 ? void 0 : _b.start.line) !== null && _d !== void 0 ? _d : 1;
1162
- };
1163
- const getDefaultExportDeclaration = (ast) => {
1164
- let declaration = null;
1165
- let identifierName = null;
1166
- recast.types.visit(ast, {
1167
- visitExportDefaultDeclaration(astPath) {
1168
- if (declaration || identifierName) {
1169
- return false;
1170
- }
1171
- const { node } = astPath;
1172
- if (node.declaration.type === 'Identifier') {
1173
- identifierName = node.declaration.name;
1174
- return false;
1175
- }
1176
- declaration = node.declaration;
1177
- return false;
1178
- },
1179
- });
1180
- if (identifierName) {
1181
- return findLocalComponentDeclaration({ ast, name: identifierName });
1182
- }
1183
- return declaration;
1184
- };
1185
- const getDeclarationByExportName = ({ ast, exportName, }) => {
1186
- if (exportName === 'default') {
1187
- return getDefaultExportDeclaration(ast);
1188
- }
1189
- return findLocalComponentDeclaration({ ast, name: exportName });
1190
- };
1191
- const canAddSequenceToComponent = ({ ast, exportName, }) => {
1192
- try {
1193
- addElementToComponentRoot({
1194
- ast,
1195
- exportName,
1196
- element: createSequenceElement(),
1197
- });
1198
- recast.print(ast);
1199
- return true;
1200
- }
1201
- catch (_a) {
1202
- return false;
1203
- }
1204
- };
1205
- const getComponentLocationInFile = async ({ remotionRoot, fileName, exportName, ast: providedAst, }) => {
1206
- var _a, _b;
1207
- const ast = providedAst !== null && providedAst !== void 0 ? providedAst : (0, parse_ast_1.parseAst)(await readSourceFile({ remotionRoot, fileName }));
1208
- const location = exportName === 'default'
1209
- ? findDefaultExportLocation(ast)
1210
- : findLocalSymbolLocation({ ast, name: exportName });
1211
- const canAddSequence = canAddSequenceToComponent({
1212
- ast,
1213
- exportName,
1214
- });
1215
- return {
1216
- source: node_path_1.default.relative(remotionRoot, fileName),
1217
- fileName,
1218
- exportName,
1219
- line: (_a = location === null || location === void 0 ? void 0 : location.line) !== null && _a !== void 0 ? _a : 1,
1220
- column: (_b = location === null || location === void 0 ? void 0 : location.column) !== null && _b !== void 0 ? _b : 0,
1221
- canAddSequence,
1222
- };
1223
- };
1224
- const getComponentLocationRecursively = async ({ remotionRoot, fileName, exportName, visited, }) => {
1225
- const key = `${fileName}:${exportName}`;
1226
- if (visited.has(key)) {
1227
- throw new Error(`Could not resolve component export "${exportName}" in ${node_path_1.default.relative(remotionRoot, fileName)}`);
1228
- }
1229
- visited.add(key);
1230
- try {
1231
- const input = await readSourceFile({ remotionRoot, fileName });
1232
- const ast = (0, parse_ast_1.parseAst)(input);
1233
- const localDeclaration = getDeclarationByExportName({
1234
- ast,
1235
- exportName,
1236
- });
1237
- if (localDeclaration) {
1238
- return await getComponentLocationInFile({
1239
- remotionRoot,
1240
- fileName,
1241
- exportName,
1242
- ast,
1243
- });
1244
- }
1245
- const reExportTargets = findReExportTargets({
1246
- ast,
1247
- exportName,
1248
- });
1249
- for (const target of reExportTargets) {
1250
- try {
1251
- const resolvedImportPath = resolveImportPath({
1252
- importPath: target.importPath,
1253
- fromFile: fileName,
1254
- });
1255
- return await getComponentLocationRecursively({
1256
- remotionRoot,
1257
- fileName: resolvedImportPath,
1258
- exportName: target.exportName,
1259
- visited,
1260
- });
1261
- }
1262
- catch (_a) {
1263
- continue;
1264
- }
1265
- }
1266
- if (reExportTargets.length > 0) {
1267
- throw new Error(`Could not resolve component export "${exportName}" in ${node_path_1.default.relative(remotionRoot, fileName)}`);
1268
- }
1269
- return await getComponentLocationInFile({
1270
- remotionRoot,
1271
- fileName,
1272
- exportName,
1273
- ast,
1274
- });
1275
- }
1276
- finally {
1277
- visited.delete(key);
1278
- }
1279
- };
1280
- const resolveCompositionComponentWithFile = async ({ remotionRoot, compositionFile, compositionId, }) => {
1281
- const compositionFileName = node_path_1.default.resolve(remotionRoot, compositionFile);
1282
- const input = await readSourceFile({
1283
- remotionRoot,
1284
- fileName: compositionFileName,
1285
- });
1286
- const ast = (0, parse_ast_1.parseAstForReadOnly)(input);
1287
- const compositionElement = findCompositionElement({ ast, compositionId });
1288
- if (!compositionElement) {
1289
- throw new Error(`Could not find composition "${compositionId}"`);
1290
- }
1291
- const lazyImportPath = getLazyImportPath(compositionElement);
1292
- if (lazyImportPath) {
1293
- const lazyComponentFile = resolveImportPath({
1294
- importPath: lazyImportPath,
1295
- fromFile: compositionFileName,
1296
- });
1297
- return getComponentLocationRecursively({
1298
- remotionRoot,
1299
- fileName: lazyComponentFile,
1300
- exportName: 'default',
1301
- visited: new Set(),
1302
- });
1303
- }
1304
- const componentName = getComponentIdentifier(compositionElement);
1305
- if (!componentName) {
1306
- throw new Error(`Could not find a component prop for composition "${compositionId}"`);
1307
- }
1308
- const importTarget = findImportTarget({ ast, componentName });
1309
- if (!importTarget) {
1310
- return getComponentLocationInFile({
1311
- remotionRoot,
1312
- fileName: compositionFileName,
1313
- exportName: componentName,
1314
- });
1315
- }
1316
- const importedComponentFile = resolveImportPath({
1317
- importPath: importTarget.importPath,
1318
- fromFile: compositionFileName,
1319
- });
1320
- return getComponentLocationRecursively({
1321
- remotionRoot,
1322
- fileName: importedComponentFile,
1323
- exportName: importTarget.exportName,
1324
- visited: new Set(),
1325
- });
1326
- };
12
+ const makeCodemodEnvironment = (remotionRoot) => ({
13
+ dirname: node_path_1.default.dirname,
14
+ extname: node_path_1.default.extname,
15
+ fileExists: (fileName) => node_fs_1.default.existsSync(fileName) && node_fs_1.default.statSync(fileName).isFile(),
16
+ formatFile: ({ contents, prettierConfigOverride }) => (0, format_file_content_1.formatFileContent)({ input: contents, prettierConfigOverride }),
17
+ isAbsolute: node_path_1.default.isAbsolute,
18
+ join: node_path_1.default.join,
19
+ pathSeparator: node_path_1.default.sep,
20
+ readFile: (fileName) => node_fs_1.default.promises.readFile(fileName, 'utf-8'),
21
+ relative: node_path_1.default.relative,
22
+ resolve: node_path_1.default.resolve,
23
+ rootDir: remotionRoot,
24
+ svgMarkupToJsx: svg_to_jsx_1.svgMarkupToJsx,
25
+ });
26
+ const resolveCompositionComponentWithFile = ({ remotionRoot, compositionFile, compositionId, }) => (0, studio_codemods_1.resolveCompositionComponentWithFile)({
27
+ compositionFile,
28
+ compositionId,
29
+ environment: makeCodemodEnvironment(remotionRoot),
30
+ });
1327
31
  exports.resolveCompositionComponentWithFile = resolveCompositionComponentWithFile;
1328
- const resolveCompositionComponent = async ({ remotionRoot, compositionFile, compositionId, }) => {
1329
- const { source, line, column, canAddSequence } = await (0, exports.resolveCompositionComponentWithFile)({
1330
- remotionRoot,
1331
- compositionFile,
1332
- compositionId,
1333
- });
1334
- return {
1335
- source,
1336
- line,
1337
- column,
1338
- canAddSequence,
1339
- };
1340
- };
32
+ const resolveCompositionComponent = ({ remotionRoot, compositionFile, compositionId, }) => (0, studio_codemods_1.resolveCompositionComponent)({
33
+ compositionFile,
34
+ compositionId,
35
+ environment: makeCodemodEnvironment(remotionRoot),
36
+ });
1341
37
  exports.resolveCompositionComponent = resolveCompositionComponent;
1342
- const createInsertableJsxElement = ({ addPositionStyleToComponent, ast, destinationFileName, element, from, remotionRoot, }) => {
1343
- if (element.type === 'solid') {
1344
- const solidLocalName = ensureSolidImport(ast);
1345
- return createSolidElement({
1346
- localName: solidLocalName,
1347
- width: element.width,
1348
- height: element.height,
1349
- position: element.position,
1350
- });
1351
- }
1352
- if (element.type === 'component') {
1353
- const componentLocalName = ensureComponentImport({
1354
- ast,
1355
- componentName: element.componentName,
1356
- importName: element.importName,
1357
- importPath: element.importPath,
1358
- });
1359
- return createComponentElement({
1360
- addPositionStyle: addPositionStyleToComponent,
1361
- from,
1362
- localName: componentLocalName,
1363
- props: element.props,
1364
- position: element.position,
1365
- });
1366
- }
1367
- if (element.type === 'svg') {
1368
- return createSvgElement({
1369
- from,
1370
- interactiveLocalName: ensureInteractiveImport(ast),
1371
- markup: element.markup,
1372
- position: element.position,
1373
- });
1374
- }
1375
- if (element.type === 'composition') {
1376
- return Promise.resolve(ensureCompositionComponentImport({
1377
- ast,
1378
- compositionFile: element.compositionFile,
1379
- compositionId: element.compositionId,
1380
- destinationFileName,
1381
- remotionRoot,
1382
- })).then((localName) => {
1383
- const props = parseSerializedCompositionProps(element.serializedResolvedPropsWithCustomSchema);
1384
- if (containsFileToken(props)) {
1385
- ensureStaticFileImport(ast);
1386
- }
1387
- return createCompositionComponentElement({ localName, props });
1388
- });
1389
- }
1390
- if (element.type === 'asset') {
1391
- if (element.srcType === 'remote' && !(0, studio_shared_1.isUrl)(element.src)) {
1392
- throw new Error('Remote asset source must be a URL');
1393
- }
1394
- const staticFileLocalName = element.srcType === 'remote' ? null : ensureStaticFileImport(ast);
1395
- let localName;
1396
- if (element.assetType === 'image') {
1397
- localName = ensureCanvasImageImport(ast);
1398
- }
1399
- else if (element.assetType === 'video') {
1400
- localName = ensureVideoImport(ast);
1401
- }
1402
- else if (element.assetType === 'gif') {
1403
- localName = ensureGifImport(ast);
1404
- }
1405
- else if (element.assetType === 'animated-image') {
1406
- localName = ensureAnimatedImageImport(ast);
1407
- }
1408
- else if (element.assetType === 'audio') {
1409
- localName = ensureAudioImport(ast);
1410
- }
1411
- else {
1412
- throw new Error('Unsupported asset type');
1413
- }
1414
- return createAssetElement({
1415
- addPositionStyle: addPositionStyleToComponent && element.assetType !== 'audio',
1416
- durationInFrames: element.assetType === 'image' ? null : element.durationInFrames,
1417
- from,
1418
- localName,
1419
- staticFileLocalName,
1420
- src: element.src,
1421
- dimensions: element.assetType === 'image' && from !== null
1422
- ? null
1423
- : element.dimensions,
1424
- position: element.position,
1425
- });
1426
- }
1427
- throw new Error('Unsupported element type');
1428
- };
1429
- const insertJsxElementIntoComposition = async ({ remotionRoot, compositionFile, compositionId, element, from, prettierConfigOverride, wrapInSequence = null, }) => {
1430
- var _a, _b;
1431
- const location = await (0, exports.resolveCompositionComponentWithFile)({
1432
- remotionRoot,
38
+ const insertJsxElementIntoComposition = ({ remotionRoot, compositionFile, compositionId, element, from, prettierConfigOverride, wrapInSequence = null, }) => {
39
+ var _a;
40
+ return (0, studio_codemods_1.insertJsxElementIntoComposition)({
1433
41
  compositionFile,
1434
42
  compositionId,
1435
- });
1436
- if (!location.canAddSequence) {
1437
- throw new Error('Cannot insert JSX element into this composition component');
1438
- }
1439
- const input = await readSourceFile({
1440
- remotionRoot,
1441
- fileName: location.fileName,
1442
- });
1443
- const ast = (0, parse_ast_1.parseAst)(input);
1444
- const capturedNodePaths = (0, get_node_path_remappings_1.captureJsxNodePaths)(ast);
1445
- if (element.type === 'composition' &&
1446
- element.compositionId === compositionId) {
1447
- throw new Error('Cannot insert a composition into itself');
1448
- }
1449
- const sequenceWrapper = element.type === 'composition'
1450
- ? {
1451
- dimensions: { width: element.width, height: element.height },
1452
- durationInFrames: element.durationInFrames,
1453
- name: element.compositionId,
1454
- position: element.position,
1455
- from,
1456
- }
1457
- : from === null ||
1458
- element.type === 'asset' ||
1459
- element.type === 'svg' ||
1460
- element.type === 'component'
1461
- ? wrapInSequence
1462
- : {
1463
- dimensions: null,
1464
- durationInFrames: null,
1465
- name: null,
1466
- position: element.position,
1467
- from,
1468
- };
1469
- const elementToInsert = await createInsertableJsxElement({
1470
- addPositionStyleToComponent: sequenceWrapper === null,
1471
- ast,
1472
- destinationFileName: location.fileName,
1473
43
  element,
44
+ environment: makeCodemodEnvironment(remotionRoot),
1474
45
  from,
1475
- remotionRoot,
1476
- });
1477
- const finalElementToInsert = sequenceWrapper
1478
- ? createSequenceWrappedElement({
1479
- child: elementToInsert,
1480
- dimensions: sequenceWrapper.dimensions,
1481
- durationInFrames: (_a = sequenceWrapper.durationInFrames) !== null && _a !== void 0 ? _a : null,
1482
- from: sequenceWrapper.from,
1483
- name: sequenceWrapper.name,
1484
- position: sequenceWrapper.position,
1485
- sequenceLocalName: ensureSequenceImport(ast),
1486
- })
1487
- : elementToInsert;
1488
- const logLine = addElementToComponentRoot({
1489
- ast,
1490
- exportName: location.exportName,
1491
- element: finalElementToInsert,
1492
- });
1493
- const finalFile = (0, parse_ast_1.serializeAst)(ast);
1494
- const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
1495
- input: finalFile,
1496
46
  prettierConfigOverride,
47
+ wrapInSequence: wrapInSequence === null
48
+ ? null
49
+ : {
50
+ dimensions: wrapInSequence.dimensions,
51
+ durationInFrames: (_a = wrapInSequence.durationInFrames) !== null && _a !== void 0 ? _a : null,
52
+ from: wrapInSequence.from,
53
+ name: wrapInSequence.name,
54
+ position: wrapInSequence.position,
55
+ },
1497
56
  });
1498
- const { finalNodePathByNode, nodePathRemappings } = (0, get_node_path_remappings_1.getNodePathRemappings)({
1499
- ast,
1500
- captured: capturedNodePaths,
1501
- output,
1502
- });
1503
- const insertedNodePath = (_b = finalNodePathByNode.get(finalElementToInsert.openingElement)) !== null && _b !== void 0 ? _b : null;
1504
- return {
1505
- fileName: location.fileName,
1506
- source: location.source,
1507
- oldContents: input,
1508
- output,
1509
- formatted,
1510
- insertedNodePath,
1511
- logLine,
1512
- nodePathRemappings,
1513
- };
1514
57
  };
1515
58
  exports.insertJsxElementIntoComposition = insertJsxElementIntoComposition;