@remotion/studio-server 4.0.484 → 4.0.485

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 (36) hide show
  1. package/dist/codemods/recast-mods.js +37 -0
  2. package/dist/codemods/split-jsx-sequence.d.ts +14 -0
  3. package/dist/codemods/split-jsx-sequence.js +345 -0
  4. package/dist/codemods/update-sequence-props/update-sequence-props.d.ts +1 -1
  5. package/dist/codemods/update-sequence-props/update-sequence-props.js +62 -7
  6. package/dist/preview-server/api-routes.js +2 -0
  7. package/dist/preview-server/routes/add-effect-keyframe.js +2 -2
  8. package/dist/preview-server/routes/add-effect.js +56 -53
  9. package/dist/preview-server/routes/add-keyframes.js +2 -2
  10. package/dist/preview-server/routes/add-sequence-keyframe.js +2 -2
  11. package/dist/preview-server/routes/apply-codemod.js +104 -101
  12. package/dist/preview-server/routes/apply-visual-control-change.js +83 -80
  13. package/dist/preview-server/routes/can-update-sequence-props.d.ts +13 -1
  14. package/dist/preview-server/routes/can-update-sequence-props.js +101 -7
  15. package/dist/preview-server/routes/delete-effect.js +83 -80
  16. package/dist/preview-server/routes/delete-jsx-node.js +74 -71
  17. package/dist/preview-server/routes/delete-keyframes.js +2 -2
  18. package/dist/preview-server/routes/duplicate-effect.js +77 -74
  19. package/dist/preview-server/routes/duplicate-jsx-node.js +53 -50
  20. package/dist/preview-server/routes/insert-element.js +2 -2
  21. package/dist/preview-server/routes/insert-jsx-element.js +2 -2
  22. package/dist/preview-server/routes/move-keyframes.js +2 -2
  23. package/dist/preview-server/routes/paste-effects.js +59 -56
  24. package/dist/preview-server/routes/reorder-effect.js +55 -52
  25. package/dist/preview-server/routes/reorder-sequence.js +55 -52
  26. package/dist/preview-server/routes/save-effect-props.js +2 -2
  27. package/dist/preview-server/routes/save-sequence-props.js +2 -2
  28. package/dist/preview-server/routes/source-file-write-queue.d.ts +1 -0
  29. package/dist/preview-server/routes/source-file-write-queue.js +11 -0
  30. package/dist/preview-server/routes/split-jsx-sequence.d.ts +3 -0
  31. package/dist/preview-server/routes/split-jsx-sequence.js +66 -0
  32. package/dist/preview-server/routes/update-default-props.js +58 -55
  33. package/dist/preview-server/routes/update-effect-keyframe-settings.js +2 -2
  34. package/dist/preview-server/routes/update-sequence-keyframe-settings.js +2 -2
  35. package/dist/preview-server/undo-stack.d.ts +3 -1
  36. package/package.json +6 -6
@@ -96,6 +96,7 @@ const mapReturnStatement = (statement, transformation, changesMade, parentFolder
96
96
  return statement;
97
97
  }
