@remotion/studio-server 4.0.471 → 4.0.472
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/codemods/add-effect.d.ts +11 -0
- package/dist/codemods/add-effect.js +14 -52
- package/dist/codemods/format-file-content.js +1 -1
- package/dist/codemods/parse-ast.js +4 -1
- package/dist/codemods/paste-effects.d.ts +15 -0
- package/dist/codemods/paste-effects.js +234 -0
- package/dist/codemods/recast-mods.js +178 -31
- package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.d.ts +1 -1
- package/dist/codemods/update-keyframes/ensure-imports-and-frame-hook.js +7 -55
- package/dist/codemods/update-keyframes/update-keyframes.d.ts +11 -6
- package/dist/codemods/update-keyframes/update-keyframes.js +127 -16
- package/dist/helpers/get-ast-node-path.js +6 -1
- package/dist/helpers/import-agnostic-node-path.d.ts +10 -0
- package/dist/helpers/import-agnostic-node-path.js +154 -0
- package/dist/helpers/imports.d.ts +16 -0
- package/dist/helpers/imports.js +145 -0
- package/dist/helpers/resolve-composition-component.js +114 -51
- package/dist/preview-server/api-routes.js +2 -0
- package/dist/preview-server/routes/add-effect-keyframe.js +2 -0
- package/dist/preview-server/routes/add-sequence-keyframe.js +1 -0
- package/dist/preview-server/routes/apply-codemod.js +18 -0
- package/dist/preview-server/routes/can-update-effect-props.d.ts +3 -2
- package/dist/preview-server/routes/can-update-effect-props.js +75 -6
- package/dist/preview-server/routes/can-update-sequence-props.js +33 -30
- package/dist/preview-server/routes/delete-keyframes.js +1 -0
- package/dist/preview-server/routes/insert-jsx-element.js +23 -0
- package/dist/preview-server/routes/paste-effects.d.ts +3 -0
- package/dist/preview-server/routes/paste-effects.js +78 -0
- package/dist/preview-server/routes/save-effect-props.js +1 -0
- package/dist/preview-server/undo-stack.d.ts +7 -1
- package/package.json +6 -6
|
@@ -42,6 +42,7 @@ const node_path_1 = __importDefault(require("node:path"));
|
|
|
42
42
|
const recast = __importStar(require("recast"));
|
|
43
43
|
const format_file_content_1 = require("../codemods/format-file-content");
|
|
44
44
|
const parse_ast_1 = require("../codemods/parse-ast");
|
|
45
|
+
const imports_1 = require("./imports");
|
|
45
46
|
const allowedFileExtensions = new Set(['.tsx', '.ts', '.jsx', '.js']);
|
|
46
47
|
const extensionsToProbe = ['.tsx', '.ts', '.jsx', '.js'];
|
|
47
48
|
const isInRemotionRoot = ({ remotionRoot, fileName, }) => {
|
|
@@ -507,13 +508,31 @@ const createSequenceElement = () => {
|
|
|
507
508
|
const createNumberAttribute = (name, value) => {
|
|
508
509
|
return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier(name), recast.types.builders.jsxExpressionContainer(recast.types.builders.numericLiteral(value)));
|
|
509
510
|
};
|
|
511
|
+
const createPositionAbsoluteStyleAttribute = () => {
|
|
512
|
+
return recast.types.builders.jsxAttribute(recast.types.builders.jsxIdentifier('style'), recast.types.builders.jsxExpressionContainer(recast.types.builders.objectExpression([
|
|
513
|
+
recast.types.builders.objectProperty(recast.types.builders.identifier('position'), recast.types.builders.stringLiteral('absolute')),
|
|
514
|
+
])));
|
|
515
|
+
};
|
|
516
|
+
const createStaticFileSrcAttribute = ({ staticFileLocalName, src, }) => {
|
|
517
|
+
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
|
+
};
|
|
510
519
|
const createSolidElement = ({ localName, width, height, }) => {
|
|
511
520
|
return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
|
|
512
521
|
createNumberAttribute('width', width),
|
|
513
522
|
createNumberAttribute('height', height),
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
523
|
+
createPositionAbsoluteStyleAttribute(),
|
|
524
|
+
], true), null, []);
|
|
525
|
+
};
|
|
526
|
+
const createAssetElement = ({ localName, staticFileLocalName, src, dimensions, }) => {
|
|
527
|
+
return recast.types.builders.jsxElement(recast.types.builders.jsxOpeningElement(recast.types.builders.jsxIdentifier(localName), [
|
|
528
|
+
createStaticFileSrcAttribute({ staticFileLocalName, src }),
|
|
529
|
+
createPositionAbsoluteStyleAttribute(),
|
|
530
|
+
...(dimensions
|
|
531
|
+
? [
|
|
532
|
+
createNumberAttribute('width', dimensions.width),
|
|
533
|
+
createNumberAttribute('height', dimensions.height),
|
|
534
|
+
]
|
|
535
|
+
: []),
|
|
517
536
|
], true), null, []);
|
|
518
537
|
};
|
|
519
538
|
const createFragmentWithElement = (element) => {
|
|
@@ -568,12 +587,6 @@ const addElementToNullComponentReturn = ({ declaration, element, }) => {
|
|
|
568
587
|
returnStatement.argument = createFragmentWithElement(element);
|
|
569
588
|
return (_b = (_a = returnStatement.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _b !== void 0 ? _b : 1;
|
|
570
589
|
};
|
|
571
|
-
const getImportedName = (specifier) => {
|
|
572
|
-
if (specifier.imported.type === 'Identifier') {
|
|
573
|
-
return specifier.imported.name;
|
|
574
|
-
}
|
|
575
|
-
return specifier.imported.value;
|
|
576
|
-
};
|
|
577
590
|
const declarationBindsName = (declaration, name) => {
|
|
578
591
|
var _a;
|
|
579
592
|
if (declaration.type === 'FunctionDeclaration' ||
|
|
@@ -619,54 +632,90 @@ const getAvailableSolidLocalName = (ast) => {
|
|
|
619
632
|
}
|
|
620
633
|
return available;
|
|
621
634
|
};
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
635
|
+
const ensureSolidImport = (ast) => {
|
|
636
|
+
return (0, imports_1.ensureNamedImport)({
|
|
637
|
+
ast,
|
|
638
|
+
importedName: 'Solid',
|
|
639
|
+
sourcePath: 'remotion',
|
|
640
|
+
localName: getAvailableSolidLocalName(ast),
|
|
641
|
+
});
|
|
642
|
+
};
|
|
643
|
+
const getImportDeclarations = ({ ast, sourcePath, }) => {
|
|
644
|
+
return ast.program.body.filter((node) => node.type === 'ImportDeclaration' &&
|
|
645
|
+
node.source.type === 'StringLiteral' &&
|
|
646
|
+
node.source.value === sourcePath);
|
|
631
647
|
};
|
|
632
|
-
const
|
|
648
|
+
const importDeclarationHasNamespaceSpecifier = (importDeclaration) => {
|
|
633
649
|
var _a;
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
650
|
+
return (_a = importDeclaration.specifiers) === null || _a === void 0 ? void 0 : _a.some((specifier) => specifier.type === 'ImportNamespaceSpecifier');
|
|
651
|
+
};
|
|
652
|
+
const hasOfficialLocalImport = ({ ast, importedName, sourcePath, }) => {
|
|
653
|
+
return getImportDeclarations({ ast, sourcePath }).some((importDeclaration) => {
|
|
654
|
+
var _a;
|
|
655
|
+
return (_a = importDeclaration.specifiers) === null || _a === void 0 ? void 0 : _a.some((specifier) => {
|
|
656
|
+
var _a;
|
|
657
|
+
var _b;
|
|
658
|
+
return (specifier.type === 'ImportSpecifier' &&
|
|
659
|
+
(0, imports_1.getImportedName)(specifier) === importedName &&
|
|
660
|
+
((_b = (_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : importedName) === importedName);
|
|
661
|
+
});
|
|
662
|
+
});
|
|
663
|
+
};
|
|
664
|
+
const addOfficialNamedImport = ({ ast, importedName, sourcePath, }) => {
|
|
665
|
+
var _a;
|
|
666
|
+
const existingImport = getImportDeclarations({ ast, sourcePath }).find((candidate) => !importDeclarationHasNamespaceSpecifier(candidate));
|
|
667
|
+
const importSpecifier = recast.types.builders.importSpecifier(recast.types.builders.identifier(importedName));
|
|
668
|
+
if (existingImport) {
|
|
669
|
+
existingImport.specifiers = [
|
|
670
|
+
...((_a = existingImport.specifiers) !== null && _a !== void 0 ? _a : []),
|
|
671
|
+
importSpecifier,
|
|
644
672
|
];
|
|
645
673
|
return;
|
|
646
674
|
}
|
|
647
|
-
const importDeclaration = recast.types.builders.importDeclaration([], recast.types.builders.stringLiteral(
|
|
648
|
-
|
|
649
|
-
insertImportDeclaration(ast, importDeclaration);
|
|
675
|
+
const importDeclaration = recast.types.builders.importDeclaration([importSpecifier], recast.types.builders.stringLiteral(sourcePath));
|
|
676
|
+
(0, imports_1.insertImportDeclaration)(ast, importDeclaration);
|
|
650
677
|
};
|
|
651
|
-
const
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
}
|
|
658
|
-
remotionImport = node;
|
|
659
|
-
const solidSpecifier = (_a = node.specifiers) === null || _a === void 0 ? void 0 : _a.find((specifier) => {
|
|
660
|
-
return (specifier.type === 'ImportSpecifier' &&
|
|
661
|
-
getImportedName(specifier) === 'Solid');
|
|
662
|
-
});
|
|
663
|
-
if ((_b = solidSpecifier === null || solidSpecifier === void 0 ? void 0 : solidSpecifier.local) === null || _b === void 0 ? void 0 : _b.name) {
|
|
664
|
-
return solidSpecifier.local.name;
|
|
665
|
-
}
|
|
678
|
+
const ensureOfficialNamedImport = ({ ast, importedName, sourcePath, label, }) => {
|
|
679
|
+
if (hasOfficialLocalImport({ ast, importedName, sourcePath })) {
|
|
680
|
+
return importedName;
|
|
681
|
+
}
|
|
682
|
+
if (hasTopLevelBinding({ ast, name: importedName })) {
|
|
683
|
+
throw new Error(`Cannot add ${label} because ${importedName} is already defined`);
|
|
666
684
|
}
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
685
|
+
addOfficialNamedImport({ ast, importedName, sourcePath });
|
|
686
|
+
return importedName;
|
|
687
|
+
};
|
|
688
|
+
const ensureStaticFileImport = (ast) => {
|
|
689
|
+
return ensureOfficialNamedImport({
|
|
690
|
+
ast,
|
|
691
|
+
importedName: 'staticFile',
|
|
692
|
+
sourcePath: 'remotion',
|
|
693
|
+
label: 'staticFile()',
|
|
694
|
+
});
|
|
695
|
+
};
|
|
696
|
+
const ensureImgImport = (ast) => {
|
|
697
|
+
return ensureOfficialNamedImport({
|
|
698
|
+
ast,
|
|
699
|
+
importedName: 'Img',
|
|
700
|
+
sourcePath: 'remotion',
|
|
701
|
+
label: '<Img>',
|
|
702
|
+
});
|
|
703
|
+
};
|
|
704
|
+
const ensureVideoImport = (ast) => {
|
|
705
|
+
return ensureOfficialNamedImport({
|
|
706
|
+
ast,
|
|
707
|
+
importedName: 'Video',
|
|
708
|
+
sourcePath: '@remotion/media',
|
|
709
|
+
label: '<Video>',
|
|
710
|
+
});
|
|
711
|
+
};
|
|
712
|
+
const ensureGifImport = (ast) => {
|
|
713
|
+
return ensureOfficialNamedImport({
|
|
714
|
+
ast,
|
|
715
|
+
importedName: 'Gif',
|
|
716
|
+
sourcePath: '@remotion/gif',
|
|
717
|
+
label: '<Gif>',
|
|
718
|
+
});
|
|
670
719
|
};
|
|
671
720
|
const addElementToComponentRoot = ({ ast, exportName, element, }) => {
|
|
672
721
|
var _a;
|
|
@@ -695,7 +744,7 @@ const addElementToComponentRoot = ({ ast, exportName, element, }) => {
|
|
|
695
744
|
if (rootNode.type === 'JSXElement' &&
|
|
696
745
|
rootNode.openingElement.name.type === 'JSXIdentifier' &&
|
|
697
746
|
CANVAS_ROOT_ELEMENTS.includes(rootNode.openingElement.name.name)) {
|
|
698
|
-
throw new Error(`Cannot insert a
|
|
747
|
+
throw new Error(`Cannot insert a JSX element into a composition whose root element is <${rootNode.openingElement.name.name}>`);
|
|
699
748
|
}
|
|
700
749
|
if (!rootNode.children) {
|
|
701
750
|
throw new Error('Composition component root does not accept children');
|
|
@@ -890,6 +939,20 @@ const createInsertableJsxElement = ({ ast, element, }) => {
|
|
|
890
939
|
height: element.height,
|
|
891
940
|
});
|
|
892
941
|
}
|
|
942
|
+
if (element.type === 'asset') {
|
|
943
|
+
const staticFileLocalName = ensureStaticFileImport(ast);
|
|
944
|
+
const localName = element.assetType === 'image'
|
|
945
|
+
? ensureImgImport(ast)
|
|
946
|
+
: element.assetType === 'video'
|
|
947
|
+
? ensureVideoImport(ast)
|
|
948
|
+
: ensureGifImport(ast);
|
|
949
|
+
return createAssetElement({
|
|
950
|
+
localName,
|
|
951
|
+
staticFileLocalName,
|
|
952
|
+
src: element.src,
|
|
953
|
+
dimensions: element.dimensions,
|
|
954
|
+
});
|
|
955
|
+
}
|
|
893
956
|
throw new Error('Unsupported element type');
|
|
894
957
|
};
|
|
895
958
|
const insertJsxElementIntoComposition = async ({ remotionRoot, compositionFile, compositionId, element, prettierConfigOverride, }) => {
|
|
@@ -18,6 +18,7 @@ const insert_jsx_element_1 = require("./routes/insert-jsx-element");
|
|
|
18
18
|
const install_dependency_1 = require("./routes/install-dependency");
|
|
19
19
|
const open_in_editor_1 = require("./routes/open-in-editor");
|
|
20
20
|
const open_in_file_explorer_1 = require("./routes/open-in-file-explorer");
|
|
21
|
+
const paste_effects_1 = require("./routes/paste-effects");
|
|
21
22
|
const project_info_1 = require("./routes/project-info");
|
|
22
23
|
const redo_1 = require("./routes/redo");
|
|
23
24
|
const register_client_render_1 = require("./routes/register-client-render");
|
|
@@ -62,6 +63,7 @@ exports.allApiRoutes = {
|
|
|
62
63
|
'/api/add-sequence-keyframe': add_sequence_keyframe_1.addSequenceKeyframeHandler,
|
|
63
64
|
'/api/add-effect-keyframe': add_effect_keyframe_1.addEffectKeyframeHandler,
|
|
64
65
|
'/api/delete-effect': delete_effect_1.deleteEffectHandler,
|
|
66
|
+
'/api/paste-effects': paste_effects_1.pasteEffectsHandler,
|
|
65
67
|
'/api/delete-jsx-node': delete_jsx_node_1.deleteJsxNodeHandler,
|
|
66
68
|
'/api/duplicate-jsx-node': duplicate_jsx_node_1.duplicateJsxNodeHandler,
|
|
67
69
|
'/api/update-available': update_available_1.handleUpdate,
|
|
@@ -27,6 +27,7 @@ const addEffectKeyframeHandler = ({ input: { fileName, sequenceNodePath, effectI
|
|
|
27
27
|
input: fileContents,
|
|
28
28
|
sequenceNodePath: sequenceNodePath.nodePath,
|
|
29
29
|
effectIndex,
|
|
30
|
+
schema,
|
|
30
31
|
updates: [
|
|
31
32
|
{
|
|
32
33
|
key,
|
|
@@ -83,6 +84,7 @@ const addEffectKeyframeHandler = ({ input: { fileName, sequenceNodePath, effectI
|
|
|
83
84
|
};
|
|
84
85
|
}
|
|
85
86
|
return (0, can_update_effect_props_1.computeEffectPropStatus)({
|
|
87
|
+
ast,
|
|
86
88
|
jsx,
|
|
87
89
|
effectIndex,
|
|
88
90
|
keys: (0, studio_shared_1.getAllSchemaKeys)(schema),
|
|
@@ -24,6 +24,7 @@ const addSequenceKeyframeHandler = ({ input: { fileName, nodePath, key, frame, v
|
|
|
24
24
|
const { output, oldValueStrings, newValueStrings, formatted, logLine, updatedNodePath, } = await (0, update_keyframes_1.updateSequenceKeyframes)({
|
|
25
25
|
input: fileContents,
|
|
26
26
|
nodePath: nodePath.nodePath,
|
|
27
|
+
schema,
|
|
27
28
|
updates: [
|
|
28
29
|
{
|
|
29
30
|
key,
|
|
@@ -37,6 +37,24 @@ const getCodemodUndoDescription = (codemod) => {
|
|
|
37
37
|
entryType: codemod.type,
|
|
38
38
|
};
|
|
39
39
|
}
|
|
40
|
+
if (codemod.type === 'delete-folder') {
|
|
41
|
+
const label = `folder "${codemod.parentName ? `${codemod.parentName}/` : ''}${codemod.folderName}"`;
|
|
42
|
+
return {
|
|
43
|
+
undoMessage: `↩️ Deletion of ${label}`,
|
|
44
|
+
redoMessage: `↪️ Deletion of ${label}`,
|
|
45
|
+
entryType: codemod.type,
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
if (codemod.type === 'rename-folder') {
|
|
49
|
+
const oldName = `${codemod.parentName ? `${codemod.parentName}/` : ''}${codemod.folderName}`;
|
|
50
|
+
const newName = `${codemod.parentName ? `${codemod.parentName}/` : ''}${codemod.newName}`;
|
|
51
|
+
const label = `folder "${oldName}" to "${newName}"`;
|
|
52
|
+
return {
|
|
53
|
+
undoMessage: `↩️ Rename of ${label}`,
|
|
54
|
+
redoMessage: `↪️ Rename of ${label}`,
|
|
55
|
+
entryType: codemod.type,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
40
58
|
return {
|
|
41
59
|
undoMessage: '↩️ Visual control change',
|
|
42
60
|
redoMessage: '↪️ Visual control change',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { JSXOpeningElement } from '@babel/types';
|
|
1
|
+
import type { File, JSXOpeningElement } from '@babel/types';
|
|
2
2
|
import type { CanUpdateEffectPropsResponse, SequenceNodePath, SequenceSchema } from 'remotion';
|
|
3
|
-
export declare const computeEffectPropStatus: ({ jsx, effectIndex, keys, }: {
|
|
3
|
+
export declare const computeEffectPropStatus: ({ ast, jsx, effectIndex, keys, }: {
|
|
4
|
+
ast: File;
|
|
4
5
|
jsx: JSXOpeningElement;
|
|
5
6
|
effectIndex: number;
|
|
6
7
|
keys: string[];
|
|
@@ -6,6 +6,10 @@ const parse_ast_1 = require("../../codemods/parse-ast");
|
|
|
6
6
|
const update_effect_props_1 = require("../../codemods/update-effect-props/update-effect-props");
|
|
7
7
|
const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
|
|
8
8
|
const can_update_sequence_props_1 = require("./can-update-sequence-props");
|
|
9
|
+
const staticStatus = (codeValue) => ({
|
|
10
|
+
status: 'static',
|
|
11
|
+
codeValue,
|
|
12
|
+
});
|
|
9
13
|
const findEffectsAttr = (jsx) => {
|
|
10
14
|
for (const attr of jsx.attributes) {
|
|
11
15
|
if (attr.type !== 'JSXAttribute') {
|
|
@@ -27,6 +31,63 @@ const getEffectsArrayElements = (attr) => {
|
|
|
27
31
|
}
|
|
28
32
|
return (0, update_effect_props_1.enumerateEffectArrayElements)(expr);
|
|
29
33
|
};
|
|
34
|
+
const getImportedName = (specifier) => {
|
|
35
|
+
var _a, _b;
|
|
36
|
+
if (!specifier.imported) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
if (specifier.imported.type === 'Identifier') {
|
|
40
|
+
return (_a = specifier.imported.name) !== null && _a !== void 0 ? _a : null;
|
|
41
|
+
}
|
|
42
|
+
return (_b = specifier.imported.value) !== null && _b !== void 0 ? _b : null;
|
|
43
|
+
};
|
|
44
|
+
const resolveEffectImport = ({ ast, call, fallbackCallee, }) => {
|
|
45
|
+
var _a, _b;
|
|
46
|
+
var _c;
|
|
47
|
+
const { callee } = call;
|
|
48
|
+
if (callee.type === 'Identifier') {
|
|
49
|
+
const localName = callee.name;
|
|
50
|
+
for (const node of ast.program.body) {
|
|
51
|
+
if (node.type !== 'ImportDeclaration') {
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const matchingSpecifier = (_a = node.specifiers) === null || _a === void 0 ? void 0 : _a.find((specifier) => {
|
|
55
|
+
var _a;
|
|
56
|
+
return (specifier.type === 'ImportSpecifier' &&
|
|
57
|
+
((_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) === localName);
|
|
58
|
+
});
|
|
59
|
+
if ((matchingSpecifier === null || matchingSpecifier === void 0 ? void 0 : matchingSpecifier.type) === 'ImportSpecifier') {
|
|
60
|
+
return {
|
|
61
|
+
callee: (_c = getImportedName(matchingSpecifier)) !== null && _c !== void 0 ? _c : fallbackCallee,
|
|
62
|
+
importPath: String(node.source.value),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if (callee.type === 'MemberExpression' &&
|
|
68
|
+
callee.object.type === 'Identifier' &&
|
|
69
|
+
callee.property.type === 'Identifier' &&
|
|
70
|
+
!callee.computed) {
|
|
71
|
+
const namespaceName = callee.object.name;
|
|
72
|
+
for (const node of ast.program.body) {
|
|
73
|
+
if (node.type !== 'ImportDeclaration') {
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
const matchingSpecifier = (_b = node.specifiers) === null || _b === void 0 ? void 0 : _b.find((specifier) => {
|
|
77
|
+
var _a;
|
|
78
|
+
return (specifier.type === 'ImportNamespaceSpecifier' &&
|
|
79
|
+
((_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) === namespaceName);
|
|
80
|
+
});
|
|
81
|
+
if (matchingSpecifier) {
|
|
82
|
+
return {
|
|
83
|
+
callee: callee.property.name,
|
|
84
|
+
importPath: String(node.source.value),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return { callee: fallbackCallee, importPath: null };
|
|
90
|
+
};
|
|
30
91
|
const getPropsFromObjectExpression = ({ objExpr, keys, }) => {
|
|
31
92
|
const out = {};
|
|
32
93
|
for (const key of keys) {
|
|
@@ -35,7 +96,7 @@ const getPropsFromObjectExpression = ({ objExpr, keys, }) => {
|
|
|
35
96
|
(p.key.type === 'StringLiteral' &&
|
|
36
97
|
p.key.value === key)));
|
|
37
98
|
if (!prop) {
|
|
38
|
-
out[key] =
|
|
99
|
+
out[key] = staticStatus(undefined);
|
|
39
100
|
continue;
|
|
40
101
|
}
|
|
41
102
|
const valueExpr = prop.value;
|
|
@@ -44,13 +105,13 @@ const getPropsFromObjectExpression = ({ objExpr, keys, }) => {
|
|
|
44
105
|
continue;
|
|
45
106
|
}
|
|
46
107
|
out[key] = {
|
|
47
|
-
|
|
108
|
+
status: 'static',
|
|
48
109
|
codeValue: (0, can_update_sequence_props_1.extractStaticValue)(valueExpr),
|
|
49
110
|
};
|
|
50
111
|
}
|
|
51
112
|
return out;
|
|
52
113
|
};
|
|
53
|
-
const computeEffectPropStatus = ({ jsx, effectIndex, keys, }) => {
|
|
114
|
+
const computeEffectPropStatus = ({ ast, jsx, effectIndex, keys, }) => {
|
|
54
115
|
const attr = findEffectsAttr(jsx);
|
|
55
116
|
const elements = getEffectsArrayElements(attr);
|
|
56
117
|
if (!elements) {
|
|
@@ -76,14 +137,20 @@ const computeEffectPropStatus = ({ jsx, effectIndex, keys, }) => {
|
|
|
76
137
|
};
|
|
77
138
|
}
|
|
78
139
|
const call = target.node;
|
|
140
|
+
const effectImport = resolveEffectImport({
|
|
141
|
+
ast,
|
|
142
|
+
call,
|
|
143
|
+
fallbackCallee: target.callee,
|
|
144
|
+
});
|
|
79
145
|
if (call.arguments.length === 0) {
|
|
80
146
|
const emptyProps = {};
|
|
81
147
|
for (const key of keys) {
|
|
82
|
-
emptyProps[key] =
|
|
148
|
+
emptyProps[key] = staticStatus(undefined);
|
|
83
149
|
}
|
|
84
150
|
return {
|
|
85
151
|
canUpdate: true,
|
|
86
|
-
callee:
|
|
152
|
+
callee: effectImport.callee,
|
|
153
|
+
importPath: effectImport.importPath,
|
|
87
154
|
effectIndex,
|
|
88
155
|
props: emptyProps,
|
|
89
156
|
};
|
|
@@ -103,7 +170,8 @@ const computeEffectPropStatus = ({ jsx, effectIndex, keys, }) => {
|
|
|
103
170
|
return {
|
|
104
171
|
canUpdate: true,
|
|
105
172
|
effectIndex,
|
|
106
|
-
callee:
|
|
173
|
+
callee: effectImport.callee,
|
|
174
|
+
importPath: effectImport.importPath,
|
|
107
175
|
props: resolvedProps,
|
|
108
176
|
};
|
|
109
177
|
};
|
|
@@ -119,6 +187,7 @@ const computeEffectPropsStatusesFromContent = ({ fileContents, sequenceNodePath,
|
|
|
119
187
|
}));
|
|
120
188
|
}
|
|
121
189
|
return effects.map((effect, effectIndex) => (0, exports.computeEffectPropStatus)({
|
|
190
|
+
ast,
|
|
122
191
|
jsx,
|
|
123
192
|
effectIndex,
|
|
124
193
|
keys: keysFor(effect),
|
|
@@ -36,12 +36,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.computeSequencePropsStatusFromFilenameByLine = exports.computeSequencePropsStatus = exports.computeSequencePropsStatusFromContent = exports.lineColumnToNodePath = exports.findNodePathForJsxElement = 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
|
+
const studio_shared_1 = require("@remotion/studio-shared");
|
|
39
40
|
const recast = __importStar(require("recast"));
|
|
40
41
|
const parse_ast_1 = require("../../codemods/parse-ast");
|
|
41
42
|
const get_ast_node_path_1 = require("../../helpers/get-ast-node-path");
|
|
43
|
+
const import_agnostic_node_path_1 = require("../../helpers/import-agnostic-node-path");
|
|
42
44
|
const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
|
|
43
45
|
const jsx_element_not_found_at_location_error_1 = require("../jsx-element-not-found-at-location-error");
|
|
44
46
|
const can_update_effect_props_1 = require("./can-update-effect-props");
|
|
47
|
+
const staticStatus = (codeValue) => ({
|
|
48
|
+
status: 'static',
|
|
49
|
+
codeValue,
|
|
50
|
+
});
|
|
51
|
+
const computedStatus = () => ({
|
|
52
|
+
status: 'computed',
|
|
53
|
+
});
|
|
45
54
|
const isStaticValue = (node) => {
|
|
46
55
|
switch (node.type) {
|
|
47
56
|
case 'NumericLiteral':
|
|
@@ -305,8 +314,7 @@ const getInterpolationKeyframes = (node) => {
|
|
|
305
314
|
}
|
|
306
315
|
const callExpression = node;
|
|
307
316
|
if (callExpression.callee.type !== 'Identifier' ||
|
|
308
|
-
(callExpression.callee.name
|
|
309
|
-
callExpression.callee.name !== 'interpolateColors')) {
|
|
317
|
+
!(0, studio_shared_1.isKeyframeInterpolationFunction)(callExpression.callee.name)) {
|
|
310
318
|
return undefined;
|
|
311
319
|
}
|
|
312
320
|
const interpolationFunction = callExpression.callee.name;
|
|
@@ -358,11 +366,11 @@ const getInterpolationKeyframes = (node) => {
|
|
|
358
366
|
const getComputedStatus = (node) => {
|
|
359
367
|
const interpolation = getInterpolationKeyframes(node);
|
|
360
368
|
if (!interpolation) {
|
|
361
|
-
return
|
|
369
|
+
return computedStatus();
|
|
362
370
|
}
|
|
363
371
|
return {
|
|
364
|
-
|
|
365
|
-
|
|
372
|
+
status: 'keyframed',
|
|
373
|
+
codeValue: undefined,
|
|
366
374
|
interpolationFunction: interpolation.interpolationFunction,
|
|
367
375
|
keyframes: interpolation.keyframes,
|
|
368
376
|
easing: interpolation.easing,
|
|
@@ -386,39 +394,33 @@ const getPropsStatus = (jsxElement) => {
|
|
|
386
394
|
}
|
|
387
395
|
const { value } = attr;
|
|
388
396
|
if (!value) {
|
|
389
|
-
props[name] =
|
|
397
|
+
props[name] = staticStatus(true);
|
|
390
398
|
continue;
|
|
391
399
|
}
|
|
392
400
|
if (value.type === 'StringLiteral') {
|
|
393
|
-
props[name] =
|
|
394
|
-
canUpdate: true,
|
|
395
|
-
codeValue: value.value,
|
|
396
|
-
};
|
|
401
|
+
props[name] = staticStatus(value.value);
|
|
397
402
|
continue;
|
|
398
403
|
}
|
|
399
404
|
if (value.type === 'JSXExpressionContainer') {
|
|
400
405
|
const { expression } = value;
|
|
401
406
|
if (expression.type === 'JSXEmptyExpression') {
|
|
402
|
-
props[name] =
|
|
407
|
+
props[name] = computedStatus();
|
|
403
408
|
continue;
|
|
404
409
|
}
|
|
405
410
|
if (!(0, exports.isStaticValue)(expression)) {
|
|
406
411
|
props[name] = (0, exports.getComputedStatus)(expression);
|
|
407
412
|
continue;
|
|
408
413
|
}
|
|
409
|
-
props[name] =
|
|
410
|
-
canUpdate: true,
|
|
411
|
-
codeValue: (0, exports.extractStaticValue)(expression),
|
|
412
|
-
};
|
|
414
|
+
props[name] = staticStatus((0, exports.extractStaticValue)(expression));
|
|
413
415
|
continue;
|
|
414
416
|
}
|
|
415
|
-
props[name] =
|
|
417
|
+
props[name] = computedStatus();
|
|
416
418
|
}
|
|
417
419
|
return props;
|
|
418
420
|
};
|
|
419
421
|
const getNodePathForRecastPath = (
|
|
420
422
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
421
|
-
recastPath) => {
|
|
423
|
+
recastPath, ast) => {
|
|
422
424
|
const segments = [];
|
|
423
425
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
424
426
|
let current = recastPath;
|
|
@@ -428,9 +430,9 @@ recastPath) => {
|
|
|
428
430
|
}
|
|
429
431
|
// Recast paths start with "root" which doesn't correspond to a real AST property
|
|
430
432
|
if (segments.length > 0 && segments[0] === 'root') {
|
|
431
|
-
return segments.slice(1);
|
|
433
|
+
return (0, import_agnostic_node_path_1.toImportAgnosticNodePath)({ ast, nodePath: segments.slice(1) });
|
|
432
434
|
}
|
|
433
|
-
return segments;
|
|
435
|
+
return (0, import_agnostic_node_path_1.toImportAgnosticNodePath)({ ast, nodePath: segments });
|
|
434
436
|
};
|
|
435
437
|
const findJsxElementAtNodePath = (ast, nodePath) => {
|
|
436
438
|
const current = (0, get_ast_node_path_1.getAstNodePath)(ast, nodePath);
|
|
@@ -448,7 +450,7 @@ const findNodePathForJsxElement = (ast, target) => {
|
|
|
448
450
|
recast.types.visit(ast, {
|
|
449
451
|
visitJSXOpeningElement(p) {
|
|
450
452
|
if (p.node === target) {
|
|
451
|
-
foundPath = getNodePathForRecastPath(p);
|
|
453
|
+
foundPath = getNodePathForRecastPath(p, ast);
|
|
452
454
|
return false;
|
|
453
455
|
}
|
|
454
456
|
return this.traverse(p);
|
|
@@ -463,7 +465,7 @@ const lineColumnToNodePath = (ast, targetLine) => {
|
|
|
463
465
|
visitJSXOpeningElement(p) {
|
|
464
466
|
const { node } = p;
|
|
465
467
|
if (node.loc && node.loc.start.line === targetLine) {
|
|
466
|
-
foundPath = getNodePathForRecastPath(p);
|
|
468
|
+
foundPath = getNodePathForRecastPath(p, ast);
|
|
467
469
|
return false;
|
|
468
470
|
}
|
|
469
471
|
return this.traverse(p);
|
|
@@ -492,16 +494,16 @@ const getNestedPropStatus = (jsxElement, parentKey, childKey) => {
|
|
|
492
494
|
a.name.name === parentKey);
|
|
493
495
|
if (!attr || !attr.value) {
|
|
494
496
|
// Parent attribute doesn't exist, nested prop can be added
|
|
495
|
-
return
|
|
497
|
+
return staticStatus(undefined);
|
|
496
498
|
}
|
|
497
499
|
if (attr.value.type !== 'JSXExpressionContainer') {
|
|
498
|
-
return
|
|
500
|
+
return computedStatus();
|
|
499
501
|
}
|
|
500
502
|
const { expression } = attr.value;
|
|
501
503
|
if (expression.type === 'JSXEmptyExpression' ||
|
|
502
504
|
expression.type !== 'ObjectExpression') {
|
|
503
505
|
// Parent is not an object literal (e.g. style={myStyles})
|
|
504
|
-
return
|
|
506
|
+
return computedStatus();
|
|
505
507
|
}
|
|
506
508
|
const objExpr = expression;
|
|
507
509
|
const prop = objExpr.properties.find((p) => p.type === 'ObjectProperty' &&
|
|
@@ -509,7 +511,7 @@ const getNestedPropStatus = (jsxElement, parentKey, childKey) => {
|
|
|
509
511
|
(p.key.type === 'StringLiteral' && p.key.value === childKey)));
|
|
510
512
|
if (!prop) {
|
|
511
513
|
// Property not set in the object, can be added
|
|
512
|
-
return
|
|
514
|
+
return staticStatus(undefined);
|
|
513
515
|
}
|
|
514
516
|
const propValue = prop.value;
|
|
515
517
|
if (!(0, exports.isStaticValue)(propValue)) {
|
|
@@ -517,12 +519,13 @@ const getNestedPropStatus = (jsxElement, parentKey, childKey) => {
|
|
|
517
519
|
}
|
|
518
520
|
const codeValue = (0, exports.extractStaticValue)(propValue);
|
|
519
521
|
if (!validateStyleValue(childKey, codeValue)) {
|
|
520
|
-
return
|
|
522
|
+
return computedStatus();
|
|
521
523
|
}
|
|
522
|
-
return
|
|
524
|
+
return staticStatus(codeValue);
|
|
523
525
|
};
|
|
524
|
-
const computeEffectsForJsx = ({ jsxElement, effects, }) => {
|
|
526
|
+
const computeEffectsForJsx = ({ ast, jsxElement, effects, }) => {
|
|
525
527
|
return effects.map((effect, effectIndex) => (0, can_update_effect_props_1.computeEffectPropStatus)({
|
|
528
|
+
ast,
|
|
526
529
|
jsx: jsxElement,
|
|
527
530
|
effectIndex,
|
|
528
531
|
keys: effect,
|
|
@@ -540,7 +543,7 @@ const computeSequenceOnlyPropsRecord = ({ jsxElement, keys, }) => {
|
|
|
540
543
|
filteredProps[key] = allProps[key];
|
|
541
544
|
}
|
|
542
545
|
else {
|
|
543
|
-
filteredProps[key] =
|
|
546
|
+
filteredProps[key] = staticStatus(undefined);
|
|
544
547
|
}
|
|
545
548
|
}
|
|
546
549
|
return filteredProps;
|
|
@@ -552,7 +555,7 @@ const computeSequencePropsStatusFromContent = ({ fileContents, nodePath, keys, e
|
|
|
552
555
|
throw new jsx_element_not_found_at_location_error_1.JsxElementNotFoundAtLocationError();
|
|
553
556
|
}
|
|
554
557
|
const filteredProps = computeSequenceOnlyPropsRecord({ jsxElement, keys });
|
|
555
|
-
const effectsStatuses = computeEffectsForJsx({ jsxElement, effects });
|
|
558
|
+
const effectsStatuses = computeEffectsForJsx({ ast, jsxElement, effects });
|
|
556
559
|
return {
|
|
557
560
|
canUpdate: true,
|
|
558
561
|
props: filteredProps,
|
|
@@ -241,6 +241,7 @@ const deleteKeyframes = async ({ sequenceKeyframes, effectKeyframes, clientId, r
|
|
|
241
241
|
};
|
|
242
242
|
}
|
|
243
243
|
return (0, can_update_effect_props_1.computeEffectPropStatus)({
|
|
244
|
+
ast,
|
|
244
245
|
jsx,
|
|
245
246
|
effectIndex: keyframe.effectIndex,
|
|
246
247
|
keys: (0, studio_shared_1.getAllSchemaKeys)(keyframe.schema),
|
|
@@ -17,12 +17,35 @@ const validateElement = (element) => {
|
|
|
17
17
|
if (element.type === 'solid') {
|
|
18
18
|
validateDimension('width', element.width);
|
|
19
19
|
validateDimension('height', element.height);
|
|
20
|
+
return;
|
|
20
21
|
}
|
|
22
|
+
if (element.type === 'asset') {
|
|
23
|
+
if (!element.src || element.src.includes('\\')) {
|
|
24
|
+
throw new Error('Asset path must be a static file path');
|
|
25
|
+
}
|
|
26
|
+
if (element.dimensions) {
|
|
27
|
+
validateDimension('width', element.dimensions.width);
|
|
28
|
+
validateDimension('height', element.dimensions.height);
|
|
29
|
+
}
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
throw new Error('Unsupported element type');
|
|
21
33
|
};
|
|
22
34
|
const getElementLabel = (element) => {
|
|
23
35
|
if (element.type === 'solid') {
|
|
24
36
|
return '<Solid>';
|
|
25
37
|
}
|
|
38
|
+
if (element.type === 'asset') {
|
|
39
|
+
if (element.assetType === 'image') {
|
|
40
|
+
return '<Img>';
|
|
41
|
+
}
|
|
42
|
+
if (element.assetType === 'video') {
|
|
43
|
+
return '<Video>';
|
|
44
|
+
}
|
|
45
|
+
if (element.assetType === 'gif') {
|
|
46
|
+
return '<Gif>';
|
|
47
|
+
}
|
|
48
|
+
}
|
|
26
49
|
throw new Error('Unsupported element type');
|
|
27
50
|
};
|
|
28
51
|
const insertJsxElementHandler = ({ input: { compositionFile, compositionId, element }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
|