@remotion/studio-server 4.0.475 → 4.0.477
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/duplicate-composition.js +9 -0
- package/dist/codemods/update-keyframes/update-keyframes.js +56 -17
- package/dist/helpers/resolve-composition-component.js +19 -9
- package/dist/preview-server/jsx-component-identity.d.ts +12 -0
- package/dist/preview-server/jsx-component-identity.js +126 -0
- package/dist/preview-server/routes/add-sequence-keyframe.js +1 -0
- package/dist/preview-server/routes/can-update-default-props.js +6 -2
- package/dist/preview-server/routes/can-update-sequence-props.d.ts +12 -5
- package/dist/preview-server/routes/can-update-sequence-props.js +86 -11
- package/dist/preview-server/routes/delete-keyframes.js +1 -0
- package/dist/preview-server/routes/download-remote-asset.js +1 -0
- package/dist/preview-server/routes/insert-jsx-element.js +9 -0
- package/dist/preview-server/routes/save-sequence-props.d.ts +18 -1
- package/dist/preview-server/routes/save-sequence-props.js +26 -17
- package/dist/preview-server/routes/subscribe-to-sequence-props.js +2 -1
- package/dist/preview-server/routes/update-sequence-keyframe-settings.js +1 -0
- package/dist/preview-server/sequence-props-watchers.d.ts +2 -1
- package/dist/preview-server/sequence-props-watchers.js +53 -27
- package/package.json +6 -6
|
@@ -34,6 +34,7 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.parseAndApplyCodemod = exports.formatOutput = void 0;
|
|
37
|
+
const imports_1 = require("../helpers/imports");
|
|
37
38
|
const parse_ast_1 = require("./parse-ast");
|
|
38
39
|
const recast_mods_1 = require("./recast-mods");
|
|
39
40
|
const getPrettier = async () => {
|
|
@@ -71,6 +72,14 @@ const parseAndApplyCodemod = ({ input, codeMod, }) => {
|
|
|
71
72
|
if (changesMade.length === 0) {
|
|
72
73
|
throw new Error('Unable to calculate the changes needed for this file. Edit the file manually.');
|
|
73
74
|
}
|
|
75
|
+
if (codeMod.type === 'duplicate-composition' && codeMod.tag) {
|
|
76
|
+
(0, imports_1.ensureNamedImport)({
|
|
77
|
+
ast: newAst,
|
|
78
|
+
importedName: codeMod.tag,
|
|
79
|
+
sourcePath: 'remotion',
|
|
80
|
+
localName: codeMod.tag,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
74
83
|
const output = (0, parse_ast_1.serializeAst)(newAst);
|
|
75
84
|
return { changesMade, newContents: output };
|
|
76
85
|
};
|
|
@@ -391,6 +391,36 @@ const normalizeEasingAfterRemovingKeyframe = ({ extraArgs, previousSegmentCount,
|
|
|
391
391
|
needsEasingImport: setEasingOption({ options, easing }),
|
|
392
392
|
};
|
|
393
393
|
};
|
|
394
|
+
const normalizeEasingAfterRemovingKeyframes = ({ extraArgs, previousSegmentCount, nextSegmentCount, removedKeyframeIndexes, }) => {
|
|
395
|
+
const options = getInlineOptionsFromExtraArgs(extraArgs);
|
|
396
|
+
if (!options) {
|
|
397
|
+
return { extraArgs, needsEasingImport: false };
|
|
398
|
+
}
|
|
399
|
+
const easing = getExistingEasingArrayOrNull({
|
|
400
|
+
options,
|
|
401
|
+
segmentCount: previousSegmentCount,
|
|
402
|
+
});
|
|
403
|
+
if (easing === null) {
|
|
404
|
+
return { extraArgs, needsEasingImport: false };
|
|
405
|
+
}
|
|
406
|
+
for (const removedKeyframeIndex of [...removedKeyframeIndexes].sort((first, second) => second - first)) {
|
|
407
|
+
if (easing.length === 0) {
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
410
|
+
const easingIndexToRemove = removedKeyframeIndex === 0 ? 0 : removedKeyframeIndex - 1;
|
|
411
|
+
easing.splice(easingIndexToRemove, 1);
|
|
412
|
+
}
|
|
413
|
+
while (easing.length > nextSegmentCount) {
|
|
414
|
+
easing.pop();
|
|
415
|
+
}
|
|
416
|
+
while (easing.length < nextSegmentCount) {
|
|
417
|
+
easing.push('linear');
|
|
418
|
+
}
|
|
419
|
+
return {
|
|
420
|
+
extraArgs: getExtraArgsWithOptions({ extraArgs, options }),
|
|
421
|
+
needsEasingImport: setEasingOption({ options, easing }),
|
|
422
|
+
};
|
|
423
|
+
};
|
|
394
424
|
const validatePosterize = (posterize) => {
|
|
395
425
|
if (posterize === undefined) {
|
|
396
426
|
return;
|
|
@@ -614,7 +644,6 @@ const removeKeyframe = ({ expression, frame, }) => {
|
|
|
614
644
|
};
|
|
615
645
|
};
|
|
616
646
|
const moveKeyframes = ({ expression, moves, }) => {
|
|
617
|
-
var _a;
|
|
618
647
|
const existing = getInterpolationExpression(expression);
|
|
619
648
|
if (!existing) {
|
|
620
649
|
throw new Error('Cannot move keyframe in non-interpolated expression');
|
|
@@ -639,28 +668,38 @@ const moveKeyframes = ({ expression, moves, }) => {
|
|
|
639
668
|
}
|
|
640
669
|
}
|
|
641
670
|
const movedFromFrames = new Set(moveMap.keys());
|
|
642
|
-
const
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
671
|
+
const movedToFrames = new Set(moveMap.values());
|
|
672
|
+
const removedKeyframeIndexes = [];
|
|
673
|
+
const nextKeyframes = existing.keyframes.flatMap((keyframe, index) => {
|
|
674
|
+
const movedFrame = moveMap.get(keyframe.frame);
|
|
675
|
+
if (movedFrame !== undefined) {
|
|
676
|
+
return [{ ...keyframe, frame: movedFrame }];
|
|
647
677
|
}
|
|
648
|
-
if (
|
|
649
|
-
|
|
678
|
+
if (movedToFrames.has(keyframe.frame) &&
|
|
679
|
+
!movedFromFrames.has(keyframe.frame)) {
|
|
680
|
+
removedKeyframeIndexes.push(index);
|
|
681
|
+
return [];
|
|
650
682
|
}
|
|
651
|
-
|
|
683
|
+
return [keyframe];
|
|
684
|
+
});
|
|
685
|
+
const nextFrames = new Set();
|
|
686
|
+
for (const keyframe of nextKeyframes) {
|
|
687
|
+
if (nextFrames.has(keyframe.frame)) {
|
|
688
|
+
throw new Error(`Cannot move keyframe to frame ${keyframe.frame}: frame already exists`);
|
|
689
|
+
}
|
|
690
|
+
nextFrames.add(keyframe.frame);
|
|
652
691
|
}
|
|
692
|
+
const normalizedEasing = normalizeEasingAfterRemovingKeyframes({
|
|
693
|
+
extraArgs: existing.extraArgs,
|
|
694
|
+
previousSegmentCount: Math.max(existing.keyframes.length - 1, 0),
|
|
695
|
+
nextSegmentCount: Math.max(nextKeyframes.length - 1, 0),
|
|
696
|
+
removedKeyframeIndexes,
|
|
697
|
+
});
|
|
653
698
|
return createInterpolateExpression({
|
|
654
699
|
callee: existing.callee,
|
|
655
700
|
input: existing.input,
|
|
656
|
-
extraArgs:
|
|
657
|
-
keyframes:
|
|
658
|
-
var _a;
|
|
659
|
-
return ({
|
|
660
|
-
...keyframe,
|
|
661
|
-
frame: (_a = moveMap.get(keyframe.frame)) !== null && _a !== void 0 ? _a : keyframe.frame,
|
|
662
|
-
});
|
|
663
|
-
}),
|
|
701
|
+
extraArgs: normalizedEasing.extraArgs,
|
|
702
|
+
keyframes: nextKeyframes,
|
|
664
703
|
});
|
|
665
704
|
};
|
|
666
705
|
const applyKeyframeOperation = ({ expression, key, operation, schema, }) => {
|
|
@@ -515,10 +515,15 @@ const createStringAttribute = (name, value) => {
|
|
|
515
515
|
const createBooleanAttribute = (name, value) => {
|
|
516
516
|
return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier(name), recast.types.builders.jsxExpressionContainer(recast.types.builders.booleanLiteral(value)));
|
|
517
517
|
};
|
|
518
|
-
const
|
|
519
|
-
|
|
518
|
+
const formatTranslateValue = ({ x, y }) => `${x}px ${y}px`;
|
|
519
|
+
const createPositionAbsoluteStyleAttribute = (position) => {
|
|
520
|
+
const properties = [
|
|
520
521
|
recast.types.builders.objectProperty(recast.types.builders.identifier('position'), recast.types.builders.stringLiteral('absolute')),
|
|
521
|
-
]
|
|
522
|
+
];
|
|
523
|
+
if (position) {
|
|
524
|
+
properties.push(recast.types.builders.objectProperty(recast.types.builders.identifier('translate'), recast.types.builders.stringLiteral(formatTranslateValue(position))));
|
|
525
|
+
}
|
|
526
|
+
return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier('style'), recast.types.builders.jsxExpressionContainer(recast.types.builders.objectExpression(properties)));
|
|
522
527
|
};
|
|
523
528
|
const createStaticFileSrcAttribute = ({ staticFileLocalName, src, }) => {
|
|
524
529
|
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)])));
|
|
@@ -535,25 +540,27 @@ const createComponentProp = ({ name, value, }) => {
|
|
|
535
540
|
const createStringSrcAttribute = (src) => {
|
|
536
541
|
return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier('src'), recast.types.builders.stringLiteral(src));
|
|
537
542
|
};
|
|
538
|
-
const createSolidElement = ({ localName, width, height, }) => {
|
|
543
|
+
const createSolidElement = ({ localName, width, height, position, }) => {
|
|
539
544
|
return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
|
|
540
545
|
createNumberAttribute('width', width),
|
|
541
546
|
createNumberAttribute('height', height),
|
|
542
|
-
createPositionAbsoluteStyleAttribute(),
|
|
547
|
+
createPositionAbsoluteStyleAttribute(position),
|
|
543
548
|
], true), null, []);
|
|
544
549
|
};
|
|
545
|
-
const createComponentElement = ({ localName, props, }) => {
|
|
550
|
+
const createComponentElement = ({ localName, props, position, }) => {
|
|
546
551
|
return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
|
|
547
552
|
...props.map(createComponentProp),
|
|
548
|
-
createPositionAbsoluteStyleAttribute(),
|
|
553
|
+
createPositionAbsoluteStyleAttribute(position),
|
|
549
554
|
], true), null, []);
|
|
550
555
|
};
|
|
551
|
-
const createAssetElement = ({ addPositionStyle, localName, staticFileLocalName, src, dimensions, }) => {
|
|
556
|
+
const createAssetElement = ({ addPositionStyle, localName, staticFileLocalName, src, dimensions, position, }) => {
|
|
552
557
|
return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
|
|
553
558
|
staticFileLocalName === null
|
|
554
559
|
? createStringSrcAttribute(src)
|
|
555
560
|
: createStaticFileSrcAttribute({ staticFileLocalName, src }),
|
|
556
|
-
...(addPositionStyle
|
|
561
|
+
...(addPositionStyle
|
|
562
|
+
? [createPositionAbsoluteStyleAttribute(position)]
|
|
563
|
+
: []),
|
|
557
564
|
...(dimensions
|
|
558
565
|
? [
|
|
559
566
|
createNumberAttribute('width', dimensions.width),
|
|
@@ -1007,6 +1014,7 @@ const createInsertableJsxElement = ({ ast, element, }) => {
|
|
|
1007
1014
|
localName: solidLocalName,
|
|
1008
1015
|
width: element.width,
|
|
1009
1016
|
height: element.height,
|
|
1017
|
+
position: element.position,
|
|
1010
1018
|
});
|
|
1011
1019
|
}
|
|
1012
1020
|
if (element.type === 'component') {
|
|
@@ -1019,6 +1027,7 @@ const createInsertableJsxElement = ({ ast, element, }) => {
|
|
|
1019
1027
|
return createComponentElement({
|
|
1020
1028
|
localName: componentLocalName,
|
|
1021
1029
|
props: element.props,
|
|
1030
|
+
position: element.position,
|
|
1022
1031
|
});
|
|
1023
1032
|
}
|
|
1024
1033
|
if (element.type === 'asset') {
|
|
@@ -1048,6 +1057,7 @@ const createInsertableJsxElement = ({ ast, element, }) => {
|
|
|
1048
1057
|
staticFileLocalName,
|
|
1049
1058
|
src: element.src,
|
|
1050
1059
|
dimensions: element.dimensions,
|
|
1060
|
+
position: element.position,
|
|
1051
1061
|
});
|
|
1052
1062
|
}
|
|
1053
1063
|
throw new Error('Unsupported element type');
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { File, JSXOpeningElement } from '@babel/types';
|
|
2
|
+
export declare class JsxElementIdentityMismatchError extends Error {
|
|
3
|
+
constructor();
|
|
4
|
+
}
|
|
5
|
+
export declare const getJsxComponentIdentity: ({ ast, jsxElement, }: {
|
|
6
|
+
ast: File;
|
|
7
|
+
jsxElement: JSXOpeningElement;
|
|
8
|
+
}) => string | null;
|
|
9
|
+
export declare const jsxComponentIdentitiesMatch: ({ expected, actual, }: {
|
|
10
|
+
expected: string | null;
|
|
11
|
+
actual: string | null;
|
|
12
|
+
}) => boolean;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.jsxComponentIdentitiesMatch = exports.getJsxComponentIdentity = exports.JsxElementIdentityMismatchError = void 0;
|
|
4
|
+
const imports_1 = require("../helpers/imports");
|
|
5
|
+
class JsxElementIdentityMismatchError extends Error {
|
|
6
|
+
constructor() {
|
|
7
|
+
super('JSX element identity changed');
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
exports.JsxElementIdentityMismatchError = JsxElementIdentityMismatchError;
|
|
11
|
+
const jsxMemberToString = (expr) => {
|
|
12
|
+
if (expr.type === 'JSXIdentifier') {
|
|
13
|
+
return expr.name;
|
|
14
|
+
}
|
|
15
|
+
return `${jsxMemberToString(expr.object)}.${expr.property.name}`;
|
|
16
|
+
};
|
|
17
|
+
const getJsxRootIdentifier = (expr) => {
|
|
18
|
+
if (expr.type === 'JSXIdentifier') {
|
|
19
|
+
return expr;
|
|
20
|
+
}
|
|
21
|
+
return getJsxRootIdentifier(expr.object);
|
|
22
|
+
};
|
|
23
|
+
const getTagName = (node) => {
|
|
24
|
+
if (node.name.type === 'JSXIdentifier') {
|
|
25
|
+
return node.name.name;
|
|
26
|
+
}
|
|
27
|
+
if (node.name.type === 'JSXMemberExpression') {
|
|
28
|
+
return jsxMemberToString(node.name);
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
};
|
|
32
|
+
const getMemberPath = (tagName) => {
|
|
33
|
+
const dotIndex = tagName.indexOf('.');
|
|
34
|
+
return dotIndex === -1 ? '' : tagName.slice(dotIndex + 1);
|
|
35
|
+
};
|
|
36
|
+
const getMemberPathAfterImportName = ({ tagName, importName, }) => {
|
|
37
|
+
const parts = tagName.split('.');
|
|
38
|
+
const importNameIndex = parts.indexOf(importName);
|
|
39
|
+
if (importNameIndex === -1) {
|
|
40
|
+
return getMemberPath(tagName);
|
|
41
|
+
}
|
|
42
|
+
return parts.slice(importNameIndex + 1).join('.');
|
|
43
|
+
};
|
|
44
|
+
const sourcePathToIdentityPrefix = (sourcePath) => {
|
|
45
|
+
if (sourcePath === 'remotion') {
|
|
46
|
+
return 'dev.remotion.remotion';
|
|
47
|
+
}
|
|
48
|
+
if (sourcePath.startsWith('@remotion/')) {
|
|
49
|
+
const packageName = sourcePath
|
|
50
|
+
.slice('@remotion/'.length)
|
|
51
|
+
.replace(/-([a-z])/g, (_, char) => char.toUpperCase());
|
|
52
|
+
return `dev.remotion.${packageName}`;
|
|
53
|
+
}
|
|
54
|
+
return null;
|
|
55
|
+
};
|
|
56
|
+
const makeImportedIdentity = ({ sourcePath, importName, memberPath, }) => {
|
|
57
|
+
const prefix = sourcePathToIdentityPrefix(sourcePath);
|
|
58
|
+
if (prefix === null) {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
return [prefix, importName, memberPath].filter(Boolean).join('.');
|
|
62
|
+
};
|
|
63
|
+
const getJsxComponentIdentity = ({ ast, jsxElement, }) => {
|
|
64
|
+
var _a;
|
|
65
|
+
const tagName = getTagName(jsxElement);
|
|
66
|
+
if (tagName === null) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
const rootIdentifier = jsxElement.name.type === 'JSXIdentifier'
|
|
70
|
+
? jsxElement.name
|
|
71
|
+
: jsxElement.name.type === 'JSXMemberExpression'
|
|
72
|
+
? getJsxRootIdentifier(jsxElement.name)
|
|
73
|
+
: null;
|
|
74
|
+
if (rootIdentifier === null) {
|
|
75
|
+
return tagName;
|
|
76
|
+
}
|
|
77
|
+
for (const node of ast.program.body) {
|
|
78
|
+
if (node.type !== 'ImportDeclaration') {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
const sourcePath = String(node.source.value);
|
|
82
|
+
for (const specifier of node.specifiers) {
|
|
83
|
+
if (specifier.type === 'ImportSpecifier' &&
|
|
84
|
+
((_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) === rootIdentifier.name) {
|
|
85
|
+
const importName = (0, imports_1.getImportedName)(specifier);
|
|
86
|
+
return makeImportedIdentity({
|
|
87
|
+
sourcePath,
|
|
88
|
+
importName,
|
|
89
|
+
memberPath: getMemberPath(tagName),
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (specifier.type === 'ImportNamespaceSpecifier' &&
|
|
93
|
+
specifier.local.name === rootIdentifier.name) {
|
|
94
|
+
const [importName, ...members] = getMemberPath(tagName).split('.');
|
|
95
|
+
if (!importName) {
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
return makeImportedIdentity({
|
|
99
|
+
sourcePath,
|
|
100
|
+
importName,
|
|
101
|
+
memberPath: members.join('.'),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
if (specifier.type === 'ImportDefaultSpecifier' &&
|
|
105
|
+
specifier.local.name === rootIdentifier.name) {
|
|
106
|
+
return makeImportedIdentity({
|
|
107
|
+
sourcePath,
|
|
108
|
+
importName: 'default',
|
|
109
|
+
memberPath: getMemberPathAfterImportName({
|
|
110
|
+
tagName,
|
|
111
|
+
importName: rootIdentifier.name,
|
|
112
|
+
}),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return tagName;
|
|
118
|
+
};
|
|
119
|
+
exports.getJsxComponentIdentity = getJsxComponentIdentity;
|
|
120
|
+
const jsxComponentIdentitiesMatch = ({ expected, actual, }) => {
|
|
121
|
+
if (expected === null) {
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
return expected === actual;
|
|
125
|
+
};
|
|
126
|
+
exports.jsxComponentIdentitiesMatch = jsxComponentIdentitiesMatch;
|
|
@@ -74,6 +74,7 @@ const addSequenceKeyframeHandler = ({ input: { fileName, nodePath, key, frame, v
|
|
|
74
74
|
fileContents: output,
|
|
75
75
|
keys: (0, studio_shared_1.getAllSchemaKeys)(schema),
|
|
76
76
|
nodePath: updatedNodePath,
|
|
77
|
+
componentIdentity: null,
|
|
77
78
|
effects: [],
|
|
78
79
|
});
|
|
79
80
|
const updatedSubscriptionKey = { ...nodePath, nodePath: updatedNodePath };
|
|
@@ -106,8 +106,12 @@ const extractDefaultPropsFromSource = (input, compositionId) => {
|
|
|
106
106
|
this.traverse(path);
|
|
107
107
|
return;
|
|
108
108
|
}
|
|
109
|
-
if ((0, can_update_sequence_props_1.isStaticValue)(expression
|
|
110
|
-
|
|
109
|
+
if ((0, can_update_sequence_props_1.isStaticValue)(expression, {
|
|
110
|
+
allowSpecialValues: true,
|
|
111
|
+
})) {
|
|
112
|
+
const value = (0, can_update_sequence_props_1.extractStaticValue)(expression, {
|
|
113
|
+
allowSpecialValues: true,
|
|
114
|
+
});
|
|
111
115
|
if (value !== null &&
|
|
112
116
|
typeof value === 'object' &&
|
|
113
117
|
!Array.isArray(value)) {
|
|
@@ -1,30 +1,37 @@
|
|
|
1
1
|
import type { Expression, File, JSXOpeningElement } from '@babel/types';
|
|
2
2
|
import type { SubscribeToSequencePropsResponse } from '@remotion/studio-shared';
|
|
3
3
|
import type { CanUpdateSequencePropsResponseTrue, CanUpdateSequencePropStatus, SequenceNodePath } from 'remotion';
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
type StaticValueOptions = {
|
|
5
|
+
allowSpecialValues: boolean;
|
|
6
|
+
};
|
|
7
|
+
export declare const isStaticValue: (node: Expression, options?: StaticValueOptions) => boolean;
|
|
8
|
+
export declare const extractStaticValue: (node: Expression, options?: StaticValueOptions) => unknown;
|
|
6
9
|
export declare const getComputedStatus: (node: Expression, ast: File) => CanUpdateSequencePropStatus;
|
|
7
10
|
export declare const findJsxElementAtNodePath: (ast: File, nodePath: SequenceNodePath) => JSXOpeningElement | null;
|
|
8
11
|
export declare const findNodePathForJsxElement: (ast: File, target: JSXOpeningElement) => SequenceNodePath | null;
|
|
9
12
|
export declare const lineColumnToNodePath: (ast: File, targetLine: number) => SequenceNodePath | null;
|
|
10
|
-
export declare const computeSequencePropsStatusFromContent: ({ fileContents, nodePath, keys, effects, }: {
|
|
13
|
+
export declare const computeSequencePropsStatusFromContent: ({ fileContents, nodePath, componentIdentity, keys, effects, }: {
|
|
11
14
|
fileContents: string;
|
|
12
15
|
nodePath: SequenceNodePath;
|
|
16
|
+
componentIdentity: string | null;
|
|
13
17
|
keys: string[];
|
|
14
18
|
effects: string[][];
|
|
15
19
|
}) => CanUpdateSequencePropsResponseTrue;
|
|
16
|
-
export declare const computeSequencePropsStatus: ({ fileName, nodePath, keys, effects, remotionRoot, }: {
|
|
20
|
+
export declare const computeSequencePropsStatus: ({ fileName, nodePath, componentIdentity, keys, effects, remotionRoot, }: {
|
|
17
21
|
fileName: string;
|
|
18
22
|
nodePath: SequenceNodePath;
|
|
23
|
+
componentIdentity: string | null;
|
|
19
24
|
keys: string[];
|
|
20
25
|
effects: string[][];
|
|
21
26
|
remotionRoot: string;
|
|
22
27
|
}) => CanUpdateSequencePropsResponseTrue;
|
|
23
|
-
export declare const computeSequencePropsStatusFromFilenameByLine: ({ fileName, line, keys, effects, remotionRoot, logLevel, }: {
|
|
28
|
+
export declare const computeSequencePropsStatusFromFilenameByLine: ({ fileName, line, componentIdentity, keys, effects, remotionRoot, logLevel, }: {
|
|
24
29
|
fileName: string;
|
|
25
30
|
line: number;
|
|
31
|
+
componentIdentity: string | null;
|
|
26
32
|
keys: string[];
|
|
27
33
|
effects: string[][];
|
|
28
34
|
remotionRoot: string;
|
|
29
35
|
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
30
36
|
}) => SubscribeToSequencePropsResponse;
|
|
37
|
+
export {};
|
|
@@ -38,10 +38,12 @@ const node_fs_1 = require("node:fs");
|
|
|
38
38
|
const renderer_1 = require("@remotion/renderer");
|
|
39
39
|
const studio_shared_1 = require("@remotion/studio-shared");
|
|
40
40
|
const recast = __importStar(require("recast"));
|
|
41
|
+
const no_react_1 = require("remotion/no-react");
|
|
41
42
|
const parse_ast_1 = require("../../codemods/parse-ast");
|
|
42
43
|
const get_ast_node_path_1 = require("../../helpers/get-ast-node-path");
|
|
43
44
|
const import_agnostic_node_path_1 = require("../../helpers/import-agnostic-node-path");
|
|
44
45
|
const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
|
|
46
|
+
const jsx_component_identity_1 = require("../jsx-component-identity");
|
|
45
47
|
const jsx_element_not_found_at_location_error_1 = require("../jsx-element-not-found-at-location-error");
|
|
46
48
|
const can_update_effect_props_1 = require("./can-update-effect-props");
|
|
47
49
|
const staticStatus = (codeValue) => ({
|
|
@@ -51,7 +53,42 @@ const staticStatus = (codeValue) => ({
|
|
|
51
53
|
const computedStatus = () => ({
|
|
52
54
|
status: 'computed',
|
|
53
55
|
});
|
|
54
|
-
|
|
56
|
+
// Mirrors the encoding that staticFile() from "remotion" applies at runtime
|
|
57
|
+
const encodeStaticFilePath = (path) => {
|
|
58
|
+
return path.split('/').map(encodeURIComponent).join('/');
|
|
59
|
+
};
|
|
60
|
+
// Detects calls that the Studio knows how to serialize back to source:
|
|
61
|
+
// staticFile("...") and new Date("...")
|
|
62
|
+
const getSpecialValueCall = (node) => {
|
|
63
|
+
if (node.type === 'CallExpression') {
|
|
64
|
+
const call = node;
|
|
65
|
+
if (call.callee.type === 'Identifier' &&
|
|
66
|
+
call.callee.name === 'staticFile' &&
|
|
67
|
+
call.arguments.length === 1 &&
|
|
68
|
+
call.arguments[0].type === 'StringLiteral') {
|
|
69
|
+
return { type: 'static-file', value: call.arguments[0].value };
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
if (node.type === 'NewExpression') {
|
|
74
|
+
const newExpr = node;
|
|
75
|
+
if (newExpr.callee.type === 'Identifier' &&
|
|
76
|
+
newExpr.callee.name === 'Date' &&
|
|
77
|
+
newExpr.arguments.length === 1 &&
|
|
78
|
+
newExpr.arguments[0].type === 'StringLiteral') {
|
|
79
|
+
return { type: 'date', value: newExpr.arguments[0].value };
|
|
80
|
+
}
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
return null;
|
|
84
|
+
};
|
|
85
|
+
const defaultStaticValueOptions = {
|
|
86
|
+
allowSpecialValues: false,
|
|
87
|
+
};
|
|
88
|
+
const isStaticValue = (node, options = defaultStaticValueOptions) => {
|
|
89
|
+
if (options.allowSpecialValues && getSpecialValueCall(node) !== null) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
55
92
|
switch (node.type) {
|
|
56
93
|
case 'NumericLiteral':
|
|
57
94
|
case 'StringLiteral':
|
|
@@ -63,18 +100,29 @@ const isStaticValue = (node) => {
|
|
|
63
100
|
node.operator === '+') &&
|
|
64
101
|
node.argument.type === 'NumericLiteral');
|
|
65
102
|
case 'TSAsExpression':
|
|
66
|
-
return (0, exports.isStaticValue)(node.expression);
|
|
103
|
+
return (0, exports.isStaticValue)(node.expression, options);
|
|
67
104
|
case 'ArrayExpression':
|
|
68
|
-
return node.elements.every((el) => el !== null &&
|
|
105
|
+
return node.elements.every((el) => el !== null &&
|
|
106
|
+
el.type !== 'SpreadElement' &&
|
|
107
|
+
(0, exports.isStaticValue)(el, options));
|
|
69
108
|
case 'ObjectExpression':
|
|
70
109
|
return node.properties.every((prop) => prop.type === 'ObjectProperty' &&
|
|
71
|
-
(0, exports.isStaticValue)(prop.value));
|
|
110
|
+
(0, exports.isStaticValue)(prop.value, options));
|
|
72
111
|
default:
|
|
73
112
|
return false;
|
|
74
113
|
}
|
|
75
114
|
};
|
|
76
115
|
exports.isStaticValue = isStaticValue;
|
|
77
|
-
const extractStaticValue = (node) => {
|
|
116
|
+
const extractStaticValue = (node, options = defaultStaticValueOptions) => {
|
|
117
|
+
if (options.allowSpecialValues) {
|
|
118
|
+
const specialValue = getSpecialValueCall(node);
|
|
119
|
+
if (specialValue !== null) {
|
|
120
|
+
if (specialValue.type === 'static-file') {
|
|
121
|
+
return `${no_react_1.NoReactInternals.FILE_TOKEN}${encodeStaticFilePath(specialValue.value)}`;
|
|
122
|
+
}
|
|
123
|
+
return `${no_react_1.NoReactInternals.DATE_TOKEN}${specialValue.value}`;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
78
126
|
switch (node.type) {
|
|
79
127
|
case 'NumericLiteral':
|
|
80
128
|
case 'StringLiteral':
|
|
@@ -91,13 +139,13 @@ const extractStaticValue = (node) => {
|
|
|
91
139
|
return undefined;
|
|
92
140
|
}
|
|
93
141
|
case 'TSAsExpression':
|
|
94
|
-
return (0, exports.extractStaticValue)(node.expression);
|
|
142
|
+
return (0, exports.extractStaticValue)(node.expression, options);
|
|
95
143
|
case 'ArrayExpression':
|
|
96
144
|
return node.elements.map((el) => {
|
|
97
145
|
if (el === null || el.type === 'SpreadElement') {
|
|
98
146
|
return undefined;
|
|
99
147
|
}
|
|
100
|
-
return (0, exports.extractStaticValue)(el);
|
|
148
|
+
return (0, exports.extractStaticValue)(el, options);
|
|
101
149
|
});
|
|
102
150
|
case 'ObjectExpression': {
|
|
103
151
|
const obj = node;
|
|
@@ -112,7 +160,7 @@ const extractStaticValue = (node) => {
|
|
|
112
160
|
? String(p.key.value)
|
|
113
161
|
: undefined;
|
|
114
162
|
if (key !== undefined) {
|
|
115
|
-
result[key] = (0, exports.extractStaticValue)(p.value);
|
|
163
|
+
result[key] = (0, exports.extractStaticValue)(p.value, options);
|
|
116
164
|
}
|
|
117
165
|
}
|
|
118
166
|
}
|
|
@@ -306,6 +354,25 @@ const getInterpolationKeyframes = (node, ast) => {
|
|
|
306
354
|
if (node.type === 'TSAsExpression') {
|
|
307
355
|
return getInterpolationKeyframes(node.expression, ast);
|
|
308
356
|
}
|
|
357
|
+
if (node.type === 'CallExpression' &&
|
|
358
|
+
node.callee.type === 'Identifier' &&
|
|
359
|
+
node.callee.name === 'String' &&
|
|
360
|
+
node.arguments.length === 1 &&
|
|
361
|
+
node.arguments[0].type !== 'ArgumentPlaceholder' &&
|
|
362
|
+
node.arguments[0].type !== 'JSXNamespacedName' &&
|
|
363
|
+
node.arguments[0].type !== 'SpreadElement') {
|
|
364
|
+
const interpolation = getInterpolationKeyframes(node.arguments[0], ast);
|
|
365
|
+
if (!interpolation) {
|
|
366
|
+
return undefined;
|
|
367
|
+
}
|
|
368
|
+
return {
|
|
369
|
+
...interpolation,
|
|
370
|
+
keyframes: interpolation.keyframes.map((keyframe) => ({
|
|
371
|
+
...keyframe,
|
|
372
|
+
value: String(keyframe.value),
|
|
373
|
+
})),
|
|
374
|
+
};
|
|
375
|
+
}
|
|
309
376
|
if (node.type !== 'CallExpression') {
|
|
310
377
|
return undefined;
|
|
311
378
|
}
|
|
@@ -580,12 +647,18 @@ const computeSequenceOnlyPropsRecord = ({ jsxElement, ast, keys, }) => {
|
|
|
580
647
|
}
|
|
581
648
|
return filteredProps;
|
|
582
649
|
};
|
|
583
|
-
const computeSequencePropsStatusFromContent = ({ fileContents, nodePath, keys, effects, }) => {
|
|
650
|
+
const computeSequencePropsStatusFromContent = ({ fileContents, nodePath, componentIdentity, keys, effects, }) => {
|
|
584
651
|
const ast = (0, parse_ast_1.parseAst)(fileContents);
|
|
585
652
|
const jsxElement = (0, exports.findJsxElementAtNodePath)(ast, nodePath);
|
|
586
653
|
if (!jsxElement) {
|
|
587
654
|
throw new jsx_element_not_found_at_location_error_1.JsxElementNotFoundAtLocationError();
|
|
588
655
|
}
|
|
656
|
+
if (!(0, jsx_component_identity_1.jsxComponentIdentitiesMatch)({
|
|
657
|
+
expected: componentIdentity,
|
|
658
|
+
actual: (0, jsx_component_identity_1.getJsxComponentIdentity)({ ast, jsxElement }),
|
|
659
|
+
})) {
|
|
660
|
+
throw new jsx_component_identity_1.JsxElementIdentityMismatchError();
|
|
661
|
+
}
|
|
589
662
|
const filteredProps = computeSequenceOnlyPropsRecord({ jsxElement, ast, keys });
|
|
590
663
|
const effectsStatuses = computeEffectsForJsx({ ast, jsxElement, effects });
|
|
591
664
|
return {
|
|
@@ -595,7 +668,7 @@ const computeSequencePropsStatusFromContent = ({ fileContents, nodePath, keys, e
|
|
|
595
668
|
};
|
|
596
669
|
};
|
|
597
670
|
exports.computeSequencePropsStatusFromContent = computeSequencePropsStatusFromContent;
|
|
598
|
-
const computeSequencePropsStatus = ({ fileName, nodePath, keys, effects, remotionRoot, }) => {
|
|
671
|
+
const computeSequencePropsStatus = ({ fileName, nodePath, componentIdentity, keys, effects, remotionRoot, }) => {
|
|
599
672
|
const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
|
|
600
673
|
remotionRoot,
|
|
601
674
|
fileName,
|
|
@@ -605,12 +678,13 @@ const computeSequencePropsStatus = ({ fileName, nodePath, keys, effects, remotio
|
|
|
605
678
|
return (0, exports.computeSequencePropsStatusFromContent)({
|
|
606
679
|
fileContents,
|
|
607
680
|
nodePath,
|
|
681
|
+
componentIdentity,
|
|
608
682
|
keys,
|
|
609
683
|
effects,
|
|
610
684
|
});
|
|
611
685
|
};
|
|
612
686
|
exports.computeSequencePropsStatus = computeSequencePropsStatus;
|
|
613
|
-
const computeSequencePropsStatusFromFilenameByLine = ({ fileName, line, keys, effects, remotionRoot, logLevel, }) => {
|
|
687
|
+
const computeSequencePropsStatusFromFilenameByLine = ({ fileName, line, componentIdentity, keys, effects, remotionRoot, logLevel, }) => {
|
|
614
688
|
try {
|
|
615
689
|
const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
|
|
616
690
|
remotionRoot,
|
|
@@ -633,6 +707,7 @@ const computeSequencePropsStatusFromFilenameByLine = ({ fileName, line, keys, ef
|
|
|
633
707
|
status: (0, exports.computeSequencePropsStatus)({
|
|
634
708
|
fileName,
|
|
635
709
|
nodePath: resolvedNodePath,
|
|
710
|
+
componentIdentity,
|
|
636
711
|
keys,
|
|
637
712
|
effects,
|
|
638
713
|
remotionRoot,
|
|
@@ -215,6 +215,7 @@ const deleteKeyframes = async ({ sequenceKeyframes, effectKeyframes, clientId, r
|
|
|
215
215
|
fileContents: output,
|
|
216
216
|
keys: (0, studio_shared_1.getAllSchemaKeys)(keyframe.schema),
|
|
217
217
|
nodePath: keyframe.nodePath.nodePath,
|
|
218
|
+
componentIdentity: null,
|
|
218
219
|
effects: [],
|
|
219
220
|
});
|
|
220
221
|
return {
|
|
@@ -14,7 +14,16 @@ const validateDimension = (name, value) => {
|
|
|
14
14
|
throw new Error(`${name} must be a positive number`);
|
|
15
15
|
}
|
|
16
16
|
};
|
|
17
|
+
const validatePosition = (position) => {
|
|
18
|
+
if (position === null) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (!Number.isFinite(position.x) || !Number.isFinite(position.y)) {
|
|
22
|
+
throw new Error('Position must be finite');
|
|
23
|
+
}
|
|
24
|
+
};
|
|
17
25
|
const validateElement = (element) => {
|
|
26
|
+
validatePosition(element.position);
|
|
18
27
|
if (element.type === 'solid') {
|
|
19
28
|
validateDimension('width', element.width);
|
|
20
29
|
validateDimension('height', element.height);
|
|
@@ -1,3 +1,20 @@
|
|
|
1
|
-
import type { SaveSequencePropsRequest, SaveSequencePropsResponse } from '@remotion/studio-shared';
|
|
1
|
+
import type { SaveSequencePropEdit, SaveSequencePropsRequest, SaveSequencePropsResponse } from '@remotion/studio-shared';
|
|
2
|
+
import { type SequencePropsNodeUpdate } from '../../codemods/update-sequence-props/update-sequence-props';
|
|
2
3
|
import type { ApiHandler } from '../api-types';
|
|
4
|
+
type ResolvedSequencePropEdit = {
|
|
5
|
+
index: number;
|
|
6
|
+
fileName: SaveSequencePropEdit['fileName'];
|
|
7
|
+
nodePath: SaveSequencePropEdit['nodePath'];
|
|
8
|
+
key: SaveSequencePropEdit['key'];
|
|
9
|
+
value: unknown;
|
|
10
|
+
valueString: string;
|
|
11
|
+
defaultValue: unknown | null;
|
|
12
|
+
defaultValueString: string | null;
|
|
13
|
+
schema: SaveSequencePropEdit['schema'];
|
|
14
|
+
};
|
|
15
|
+
export declare const convertSequencePropEditToCodemodChange: (edit: Pick<ResolvedSequencePropEdit, "defaultValue" | "key" | "nodePath" | "schema" | "value">) => SequencePropsNodeUpdate;
|
|
16
|
+
export declare const shouldSuppressHmrForSequencePropEdits: (edits: readonly {
|
|
17
|
+
key: string;
|
|
18
|
+
}[]) => boolean;
|
|
3
19
|
export declare const saveSequencePropsHandler: ApiHandler<SaveSequencePropsRequest, SaveSequencePropsResponse>;
|
|
20
|
+
export {};
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.saveSequencePropsHandler = void 0;
|
|
3
|
+
exports.saveSequencePropsHandler = exports.shouldSuppressHmrForSequencePropEdits = exports.convertSequencePropEditToCodemodChange = void 0;
|
|
4
4
|
const node_fs_1 = require("node:fs");
|
|
5
5
|
const renderer_1 = require("@remotion/renderer");
|
|
6
6
|
const studio_shared_1 = require("@remotion/studio-shared");
|
|
7
|
-
const no_react_1 = require("remotion/no-react");
|
|
8
7
|
const update_sequence_props_1 = require("../../codemods/update-sequence-props/update-sequence-props");
|
|
9
8
|
const file_watcher_1 = require("../../file-watcher");
|
|
10
9
|
const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
|
|
@@ -13,6 +12,24 @@ const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
|
|
|
13
12
|
const can_update_sequence_props_1 = require("./can-update-sequence-props");
|
|
14
13
|
const log_update_1 = require("./log-updates/log-update");
|
|
15
14
|
const save_props_mutex_1 = require("./save-props-mutex");
|
|
15
|
+
const convertSequencePropEditToCodemodChange = (edit) => {
|
|
16
|
+
return {
|
|
17
|
+
nodePath: edit.nodePath.nodePath,
|
|
18
|
+
updates: [
|
|
19
|
+
{
|
|
20
|
+
key: edit.key,
|
|
21
|
+
value: edit.value,
|
|
22
|
+
defaultValue: edit.defaultValue,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
schema: edit.schema,
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
exports.convertSequencePropEditToCodemodChange = convertSequencePropEditToCodemodChange;
|
|
29
|
+
const shouldSuppressHmrForSequencePropEdits = (edits) => {
|
|
30
|
+
return edits.every((edit) => edit.key !== 'showInTimeline');
|
|
31
|
+
};
|
|
32
|
+
exports.shouldSuppressHmrForSequencePropEdits = shouldSuppressHmrForSequencePropEdits;
|
|
16
33
|
const saveSequencePropsHandler = ({ input: { edits, clientId, undoLabel, redoLabel }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
|
|
17
34
|
var _a;
|
|
18
35
|
if (edits.length === 0) {
|
|
@@ -54,19 +71,7 @@ const saveSequencePropsHandler = ({ input: { edits, clientId, undoLabel, redoLab
|
|
|
54
71
|
const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
|
|
55
72
|
const { output, formatted, results: updateResults, } = await (0, update_sequence_props_1.updateMultipleSequenceProps)({
|
|
56
73
|
input: fileContents,
|
|
57
|
-
changes: group.edits.map(
|
|
58
|
-
return {
|
|
59
|
-
nodePath: edit.nodePath.nodePath,
|
|
60
|
-
updates: [
|
|
61
|
-
{
|
|
62
|
-
key: edit.key,
|
|
63
|
-
value: edit.value,
|
|
64
|
-
defaultValue: edit.defaultValue,
|
|
65
|
-
},
|
|
66
|
-
],
|
|
67
|
-
schema: no_react_1.NoReactInternals.sequenceSchema,
|
|
68
|
-
};
|
|
69
|
-
}),
|
|
74
|
+
changes: group.edits.map(exports.convertSequencePropEditToCodemodChange),
|
|
70
75
|
prettierConfigOverride: null,
|
|
71
76
|
});
|
|
72
77
|
const [{ logLine: firstLogLine }] = updateResults;
|
|
@@ -89,17 +94,20 @@ const saveSequencePropsHandler = ({ input: { edits, clientId, undoLabel, redoLab
|
|
|
89
94
|
}
|
|
90
95
|
const undoMessage = `↩️ ${undoLabel}`;
|
|
91
96
|
const redoMessage = `↪️ ${redoLabel}`;
|
|
97
|
+
const suppressHmr = (0, exports.shouldSuppressHmrForSequencePropEdits)(edits);
|
|
92
98
|
(0, undo_stack_1.pushTransactionToUndoStack)({
|
|
93
99
|
snapshots,
|
|
94
100
|
logLevel,
|
|
95
101
|
remotionRoot,
|
|
96
102
|
description: { undoMessage, redoMessage },
|
|
97
103
|
entryType: 'sequence-props',
|
|
98
|
-
suppressHmrOnFileRestore:
|
|
104
|
+
suppressHmrOnFileRestore: suppressHmr,
|
|
99
105
|
});
|
|
100
106
|
for (const [absolutePath, output] of outputByPath) {
|
|
101
107
|
(0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
|
|
102
|
-
|
|
108
|
+
if (suppressHmr) {
|
|
109
|
+
(0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
|
|
110
|
+
}
|
|
103
111
|
(0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output, clientId);
|
|
104
112
|
}
|
|
105
113
|
for (const { edits: groupEdits, fileRelativeToRoot } of editGroups.values()) {
|
|
@@ -137,6 +145,7 @@ const saveSequencePropsHandler = ({ input: { edits, clientId, undoLabel, redoLab
|
|
|
137
145
|
fileContents: output,
|
|
138
146
|
keys: (0, studio_shared_1.getAllSchemaKeys)(edit.schema),
|
|
139
147
|
nodePath: edit.nodePath.nodePath,
|
|
148
|
+
componentIdentity: null,
|
|
140
149
|
effects: [],
|
|
141
150
|
});
|
|
142
151
|
return {
|
|
@@ -2,12 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.subscribeToSequenceProps = void 0;
|
|
4
4
|
const sequence_props_watchers_1 = require("../sequence-props-watchers");
|
|
5
|
-
const subscribeToSequenceProps = ({ input: { fileName, line, column, nodePath, keys, effects, clientId }, remotionRoot, logLevel, }) => {
|
|
5
|
+
const subscribeToSequenceProps = ({ input: { fileName, line, column, nodePath, componentIdentity, keys, effects, clientId, }, remotionRoot, logLevel, }) => {
|
|
6
6
|
const result = (0, sequence_props_watchers_1.subscribeToSequencePropsWatchers)({
|
|
7
7
|
fileName,
|
|
8
8
|
line,
|
|
9
9
|
column,
|
|
10
10
|
nodePath,
|
|
11
|
+
componentIdentity,
|
|
11
12
|
keys,
|
|
12
13
|
effects,
|
|
13
14
|
remotionRoot,
|
|
@@ -77,6 +77,7 @@ const updateSequenceKeyframeSettingsHandler = ({ input: { fileName, nodePath, ke
|
|
|
77
77
|
fileContents: output,
|
|
78
78
|
keys: (0, studio_shared_1.getAllSchemaKeys)(schema),
|
|
79
79
|
nodePath: updatedNodePath,
|
|
80
|
+
componentIdentity: null,
|
|
80
81
|
effects: [],
|
|
81
82
|
});
|
|
82
83
|
const updatedSubscriptionKey = { ...nodePath, nodePath: updatedNodePath };
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { type SubscribeToSequencePropsResponse } from '@remotion/studio-shared';
|
|
2
2
|
import type { SequenceNodePath } from 'remotion';
|
|
3
|
-
export declare const subscribeToSequencePropsWatchers: ({ fileName, line, column, nodePath: preferredNodePath, keys, effects, remotionRoot, clientId, logLevel, }: {
|
|
3
|
+
export declare const subscribeToSequencePropsWatchers: ({ fileName, line, column, nodePath: preferredNodePath, componentIdentity, keys, effects, remotionRoot, clientId, logLevel, }: {
|
|
4
4
|
fileName: string;
|
|
5
5
|
line: number;
|
|
6
6
|
column: number;
|
|
7
7
|
nodePath: SequenceNodePath | null;
|
|
8
|
+
componentIdentity: string | null;
|
|
8
9
|
keys: string[];
|
|
9
10
|
effects: string[][];
|
|
10
11
|
remotionRoot: string;
|
|
@@ -8,42 +8,64 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
8
8
|
const renderer_1 = require("@remotion/renderer");
|
|
9
9
|
const studio_shared_1 = require("@remotion/studio-shared");
|
|
10
10
|
const file_watcher_1 = require("../file-watcher");
|
|
11
|
+
const jsx_component_identity_1 = require("./jsx-component-identity");
|
|
11
12
|
const jsx_element_not_found_at_location_error_1 = require("./jsx-element-not-found-at-location-error");
|
|
12
13
|
const live_events_1 = require("./live-events");
|
|
13
14
|
const node_path_cache_1 = require("./node-path-cache");
|
|
14
15
|
const can_update_sequence_props_1 = require("./routes/can-update-sequence-props");
|
|
15
16
|
const sequencePropsWatchers = {};
|
|
16
|
-
const getSequencePropsStatus = ({ fileName, line, column, preferredNodePath, keys, effects, remotionRoot, logLevel, }) => {
|
|
17
|
+
const getSequencePropsStatus = ({ fileName, line, column, preferredNodePath, componentIdentity, keys, effects, remotionRoot, logLevel, }) => {
|
|
17
18
|
if (preferredNodePath) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
keys,
|
|
22
|
-
effects,
|
|
23
|
-
remotionRoot,
|
|
24
|
-
});
|
|
25
|
-
return {
|
|
26
|
-
status: fromNodePath,
|
|
27
|
-
nodePath: {
|
|
28
|
-
absolutePath: node_path_1.default.resolve(remotionRoot, fileName),
|
|
19
|
+
try {
|
|
20
|
+
const fromNodePath = (0, can_update_sequence_props_1.computeSequencePropsStatus)({
|
|
21
|
+
fileName,
|
|
29
22
|
nodePath: preferredNodePath,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
23
|
+
componentIdentity,
|
|
24
|
+
keys,
|
|
25
|
+
effects,
|
|
26
|
+
remotionRoot,
|
|
27
|
+
});
|
|
28
|
+
return {
|
|
29
|
+
status: fromNodePath,
|
|
30
|
+
nodePath: {
|
|
31
|
+
absolutePath: node_path_1.default.resolve(remotionRoot, fileName),
|
|
32
|
+
nodePath: preferredNodePath,
|
|
33
|
+
sequenceKeys: keys,
|
|
34
|
+
effectKeys: effects,
|
|
35
|
+
},
|
|
36
|
+
success: true,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
if (!(error instanceof jsx_component_identity_1.JsxElementIdentityMismatchError ||
|
|
41
|
+
error instanceof jsx_element_not_found_at_location_error_1.JsxElementNotFoundAtLocationError)) {
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
35
45
|
}
|
|
36
46
|
// Try cached nodePath first (handles stale source maps after suppressed rebuilds)
|
|
37
47
|
const cachedNodePath = (0, node_path_cache_1.getCachedNodePath)(fileName, line, column);
|
|
38
48
|
if (cachedNodePath) {
|
|
39
|
-
const cachedResult = (
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
const cachedResult = (() => {
|
|
50
|
+
try {
|
|
51
|
+
return (0, can_update_sequence_props_1.computeSequencePropsStatus)({
|
|
52
|
+
fileName,
|
|
53
|
+
nodePath: cachedNodePath,
|
|
54
|
+
componentIdentity,
|
|
55
|
+
keys,
|
|
56
|
+
effects,
|
|
57
|
+
remotionRoot,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
if (error instanceof jsx_component_identity_1.JsxElementIdentityMismatchError ||
|
|
62
|
+
error instanceof jsx_element_not_found_at_location_error_1.JsxElementNotFoundAtLocationError) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
throw error;
|
|
66
|
+
}
|
|
67
|
+
})();
|
|
68
|
+
if (cachedResult === null || cachedResult === void 0 ? void 0 : cachedResult.canUpdate) {
|
|
47
69
|
return {
|
|
48
70
|
status: cachedResult,
|
|
49
71
|
nodePath: {
|
|
@@ -59,6 +81,7 @@ const getSequencePropsStatus = ({ fileName, line, column, preferredNodePath, key
|
|
|
59
81
|
const status = (0, can_update_sequence_props_1.computeSequencePropsStatusFromFilenameByLine)({
|
|
60
82
|
fileName,
|
|
61
83
|
line,
|
|
84
|
+
componentIdentity,
|
|
62
85
|
keys,
|
|
63
86
|
effects,
|
|
64
87
|
remotionRoot,
|
|
@@ -66,13 +89,14 @@ const getSequencePropsStatus = ({ fileName, line, column, preferredNodePath, key
|
|
|
66
89
|
});
|
|
67
90
|
return status;
|
|
68
91
|
};
|
|
69
|
-
const subscribeToSequencePropsWatchers = ({ fileName, line, column, nodePath: preferredNodePath, keys, effects, remotionRoot, clientId, logLevel, }) => {
|
|
92
|
+
const subscribeToSequencePropsWatchers = ({ fileName, line, column, nodePath: preferredNodePath, componentIdentity, keys, effects, remotionRoot, clientId, logLevel, }) => {
|
|
70
93
|
var _a;
|
|
71
94
|
const initialResult = getSequencePropsStatus({
|
|
72
95
|
fileName,
|
|
73
96
|
line,
|
|
74
97
|
column,
|
|
75
98
|
preferredNodePath,
|
|
99
|
+
componentIdentity,
|
|
76
100
|
keys,
|
|
77
101
|
effects,
|
|
78
102
|
remotionRoot,
|
|
@@ -105,6 +129,7 @@ const subscribeToSequencePropsWatchers = ({ fileName, line, column, nodePath: pr
|
|
|
105
129
|
const result = (0, can_update_sequence_props_1.computeSequencePropsStatusFromContent)({
|
|
106
130
|
fileContents: event.content,
|
|
107
131
|
nodePath: nodePath.nodePath,
|
|
132
|
+
componentIdentity,
|
|
108
133
|
keys,
|
|
109
134
|
effects,
|
|
110
135
|
});
|
|
@@ -125,7 +150,8 @@ const subscribeToSequencePropsWatchers = ({ fileName, line, column, nodePath: pr
|
|
|
125
150
|
});
|
|
126
151
|
}
|
|
127
152
|
catch (error) {
|
|
128
|
-
if (error instanceof jsx_element_not_found_at_location_error_1.JsxElementNotFoundAtLocationError
|
|
153
|
+
if (error instanceof jsx_element_not_found_at_location_error_1.JsxElementNotFoundAtLocationError ||
|
|
154
|
+
error instanceof jsx_component_identity_1.JsxElementIdentityMismatchError) {
|
|
129
155
|
(0, live_events_1.waitForLiveEventsListener)().then((listener) => {
|
|
130
156
|
listener.sendEventToClientId(clientId, {
|
|
131
157
|
type: 'lost-node-path',
|
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.477",
|
|
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.477",
|
|
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.477",
|
|
33
|
+
"@remotion/renderer": "4.0.477",
|
|
34
|
+
"@remotion/studio-shared": "4.0.477",
|
|
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.477",
|
|
43
43
|
"eslint": "9.19.0",
|
|
44
44
|
"@types/node": "20.12.14",
|
|
45
45
|
"@typescript/native-preview": "7.0.0-dev.20260217.1"
|