98
98
  if (transformation.type === 'new-composition' &&
99
+ transformation.folderName === null &&
99
100
  (statement.argument.type === 'JSXElement' ||
100
101
  statement.argument.type === 'JSXFragment')) {
101
102
  return {
@@ -191,6 +192,30 @@ const addNewCompositionToRootJsx = (root, transformation, changesMade) => {
191
192
  }
192
193
  return wrapInJsxFragment([root, newCompositionElement(transformation)]);
193
194
  };
195
+ const addNewCompositionToFolder = (folderElement, transformation, changesMade) => {
196
+ var _a;
197
+ if (changesMade.length > 0) {
198
+ return folderElement;
199
+ }
200
+ changesMade.push({
201
+ description: 'Added new composition',
202
+ });
203
+ return {
204
+ ...folderElement,
205
+ openingElement: {
206
+ ...folderElement.openingElement,
207
+ selfClosing: false,
208
+ },
209
+ closingElement: (_a = folderElement.closingElement) !== null && _a !== void 0 ? _a : {
210
+ type: 'JSXClosingElement',
211
+ name: folderElement.openingElement.name,
212
+ },
213
+ children: [
214
+ ...folderElement.children,
215
+ newCompositionElement(transformation),
216
+ ],
217
+ };
218
+ };
194
219
  // When a <Composition> JSX element appears in a position where it cannot
195
220
  // simply be removed from a parent's children list (e.g. as the sole return
196
221
  // value of a wrapper component or as the concise body of an arrow function),
@@ -208,6 +233,9 @@ const transformLoneJsxElement = (expression, transformation, changesMade, parent
208
233
  folderName === transformation.folderName &&
209
234
  parentFolderName === transformation.parentName) ||
210
235
  (transformation.type === 'rename-folder' &&
236
+ folderName === transformation.folderName &&
237
+ parentFolderName === transformation.parentName) ||
238
+ (transformation.type === 'new-composition' &&
211
239
  folderName === transformation.folderName &&
212
240
  parentFolderName === transformation.parentName));
213
241
  if (!isFolderMatch) {
@@ -224,6 +252,9 @@ const transformLoneJsxElement = (expression, transformation, changesMade, parent
224
252
  folderName === transformation.folderName &&
225
253
  parentFolderName === transformation.parentName) ||
226
254
  (transformation.type === 'rename-folder' &&
255
+ folderName === transformation.folderName &&
256
+ parentFolderName === transformation.parentName) ||
257
+ (transformation.type === 'new-composition' &&
227
258
  folderName === transformation.folderName &&
228
259
  parentFolderName === transformation.parentName);
229
260
  if (!isMatch) {
@@ -318,6 +349,11 @@ const mapJsxChild = (c, transformation, changesMade, parentFolderName) => {
318
349
  });
319
350
  return c.children;
320
351
  }
352
+ if (transformation.type === 'new-composition' &&
353
+ folderName === transformation.folderName &&
354
+ parentFolderName === transformation.parentName) {
355
+ return [addNewCompositionToFolder(c, transformation, changesMade)];
356
+ }
321
357
  const childParentFolderName = folderName
322
358
  ? getChildFolderParentName({ folderName, parentFolderName })
323
359
  : parentFolderName;
