@remotion/studio-server 4.0.484 → 4.0.486

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.
Files changed (41) hide show
  1. package/dist/codemods/duplicate-composition.js +8 -0
  2. package/dist/codemods/recast-mods.js +246 -5
  3. package/dist/codemods/split-jsx-sequence.d.ts +14 -0
  4. package/dist/codemods/split-jsx-sequence.js +345 -0
  5. package/dist/codemods/update-sequence-props/update-sequence-props.d.ts +3 -1
  6. package/dist/codemods/update-sequence-props/update-sequence-props.js +406 -9
  7. package/dist/helpers/import-agnostic-node-path.js +30 -4
  8. package/dist/helpers/resolve-composition-component.d.ts +1 -0
  9. package/dist/helpers/resolve-composition-component.js +206 -9
  10. package/dist/preview-server/api-routes.js +2 -0
  11. package/dist/preview-server/routes/add-effect-keyframe.js +2 -2
  12. package/dist/preview-server/routes/add-effect.js +56 -53
  13. package/dist/preview-server/routes/add-keyframes.js +2 -2
  14. package/dist/preview-server/routes/add-sequence-keyframe.js +2 -2
  15. package/dist/preview-server/routes/apply-codemod.js +123 -101
  16. package/dist/preview-server/routes/apply-visual-control-change.js +83 -80
  17. package/dist/preview-server/routes/can-update-sequence-props.d.ts +13 -1
  18. package/dist/preview-server/routes/can-update-sequence-props.js +101 -7
  19. package/dist/preview-server/routes/delete-effect.js +83 -80
  20. package/dist/preview-server/routes/delete-jsx-node.js +74 -71
  21. package/dist/preview-server/routes/delete-keyframes.js +2 -2
  22. package/dist/preview-server/routes/duplicate-effect.js +77 -74
  23. package/dist/preview-server/routes/duplicate-jsx-node.js +53 -50
  24. package/dist/preview-server/routes/insert-element.js +2 -2
  25. package/dist/preview-server/routes/insert-jsx-element.js +53 -4
  26. package/dist/preview-server/routes/move-keyframes.js +2 -2
  27. package/dist/preview-server/routes/paste-effects.js +59 -56
  28. package/dist/preview-server/routes/reorder-effect.js +55 -52
  29. package/dist/preview-server/routes/reorder-sequence.js +55 -52
  30. package/dist/preview-server/routes/save-effect-props.js +2 -2
  31. package/dist/preview-server/routes/save-sequence-props.d.ts +3 -1
  32. package/dist/preview-server/routes/save-sequence-props.js +208 -24
  33. package/dist/preview-server/routes/source-file-write-queue.d.ts +1 -0
  34. package/dist/preview-server/routes/source-file-write-queue.js +11 -0
  35. package/dist/preview-server/routes/split-jsx-sequence.d.ts +3 -0
  36. package/dist/preview-server/routes/split-jsx-sequence.js +66 -0
  37. package/dist/preview-server/routes/update-default-props.js +58 -55
  38. package/dist/preview-server/routes/update-effect-keyframe-settings.js +2 -2
  39. package/dist/preview-server/routes/update-sequence-keyframe-settings.js +2 -2
  40. package/dist/preview-server/undo-stack.d.ts +7 -1
  41. package/package.json +6 -6
