@remotion/studio-server 4.0.470 → 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 +26 -0
- package/dist/codemods/add-effect.js +193 -0
- 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/reorder-effect.d.ts +13 -0
- package/dist/codemods/reorder-effect.js +61 -0
- 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 +15 -6
- package/dist/codemods/update-keyframes/update-keyframes.js +152 -26
- 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/open-in-editor.d.ts +2 -2
- package/dist/helpers/open-in-editor.js +35 -2
- package/dist/helpers/resolve-composition-component.d.ts +15 -0
- package/dist/helpers/resolve-composition-component.js +332 -31
- package/dist/preview-server/api-routes.js +10 -4
- package/dist/preview-server/routes/add-effect-keyframe.js +4 -2
- package/dist/preview-server/routes/add-effect.d.ts +3 -0
- package/dist/preview-server/routes/add-effect.js +68 -0
- package/dist/preview-server/routes/add-sequence-keyframe.js +7 -3
- 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.d.ts +1 -0
- package/dist/preview-server/routes/can-update-sequence-props.js +47 -30
- package/dist/preview-server/routes/delete-keyframes.d.ts +13 -0
- package/dist/preview-server/routes/delete-keyframes.js +264 -0
- package/dist/preview-server/routes/insert-jsx-element.d.ts +3 -0
- package/dist/preview-server/routes/insert-jsx-element.js +102 -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/reorder-effect.d.ts +3 -0
- package/dist/preview-server/routes/reorder-effect.js +67 -0
- package/dist/preview-server/routes/save-effect-props.js +1 -0
- package/dist/preview-server/routes/subscribe-to-sequence-props.js +2 -1
- package/dist/preview-server/sequence-props-watchers.d.ts +2 -1
- package/dist/preview-server/sequence-props-watchers.js +22 -2
- package/dist/preview-server/undo-stack.d.ts +15 -1
- package/package.json +6 -6
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { File, ObjectExpression } from '@babel/types';
|
|
2
|
+
import type { SequenceNodePath } from 'remotion';
|
|
3
|
+
export declare const assertValidEffect: ({ effectName, effectImportPath, }: {
|
|
4
|
+
effectName: string;
|
|
5
|
+
effectImportPath: string;
|
|
6
|
+
}) => void;
|
|
7
|
+
export declare const ensureEffectImport: ({ ast, effectName, effectImportPath, }: {
|
|
8
|
+
ast: File;
|
|
9
|
+
effectName: string;
|
|
10
|
+
effectImportPath: string;
|
|
11
|
+
}) => string;
|
|
12
|
+
export declare const makeConfigObjectExpression: (config: Record<string, unknown>) => ObjectExpression;
|
|
13
|
+
export declare const addEffect: ({ input, sequenceNodePath, effectName, effectImportPath, effectConfig, prettierConfigOverride, }: {
|
|
14
|
+
input: string;
|
|
15
|
+
sequenceNodePath: SequenceNodePath;
|
|
16
|
+
effectName: string;
|
|
17
|
+
effectImportPath: string;
|
|
18
|
+
effectConfig: Record<string, unknown>;
|
|
19
|
+
prettierConfigOverride?: Record<string, unknown> | null | undefined;
|
|
20
|
+
}) => Promise<{
|
|
21
|
+
output: string;
|
|
22
|
+
formatted: boolean;
|
|
23
|
+
effectLabel: string;
|
|
24
|
+
nodeLabel: string;
|
|
25
|
+
logLine: number;
|
|
26
|
+
}>;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.addEffect = exports.makeConfigObjectExpression = exports.ensureEffectImport = exports.assertValidEffect = void 0;
|
|
37
|
+
const studio_shared_1 = require("@remotion/studio-shared");
|
|
38
|
+
const recast = __importStar(require("recast"));
|
|
39
|
+
const imports_1 = require("../helpers/imports");
|
|
40
|
+
const can_update_sequence_props_1 = require("../preview-server/routes/can-update-sequence-props");
|
|
41
|
+
const format_file_content_1 = require("./format-file-content");
|
|
42
|
+
const parse_ast_1 = require("./parse-ast");
|
|
43
|
+
const update_effect_props_1 = require("./update-effect-props/update-effect-props");
|
|
44
|
+
const b = recast.types.builders;
|
|
45
|
+
const identifierRegex = /^[A-Za-z_$][0-9A-Za-z_$]*$/;
|
|
46
|
+
const assertValidEffect = ({ effectName, effectImportPath, }) => {
|
|
47
|
+
if (!identifierRegex.test(effectName)) {
|
|
48
|
+
throw new Error(`Invalid effect name "${effectName}"`);
|
|
49
|
+
}
|
|
50
|
+
const allowedImport = effectImportPath.startsWith('@remotion/effects/') ||
|
|
51
|
+
effectImportPath === '@remotion/light-leaks' ||
|
|
52
|
+
effectImportPath === '@remotion/starburst';
|
|
53
|
+
if (!allowedImport) {
|
|
54
|
+
throw new Error(`Unsupported effect import "${effectImportPath}"`);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
exports.assertValidEffect = assertValidEffect;
|
|
58
|
+
const parseValueExpression = (value) => {
|
|
59
|
+
const code = `a = ${(0, studio_shared_1.stringifyDefaultProps)({ props: value, enumPaths: [] })}`;
|
|
60
|
+
const ast = (0, parse_ast_1.parseAst)(code);
|
|
61
|
+
const stmt = ast.program.body[0];
|
|
62
|
+
if (stmt.type !== 'ExpressionStatement' ||
|
|
63
|
+
stmt.expression.type !== 'AssignmentExpression') {
|
|
64
|
+
throw new Error('Failed to parse effect config value');
|
|
65
|
+
}
|
|
66
|
+
return stmt.expression.right;
|
|
67
|
+
};
|
|
68
|
+
const declarationBindsName = (declaration, name) => {
|
|
69
|
+
var _a, _b;
|
|
70
|
+
if (declaration.type === 'ClassDeclaration') {
|
|
71
|
+
return ((_a = declaration.id) === null || _a === void 0 ? void 0 : _a.name) === name;
|
|
72
|
+
}
|
|
73
|
+
if (declaration.type === 'FunctionDeclaration') {
|
|
74
|
+
return ((_b = declaration.id) === null || _b === void 0 ? void 0 : _b.name) === name;
|
|
75
|
+
}
|
|
76
|
+
return declaration.declarations.some((variableDeclaration) => {
|
|
77
|
+
return (variableDeclaration.id.type === 'Identifier' &&
|
|
78
|
+
variableDeclaration.id.name === name);
|
|
79
|
+
});
|
|
80
|
+
};
|
|
81
|
+
const hasTopLevelBinding = ({ ast, name }) => {
|
|
82
|
+
return ast.program.body.some((node) => {
|
|
83
|
+
var _a;
|
|
84
|
+
if (node.type === 'FunctionDeclaration' ||
|
|
85
|
+
node.type === 'ClassDeclaration' ||
|
|
86
|
+
node.type === 'VariableDeclaration') {
|
|
87
|
+
return declarationBindsName(node, name);
|
|
88
|
+
}
|
|
89
|
+
if (node.type === 'ExportNamedDeclaration' &&
|
|
90
|
+
node.declaration &&
|
|
91
|
+
(node.declaration.type === 'FunctionDeclaration' ||
|
|
92
|
+
node.declaration.type === 'ClassDeclaration' ||
|
|
93
|
+
node.declaration.type === 'VariableDeclaration')) {
|
|
94
|
+
return declarationBindsName(node.declaration, name);
|
|
95
|
+
}
|
|
96
|
+
if (node.type !== 'ImportDeclaration') {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
return (_a = node.specifiers) === null || _a === void 0 ? void 0 : _a.some((specifier) => {
|
|
100
|
+
var _a;
|
|
101
|
+
return ((_a = specifier.local) === null || _a === void 0 ? void 0 : _a.name) === name;
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
};
|
|
105
|
+
const getAvailableLocalName = ({ ast, effectName, }) => {
|
|
106
|
+
if (!hasTopLevelBinding({ ast, name: effectName })) {
|
|
107
|
+
return effectName;
|
|
108
|
+
}
|
|
109
|
+
const base = `${effectName}Effect`;
|
|
110
|
+
if (!hasTopLevelBinding({ ast, name: base })) {
|
|
111
|
+
return base;
|
|
112
|
+
}
|
|
113
|
+
for (let i = 2; i < 100; i++) {
|
|
114
|
+
const candidate = `${base}${i}`;
|
|
115
|
+
if (!hasTopLevelBinding({ ast, name: candidate })) {
|
|
116
|
+
return candidate;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
throw new Error(`Cannot find a local name for ${effectName}`);
|
|
120
|
+
};
|
|
121
|
+
const ensureEffectImport = ({ ast, effectName, effectImportPath, }) => {
|
|
122
|
+
const localName = getAvailableLocalName({ ast, effectName });
|
|
123
|
+
return (0, imports_1.ensureNamedImport)({
|
|
124
|
+
ast,
|
|
125
|
+
importedName: effectName,
|
|
126
|
+
sourcePath: effectImportPath,
|
|
127
|
+
localName,
|
|
128
|
+
});
|
|
129
|
+
};
|
|
130
|
+
exports.ensureEffectImport = ensureEffectImport;
|
|
131
|
+
const getEffectsArray = (attr) => {
|
|
132
|
+
if (!attr.value || attr.value.type !== 'JSXExpressionContainer') {
|
|
133
|
+
throw new Error('Cannot add effect: effects prop is not an array');
|
|
134
|
+
}
|
|
135
|
+
const expr = attr.value.expression;
|
|
136
|
+
if (expr.type !== 'ArrayExpression') {
|
|
137
|
+
throw new Error('Cannot add effect: effects prop is not an array');
|
|
138
|
+
}
|
|
139
|
+
return expr;
|
|
140
|
+
};
|
|
141
|
+
const makeEffectsAttr = (array) => {
|
|
142
|
+
return b.jsxAttribute(b.jsxIdentifier('effects'), b.jsxExpressionContainer(array));
|
|
143
|
+
};
|
|
144
|
+
const makeConfigObjectExpression = (config) => {
|
|
145
|
+
return b.objectExpression(Object.entries(config).map(([key, value]) => {
|
|
146
|
+
const keyNode = identifierRegex.test(key)
|
|
147
|
+
? b.identifier(key)
|
|
148
|
+
: b.stringLiteral(key);
|
|
149
|
+
return b.objectProperty(keyNode, parseValueExpression(value));
|
|
150
|
+
}));
|
|
151
|
+
};
|
|
152
|
+
exports.makeConfigObjectExpression = makeConfigObjectExpression;
|
|
153
|
+
const getJsxTagLabel = (name) => {
|
|
154
|
+
if (name.type === 'JSXIdentifier') {
|
|
155
|
+
return `<${name.name}>`;
|
|
156
|
+
}
|
|
157
|
+
return 'element';
|
|
158
|
+
};
|
|
159
|
+
const addEffect = async ({ input, sequenceNodePath, effectName, effectImportPath, effectConfig, prettierConfigOverride, }) => {
|
|
160
|
+
var _a;
|
|
161
|
+
var _b, _c;
|
|
162
|
+
(0, exports.assertValidEffect)({ effectName, effectImportPath });
|
|
163
|
+
const ast = (0, parse_ast_1.parseAst)(input);
|
|
164
|
+
const jsx = (0, can_update_sequence_props_1.findJsxElementAtNodePath)(ast, sequenceNodePath);
|
|
165
|
+
if (!jsx) {
|
|
166
|
+
throw new Error('Could not find a JSX element at the specified location to add effect');
|
|
167
|
+
}
|
|
168
|
+
const localName = (0, exports.ensureEffectImport)({ ast, effectName, effectImportPath });
|
|
169
|
+
const effectCall = b.callExpression(b.identifier(localName), [
|
|
170
|
+
(0, exports.makeConfigObjectExpression)(effectConfig),
|
|
171
|
+
]);
|
|
172
|
+
const attr = (0, update_effect_props_1.findEffectsAttr)((_b = jsx.attributes) !== null && _b !== void 0 ? _b : []);
|
|
173
|
+
if (attr) {
|
|
174
|
+
getEffectsArray(attr).elements.push(effectCall);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
const effectsArray = b.arrayExpression([effectCall]);
|
|
178
|
+
jsx.attributes.push(makeEffectsAttr(effectsArray));
|
|
179
|
+
}
|
|
180
|
+
const finalFile = (0, parse_ast_1.serializeAst)(ast);
|
|
181
|
+
const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
|
|
182
|
+
input: finalFile,
|
|
183
|
+
prettierConfigOverride,
|
|
184
|
+
});
|
|
185
|
+
return {
|
|
186
|
+
output,
|
|
187
|
+
formatted,
|
|
188
|
+
effectLabel: `${effectName}()`,
|
|
189
|
+
nodeLabel: getJsxTagLabel(jsx.name),
|
|
190
|
+
logLine: (_c = (_a = jsx.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _c !== void 0 ? _c : 1,
|
|
191
|
+
};
|
|
192
|
+
};
|
|
193
|
+
exports.addEffect = addEffect;
|
|
@@ -47,7 +47,7 @@ const formatFileContent = async ({ input, prettierConfigOverride, }) => {
|
|
|
47
47
|
}
|
|
48
48
|
const { format, resolveConfig, resolveConfigFile } = prettier;
|
|
49
49
|
let prettierConfig;
|
|
50
|
-
if (prettierConfigOverride !== undefined) {
|
|
50
|
+
if (prettierConfigOverride !== undefined && prettierConfigOverride !== null) {
|
|
51
51
|
prettierConfig = prettierConfigOverride;
|
|
52
52
|
}
|
|
53
53
|
else {
|
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.serializeAst = exports.parseAst = void 0;
|
|
37
37
|
const recast = __importStar(require("recast"));
|
|
38
38
|
const tsParser = __importStar(require("recast/parsers/babel-ts"));
|
|
39
|
+
const imports_1 = require("../helpers/imports");
|
|
39
40
|
const parseAst = (input) => {
|
|
40
41
|
return recast.parse(input, {
|
|
41
42
|
parser: tsParser,
|
|
@@ -43,8 +44,10 @@ const parseAst = (input) => {
|
|
|
43
44
|
};
|
|
44
45
|
exports.parseAst = parseAst;
|
|
45
46
|
const serializeAst = (ast) => {
|
|
46
|
-
|
|
47
|
+
const raw = recast.print(ast, {
|
|
47
48
|
parser: tsParser,
|
|
48
49
|
}).code;
|
|
50
|
+
// Normalize Windows line endings so normalizeImportSpacing regex works
|
|
51
|
+
return (0, imports_1.normalizeImportSpacing)(raw.replace(/\r\n/g, '\n'));
|
|
49
52
|
};
|
|
50
53
|
exports.serializeAst = serializeAst;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { EffectClipboardPasteType, EffectClipboardSnapshot } from '@remotion/studio-shared';
|
|
2
|
+
import type { SequenceNodePath } from 'remotion';
|
|
3
|
+
export declare const pasteEffects: ({ input, targetSequenceNodePath, type, effects, prettierConfigOverride, }: {
|
|
4
|
+
readonly input: string;
|
|
5
|
+
readonly targetFileName: string;
|
|
6
|
+
readonly targetSequenceNodePath: SequenceNodePath;
|
|
7
|
+
readonly type: EffectClipboardPasteType;
|
|
8
|
+
readonly effects: EffectClipboardSnapshot[];
|
|
9
|
+
readonly prettierConfigOverride?: Record<string, unknown> | null | undefined;
|
|
10
|
+
}) => Promise<{
|
|
11
|
+
readonly output: string;
|
|
12
|
+
readonly formatted: boolean;
|
|
13
|
+
readonly effectLabels: string[];
|
|
14
|
+
readonly logLine: number;
|
|
15
|
+
}>;
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.pasteEffects = void 0;
|
|
37
|
+
const recast = __importStar(require("recast"));
|
|
38
|
+
const get_ast_node_path_1 = require("../helpers/get-ast-node-path");
|
|
39
|
+
const imports_1 = require("../helpers/imports");
|
|
40
|
+
const can_update_sequence_props_1 = require("../preview-server/routes/can-update-sequence-props");
|
|
41
|
+
const add_effect_1 = require("./add-effect");
|
|
42
|
+
const format_file_content_1 = require("./format-file-content");
|
|
43
|
+
const parse_ast_1 = require("./parse-ast");
|
|
44
|
+
const update_effect_props_1 = require("./update-effect-props/update-effect-props");
|
|
45
|
+
const ensure_imports_and_frame_hook_1 = require("./update-keyframes/ensure-imports-and-frame-hook");
|
|
46
|
+
const update_nested_prop_1 = require("./update-nested-prop");
|
|
47
|
+
const b = recast.types.builders;
|
|
48
|
+
const identifierRegex = /^[A-Za-z_$][0-9A-Za-z_$]*$/;
|
|
49
|
+
const getEffectsArray = (attr) => {
|
|
50
|
+
if (!attr.value || attr.value.type !== 'JSXExpressionContainer') {
|
|
51
|
+
throw new Error('Cannot append effects: effects prop is not an array');
|
|
52
|
+
}
|
|
53
|
+
const expr = attr.value.expression;
|
|
54
|
+
if (expr.type !== 'ArrayExpression') {
|
|
55
|
+
throw new Error('Cannot append effects: effects prop is not an array');
|
|
56
|
+
}
|
|
57
|
+
return expr;
|
|
58
|
+
};
|
|
59
|
+
const makeEffectsAttr = (array) => {
|
|
60
|
+
return b.jsxAttribute(b.jsxIdentifier('effects'), b.jsxExpressionContainer(array));
|
|
61
|
+
};
|
|
62
|
+
const makeEffectsArray = (calls) => {
|
|
63
|
+
return b.arrayExpression(calls);
|
|
64
|
+
};
|
|
65
|
+
const isNonLinearEasing = (easing) => easing !== 'linear';
|
|
66
|
+
const keyframedParamNeedsEasingImport = (param) => {
|
|
67
|
+
return (param.interpolationFunction !== 'interpolateColors' &&
|
|
68
|
+
param.easing.some(isNonLinearEasing));
|
|
69
|
+
};
|
|
70
|
+
const getRequiredRemotionImports = (effects) => {
|
|
71
|
+
const requiredImports = new Set();
|
|
72
|
+
for (const effect of effects) {
|
|
73
|
+
for (const param of Object.values(effect.params)) {
|
|
74
|
+
if (param.type !== 'keyframed') {
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
requiredImports.add('useCurrentFrame');
|
|
78
|
+
requiredImports.add(param.interpolationFunction);
|
|
79
|
+
if (keyframedParamNeedsEasingImport(param)) {
|
|
80
|
+
requiredImports.add('Easing');
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return requiredImports;
|
|
85
|
+
};
|
|
86
|
+
const ensureRemotionImportLocalNames = ({ ast, requiredImports, }) => {
|
|
87
|
+
const localNames = {};
|
|
88
|
+
for (const importedName of requiredImports) {
|
|
89
|
+
localNames[importedName] = (0, imports_1.ensureNamedImport)({
|
|
90
|
+
ast,
|
|
91
|
+
importedName,
|
|
92
|
+
sourcePath: 'remotion',
|
|
93
|
+
localName: importedName,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return localNames;
|
|
97
|
+
};
|
|
98
|
+
const makeEasingExpression = ({ easing, easingLocalName, }) => {
|
|
99
|
+
if (easing === 'linear') {
|
|
100
|
+
return b.memberExpression(b.identifier(easingLocalName), b.identifier('linear'));
|
|
101
|
+
}
|
|
102
|
+
return b.callExpression(b.memberExpression(b.identifier(easingLocalName), b.identifier('bezier')), easing.map((value) => (0, update_nested_prop_1.parseValueExpression)(value)));
|
|
103
|
+
};
|
|
104
|
+
const makeKeyframedOptions = ({ param, remotionLocalNames, }) => {
|
|
105
|
+
var _a;
|
|
106
|
+
const properties = [];
|
|
107
|
+
if (param.interpolationFunction !== 'interpolateColors') {
|
|
108
|
+
if (param.clamping.left !== 'extend') {
|
|
109
|
+
properties.push(b.objectProperty(b.identifier('extrapolateLeft'), b.stringLiteral(param.clamping.left)));
|
|
110
|
+
}
|
|
111
|
+
if (param.clamping.right !== 'extend') {
|
|
112
|
+
properties.push(b.objectProperty(b.identifier('extrapolateRight'), b.stringLiteral(param.clamping.right)));
|
|
113
|
+
}
|
|
114
|
+
if (keyframedParamNeedsEasingImport(param)) {
|
|
115
|
+
const easingLocalName = (_a = remotionLocalNames.Easing) !== null && _a !== void 0 ? _a : 'Easing';
|
|
116
|
+
properties.push(b.objectProperty(b.identifier('easing'), b.arrayExpression(param.easing.map((easing) => makeEasingExpression({ easing, easingLocalName })))));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (param.posterize !== undefined) {
|
|
120
|
+
properties.push(b.objectProperty(b.identifier('posterize'), (0, update_nested_prop_1.parseValueExpression)(param.posterize)));
|
|
121
|
+
}
|
|
122
|
+
if (properties.length === 0) {
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
return b.objectExpression(properties);
|
|
126
|
+
};
|
|
127
|
+
const makeKeyframedExpression = ({ param, remotionLocalNames, }) => {
|
|
128
|
+
var _a;
|
|
129
|
+
const expectedEasingCount = Math.max(0, param.keyframes.length - 1);
|
|
130
|
+
if (param.easing.length !== expectedEasingCount) {
|
|
131
|
+
throw new Error('Cannot paste keyframed effect: invalid easing metadata');
|
|
132
|
+
}
|
|
133
|
+
const calleeName = (_a = remotionLocalNames[param.interpolationFunction]) !== null && _a !== void 0 ? _a : param.interpolationFunction;
|
|
134
|
+
const args = [
|
|
135
|
+
b.identifier('frame'),
|
|
136
|
+
b.arrayExpression(param.keyframes.map((keyframe) => (0, update_nested_prop_1.parseValueExpression)(keyframe.frame))),
|
|
137
|
+
b.arrayExpression(param.keyframes.map((keyframe) => (0, update_nested_prop_1.parseValueExpression)(keyframe.value))),
|
|
138
|
+
];
|
|
139
|
+
const options = makeKeyframedOptions({ param, remotionLocalNames });
|
|
140
|
+
if (options) {
|
|
141
|
+
args.push(options);
|
|
142
|
+
}
|
|
143
|
+
return b.callExpression(b.identifier(calleeName), args);
|
|
144
|
+
};
|
|
145
|
+
const makeParamExpression = ({ param, remotionLocalNames, }) => {
|
|
146
|
+
if (param.type === 'static') {
|
|
147
|
+
return (0, update_nested_prop_1.parseValueExpression)(param.value);
|
|
148
|
+
}
|
|
149
|
+
return makeKeyframedExpression({ param, remotionLocalNames });
|
|
150
|
+
};
|
|
151
|
+
const makeParamsObjectExpression = ({ params, remotionLocalNames, }) => {
|
|
152
|
+
return b.objectExpression(Object.entries(params).map(([key, param]) => {
|
|
153
|
+
const keyNode = identifierRegex.test(key)
|
|
154
|
+
? b.identifier(key)
|
|
155
|
+
: b.stringLiteral(key);
|
|
156
|
+
return b.objectProperty(keyNode, makeParamExpression({ param, remotionLocalNames }));
|
|
157
|
+
}));
|
|
158
|
+
};
|
|
159
|
+
const makeEffectCall = ({ ast, effect, remotionLocalNames, }) => {
|
|
160
|
+
(0, add_effect_1.assertValidEffect)({
|
|
161
|
+
effectName: effect.callee,
|
|
162
|
+
effectImportPath: effect.importPath,
|
|
163
|
+
});
|
|
164
|
+
const localName = (0, add_effect_1.ensureEffectImport)({
|
|
165
|
+
ast,
|
|
166
|
+
effectName: effect.callee,
|
|
167
|
+
effectImportPath: effect.importPath,
|
|
168
|
+
});
|
|
169
|
+
return b.callExpression(b.identifier(localName), [
|
|
170
|
+
makeParamsObjectExpression({
|
|
171
|
+
params: effect.params,
|
|
172
|
+
remotionLocalNames,
|
|
173
|
+
}),
|
|
174
|
+
]);
|
|
175
|
+
};
|
|
176
|
+
const removeEffectsAttr = (attributes, attr) => {
|
|
177
|
+
const index = attributes.indexOf(attr);
|
|
178
|
+
if (index !== -1) {
|
|
179
|
+
attributes.splice(index, 1);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
const pasteEffects = async ({ input, targetSequenceNodePath, type, effects, prettierConfigOverride, }) => {
|
|
183
|
+
var _a;
|
|
184
|
+
var _b, _c, _d;
|
|
185
|
+
const ast = (0, parse_ast_1.parseAst)(input);
|
|
186
|
+
const targetJsxPath = (0, get_ast_node_path_1.getAstNodePath)(ast, targetSequenceNodePath);
|
|
187
|
+
const targetJsx = (0, can_update_sequence_props_1.findJsxElementAtNodePath)(ast, targetSequenceNodePath);
|
|
188
|
+
if (!targetJsx || !targetJsxPath) {
|
|
189
|
+
throw new Error('Could not find a JSX element at the specified location to paste effects');
|
|
190
|
+
}
|
|
191
|
+
const requiredRemotionImports = getRequiredRemotionImports(effects);
|
|
192
|
+
const remotionLocalNames = ensureRemotionImportLocalNames({
|
|
193
|
+
ast,
|
|
194
|
+
requiredImports: requiredRemotionImports,
|
|
195
|
+
});
|
|
196
|
+
if (requiredRemotionImports.has('useCurrentFrame')) {
|
|
197
|
+
const fnPath = (0, ensure_imports_and_frame_hook_1.findEnclosingFunctionPath)(targetJsxPath);
|
|
198
|
+
if (fnPath) {
|
|
199
|
+
(0, ensure_imports_and_frame_hook_1.ensureUseCurrentFrameHook)(fnPath, (_b = remotionLocalNames.useCurrentFrame) !== null && _b !== void 0 ? _b : 'useCurrentFrame');
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
const effectCalls = effects.map((effect) => makeEffectCall({ ast, effect, remotionLocalNames }));
|
|
203
|
+
const effectLabels = effects.map((effect) => `${effect.callee}()`);
|
|
204
|
+
const existingAttr = (0, update_effect_props_1.findEffectsAttr)((_c = targetJsx.attributes) !== null && _c !== void 0 ? _c : []);
|
|
205
|
+
if (type === 'effects-replacing') {
|
|
206
|
+
if (existingAttr) {
|
|
207
|
+
removeEffectsAttr(targetJsx.attributes, existingAttr);
|
|
208
|
+
}
|
|
209
|
+
if (effectCalls.length > 0) {
|
|
210
|
+
targetJsx.attributes.push(makeEffectsAttr(makeEffectsArray(effectCalls)));
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
else if (existingAttr) {
|
|
214
|
+
getEffectsArray(existingAttr).elements.push(...effectCalls);
|
|
215
|
+
}
|
|
216
|
+
else if (effectCalls.length > 0) {
|
|
217
|
+
targetJsx.attributes.push(makeEffectsAttr(makeEffectsArray(effectCalls)));
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
throw new Error('Cannot paste effects: no effects were copied');
|
|
221
|
+
}
|
|
222
|
+
const finalFile = (0, parse_ast_1.serializeAst)(ast);
|
|
223
|
+
const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
|
|
224
|
+
input: finalFile,
|
|
225
|
+
prettierConfigOverride,
|
|
226
|
+
});
|
|
227
|
+
return {
|
|
228
|
+
output,
|
|
229
|
+
formatted,
|
|
230
|
+
effectLabels,
|
|
231
|
+
logLine: (_d = (_a = targetJsx.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _d !== void 0 ? _d : 1,
|
|
232
|
+
};
|
|
233
|
+
};
|
|
234
|
+
exports.pasteEffects = pasteEffects;
|