@@ -330,6 +366,7 @@ const mapRecognizedType = (expression, transformation, changesMade, parentFolder
330
366
  if (expression.type === 'ArrowFunctionExpression' ||
331
367
  expression.type === 'FunctionExpression') {
332
368
  if (transformation.type === 'new-composition' &&
369
+ transformation.folderName === null &&
333
370
  (expression.body.type === 'JSXElement' ||
334
371
  expression.body.type === 'JSXFragment')) {
335
372
  return {
@@ -0,0 +1,14 @@
1
+ import type { SequenceNodePath } from 'remotion';
2
+ export declare const getSplitUnsupportedSequenceTagReason: (tagName: string) => string | null;
3
+ export declare const getIsSplittableSequenceTag: (tagName: string) => boolean;
4
+ export declare const splitJsxSequence: ({ input, nodePath, splitFrame, prettierConfigOverride, }: {
5
+ input: string;
6
+ nodePath: SequenceNodePath;
7
+ splitFrame: number;
8
+ prettierConfigOverride?: Record<string, unknown> | null | undefined;
9
+ }) => Promise<{
10
+ output: string;
11
+ formatted: boolean;
12
+ nodeLabel: string;
13
+ logLine: number;
14
+ }>;
@@ -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,4 +1,4 @@
1
- import type { SequenceNodePath, InteractivitySchema } from 'remotion';
1
+ import type { InteractivitySchema, SequenceNodePath } from 'remotion';
2
2
  export type SequencePropUpdate = {
3
3
  key: string;
4
4
  value: unknown;
@@ -85,9 +85,59 @@ const snapshotTopLevelAttrs = (node) => {
85
85
  }
86
86
  return result;
87
87
  };
88
- const updateSequencePropsNode = ({ node, updates, schema, }) => {
88
+ const escapeJsxText = (value) => {
89
+ return value
90
+ .replace(/&/g, '&amp;')
91
+ .replace(/</g, '&lt;')
92
+ .replace(/>/g, '&gt;')
93
+ .replace(/{/g, '&#123;')
94
+ .replace(/}/g, '&#125;');
95
+ };
96
+ const findChildrenAttribute = (node) => {
97
+ var _a;
98
+ return (_a = node.attributes) === null || _a === void 0 ? void 0 : _a.find((attr) => {
99
+ return (attr.type === 'JSXAttribute' &&
100
+ attr.name.type === 'JSXIdentifier' &&
101
+ attr.name.name === 'children');
102
+ });
103
+ };
104
+ const updateJsxTextContent = ({ jsxElement, value, }) => {
105
+ const nextValue = String(value !== null && value !== void 0 ? value : '');
106
+ const staticChildrenAttribute = (0, can_update_sequence_props_1.getStaticJsxChildrenAttribute)(jsxElement.openingElement);
107
+ if (staticChildrenAttribute) {
108
+ const childrenAttribute = findChildrenAttribute(jsxElement.openingElement);
109
+ if (!childrenAttribute) {
110
+ throw new Error('Expected static children attribute to exist');
111
+ }
112
+ childrenAttribute.value = b.stringLiteral(nextValue);
113
+ return staticChildrenAttribute.value;
114
+ }
115
+ if ((0, can_update_sequence_props_1.hasJsxChildrenAttribute)(jsxElement.openingElement)) {
116
+ throw new Error('Cannot update text content because the children attribute is not static text');
117
+ }
118
+ const staticTextContent = (0, can_update_sequence_props_1.getStaticJsxTextContent)(jsxElement);
119
+ if (!staticTextContent) {
120
+ throw new Error('Cannot update text content because JSX children are not static text');
121
+ }
122
+ const canRepresentAsJsxText = staticTextContent.kind === 'jsx-text' &&
123
+ !nextValue.includes('\n') &&
124
+ nextValue.trim() === nextValue;
125
+ if (canRepresentAsJsxText) {
126
+ jsxElement.children = [
127
+ b.jsxText(escapeJsxText(nextValue)),
128
+ ];
129
+ }
130
+ else {
131
+ jsxElement.children = [
132
+ b.jsxExpressionContainer(b.stringLiteral(nextValue)),
133
+ ];
134
+ }
135
+ return staticTextContent.value;
136
+ };
137
+ const updateSequencePropsNode = ({ jsxElement, updates, schema, }) => {
89
138
  var _a, _b, _c;
90
139
  var _d, _e;
140
+ const node = jsxElement.openingElement;
91
141
  const logLine = (_d = (_a = node.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _d !== void 0 ? _d : 1;
92
142
  const oldValueStrings = [];
93
143
  const initialAttrs = snapshotTopLevelAttrs(node);
@@ -97,6 +147,11 @@ const updateSequencePropsNode = ({ node, updates, schema, }) => {
97
147
  }));
98
148
  for (const { key, value, defaultValue } of updates) {
99
149
  let oldValueString = '';
150
+ if (key === 'children') {
151
+ oldValueString = updateJsxTextContent({ jsxElement, value });
152
+ oldValueStrings.push(oldValueString);
153
+ continue;
154
+ }
100
155
  const isDefault = defaultValue !== null &&
101
156
  JSON.stringify(value) === JSON.stringify(defaultValue);
102
157
  const dotIndex = key.indexOf('.');
@@ -197,12 +252,12 @@ const updateSequencePropsNode = ({ node, updates, schema, }) => {
197
252
  };
198
253
  const updateSequencePropsAst = ({ input, nodePath, updates, schema, }) => {
199
254
  const ast = (0, parse_ast_1.parseAst)(input);
200
- const node = (0, can_update_sequence_props_1.findJsxElementAtNodePath)(ast, nodePath);
201
- if (!node) {
255
+ const jsxElement = (0, can_update_sequence_props_1.findJsxElementNodeAtNodePath)(ast, nodePath);
256
+ if (!jsxElement) {
202
257
  throw new Error('Could not find a JSX element at the specified line to update');
203
258
  }
204
259
  const { oldValueStrings, logLine, removedProps } = updateSequencePropsNode({
205
- node,
260
+ jsxElement,
206
261
  updates,
207
262
  schema,
208
263
  });
@@ -217,11 +272,11 @@ exports.updateSequencePropsAst = updateSequencePropsAst;
217
272
  const updateMultipleSequenceProps = async ({ input, changes, prettierConfigOverride, }) => {
218
273
  const ast = (0, parse_ast_1.parseAst)(input);
219
274
  const results = changes.map(({ nodePath, updates, schema }) => {
220
- const node = (0, can_update_sequence_props_1.findJsxElementAtNodePath)(ast, nodePath);
221
- if (!node) {
275
+ const jsxElement = (0, can_update_sequence_props_1.findJsxElementNodeAtNodePath)(ast, nodePath);
276
+ if (!jsxElement) {
222
277
  throw new Error('Could not find a JSX element at the specified line to update');
223
278
  }
224
- return updateSequencePropsNode({ node, updates, schema });
279
+ return updateSequencePropsNode({ jsxElement, updates, schema });
225
280
  });
226
281
  const { output, formatted } = await (0, format_file_content_1.formatFileContent)({
227
282
  input: (0, parse_ast_1.serializeAst)(ast),
@@ -35,6 +35,7 @@ const reorder_sequence_1 = require("./routes/reorder-sequence");
35
35
  const restart_studio_1 = require("./routes/restart-studio");
36
36
  const save_effect_props_1 = require("./routes/save-effect-props");
37
37
  const save_sequence_props_1 = require("./routes/save-sequence-props");
38
+ const split_jsx_sequence_1 = require("./routes/split-jsx-sequence");
38
39
  const subscribe_to_default_props_1 = require("./routes/subscribe-to-default-props");
39
40
  const subscribe_to_file_existence_1 = require("./routes/subscribe-to-file-existence");
40
41
  const subscribe_to_sequence_props_1 = require("./routes/subscribe-to-sequence-props");
@@ -82,6 +83,7 @@ exports.allApiRoutes = {
82
83
  '/api/paste-effects': paste_effects_1.pasteEffectsHandler,
83
84
  '/api/delete-jsx-node': delete_jsx_node_1.deleteJsxNodeHandler,
84
85
  '/api/duplicate-jsx-node': duplicate_jsx_node_1.duplicateJsxNodeHandler,
86
+ '/api/split-jsx-sequence': split_jsx_sequence_1.splitJsxSequenceHandler,
85
87
  '/api/update-available': update_available_1.handleUpdate,
86
88
  '/api/project-info': project_info_1.projectInfoHandler,
87
89
  '/api/delete-static-file': delete_static_file_1.deleteStaticFileHandler,
@@ -13,8 +13,8 @@ const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
13
13
  const can_update_effect_props_1 = require("./can-update-effect-props");
14
14
  const can_update_sequence_props_1 = require("./can-update-sequence-props");
15
15
  const log_effect_update_1 = require("./log-updates/log-effect-update");
16
- const save_props_mutex_1 = require("./save-props-mutex");
17
- const addEffectKeyframeHandler = ({ input: { fileName, sequenceNodePath, effectIndex, key, frame, value, schema, clientId, }, remotionRoot, logLevel, }) => (0, save_props_mutex_1.withSavePropsLock)(async () => {
16
+ const source_file_write_queue_1 = require("./source-file-write-queue");
17
+ const addEffectKeyframeHandler = ({ input: { fileName, sequenceNodePath, effectIndex, key, frame, value, schema, clientId, }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
18
18
  renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[add-effect-keyframe] Received request for fileName="${fileName}" effectIndex=${effectIndex} key="${key}" frame=${frame}`);
19
19
  const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
20
20
  remotionRoot,