@@ -0,0 +1,345 @@
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.splitJsxSequence = exports.getIsSplittableSequenceTag = exports.getSplitUnsupportedSequenceTagReason = void 0;
37
+ const types_1 = require("@babel/types");
38
+ const recast = __importStar(require("recast"));
39
+ const delete_jsx_node_1 = require("./delete-jsx-node");
40
+ const format_file_content_1 = require("./format-file-content");
41
+ const parse_ast_1 = require("./parse-ast");
42
+ const { builders: b, namedTypes } = recast.types;
43
+ const jsxId = (name) => ({ type: 'JSXIdentifier', name });
44
+ const numericAttribute = (name, value) => ({
45
+ type: 'JSXAttribute',
46
+ name: jsxId(name),
47
+ value: {
48
+ type: 'JSXExpressionContainer',
49
+ expression: value === Infinity ? b.identifier('Infinity') : b.numericLiteral(value),
50
+ },
51
+ });
52
+ const getAttributeName = (attribute) => {
53
+ if (attribute.type !== 'JSXAttribute' ||
54
+ attribute.name.type !== 'JSXIdentifier') {
55
+ return null;
56
+ }
57
+ return attribute.name.name;
58
+ };
59
+ const getStaticNumber = (attribute) => {
60
+ if (attribute.type !== 'JSXAttribute') {
61
+ return null;
62
+ }
63
+ if (!attribute.value) {
64
+ return null;
65
+ }
66
+ if (attribute.value.type === 'StringLiteral') {
67
+ const parsed = Number(attribute.value.value);
68
+ return Number.isFinite(parsed) ? parsed : null;
69
+ }
70
+ if (attribute.value.type !== 'JSXExpressionContainer') {
71
+ return null;
72
+ }
73
+ const { expression } = attribute.value;
74
+ if (expression.type === 'NumericLiteral') {
75
+ return expression.value;
76
+ }
77
+ if (expression.type === 'Identifier' && expression.name === 'Infinity') {
78
+ return Infinity;
79
+ }
80
+ return null;
81
+ };
82
+ const readSequenceTiming = (element) => {
83
+ let from = 0;
84
+ let durationInFrames = Infinity;
85
+ let trimBefore = 0;
86
+ let hasFrom = false;
87
+ let hasDurationInFrames = false;
88
+ let hasTrimBefore = false;
89
+ for (const attribute of element.openingElement.attributes) {
90
+ const name = getAttributeName(attribute);
91
+ if (!name) {
92
+ continue;
93
+ }
94
+ if (name !== 'from' &&
95
+ name !== 'durationInFrames' &&
96
+ name !== 'trimBefore') {
97
+ continue;
98
+ }
99
+ const value = getStaticNumber(attribute);
100
+ if (value === null) {
101
+ throw new Error(`Cannot split sequence with dynamic ${name}`);
102
+ }
103
+ if (name === 'from') {
104
+ from = value;
105
+ hasFrom = true;
106
+ }
107
+ if (name === 'durationInFrames') {
108
+ durationInFrames = value;
109
+ hasDurationInFrames = true;
110
+ }
111
+ if (name === 'trimBefore') {
112
+ trimBefore = value;
113
+ hasTrimBefore = true;
114
+ }
115
+ }
116
+ return {
117
+ from,
118
+ durationInFrames,
119
+ trimBefore,
120
+ hasFrom,
121
+ hasDurationInFrames,
122
+ hasTrimBefore,
123
+ };
124
+ };
125
+ const setNumericAttribute = ({ element, name, value, omitIfMissing, }) => {
126
+ const { openingElement: { attributes }, } = element;
127
+ const index = attributes.findIndex((attribute) => getAttributeName(attribute) === name);
128
+ if (value === null || (index === -1 && omitIfMissing)) {
129
+ if (index !== -1) {
130
+ attributes.splice(index, 1);
131
+ }
132
+ return;
133
+ }
134
+ const next = numericAttribute(name, value);
135
+ if (index === -1) {
136
+ attributes.push(next);
137
+ }
138
+ else {
139
+ attributes[index] = next;
140
+ }
141
+ };
142
+ const timingAttributeOrder = ['from', 'durationInFrames', 'trimBefore'];
143
+ const orderTimingAttributes = (element) => {
144
+ const { openingElement: { attributes }, } = element;
145
+ const timingAttributes = new Map();
146
+ const otherAttributes = [];
147
+ let firstTimingIndex = null;
148
+ for (let i = 0; i < attributes.length; i++) {
149
+ const attribute = attributes[i];
150
+ const name = getAttributeName(attribute);
151
+ if (name && timingAttributeOrder.includes(name)) {
152
+ timingAttributes.set(name, attribute);
153
+ firstTimingIndex = firstTimingIndex === null ? i : firstTimingIndex;
154
+ }
155
+ else {
156
+ otherAttributes.push(attribute);
157
+ }
158
+ }
159
+ if (firstTimingIndex === null) {
160
+ return;
161
+ }
162
+ const orderedTimingAttributes = timingAttributeOrder.flatMap((name) => {
163
+ const attribute = timingAttributes.get(name);
164
+ return attribute ? [attribute] : [];
165
+ });
166
+ const insertionIndex = Math.min(firstTimingIndex, otherAttributes.length);
167
+ attributes.splice(0, attributes.length, ...otherAttributes.slice(0, insertionIndex), ...orderedTimingAttributes, ...otherAttributes.slice(insertionIndex));
168
+ };
169
+ const splittableSequenceTags = new Set([
170
+ 'AnimatedImage',
171
+ 'Arrow',
172
+ 'Audio',
173
+ 'Callout',
174
+ 'CanvasImage',
175
+ 'Circle',
176
+ 'Ellipse',
177
+ 'Gif',
178
+ 'Heart',
179
+ 'Html5Audio',
180
+ 'Html5Video',
181
+ 'HtmlInCanvas',
182
+ 'Img',
183
+ 'OffthreadVideo',
184
+ 'Pie',
185
+ 'Polygon',
186
+ 'Rect',
187
+ 'RemotionRiveCanvas',
188
+ 'Sequence',
189
+ 'Solid',
190
+ 'Spark',
191
+ 'Star',
192
+ 'Starburst',
193
+ 'Triangle',
194
+ 'Video',
195
+ ]);
196
+ const unsupportedSequenceTags = new Set([
197
+ 'Series.Sequence',
198
+ 'TransitionSeries.Overlay',
199
+ 'TransitionSeries.Sequence',
200
+ ]);
201
+ const jsxMemberNameToString = (name) => {
202
+ if (name.type === 'JSXIdentifier') {
203
+ return name.name;
204
+ }
205
+ return `${jsxMemberNameToString(name.object)}.${name.property.name}`;
206
+ };
207
+ const jsxNameToString = (name) => {
208
+ if (name.type === 'JSXNamespacedName') {
209
+ return `${name.namespace.name}:${name.name.name}`;
210
+ }
211
+ return jsxMemberNameToString(name);
212
+ };
213
+ const getSplitUnsupportedSequenceTagReason = (tagName) => {
214
+ if (tagName === 'Series.Sequence' ||
215
+ tagName === 'TransitionSeries.Sequence' ||
216
+ tagName === 'TransitionSeries.Overlay') {
217
+ return `<${tagName}> cannot be split from source`;
218
+ }
219
+ return null;
220
+ };
221
+ exports.getSplitUnsupportedSequenceTagReason = getSplitUnsupportedSequenceTagReason;
222
+ const getIsSplittableSequenceTag = (tagName) => {
223
+ if (unsupportedSequenceTags.has(tagName)) {
224
+ return false;
225
+ }
226
+ if (tagName.startsWith('Interactive.')) {
227
+ return true;
228
+ }
229
+ return splittableSequenceTags.has(tagName);
230
+ };
231
+ exports.getIsSplittableSequenceTag = getIsSplittableSequenceTag;
232
+ const getSplittableSequenceTagName = (element) => {
233
+ return jsxNameToString(element.openingElement.name);
234
+ };
235
+ const makeFragment = (first, second) => ({
236
+ type: 'JSXFragment',
237
+ openingFragment: { type: 'JSXOpeningFragment' },
238
+ closingFragment: { type: 'JSXClosingFragment' },
239
+ children: [first, second],
240
+ });
241
+ const insertAfter = (parentNode, node, clone) => {
242
+ if (namedTypes.JSXElement.check(parentNode) ||
243
+ namedTypes.JSXFragment.check(parentNode)) {
244
+ const idx = parentNode.children.indexOf(node);
245
+ if (idx !== -1) {
246
+ parentNode.children.splice(idx + 1, 0, clone);
247
+ return true;
248
+ }
249
+ }
250
+ if (namedTypes.ReturnStatement.check(parentNode)) {
251
+ const parent = parentNode;
252
+ if (parent.argument === node) {
253
+ parent.argument = makeFragment(node, clone);
254
+ return true;
255
+ }
256
+ }
257
+ if (namedTypes.ArrowFunctionExpression.check(parentNode)) {
258
+ const parent = parentNode;
259
+ if (parent.body === node) {
260
+ parent.body = makeFragment(node, clone);
261
+ return true;
262
+ }
263
+ }
264
+ return false;
265
+ };
266
+ const splitJsxSequence = async ({ input, nodePath, splitFrame, prettierConfigOverride, }) => {
267
+ var _a, _b;
268
+ var _c, _d;
269
+ if (!Number.isInteger(splitFrame)) {
270
+ throw new Error('Split frame must be an integer');
271
+ }
272
+ const ast = (0, parse_ast_1.parseAst)(input);
273
+ const jsxPath = (0, delete_jsx_node_1.findJsxElementPathForDeletion)(ast, nodePath);
274
+ if (!jsxPath) {
275
+ throw new Error('Could not find a JSX sequence at the specified location to split');
276
+ }
277
+ const jsxElement = jsxPath.node;
278
+ const tagName = getSplittableSequenceTagName(jsxElement);
279
+ const unsupportedReason = (0, exports.getSplitUnsupportedSequenceTagReason)(tagName);
280
+ if (unsupportedReason) {
281
+ throw new Error(unsupportedReason);
282
+ }
283
+ if (!(0, exports.getIsSplittableSequenceTag)(tagName)) {
284
+ throw new Error(`<${tagName}> does not support sequence timing props and cannot be split`);
285
+ }
286
+ const timing = readSequenceTiming(jsxElement);
287
+ const finiteEnd = timing.durationInFrames === Infinity
288
+ ? Infinity
289
+ : timing.from + timing.durationInFrames;
290
+ if (splitFrame <= timing.from) {
291
+ throw new Error('Cannot split at or before the sequence start');
292
+ }
293
+ if (splitFrame >= finiteEnd) {
294
+ throw new Error('Cannot split at or after the sequence end');
295
+ }
296
+ const right = (0, types_1.cloneNode)(jsxElement, true);
297
+ const leftDuration = splitFrame - timing.from;
298
+ const rightDuration = timing.durationInFrames === Infinity ? Infinity : finiteEnd - splitFrame;
299
+ const rightTrimBefore = timing.trimBefore + leftDuration;
300
+ setNumericAttribute({
301
+ element: jsxElement,
302
+ name: 'durationInFrames',
303
+ value: leftDuration,
304
+ omitIfMissing: false,
305
+ });
306
+ setNumericAttribute({
307
+ element: right,
308
+ name: 'from',
309
+ value: splitFrame,
310
+ omitIfMissing: false,
311
+ });
312
+ setNumericAttribute({
313
+ element: right,
314
+ name: 'durationInFrames',
315
+ value: rightDuration === Infinity ? null : rightDuration,
316
+ omitIfMissing: !timing.hasDurationInFrames,
317
+ });
318
+ setNumericAttribute({
319
+ element: right,
320
+ name: 'trimBefore',
321
+ value: rightTrimBefore === 0 ? null : rightTrimBefore,
322
+ omitIfMissing: !timing.hasTrimBefore && rightTrimBefore === 0,
323
+ });
324
+ orderTimingAttributes(jsxElement);
325
+ orderTimingAttributes(right);
326
+ const { parentPath } = jsxPath;
327
+ if (!parentPath) {
328
+ throw new Error('Cannot split JSX sequence with no parent');
329
+ }
330
+ if (!insertAfter(parentPath.node, jsxElement, right)) {
331
+ jsxPath.replace(makeFragment(jsxElement, right));
332
+ }
333
+ const finalFile = (0, parse_ast_1.serializeAst)(ast);
334
+ const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
335
+ input: finalFile,
336
+ prettierConfigOverride,
337
+ });
338
+ return {
339
+ output,
340
+ formatted,
341
+ nodeLabel: (0, delete_jsx_node_1.getJsxElementTagLabel)(jsxElement),
342
+ logLine: (_d = (_c = (_a = jsxElement.openingElement.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _c !== void 0 ? _c : (_b = jsxElement.loc) === null || _b === void 0 ? void 0 : _b.start.line) !== null && _d !== void 0 ? _d : 1,
343
+ };
344
+ };
345
+ exports.splitJsxSequence = splitJsxSequence;
@@ -1,8 +1,10 @@
1
- import type { SequenceNodePath, InteractivitySchema } from 'remotion';
1
+ import type { GoogleFontSourceEdit } from '@remotion/studio-shared';
2
+ import type { InteractivitySchema, SequenceNodePath } from 'remotion';
2
3
  export type SequencePropUpdate = {
3
4
  key: string;
4
5
  value: unknown;
5
6
  defaultValue: unknown | null;
7
+ googleFont?: GoogleFontSourceEdit | null;
6
8
  };
7
9
  export type RemovedProp = {
8
10
  key: string;