@remotion/studio-server 4.0.472 → 4.0.474
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codemods/effect-param-expression.d.ts +15 -0
- package/dist/codemods/effect-param-expression.js +131 -0
- package/dist/codemods/paste-effects.js +4 -91
- package/dist/codemods/reorder-sequence.d.ts +14 -0
- package/dist/codemods/reorder-sequence.js +109 -0
- package/dist/codemods/update-effect-props/update-effect-props.d.ts +7 -0
- package/dist/codemods/update-effect-props/update-effect-props.js +64 -16
- package/dist/codemods/update-keyframes/update-keyframes.d.ts +14 -1
- package/dist/codemods/update-keyframes/update-keyframes.js +152 -0
- package/dist/helpers/resolve-composition-component.d.ts +1 -1
- package/dist/helpers/resolve-composition-component.js +103 -7
- package/dist/preview-server/api-routes.js +14 -0
- package/dist/preview-server/routes/can-update-effect-props.js +3 -2
- package/dist/preview-server/routes/can-update-sequence-props.d.ts +1 -1
- package/dist/preview-server/routes/can-update-sequence-props.js +52 -17
- package/dist/preview-server/routes/download-remote-asset.d.ts +7 -0
- package/dist/preview-server/routes/download-remote-asset.js +268 -0
- package/dist/preview-server/routes/insert-jsx-element.d.ts +1 -1
- package/dist/preview-server/routes/insert-jsx-element.js +28 -1
- package/dist/preview-server/routes/log-studio-error.d.ts +3 -0
- package/dist/preview-server/routes/log-studio-error.js +58 -0
- package/dist/preview-server/routes/move-keyframes.d.ts +7 -0
- package/dist/preview-server/routes/move-keyframes.js +242 -0
- package/dist/preview-server/routes/rename-static-file.d.ts +3 -0
- package/dist/preview-server/routes/rename-static-file.js +53 -0
- package/dist/preview-server/routes/reorder-sequence.d.ts +3 -0
- package/dist/preview-server/routes/reorder-sequence.js +67 -0
- package/dist/preview-server/routes/save-effect-props.js +24 -9
- package/dist/preview-server/routes/save-sequence-props.js +2 -34
- package/dist/preview-server/routes/update-effect-keyframe-settings.d.ts +3 -0
- package/dist/preview-server/routes/update-effect-keyframe-settings.js +90 -0
- package/dist/preview-server/routes/update-sequence-keyframe-settings.d.ts +3 -0
- package/dist/preview-server/routes/update-sequence-keyframe-settings.js +85 -0
- package/dist/preview-server/undo-stack.d.ts +3 -1
- package/package.json +6 -6
|
@@ -141,6 +141,92 @@ const createClampOptionsExpression = () => {
|
|
|
141
141
|
b.objectProperty(b.identifier('extrapolateRight'), b.stringLiteral('clamp')),
|
|
142
142
|
]);
|
|
143
143
|
};
|
|
144
|
+
const createEmptyOptionsExpression = () => b.objectExpression([]);
|
|
145
|
+
const findObjectOptionProperty = (options, propertyName) => {
|
|
146
|
+
const propIndex = options.properties.findIndex((prop) => prop.type === 'ObjectProperty' &&
|
|
147
|
+
!prop.computed &&
|
|
148
|
+
((prop.key.type === 'Identifier' && prop.key.name === propertyName) ||
|
|
149
|
+
(prop.key.type === 'StringLiteral' && prop.key.value === propertyName)));
|
|
150
|
+
return {
|
|
151
|
+
propIndex,
|
|
152
|
+
prop: propIndex === -1
|
|
153
|
+
? undefined
|
|
154
|
+
: options.properties[propIndex],
|
|
155
|
+
};
|
|
156
|
+
};
|
|
157
|
+
const setOptionsProperty = ({ options, propertyName, value, }) => {
|
|
158
|
+
const { propIndex, prop } = findObjectOptionProperty(options, propertyName);
|
|
159
|
+
if (value === null) {
|
|
160
|
+
if (propIndex !== -1) {
|
|
161
|
+
options.properties.splice(propIndex, 1);
|
|
162
|
+
}
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (prop) {
|
|
166
|
+
prop.value = value;
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
options.properties.push(b.objectProperty(b.identifier(propertyName), value));
|
|
170
|
+
};
|
|
171
|
+
const validatePosterize = (posterize) => {
|
|
172
|
+
if (posterize === undefined) {
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
if (!Number.isFinite(posterize) || posterize <= 0) {
|
|
176
|
+
throw new Error('Cannot update keyframe settings: posterize must be > 0');
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
const updateKeyframeSettings = ({ expression, clamping, posterize, }) => {
|
|
180
|
+
validatePosterize(posterize);
|
|
181
|
+
const existing = getInterpolationExpression(expression);
|
|
182
|
+
if (!existing) {
|
|
183
|
+
throw new Error('Cannot update keyframe settings on non-keyframed value');
|
|
184
|
+
}
|
|
185
|
+
const calleeName = existing.callee.type === 'Identifier' ? existing.callee.name : null;
|
|
186
|
+
const isColorInterpolation = calleeName === 'interpolateColors';
|
|
187
|
+
const extraArgs = [...existing.extraArgs];
|
|
188
|
+
const existingOptions = extraArgs[0];
|
|
189
|
+
if (existingOptions && existingOptions.type !== 'ObjectExpression') {
|
|
190
|
+
throw new Error('Cannot update keyframe settings: options must be inline');
|
|
191
|
+
}
|
|
192
|
+
const options = (existingOptions === null || existingOptions === void 0 ? void 0 : existingOptions.type) === 'ObjectExpression'
|
|
193
|
+
? existingOptions
|
|
194
|
+
: createEmptyOptionsExpression();
|
|
195
|
+
if (isColorInterpolation) {
|
|
196
|
+
setOptionsProperty({ options, propertyName: 'extrapolateLeft', value: null });
|
|
197
|
+
setOptionsProperty({
|
|
198
|
+
options,
|
|
199
|
+
propertyName: 'extrapolateRight',
|
|
200
|
+
value: null,
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
else if (clamping) {
|
|
204
|
+
setOptionsProperty({
|
|
205
|
+
options,
|
|
206
|
+
propertyName: 'extrapolateLeft',
|
|
207
|
+
value: b.stringLiteral(clamping.left),
|
|
208
|
+
});
|
|
209
|
+
setOptionsProperty({
|
|
210
|
+
options,
|
|
211
|
+
propertyName: 'extrapolateRight',
|
|
212
|
+
value: b.stringLiteral(clamping.right),
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
setOptionsProperty({
|
|
216
|
+
options,
|
|
217
|
+
propertyName: 'posterize',
|
|
218
|
+
value: posterize === undefined ? null : b.numericLiteral(posterize),
|
|
219
|
+
});
|
|
220
|
+
const nextExtraArgs = options.properties.length === 0
|
|
221
|
+
? extraArgs.slice(1)
|
|
222
|
+
: [options, ...extraArgs.slice(1)];
|
|
223
|
+
return createInterpolateExpression({
|
|
224
|
+
callee: existing.callee,
|
|
225
|
+
input: existing.input,
|
|
226
|
+
extraArgs: nextExtraArgs,
|
|
227
|
+
keyframes: existing.keyframes,
|
|
228
|
+
});
|
|
229
|
+
};
|
|
144
230
|
const createInterpolateExpression = ({ callee, input, extraArgs, keyframes, }) => {
|
|
145
231
|
const sortedKeyframes = [...keyframes].sort((first, second) => first.frame - second.frame);
|
|
146
232
|
return b.callExpression(callee, [
|
|
@@ -239,6 +325,56 @@ const removeKeyframe = ({ expression, frame, }) => {
|
|
|
239
325
|
keyframes: nextKeyframes,
|
|
240
326
|
});
|
|
241
327
|
};
|
|
328
|
+
const moveKeyframes = ({ expression, moves, }) => {
|
|
329
|
+
var _a;
|
|
330
|
+
const existing = getInterpolationExpression(expression);
|
|
331
|
+
if (!existing) {
|
|
332
|
+
throw new Error('Cannot move keyframe in non-interpolated expression');
|
|
333
|
+
}
|
|
334
|
+
const moveMap = new Map();
|
|
335
|
+
for (const move of moves) {
|
|
336
|
+
if (move.fromFrame === move.toFrame) {
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
if (moveMap.has(move.fromFrame)) {
|
|
340
|
+
throw new Error(`Cannot move keyframe at frame ${move.fromFrame} twice`);
|
|
341
|
+
}
|
|
342
|
+
moveMap.set(move.fromFrame, move.toFrame);
|
|
343
|
+
}
|
|
344
|
+
if (moveMap.size === 0) {
|
|
345
|
+
return expression;
|
|
346
|
+
}
|
|
347
|
+
const frames = new Set(existing.keyframes.map((keyframe) => keyframe.frame));
|
|
348
|
+
for (const fromFrame of moveMap.keys()) {
|
|
349
|
+
if (!frames.has(fromFrame)) {
|
|
350
|
+
throw new Error(`Cannot move keyframe at frame ${fromFrame}: not found`);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
const movedFromFrames = new Set(moveMap.keys());
|
|
354
|
+
const nextFrames = new Set();
|
|
355
|
+
for (const keyframe of existing.keyframes) {
|
|
356
|
+
const nextFrame = (_a = moveMap.get(keyframe.frame)) !== null && _a !== void 0 ? _a : keyframe.frame;
|
|
357
|
+
if (nextFrames.has(nextFrame)) {
|
|
358
|
+
throw new Error(`Cannot move keyframe to frame ${nextFrame}: frame already exists`);
|
|
359
|
+
}
|
|
360
|
+
if (!movedFromFrames.has(keyframe.frame) && moveMap.has(nextFrame)) {
|
|
361
|
+
throw new Error(`Cannot move keyframe to frame ${nextFrame}: frame already exists`);
|
|
362
|
+
}
|
|
363
|
+
nextFrames.add(nextFrame);
|
|
364
|
+
}
|
|
365
|
+
return createInterpolateExpression({
|
|
366
|
+
callee: existing.callee,
|
|
367
|
+
input: existing.input,
|
|
368
|
+
extraArgs: existing.extraArgs,
|
|
369
|
+
keyframes: existing.keyframes.map((keyframe) => {
|
|
370
|
+
var _a;
|
|
371
|
+
return ({
|
|
372
|
+
...keyframe,
|
|
373
|
+
frame: (_a = moveMap.get(keyframe.frame)) !== null && _a !== void 0 ? _a : keyframe.frame,
|
|
374
|
+
});
|
|
375
|
+
}),
|
|
376
|
+
});
|
|
377
|
+
};
|
|
242
378
|
const applyKeyframeOperation = ({ expression, key, operation, schema, }) => {
|
|
243
379
|
if (operation.type === 'add') {
|
|
244
380
|
return addKeyframe({
|
|
@@ -249,6 +385,22 @@ const applyKeyframeOperation = ({ expression, key, operation, schema, }) => {
|
|
|
249
385
|
schema,
|
|
250
386
|
});
|
|
251
387
|
}
|
|
388
|
+
if (operation.type === 'settings') {
|
|
389
|
+
return {
|
|
390
|
+
expression: updateKeyframeSettings({
|
|
391
|
+
expression,
|
|
392
|
+
clamping: operation.clamping,
|
|
393
|
+
posterize: operation.posterize,
|
|
394
|
+
}),
|
|
395
|
+
introduced: noIntroducedIdentifiers,
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
if (operation.type === 'move') {
|
|
399
|
+
return {
|
|
400
|
+
expression: moveKeyframes({ expression, moves: operation.moves }),
|
|
401
|
+
introduced: noIntroducedIdentifiers,
|
|
402
|
+
};
|
|
403
|
+
}
|
|
252
404
|
return {
|
|
253
405
|
expression: removeKeyframe({ expression, frame: operation.frame }),
|
|
254
406
|
introduced: noIntroducedIdentifiers,
|
|
@@ -39,6 +39,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
39
39
|
exports.insertJsxElementIntoComposition = exports.resolveCompositionComponent = void 0;
|
|
40
40
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
41
41
|
const node_path_1 = __importDefault(require("node:path"));
|
|
42
|
+
const studio_shared_1 = require("@remotion/studio-shared");
|
|
42
43
|
const recast = __importStar(require("recast"));
|
|
43
44
|
const format_file_content_1 = require("../codemods/format-file-content");
|
|
44
45
|
const parse_ast_1 = require("../codemods/parse-ast");
|
|
@@ -508,6 +509,12 @@ const createSequenceElement = () => {
|
|
|
508
509
|
const createNumberAttribute = (name, value) => {
|
|
509
510
|
return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier(name), recast.types.builders.jsxExpressionContainer(recast.types.builders.numericLiteral(value)));
|
|
510
511
|
};
|
|
512
|
+
const createStringAttribute = (name, value) => {
|
|
513
|
+
return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier(name), recast.types.builders.stringLiteral(value));
|
|
514
|
+
};
|
|
515
|
+
const createBooleanAttribute = (name, value) => {
|
|
516
|
+
return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier(name), recast.types.builders.jsxExpressionContainer(recast.types.builders.booleanLiteral(value)));
|
|
517
|
+
};
|
|
511
518
|
const createPositionAbsoluteStyleAttribute = () => {
|
|
512
519
|
return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier('style'), recast.types.builders.jsxExpressionContainer(recast.types.builders.objectExpression([
|
|
513
520
|
recast.types.builders.objectProperty(recast.types.builders.identifier('position'), recast.types.builders.stringLiteral('absolute')),
|
|
@@ -516,6 +523,18 @@ const createPositionAbsoluteStyleAttribute = () => {
|
|
|
516
523
|
const createStaticFileSrcAttribute = ({ staticFileLocalName, src, }) => {
|
|
517
524
|
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)])));
|
|
518
525
|
};
|
|
526
|
+
const createComponentProp = ({ name, value, }) => {
|
|
527
|
+
if (typeof value === 'number') {
|
|
528
|
+
return createNumberAttribute(name, value);
|
|
529
|
+
}
|
|
530
|
+
if (typeof value === 'boolean') {
|
|
531
|
+
return createBooleanAttribute(name, value);
|
|
532
|
+
}
|
|
533
|
+
return createStringAttribute(name, value);
|
|
534
|
+
};
|
|
535
|
+
const createStringSrcAttribute = (src) => {
|
|
536
|
+
return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier('src'), recast.types.builders.stringLiteral(src));
|
|
537
|
+
};
|
|
519
538
|
const createSolidElement = ({ localName, width, height, }) => {
|
|
520
539
|
return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
|
|
521
540
|
createNumberAttribute('width', width),
|
|
@@ -523,9 +542,17 @@ const createSolidElement = ({ localName, width, height, }) => {
|
|
|
523
542
|
createPositionAbsoluteStyleAttribute(),
|
|
524
543
|
], true), null, []);
|
|
525
544
|
};
|
|
545
|
+
const createComponentElement = ({ localName, props, }) => {
|
|
546
|
+
return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
|
|
547
|
+
...props.map(createComponentProp),
|
|
548
|
+
createPositionAbsoluteStyleAttribute(),
|
|
549
|
+
], true), null, []);
|
|
550
|
+
};
|
|
526
551
|
const createAssetElement = ({ localName, staticFileLocalName, src, dimensions, }) => {
|
|
527
552
|
return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
|
|
528
|
-
|
|
553
|
+
staticFileLocalName === null
|
|
554
|
+
? createStringSrcAttribute(src)
|
|
555
|
+
: createStaticFileSrcAttribute({ staticFileLocalName, src }),
|
|
529
556
|
createPositionAbsoluteStyleAttribute(),
|
|
530
557
|
...(dimensions
|
|
531
558
|
? [
|
|
@@ -709,6 +736,14 @@ const ensureVideoImport = (ast) => {
|
|
|
709
736
|
label: '<Video>',
|
|
710
737
|
});
|
|
711
738
|
};
|
|
739
|
+
const ensureAudioImport = (ast) => {
|
|
740
|
+
return ensureOfficialNamedImport({
|
|
741
|
+
ast,
|
|
742
|
+
importedName: 'Audio',
|
|
743
|
+
sourcePath: '@remotion/media',
|
|
744
|
+
label: '<Audio>',
|
|
745
|
+
});
|
|
746
|
+
};
|
|
712
747
|
const ensureGifImport = (ast) => {
|
|
713
748
|
return ensureOfficialNamedImport({
|
|
714
749
|
ast,
|
|
@@ -717,6 +752,41 @@ const ensureGifImport = (ast) => {
|
|
|
717
752
|
label: '<Gif>',
|
|
718
753
|
});
|
|
719
754
|
};
|
|
755
|
+
const hasComponentLocalImport = ({ ast, importName, importPath, }) => {
|
|
756
|
+
var _a;
|
|
757
|
+
var _b, _c;
|
|
758
|
+
for (const importDeclaration of getImportDeclarations({
|
|
759
|
+
ast,
|
|
760
|
+
sourcePath: importPath,
|
|
761
|
+
})) {
|
|
762
|
+
for (const specifier of (_b = importDeclaration.specifiers) !== null && _b !== void 0 ? _b : []) {
|
|
763
|
+
if (specifier.type === 'ImportSpecifier' &&
|
|
764
|
+
(0, imports_1.getImportedName)(specifier) === importName) {
|
|
765
|
+
return (_c = (_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) !== null && _c !== void 0 ? _c : importName;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
return null;
|
|
770
|
+
};
|
|
771
|
+
const ensureComponentImport = ({ ast, componentName, importName, importPath, }) => {
|
|
772
|
+
const existingLocalName = hasComponentLocalImport({
|
|
773
|
+
ast,
|
|
774
|
+
importName,
|
|
775
|
+
importPath,
|
|
776
|
+
});
|
|
777
|
+
if (existingLocalName) {
|
|
778
|
+
return existingLocalName;
|
|
779
|
+
}
|
|
780
|
+
if (hasTopLevelBinding({ ast, name: componentName })) {
|
|
781
|
+
throw new Error(`Cannot add <${componentName}> because ${componentName} is already defined`);
|
|
782
|
+
}
|
|
783
|
+
return (0, imports_1.ensureNamedImport)({
|
|
784
|
+
ast,
|
|
785
|
+
importedName: importName,
|
|
786
|
+
sourcePath: importPath,
|
|
787
|
+
localName: componentName,
|
|
788
|
+
});
|
|
789
|
+
};
|
|
720
790
|
const addElementToComponentRoot = ({ ast, exportName, element, }) => {
|
|
721
791
|
var _a;
|
|
722
792
|
var _b;
|
|
@@ -939,13 +1009,39 @@ const createInsertableJsxElement = ({ ast, element, }) => {
|
|
|
939
1009
|
height: element.height,
|
|
940
1010
|
});
|
|
941
1011
|
}
|
|
1012
|
+
if (element.type === 'component') {
|
|
1013
|
+
const componentLocalName = ensureComponentImport({
|
|
1014
|
+
ast,
|
|
1015
|
+
componentName: element.componentName,
|
|
1016
|
+
importName: element.importName,
|
|
1017
|
+
importPath: element.importPath,
|
|
1018
|
+
});
|
|
1019
|
+
return createComponentElement({
|
|
1020
|
+
localName: componentLocalName,
|
|
1021
|
+
props: element.props,
|
|
1022
|
+
});
|
|
1023
|
+
}
|
|
942
1024
|
if (element.type === 'asset') {
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
1025
|
+
if (element.srcType === 'remote' && !(0, studio_shared_1.isUrl)(element.src)) {
|
|
1026
|
+
throw new Error('Remote asset source must be a URL');
|
|
1027
|
+
}
|
|
1028
|
+
const staticFileLocalName = element.srcType === 'remote' ? null : ensureStaticFileImport(ast);
|
|
1029
|
+
let localName;
|
|
1030
|
+
if (element.assetType === 'image') {
|
|
1031
|
+
localName = ensureImgImport(ast);
|
|
1032
|
+
}
|
|
1033
|
+
else if (element.assetType === 'video') {
|
|
1034
|
+
localName = ensureVideoImport(ast);
|
|
1035
|
+
}
|
|
1036
|
+
else if (element.assetType === 'gif') {
|
|
1037
|
+
localName = ensureGifImport(ast);
|
|
1038
|
+
}
|
|
1039
|
+
else if (element.assetType === 'audio') {
|
|
1040
|
+
localName = ensureAudioImport(ast);
|
|
1041
|
+
}
|
|
1042
|
+
else {
|
|
1043
|
+
throw new Error('Unsupported asset type');
|
|
1044
|
+
}
|
|
949
1045
|
return createAssetElement({
|
|
950
1046
|
localName,
|
|
951
1047
|
staticFileLocalName,
|
|
@@ -13,9 +13,12 @@ const delete_effect_1 = require("./routes/delete-effect");
|
|
|
13
13
|
const delete_jsx_node_1 = require("./routes/delete-jsx-node");
|
|
14
14
|
const delete_keyframes_1 = require("./routes/delete-keyframes");
|
|
15
15
|
const delete_static_file_1 = require("./routes/delete-static-file");
|
|
16
|
+
const download_remote_asset_1 = require("./routes/download-remote-asset");
|
|
16
17
|
const duplicate_jsx_node_1 = require("./routes/duplicate-jsx-node");
|
|
17
18
|
const insert_jsx_element_1 = require("./routes/insert-jsx-element");
|
|
18
19
|
const install_dependency_1 = require("./routes/install-dependency");
|
|
20
|
+
const log_studio_error_1 = require("./routes/log-studio-error");
|
|
21
|
+
const move_keyframes_1 = require("./routes/move-keyframes");
|
|
19
22
|
const open_in_editor_1 = require("./routes/open-in-editor");
|
|
20
23
|
const open_in_file_explorer_1 = require("./routes/open-in-file-explorer");
|
|
21
24
|
const paste_effects_1 = require("./routes/paste-effects");
|
|
@@ -23,7 +26,9 @@ const project_info_1 = require("./routes/project-info");
|
|
|
23
26
|
const redo_1 = require("./routes/redo");
|
|
24
27
|
const register_client_render_1 = require("./routes/register-client-render");
|
|
25
28
|
const remove_render_1 = require("./routes/remove-render");
|
|
29
|
+
const rename_static_file_1 = require("./routes/rename-static-file");
|
|
26
30
|
const reorder_effect_1 = require("./routes/reorder-effect");
|
|
31
|
+
const reorder_sequence_1 = require("./routes/reorder-sequence");
|
|
27
32
|
const restart_studio_1 = require("./routes/restart-studio");
|
|
28
33
|
const save_effect_props_1 = require("./routes/save-effect-props");
|
|
29
34
|
const save_sequence_props_1 = require("./routes/save-sequence-props");
|
|
@@ -37,6 +42,8 @@ const unsubscribe_from_file_existence_1 = require("./routes/unsubscribe-from-fil
|
|
|
37
42
|
const unsubscribe_from_sequence_props_1 = require("./routes/unsubscribe-from-sequence-props");
|
|
38
43
|
const update_available_1 = require("./routes/update-available");
|
|
39
44
|
const update_default_props_1 = require("./routes/update-default-props");
|
|
45
|
+
const update_effect_keyframe_settings_1 = require("./routes/update-effect-keyframe-settings");
|
|
46
|
+
const update_sequence_keyframe_settings_1 = require("./routes/update-sequence-keyframe-settings");
|
|
40
47
|
exports.allApiRoutes = {
|
|
41
48
|
'/api/composition-component-info': composition_component_info_1.compositionComponentInfoHandler,
|
|
42
49
|
'/api/cancel': cancel_render_1.handleCancelRender,
|
|
@@ -59,9 +66,13 @@ exports.allApiRoutes = {
|
|
|
59
66
|
'/api/save-effect-props': save_effect_props_1.saveEffectPropsHandler,
|
|
60
67
|
'/api/add-effect': add_effect_1.addEffectHandler,
|
|
61
68
|
'/api/reorder-effect': reorder_effect_1.reorderEffectHandler,
|
|
69
|
+
'/api/reorder-sequence': reorder_sequence_1.reorderSequenceHandler,
|
|
62
70
|
'/api/delete-keyframes': delete_keyframes_1.deleteKeyframesHandler,
|
|
71
|
+
'/api/move-keyframes': move_keyframes_1.moveKeyframesHandler,
|
|
63
72
|
'/api/add-sequence-keyframe': add_sequence_keyframe_1.addSequenceKeyframeHandler,
|
|
64
73
|
'/api/add-effect-keyframe': add_effect_keyframe_1.addEffectKeyframeHandler,
|
|
74
|
+
'/api/update-sequence-keyframe-settings': update_sequence_keyframe_settings_1.updateSequenceKeyframeSettingsHandler,
|
|
75
|
+
'/api/update-effect-keyframe-settings': update_effect_keyframe_settings_1.updateEffectKeyframeSettingsHandler,
|
|
65
76
|
'/api/delete-effect': delete_effect_1.deleteEffectHandler,
|
|
66
77
|
'/api/paste-effects': paste_effects_1.pasteEffectsHandler,
|
|
67
78
|
'/api/delete-jsx-node': delete_jsx_node_1.deleteJsxNodeHandler,
|
|
@@ -69,9 +80,12 @@ exports.allApiRoutes = {
|
|
|
69
80
|
'/api/update-available': update_available_1.handleUpdate,
|
|
70
81
|
'/api/project-info': project_info_1.projectInfoHandler,
|
|
71
82
|
'/api/delete-static-file': delete_static_file_1.deleteStaticFileHandler,
|
|
83
|
+
'/api/rename-static-file': rename_static_file_1.renameStaticFileHandler,
|
|
72
84
|
'/api/restart-studio': restart_studio_1.handleRestartStudio,
|
|
73
85
|
'/api/install-package': install_dependency_1.handleInstallPackage,
|
|
74
86
|
'/api/insert-jsx-element': insert_jsx_element_1.insertJsxElementHandler,
|
|
87
|
+
'/api/download-remote-asset': download_remote_asset_1.downloadRemoteAssetHandler,
|
|
75
88
|
'/api/undo': undo_1.undoHandler,
|
|
76
89
|
'/api/redo': redo_1.redoHandler,
|
|
90
|
+
'/api/log-studio-error': log_studio_error_1.logStudioErrorHandler,
|
|
77
91
|
};
|
|
@@ -88,7 +88,7 @@ const resolveEffectImport = ({ ast, call, fallbackCallee, }) => {
|
|
|
88
88
|
}
|
|
89
89
|
return { callee: fallbackCallee, importPath: null };
|
|
90
90
|
};
|
|
91
|
-
const getPropsFromObjectExpression = ({ objExpr, keys, }) => {
|
|
91
|
+
const getPropsFromObjectExpression = ({ ast, objExpr, keys, }) => {
|
|
92
92
|
const out = {};
|
|
93
93
|
for (const key of keys) {
|
|
94
94
|
const prop = objExpr.properties.find((p) => p.type === 'ObjectProperty' &&
|
|
@@ -101,7 +101,7 @@ const getPropsFromObjectExpression = ({ objExpr, keys, }) => {
|
|
|
101
101
|
}
|
|
102
102
|
const valueExpr = prop.value;
|
|
103
103
|
if (!(0, can_update_sequence_props_1.isStaticValue)(valueExpr)) {
|
|
104
|
-
out[key] = (0, can_update_sequence_props_1.getComputedStatus)(valueExpr);
|
|
104
|
+
out[key] = (0, can_update_sequence_props_1.getComputedStatus)(valueExpr, ast);
|
|
105
105
|
continue;
|
|
106
106
|
}
|
|
107
107
|
out[key] = {
|
|
@@ -164,6 +164,7 @@ const computeEffectPropStatus = ({ ast, jsx, effectIndex, keys, }) => {
|
|
|
164
164
|
};
|
|
165
165
|
}
|
|
166
166
|
const resolvedProps = getPropsFromObjectExpression({
|
|
167
|
+
ast,
|
|
167
168
|
objExpr: firstArg,
|
|
168
169
|
keys,
|
|
169
170
|
});
|
|
@@ -3,7 +3,7 @@ import type { SubscribeToSequencePropsResponse } from '@remotion/studio-shared';
|
|
|
3
3
|
import type { CanUpdateSequencePropsResponseTrue, CanUpdateSequencePropStatus, SequenceNodePath } from 'remotion';
|
|
4
4
|
export declare const isStaticValue: (node: Expression) => boolean;
|
|
5
5
|
export declare const extractStaticValue: (node: Expression) => unknown;
|
|
6
|
-
export declare const getComputedStatus: (node: Expression) => CanUpdateSequencePropStatus;
|
|
6
|
+
export declare const getComputedStatus: (node: Expression, ast: File) => CanUpdateSequencePropStatus;
|
|
7
7
|
export declare const findJsxElementAtNodePath: (ast: File, nodePath: SequenceNodePath) => JSXOpeningElement | null;
|
|
8
8
|
export declare const findNodePathForJsxElement: (ast: File, target: JSXOpeningElement) => SequenceNodePath | null;
|
|
9
9
|
export declare const lineColumnToNodePath: (ast: File, targetLine: number) => SequenceNodePath | null;
|
|
@@ -305,9 +305,9 @@ const getInterpolationMetadata = (interpolationFunction, callExpression, keyfram
|
|
|
305
305
|
posterize,
|
|
306
306
|
};
|
|
307
307
|
};
|
|
308
|
-
const getInterpolationKeyframes = (node) => {
|
|
308
|
+
const getInterpolationKeyframes = (node, ast) => {
|
|
309
309
|
if (node.type === 'TSAsExpression') {
|
|
310
|
-
return getInterpolationKeyframes(node.expression);
|
|
310
|
+
return getInterpolationKeyframes(node.expression, ast);
|
|
311
311
|
}
|
|
312
312
|
if (node.type !== 'CallExpression') {
|
|
313
313
|
return undefined;
|
|
@@ -318,9 +318,13 @@ const getInterpolationKeyframes = (node) => {
|
|
|
318
318
|
return undefined;
|
|
319
319
|
}
|
|
320
320
|
const interpolationFunction = callExpression.callee.name;
|
|
321
|
+
const frameArg = callExpression.arguments[0];
|
|
321
322
|
const inputArg = callExpression.arguments[1];
|
|
322
323
|
const outputArg = callExpression.arguments[2];
|
|
323
|
-
if (!
|
|
324
|
+
if (!frameArg ||
|
|
325
|
+
frameArg.type === 'SpreadElement' ||
|
|
326
|
+
!isCurrentFrameIdentifier(frameArg, ast) ||
|
|
327
|
+
!inputArg ||
|
|
324
328
|
!outputArg ||
|
|
325
329
|
inputArg.type !== 'ArrayExpression' ||
|
|
326
330
|
outputArg.type !== 'ArrayExpression') {
|
|
@@ -363,14 +367,45 @@ const getInterpolationKeyframes = (node) => {
|
|
|
363
367
|
posterize: metadata.posterize,
|
|
364
368
|
};
|
|
365
369
|
};
|
|
366
|
-
const
|
|
367
|
-
|
|
370
|
+
const isUseCurrentFrameCall = (node) => {
|
|
371
|
+
return (node.type === 'CallExpression' &&
|
|
372
|
+
node.callee.type === 'Identifier' &&
|
|
373
|
+
node.callee.name === 'useCurrentFrame' &&
|
|
374
|
+
node.arguments.length === 0);
|
|
375
|
+
};
|
|
376
|
+
const isCurrentFrameIdentifier = (node, ast) => {
|
|
377
|
+
if (node.type === 'TSAsExpression') {
|
|
378
|
+
return isCurrentFrameIdentifier(node.expression, ast);
|
|
379
|
+
}
|
|
380
|
+
if (node.type !== 'Identifier') {
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
let hasUseCurrentFrameDeclaration = false;
|
|
384
|
+
let hasOtherDeclaration = false;
|
|
385
|
+
recast.types.visit(ast, {
|
|
386
|
+
visitVariableDeclarator(p) {
|
|
387
|
+
const { id, init } = p.node;
|
|
388
|
+
if (id.type !== 'Identifier' || id.name !== node.name) {
|
|
389
|
+
return this.traverse(p);
|
|
390
|
+
}
|
|
391
|
+
if (init && isUseCurrentFrameCall(init)) {
|
|
392
|
+
hasUseCurrentFrameDeclaration = true;
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
hasOtherDeclaration = true;
|
|
396
|
+
}
|
|
397
|
+
return false;
|
|
398
|
+
},
|
|
399
|
+
});
|
|
400
|
+
return hasUseCurrentFrameDeclaration && !hasOtherDeclaration;
|
|
401
|
+
};
|
|
402
|
+
const getComputedStatus = (node, ast) => {
|
|
403
|
+
const interpolation = getInterpolationKeyframes(node, ast);
|
|
368
404
|
if (!interpolation) {
|
|
369
405
|
return computedStatus();
|
|
370
406
|
}
|
|
371
407
|
return {
|
|
372
408
|
status: 'keyframed',
|
|
373
|
-
codeValue: undefined,
|
|
374
409
|
interpolationFunction: interpolation.interpolationFunction,
|
|
375
410
|
keyframes: interpolation.keyframes,
|
|
376
411
|
easing: interpolation.easing,
|
|
@@ -379,7 +414,7 @@ const getComputedStatus = (node) => {
|
|
|
379
414
|
};
|
|
380
415
|
};
|
|
381
416
|
exports.getComputedStatus = getComputedStatus;
|
|
382
|
-
const getPropsStatus = (jsxElement) => {
|
|
417
|
+
const getPropsStatus = (jsxElement, ast) => {
|
|
383
418
|
const props = {};
|
|
384
419
|
for (const attr of jsxElement.attributes) {
|
|
385
420
|
if (attr.type === 'JSXSpreadAttribute') {
|
|
@@ -408,7 +443,7 @@ const getPropsStatus = (jsxElement) => {
|
|
|
408
443
|
continue;
|
|
409
444
|
}
|
|
410
445
|
if (!(0, exports.isStaticValue)(expression)) {
|
|
411
|
-
props[name] = (0, exports.getComputedStatus)(expression);
|
|
446
|
+
props[name] = (0, exports.getComputedStatus)(expression, ast);
|
|
412
447
|
continue;
|
|
413
448
|
}
|
|
414
449
|
props[name] = staticStatus((0, exports.extractStaticValue)(expression));
|
|
@@ -488,7 +523,7 @@ const validateStyleValue = (childKey, value) => {
|
|
|
488
523
|
}
|
|
489
524
|
return true;
|
|
490
525
|
};
|
|
491
|
-
const getNestedPropStatus = (jsxElement, parentKey, childKey) => {
|
|
526
|
+
const getNestedPropStatus = (jsxElement, ast, parentKey, childKey) => {
|
|
492
527
|
const attr = jsxElement.attributes.find((a) => a.type !== 'JSXSpreadAttribute' &&
|
|
493
528
|
a.name.type !== 'JSXNamespacedName' &&
|
|
494
529
|
a.name.name === parentKey);
|
|
@@ -515,13 +550,13 @@ const getNestedPropStatus = (jsxElement, parentKey, childKey) => {
|
|
|
515
550
|
}
|
|
516
551
|
const propValue = prop.value;
|
|
517
552
|
if (!(0, exports.isStaticValue)(propValue)) {
|
|
518
|
-
return (0, exports.getComputedStatus)(propValue);
|
|
553
|
+
return (0, exports.getComputedStatus)(propValue, ast);
|
|
519
554
|
}
|
|
520
|
-
const
|
|
521
|
-
if (!validateStyleValue(childKey,
|
|
555
|
+
const propStatus = (0, exports.extractStaticValue)(propValue);
|
|
556
|
+
if (!validateStyleValue(childKey, propStatus)) {
|
|
522
557
|
return computedStatus();
|
|
523
558
|
}
|
|
524
|
-
return staticStatus(
|
|
559
|
+
return staticStatus(propStatus);
|
|
525
560
|
};
|
|
526
561
|
const computeEffectsForJsx = ({ ast, jsxElement, effects, }) => {
|
|
527
562
|
return effects.map((effect, effectIndex) => (0, can_update_effect_props_1.computeEffectPropStatus)({
|
|
@@ -531,13 +566,13 @@ const computeEffectsForJsx = ({ ast, jsxElement, effects, }) => {
|
|
|
531
566
|
keys: effect,
|
|
532
567
|
}));
|
|
533
568
|
};
|
|
534
|
-
const computeSequenceOnlyPropsRecord = ({ jsxElement, keys, }) => {
|
|
535
|
-
const allProps = getPropsStatus(jsxElement);
|
|
569
|
+
const computeSequenceOnlyPropsRecord = ({ jsxElement, ast, keys, }) => {
|
|
570
|
+
const allProps = getPropsStatus(jsxElement, ast);
|
|
536
571
|
const filteredProps = {};
|
|
537
572
|
for (const key of keys) {
|
|
538
573
|
const dotIndex = key.indexOf('.');
|
|
539
574
|
if (dotIndex !== -1) {
|
|
540
|
-
filteredProps[key] = getNestedPropStatus(jsxElement, key.slice(0, dotIndex), key.slice(dotIndex + 1));
|
|
575
|
+
filteredProps[key] = getNestedPropStatus(jsxElement, ast, key.slice(0, dotIndex), key.slice(dotIndex + 1));
|
|
541
576
|
}
|
|
542
577
|
else if (key in allProps) {
|
|
543
578
|
filteredProps[key] = allProps[key];
|
|
@@ -554,7 +589,7 @@ const computeSequencePropsStatusFromContent = ({ fileContents, nodePath, keys, e
|
|
|
554
589
|
if (!jsxElement) {
|
|
555
590
|
throw new jsx_element_not_found_at_location_error_1.JsxElementNotFoundAtLocationError();
|
|
556
591
|
}
|
|
557
|
-
const filteredProps = computeSequenceOnlyPropsRecord({ jsxElement, keys });
|
|
592
|
+
const filteredProps = computeSequenceOnlyPropsRecord({ jsxElement, ast, keys });
|
|
558
593
|
const effectsStatuses = computeEffectsForJsx({ ast, jsxElement, effects });
|
|
559
594
|
return {
|
|
560
595
|
canUpdate: true,
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type DownloadRemoteAssetRequest, type DownloadRemoteAssetResponse, type ImageFileType } from '@remotion/studio-shared';
|
|
2
|
+
import type { ApiHandler } from '../api-types';
|
|
3
|
+
export declare const getRemoteAssetFilename: ({ fileType, url, }: {
|
|
4
|
+
fileType: ImageFileType;
|
|
5
|
+
url: URL;
|
|
6
|
+
}) => string;
|
|
7
|
+
export declare const downloadRemoteAssetHandler: ApiHandler<DownloadRemoteAssetRequest, DownloadRemoteAssetResponse>;
|