@remotion/studio-server 4.0.468 → 4.0.469
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/update-keyframes/update-keyframes.js +7 -10
- package/dist/preview-server/routes/can-update-sequence-props.d.ts +0 -9
- package/dist/preview-server/routes/can-update-sequence-props.js +172 -24
- package/dist/preview-server/routes/save-sequence-props.js +7 -4
- package/package.json +6 -6
|
@@ -159,11 +159,14 @@ const addKeyframe = ({ expression, frame, value, }) => {
|
|
|
159
159
|
if (!(0, can_update_sequence_props_1.isStaticValue)(expression)) {
|
|
160
160
|
throw new Error('Cannot add keyframe to computed expression');
|
|
161
161
|
}
|
|
162
|
-
if (frame === 0) {
|
|
163
|
-
throw new Error('Cannot add keyframe to static expression at frame 0 because interpolate requires two distinct frames');
|
|
164
|
-
}
|
|
165
162
|
const staticValue = (0, can_update_sequence_props_1.extractStaticValue)(expression);
|
|
166
163
|
const staticOutput = (0, update_nested_prop_1.parseValueExpression)(staticValue);
|
|
164
|
+
const keyframes = frame === 0
|
|
165
|
+
? [{ frame, output: newOutput, value }]
|
|
166
|
+
: [
|
|
167
|
+
{ frame: 0, output: staticOutput, value: staticValue },
|
|
168
|
+
{ frame, output: newOutput, value },
|
|
169
|
+
];
|
|
167
170
|
return createInterpolateExpression({
|
|
168
171
|
callee: getInterpolationCalleeForValues({
|
|
169
172
|
staticValue,
|
|
@@ -171,10 +174,7 @@ const addKeyframe = ({ expression, frame, value, }) => {
|
|
|
171
174
|
}),
|
|
172
175
|
input: b.identifier('frame'),
|
|
173
176
|
extraArgs: [],
|
|
174
|
-
keyframes
|
|
175
|
-
{ frame: 0, output: staticOutput, value: staticValue },
|
|
176
|
-
{ frame, output: newOutput, value },
|
|
177
|
-
],
|
|
177
|
+
keyframes,
|
|
178
178
|
});
|
|
179
179
|
};
|
|
180
180
|
const removeKeyframe = ({ expression, frame, }) => {
|
|
@@ -187,9 +187,6 @@ const removeKeyframe = ({ expression, frame, }) => {
|
|
|
187
187
|
throw new Error(`Cannot remove keyframe at frame ${frame}: not found`);
|
|
188
188
|
}
|
|
189
189
|
const nextKeyframes = existing.keyframes.filter((_keyframe, index) => index !== keyframeIndex);
|
|
190
|
-
if (nextKeyframes.length === 1) {
|
|
191
|
-
return (0, update_nested_prop_1.parseValueExpression)(nextKeyframes[0].value);
|
|
192
|
-
}
|
|
193
190
|
return createInterpolateExpression({
|
|
194
191
|
callee: existing.callee,
|
|
195
192
|
input: existing.input,
|
|
@@ -6,15 +6,6 @@ export declare const extractStaticValue: (node: Expression) => unknown;
|
|
|
6
6
|
export declare const getComputedStatus: (node: Expression) => CanUpdateSequencePropStatus;
|
|
7
7
|
export declare const findJsxElementAtNodePath: (ast: File, nodePath: SequenceNodePath) => JSXOpeningElement | null;
|
|
8
8
|
export declare const lineColumnToNodePath: (ast: File, targetLine: number) => SequenceNodePath | null;
|
|
9
|
-
export declare const computeSequencePropsOnlyStatus: ({ fileName, nodePath, keys, remotionRoot, }: {
|
|
10
|
-
fileName: string;
|
|
11
|
-
nodePath: SequenceNodePath;
|
|
12
|
-
keys: string[];
|
|
13
|
-
remotionRoot: string;
|
|
14
|
-
}) => {
|
|
15
|
-
canUpdate: true;
|
|
16
|
-
props: Record<string, CanUpdateSequencePropStatus>;
|
|
17
|
-
};
|
|
18
9
|
export declare const computeSequencePropsStatusFromContent: ({ fileContents, nodePath, keys, effects, }: {
|
|
19
10
|
fileContents: string;
|
|
20
11
|
nodePath: SequenceNodePath;
|
|
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.computeSequencePropsStatusFromFilenameByLine = exports.computeSequencePropsStatus = exports.computeSequencePropsStatusFromContent = exports.
|
|
36
|
+
exports.computeSequencePropsStatusFromFilenameByLine = exports.computeSequencePropsStatus = exports.computeSequencePropsStatusFromContent = exports.lineColumnToNodePath = exports.findJsxElementAtNodePath = exports.getComputedStatus = exports.extractStaticValue = exports.isStaticValue = void 0;
|
|
37
37
|
const node_fs_1 = require("node:fs");
|
|
38
38
|
const renderer_1 = require("@remotion/renderer");
|
|
39
39
|
const recast = __importStar(require("recast"));
|
|
@@ -128,6 +128,159 @@ const getNumericValue = (node) => {
|
|
|
128
128
|
}
|
|
129
129
|
return null;
|
|
130
130
|
};
|
|
131
|
+
const getExtrapolateType = (node) => {
|
|
132
|
+
if (node.type === 'StringLiteral') {
|
|
133
|
+
if (node.value === 'extend' ||
|
|
134
|
+
node.value === 'identity' ||
|
|
135
|
+
node.value === 'clamp' ||
|
|
136
|
+
node.value === 'wrap') {
|
|
137
|
+
return node.value;
|
|
138
|
+
}
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
if (node.type === 'TSAsExpression') {
|
|
142
|
+
return getExtrapolateType(node.expression);
|
|
143
|
+
}
|
|
144
|
+
return null;
|
|
145
|
+
};
|
|
146
|
+
const getKeyframeEasing = (node) => {
|
|
147
|
+
if (node.type === 'TSAsExpression') {
|
|
148
|
+
return getKeyframeEasing(node.expression);
|
|
149
|
+
}
|
|
150
|
+
if (node.type === 'MemberExpression' &&
|
|
151
|
+
node.object.type === 'Identifier' &&
|
|
152
|
+
node.object.name === 'Easing' &&
|
|
153
|
+
node.property.type === 'Identifier' &&
|
|
154
|
+
node.property.name === 'linear' &&
|
|
155
|
+
node.computed === false) {
|
|
156
|
+
return 'linear';
|
|
157
|
+
}
|
|
158
|
+
if (node.type !== 'CallExpression' ||
|
|
159
|
+
node.callee.type !== 'MemberExpression' ||
|
|
160
|
+
node.callee.object.type !== 'Identifier' ||
|
|
161
|
+
node.callee.object.name !== 'Easing' ||
|
|
162
|
+
node.callee.property.type !== 'Identifier' ||
|
|
163
|
+
node.callee.property.name !== 'bezier' ||
|
|
164
|
+
node.callee.computed) {
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
if (node.arguments.length !== 4) {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
const values = node.arguments.map((arg) => {
|
|
171
|
+
if (arg.type === 'ArgumentPlaceholder' ||
|
|
172
|
+
arg.type === 'JSXNamespacedName' ||
|
|
173
|
+
arg.type === 'SpreadElement') {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
return getNumericValue(arg);
|
|
177
|
+
});
|
|
178
|
+
if (values.some((v) => v === null)) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
return values;
|
|
182
|
+
};
|
|
183
|
+
const getKeyframeEasingArray = ({ easingNode, segments, }) => {
|
|
184
|
+
if (segments === 0) {
|
|
185
|
+
return [];
|
|
186
|
+
}
|
|
187
|
+
if (easingNode.type === 'TSAsExpression') {
|
|
188
|
+
return getKeyframeEasingArray({
|
|
189
|
+
easingNode: easingNode.expression,
|
|
190
|
+
segments,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
if (easingNode.type === 'ArrayExpression') {
|
|
194
|
+
if (easingNode.elements.length !== segments) {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
const parsed = easingNode.elements.map((element) => {
|
|
198
|
+
if (!element || element.type === 'SpreadElement') {
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
return getKeyframeEasing(element);
|
|
202
|
+
});
|
|
203
|
+
if (parsed.some((value) => value === null)) {
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
206
|
+
return parsed;
|
|
207
|
+
}
|
|
208
|
+
const easing = getKeyframeEasing(easingNode);
|
|
209
|
+
if (!easing) {
|
|
210
|
+
return null;
|
|
211
|
+
}
|
|
212
|
+
return new Array(segments).fill(easing);
|
|
213
|
+
};
|
|
214
|
+
const getInterpolationMetadata = (callExpression, keyframeCount) => {
|
|
215
|
+
const segments = Math.max(0, keyframeCount - 1);
|
|
216
|
+
if (callExpression.callee.type !== 'Identifier') {
|
|
217
|
+
return null;
|
|
218
|
+
}
|
|
219
|
+
const defaultClamping = callExpression.callee.name === 'interpolateColors'
|
|
220
|
+
? {
|
|
221
|
+
left: 'clamp',
|
|
222
|
+
right: 'clamp',
|
|
223
|
+
}
|
|
224
|
+
: {
|
|
225
|
+
left: 'extend',
|
|
226
|
+
right: 'extend',
|
|
227
|
+
};
|
|
228
|
+
const defaults = {
|
|
229
|
+
easing: new Array(segments).fill('linear'),
|
|
230
|
+
clamping: defaultClamping,
|
|
231
|
+
};
|
|
232
|
+
if (callExpression.callee.name === 'interpolateColors') {
|
|
233
|
+
return defaults;
|
|
234
|
+
}
|
|
235
|
+
if (callExpression.callee.name !== 'interpolate') {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
const optionsArg = callExpression.arguments[3];
|
|
239
|
+
if (!optionsArg) {
|
|
240
|
+
return defaults;
|
|
241
|
+
}
|
|
242
|
+
if (optionsArg.type !== 'ObjectExpression') {
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
let { easing } = defaults;
|
|
246
|
+
let { clamping } = defaults;
|
|
247
|
+
for (const property of optionsArg.properties) {
|
|
248
|
+
if (property.type !== 'ObjectProperty' || property.computed) {
|
|
249
|
+
return null;
|
|
250
|
+
}
|
|
251
|
+
const key = property.key.type === 'Identifier'
|
|
252
|
+
? property.key.name
|
|
253
|
+
: property.key.type === 'StringLiteral'
|
|
254
|
+
? property.key.value
|
|
255
|
+
: null;
|
|
256
|
+
if (!key) {
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
const value = property.value;
|
|
260
|
+
if (key === 'easing') {
|
|
261
|
+
const parsedEasing = getKeyframeEasingArray({
|
|
262
|
+
easingNode: value,
|
|
263
|
+
segments,
|
|
264
|
+
});
|
|
265
|
+
if (!parsedEasing) {
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
easing = parsedEasing;
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
if (key === 'extrapolateLeft' || key === 'extrapolateRight') {
|
|
272
|
+
const extrapolateType = getExtrapolateType(value);
|
|
273
|
+
if (!extrapolateType) {
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
clamping =
|
|
277
|
+
key === 'extrapolateLeft'
|
|
278
|
+
? { ...clamping, left: extrapolateType }
|
|
279
|
+
: { ...clamping, right: extrapolateType };
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
return { easing, clamping };
|
|
283
|
+
};
|
|
131
284
|
const getInterpolationKeyframes = (node) => {
|
|
132
285
|
if (node.type === 'TSAsExpression') {
|
|
133
286
|
return getInterpolationKeyframes(node.expression);
|
|
@@ -171,17 +324,30 @@ const getInterpolationKeyframes = (node) => {
|
|
|
171
324
|
value: (0, exports.extractStaticValue)(outputElement),
|
|
172
325
|
});
|
|
173
326
|
}
|
|
174
|
-
|
|
327
|
+
if (keyframes.length === 0) {
|
|
328
|
+
return undefined;
|
|
329
|
+
}
|
|
330
|
+
const metadata = getInterpolationMetadata(callExpression, keyframes.length);
|
|
331
|
+
if (!metadata) {
|
|
332
|
+
return undefined;
|
|
333
|
+
}
|
|
334
|
+
return {
|
|
335
|
+
keyframes,
|
|
336
|
+
easing: metadata.easing,
|
|
337
|
+
clamping: metadata.clamping,
|
|
338
|
+
};
|
|
175
339
|
};
|
|
176
340
|
const getComputedStatus = (node) => {
|
|
177
|
-
const
|
|
178
|
-
if (!
|
|
341
|
+
const interpolation = getInterpolationKeyframes(node);
|
|
342
|
+
if (!interpolation) {
|
|
179
343
|
return { canUpdate: false, reason: 'computed' };
|
|
180
344
|
}
|
|
181
345
|
return {
|
|
182
346
|
canUpdate: false,
|
|
183
|
-
reason: '
|
|
184
|
-
keyframes,
|
|
347
|
+
reason: 'keyframed',
|
|
348
|
+
keyframes: interpolation.keyframes,
|
|
349
|
+
easing: interpolation.easing,
|
|
350
|
+
clamping: interpolation.clamping,
|
|
185
351
|
};
|
|
186
352
|
};
|
|
187
353
|
exports.getComputedStatus = getComputedStatus;
|
|
@@ -345,24 +511,6 @@ const computeSequenceOnlyPropsRecord = ({ jsxElement, keys, }) => {
|
|
|
345
511
|
}
|
|
346
512
|
return filteredProps;
|
|
347
513
|
};
|
|
348
|
-
const computeSequencePropsOnlyStatus = ({ fileName, nodePath, keys, remotionRoot, }) => {
|
|
349
|
-
const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
|
|
350
|
-
remotionRoot,
|
|
351
|
-
fileName,
|
|
352
|
-
action: 'read',
|
|
353
|
-
});
|
|
354
|
-
const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
|
|
355
|
-
const ast = (0, parse_ast_1.parseAst)(fileContents);
|
|
356
|
-
const jsxElement = (0, exports.findJsxElementAtNodePath)(ast, nodePath);
|
|
357
|
-
if (!jsxElement) {
|
|
358
|
-
throw new Error('Cannot compute sequence props: Could not find a JSX element at the specified location');
|
|
359
|
-
}
|
|
360
|
-
return {
|
|
361
|
-
canUpdate: true,
|
|
362
|
-
props: computeSequenceOnlyPropsRecord({ jsxElement, keys }),
|
|
363
|
-
};
|
|
364
|
-
};
|
|
365
|
-
exports.computeSequencePropsOnlyStatus = computeSequencePropsOnlyStatus;
|
|
366
514
|
const computeSequencePropsStatusFromContent = ({ fileContents, nodePath, keys, effects, }) => {
|
|
367
515
|
const ast = (0, parse_ast_1.parseAst)(fileContents);
|
|
368
516
|
const jsxElement = (0, exports.findJsxElementAtNodePath)(ast, nodePath);
|
|
@@ -86,12 +86,15 @@ const saveSequencePropsHandler = ({ input: { fileName, nodePath, key, value, def
|
|
|
86
86
|
addedProps: [],
|
|
87
87
|
});
|
|
88
88
|
(0, undo_stack_1.printUndoHint)(logLevel);
|
|
89
|
-
const newStatus = (0, can_update_sequence_props_1.
|
|
90
|
-
|
|
89
|
+
const newStatus = (0, can_update_sequence_props_1.computeSequencePropsStatusFromContent)({
|
|
90
|
+
fileContents: output,
|
|
91
91
|
keys: (0, studio_shared_1.getAllSchemaKeys)(schema),
|
|
92
92
|
nodePath: nodePath.nodePath,
|
|
93
|
-
|
|
93
|
+
effects: [],
|
|
94
94
|
});
|
|
95
|
-
return
|
|
95
|
+
return {
|
|
96
|
+
canUpdate: true,
|
|
97
|
+
props: newStatus.props,
|
|
98
|
+
};
|
|
96
99
|
});
|
|
97
100
|
exports.saveSequencePropsHandler = saveSequencePropsHandler;
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"url": "https://github.com/remotion-dev/remotion/tree/main/packages/studio-server"
|
|
4
4
|
},
|
|
5
5
|
"name": "@remotion/studio-server",
|
|
6
|
-
"version": "4.0.
|
|
6
|
+
"version": "4.0.469",
|
|
7
7
|
"description": "Run a Remotion Studio with a server backend",
|
|
8
8
|
"main": "dist",
|
|
9
9
|
"scripts": {
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"@babel/parser": "7.24.1",
|
|
28
28
|
"semver": "7.5.3",
|
|
29
29
|
"prettier": "3.8.1",
|
|
30
|
-
"remotion": "4.0.
|
|
30
|
+
"remotion": "4.0.469",
|
|
31
31
|
"recast": "0.23.11",
|
|
32
|
-
"@remotion/bundler": "4.0.
|
|
33
|
-
"@remotion/renderer": "4.0.
|
|
34
|
-
"@remotion/studio-shared": "4.0.
|
|
32
|
+
"@remotion/bundler": "4.0.469",
|
|
33
|
+
"@remotion/renderer": "4.0.469",
|
|
34
|
+
"@remotion/studio-shared": "4.0.469",
|
|
35
35
|
"memfs": "3.4.3",
|
|
36
36
|
"open": "8.4.2"
|
|
37
37
|
},
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"ast-types": "0.16.1",
|
|
40
40
|
"react": "19.2.3",
|
|
41
41
|
"@types/semver": "7.5.3",
|
|
42
|
-
"@remotion/eslint-config-internal": "4.0.
|
|
42
|
+
"@remotion/eslint-config-internal": "4.0.469",
|
|
43
43
|
"eslint": "9.19.0",
|
|
44
44
|
"@types/node": "20.12.14",
|
|
45
45
|
"@typescript/native-preview": "7.0.0-dev.20260217.1"
|