@remotion/studio-server 4.0.443 → 4.0.445

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.
@@ -0,0 +1,16 @@
1
+ import type { File, JSXElement } from '@babel/types';
2
+ import type { SequenceNodePath } from '@remotion/studio-shared';
3
+ /** e.g. `<Video>` or `<Remotion.Sequence>` for logs and undo copy. */
4
+ export declare const getJsxElementTagLabel: (element: JSXElement) => string;
5
+ export declare const findJsxElementPathForDeletion: (ast: File, nodePath: SequenceNodePath) => import("ast-types/lib/node-path").NodePath<N, V> | null;
6
+ export declare const deleteJsxElementAtPath: (jsxPath: import("ast-types/lib/node-path").NodePath<N, V>) => void;
7
+ export declare const deleteJsxNode: ({ input, nodePath, prettierConfigOverride, }: {
8
+ input: string;
9
+ nodePath: SequenceNodePath;
10
+ prettierConfigOverride?: Record<string, unknown> | null | undefined;
11
+ }) => Promise<{
12
+ output: string;
13
+ formatted: boolean;
14
+ nodeLabel: string;
15
+ logLine: number;
16
+ }>;
@@ -0,0 +1,354 @@
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.deleteJsxNode = exports.deleteJsxElementAtPath = exports.findJsxElementPathForDeletion = exports.getJsxElementTagLabel = void 0;
37
+ const recast = __importStar(require("recast"));
38
+ const parse_ast_1 = require("./parse-ast");
39
+ const { builders: b, namedTypes } = recast.types;
40
+ /** Recast `builders.nullLiteral()` is typed against ast-types; normalize to Babel `Expression`. */
41
+ const nullLiteralExpr = () => b.nullLiteral();
42
+ const jsxOpeningNameToString = (name) => {
43
+ if (name.type === 'JSXIdentifier') {
44
+ return name.name;
45
+ }
46
+ if (name.type === 'JSXNamespacedName') {
47
+ return `${name.namespace.name}:${name.name.name}`;
48
+ }
49
+ if (name.type === 'JSXMemberExpression') {
50
+ const memberToString = (expr) => {
51
+ if (expr.type === 'JSXIdentifier') {
52
+ return expr.name;
53
+ }
54
+ return `${memberToString(expr.object)}.${expr.property.name}`;
55
+ };
56
+ return memberToString(name);
57
+ }
58
+ return 'Unknown';
59
+ };
60
+ /** e.g. `<Video>` or `<Remotion.Sequence>` for logs and undo copy. */
61
+ const getJsxElementTagLabel = (element) => {
62
+ return `<${jsxOpeningNameToString(element.openingElement.name)}>`;
63
+ };
64
+ exports.getJsxElementTagLabel = getJsxElementTagLabel;
65
+ const findJsxElementPathForDeletion = (ast, nodePath) => {
66
+ let current = new recast.types.NodePath(ast);
67
+ for (const segment of nodePath) {
68
+ current = current.get(segment);
69
+ if (current.value === null || current.value === undefined) {
70
+ return null;
71
+ }
72
+ }
73
+ if (namedTypes.JSXOpeningElement.check(current.value)) {
74
+ const parent = current.parentPath;
75
+ if (parent && namedTypes.JSXElement.check(parent.value)) {
76
+ return parent;
77
+ }
78
+ return null;
79
+ }
80
+ if (namedTypes.JSXElement.check(current.value)) {
81
+ return current;
82
+ }
83
+ return null;
84
+ };
85
+ exports.findJsxElementPathForDeletion = findJsxElementPathForDeletion;
86
+ const replaceInLogicalExpression = (parent, node) => {
87
+ const nl = nullLiteralExpr();
88
+ if (parent.left === node) {
89
+ parent.left = nl;
90
+ return true;
91
+ }
92
+ if (parent.right === node) {
93
+ parent.right = nl;
94
+ return true;
95
+ }
96
+ return false;
97
+ };
98
+ const replaceInConditionalExpression = (parent, node) => {
99
+ const nl = nullLiteralExpr();
100
+ if (parent.consequent === node) {
101
+ parent.consequent = nl;
102
+ return true;
103
+ }
104
+ if (parent.alternate === node) {
105
+ parent.alternate = nl;
106
+ return true;
107
+ }
108
+ return false;
109
+ };
110
+ const replaceInArrowFunctionExpression = (parent, node) => {
111
+ if (parent.body === node) {
112
+ parent.body = nullLiteralExpr();
113
+ return true;
114
+ }
115
+ return false;
116
+ };
117
+ const replaceInReturnStatement = (parent, node) => {
118
+ if (parent.argument === node) {
119
+ parent.argument = nullLiteralExpr();
120
+ return true;
121
+ }
122
+ return false;
123
+ };
124
+ const replaceInCallExpression = (parent, node) => {
125
+ const idx = parent.arguments.indexOf(node);
126
+ if (idx !== -1) {
127
+ parent.arguments[idx] = nullLiteralExpr();
128
+ return true;
129
+ }
130
+ return false;
131
+ };
132
+ const replaceInOptionalCallExpression = (parent, node) => {
133
+ const idx = parent.arguments.indexOf(node);
134
+ if (idx !== -1) {
135
+ parent.arguments[idx] = nullLiteralExpr();
136
+ return true;
137
+ }
138
+ return false;
139
+ };
140
+ const replaceInArrayExpression = (parent, node) => {
141
+ const idx = parent.elements.indexOf(node);
142
+ if (idx !== -1) {
143
+ parent.elements[idx] = nullLiteralExpr();
144
+ return true;
145
+ }
146
+ return false;
147
+ };
148
+ const replaceInAssignmentExpression = (parent, node) => {
149
+ if (parent.right === node) {
150
+ parent.right = nullLiteralExpr();
151
+ return true;
152
+ }
153
+ return false;
154
+ };
155
+ const replaceInVariableDeclarator = (parent, node) => {
156
+ if (parent.init === node) {
157
+ parent.init = nullLiteralExpr();
158
+ return true;
159
+ }
160
+ return false;
161
+ };
162
+ const replaceInExportDefaultDeclaration = (parent, node) => {
163
+ if (parent.declaration === node) {
164
+ parent.declaration = nullLiteralExpr();
165
+ return true;
166
+ }
167
+ return false;
168
+ };
169
+ const replaceInSequenceExpression = (parent, node) => {
170
+ const idx = parent.expressions.indexOf(node);
171
+ if (idx !== -1) {
172
+ parent.expressions[idx] = nullLiteralExpr();
173
+ return true;
174
+ }
175
+ return false;
176
+ };
177
+ const replaceInNewExpression = (parent, node) => {
178
+ const idx = parent.arguments.indexOf(node);
179
+ if (idx !== -1) {
180
+ parent.arguments[idx] = nullLiteralExpr();
181
+ return true;
182
+ }
183
+ return false;
184
+ };
185
+ const replaceInExpressionStatement = (parent, node) => {
186
+ if (parent.expression === node) {
187
+ parent.expression = nullLiteralExpr();
188
+ return true;
189
+ }
190
+ return false;
191
+ };
192
+ const replaceInParenthesizedExpression = (parent, node) => {
193
+ if (parent.expression === node) {
194
+ parent.expression = nullLiteralExpr();
195
+ return true;
196
+ }
197
+ return false;
198
+ };
199
+ const replaceInJSXExpressionContainer = (parent, node) => {
200
+ if (parent.expression === node) {
201
+ parent.expression = nullLiteralExpr();
202
+ return true;
203
+ }
204
+ return false;
205
+ };
206
+ const replaceInTSAsExpression = (parent, node) => {
207
+ if (parent.expression === node) {
208
+ parent.expression = nullLiteralExpr();
209
+ return true;
210
+ }
211
+ return false;
212
+ };
213
+ const replaceInJSXParentChildren = (parent, node) => {
214
+ const idx = parent.children.indexOf(node);
215
+ if (idx !== -1) {
216
+ parent.children.splice(idx, 1);
217
+ return true;
218
+ }
219
+ return false;
220
+ };
221
+ const replaceNodeWithNull = (parentNode, node) => {
222
+ if (namedTypes.LogicalExpression.check(parentNode)) {
223
+ return replaceInLogicalExpression(parentNode, node);
224
+ }
225
+ if (namedTypes.ConditionalExpression.check(parentNode)) {
226
+ return replaceInConditionalExpression(parentNode, node);
227
+ }
228
+ if (namedTypes.ArrowFunctionExpression.check(parentNode)) {
229
+ return replaceInArrowFunctionExpression(parentNode, node);
230
+ }
231
+ if (namedTypes.ReturnStatement.check(parentNode)) {
232
+ return replaceInReturnStatement(parentNode, node);
233
+ }
234
+ if (namedTypes.CallExpression.check(parentNode)) {
235
+ return replaceInCallExpression(parentNode, node);
236
+ }
237
+ if (parentNode.type === 'OptionalCallExpression') {
238
+ return replaceInOptionalCallExpression(parentNode, node);
239
+ }
240
+ if (namedTypes.ArrayExpression.check(parentNode)) {
241
+ return replaceInArrayExpression(parentNode, node);
242
+ }
243
+ if (namedTypes.AssignmentExpression.check(parentNode)) {
244
+ return replaceInAssignmentExpression(parentNode, node);
245
+ }
246
+ if (namedTypes.VariableDeclarator.check(parentNode)) {
247
+ return replaceInVariableDeclarator(parentNode, node);
248
+ }
249
+ if (namedTypes.ExportDefaultDeclaration.check(parentNode)) {
250
+ return replaceInExportDefaultDeclaration(parentNode, node);
251
+ }
252
+ if (namedTypes.SequenceExpression.check(parentNode)) {
253
+ return replaceInSequenceExpression(parentNode, node);
254
+ }
255
+ if (namedTypes.NewExpression.check(parentNode)) {
256
+ return replaceInNewExpression(parentNode, node);
257
+ }
258
+ if (namedTypes.ExpressionStatement.check(parentNode)) {
259
+ return replaceInExpressionStatement(parentNode, node);
260
+ }
261
+ if (namedTypes.ParenthesizedExpression.check(parentNode)) {
262
+ return replaceInParenthesizedExpression(parentNode, node);
263
+ }
264
+ if (namedTypes.JSXExpressionContainer.check(parentNode)) {
265
+ return replaceInJSXExpressionContainer(parentNode, node);
266
+ }
267
+ if (namedTypes.TSAsExpression.check(parentNode)) {
268
+ return replaceInTSAsExpression(parentNode, node);
269
+ }
270
+ if (namedTypes.JSXElement.check(parentNode)) {
271
+ return replaceInJSXParentChildren(parentNode, node);
272
+ }
273
+ if (namedTypes.JSXFragment.check(parentNode)) {
274
+ return replaceInJSXParentChildren(parentNode, node);
275
+ }
276
+ return false;
277
+ };
278
+ const deleteJsxElementAtPath = (jsxPath) => {
279
+ const { node, parentPath } = jsxPath;
280
+ if (!parentPath) {
281
+ throw new Error('Cannot delete JSX element with no parent');
282
+ }
283
+ const jsxNode = node;
284
+ if (replaceNodeWithNull(parentPath.node, jsxNode)) {
285
+ return;
286
+ }
287
+ // Recast can replace this node in arbitrary parent contexts.
288
+ jsxPath.replace(b.nullLiteral());
289
+ };
290
+ exports.deleteJsxElementAtPath = deleteJsxElementAtPath;
291
+ const deleteJsxNode = async ({ input, nodePath, prettierConfigOverride, }) => {
292
+ var _a, _b;
293
+ var _c, _d;
294
+ const ast = (0, parse_ast_1.parseAst)(input);
295
+ const jsxPath = (0, exports.findJsxElementPathForDeletion)(ast, nodePath);
296
+ if (!jsxPath) {
297
+ throw new Error('Could not find a JSX element at the specified location to delete');
298
+ }
299
+ const jsxElement = jsxPath.node;
300
+ const nodeLabel = (0, exports.getJsxElementTagLabel)(jsxElement);
301
+ const 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;
302
+ (0, exports.deleteJsxElementAtPath)(jsxPath);
303
+ const finalFile = (0, parse_ast_1.serializeAst)(ast);
304
+ let prettier = null;
305
+ try {
306
+ prettier = await Promise.resolve().then(() => __importStar(require('prettier')));
307
+ }
308
+ catch (_e) {
309
+ return {
310
+ output: finalFile,
311
+ formatted: false,
312
+ nodeLabel,
313
+ logLine,
314
+ };
315
+ }
316
+ const { format, resolveConfig, resolveConfigFile } = prettier;
317
+ let prettierConfig;
318
+ if (prettierConfigOverride !== undefined) {
319
+ prettierConfig = prettierConfigOverride;
320
+ }
321
+ else {
322
+ const configFilePath = await resolveConfigFile();
323
+ if (!configFilePath) {
324
+ return {
325
+ output: finalFile,
326
+ formatted: false,
327
+ nodeLabel,
328
+ logLine,
329
+ };
330
+ }
331
+ prettierConfig = await resolveConfig(configFilePath);
332
+ }
333
+ if (!prettierConfig) {
334
+ return {
335
+ output: finalFile,
336
+ formatted: false,
337
+ nodeLabel,
338
+ logLine,
339
+ };
340
+ }
341
+ const prettified = await format(finalFile, {
342
+ ...prettierConfig,
343
+ filepath: 'test.tsx',
344
+ plugins: [],
345
+ endOfLine: 'lf',
346
+ });
347
+ return {
348
+ output: prettified,
349
+ formatted: true,
350
+ nodeLabel,
351
+ logLine,
352
+ };
353
+ };
354
+ exports.deleteJsxNode = deleteJsxNode;
@@ -8,3 +8,8 @@ export declare const updateDefaultProps: ({ input, compositionId, newDefaultProp
8
8
  output: string;
9
9
  formatted: boolean;
10
10
  }>;
11
+ /** Line of the matching `<Composition>` / `<Still>` opening tag (for log links). */
12
+ export declare const getCompositionDefaultPropsLine: ({ input, compositionId, }: {
13
+ input: string;
14
+ compositionId: string;
15
+ }) => number;
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.updateDefaultProps = void 0;
36
+ exports.getCompositionDefaultPropsLine = exports.updateDefaultProps = void 0;
37
37
  const studio_shared_1 = require("@remotion/studio-shared");
38
38
  const recast = __importStar(require("recast"));
39
39
  const format_inline_content_1 = require("./format-inline-content");
@@ -169,3 +169,56 @@ const updateDefaultProps = async ({ input, compositionId, newDefaultProps, enumP
169
169
  return { output, formatted: didFormat };
170
170
  };
171
171
  exports.updateDefaultProps = updateDefaultProps;
172
+ /** Line of the matching `<Composition>` / `<Still>` opening tag (for log links). */
173
+ const getCompositionDefaultPropsLine = ({ input, compositionId, }) => {
174
+ const ast = (0, parse_ast_1.parseAst)(input);
175
+ let line = 1;
176
+ let found = false;
177
+ recast.types.visit(ast, {
178
+ visitJSXElement(path) {
179
+ var _a, _b, _c;
180
+ var _d, _e;
181
+ if (found) {
182
+ this.traverse(path);
183
+ return;
184
+ }
185
+ const { openingElement } = path.node;
186
+ const openingName = openingElement.name;
187
+ if (openingName.type !== 'JSXIdentifier' &&
188
+ openingName.type !== 'JSXNamespacedName') {
189
+ this.traverse(path);
190
+ return;
191
+ }
192
+ if (openingName.name !== 'Composition' && openingName.name !== 'Still') {
193
+ this.traverse(path);
194
+ return;
195
+ }
196
+ if (!((_a = openingElement.attributes) === null || _a === void 0 ? void 0 : _a.some((attr) => {
197
+ if (attr.type === 'JSXSpreadAttribute') {
198
+ return;
199
+ }
200
+ if (!attr.value) {
201
+ return;
202
+ }
203
+ if (attr.value.type === 'JSXElement') {
204
+ return;
205
+ }
206
+ if (attr.value.type === 'JSXExpressionContainer') {
207
+ return;
208
+ }
209
+ if (attr.value.type === 'JSXFragment') {
210
+ return;
211
+ }
212
+ return attr.name.name === 'id' && attr.value.value === compositionId;
213
+ }))) {
214
+ this.traverse(path);
215
+ return;
216
+ }
217
+ found = true;
218
+ line = (_e = (_d = (_b = openingElement.loc) === null || _b === void 0 ? void 0 : _b.start.line) !== null && _d !== void 0 ? _d : (_c = path.node.loc) === null || _c === void 0 ? void 0 : _c.start.line) !== null && _e !== void 0 ? _e : 1;
219
+ this.traverse(path);
220
+ },
221
+ });
222
+ return line;
223
+ };
224
+ exports.getCompositionDefaultPropsLine = getCompositionDefaultPropsLine;
@@ -10,4 +10,5 @@ export declare const updateSequenceProps: ({ input, nodePath, key, value, defaul
10
10
  output: string;
11
11
  oldValueString: string;
12
12
  formatted: boolean;
13
+ logLine: number;
13
14
  }>;
@@ -40,7 +40,8 @@ const parse_ast_1 = require("./parse-ast");
40
40
  const update_nested_prop_1 = require("./update-nested-prop");
41
41
  const b = recast.types.builders;
42
42
  const updateSequenceProps = async ({ input, nodePath, key, value, defaultValue, prettierConfigOverride, }) => {
43
- var _a, _b;
43
+ var _a, _b, _c;
44
+ var _d;
44
45
  const ast = (0, parse_ast_1.parseAst)(input);
45
46
  let oldValueString = '';
46
47
  const isDefault = defaultValue !== null &&
@@ -53,6 +54,7 @@ const updateSequenceProps = async ({ input, nodePath, key, value, defaultValue,
53
54
  if (!node) {
54
55
  throw new Error('Could not find a JSX element at the specified line to update');
55
56
  }
57
+ const logLine = (_d = (_a = node.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _d !== void 0 ? _d : 1;
56
58
  if (isNested) {
57
59
  oldValueString = (0, update_nested_prop_1.updateNestedProp)({
58
60
  node,
@@ -64,7 +66,7 @@ const updateSequenceProps = async ({ input, nodePath, key, value, defaultValue,
64
66
  });
65
67
  }
66
68
  else {
67
- const attrIndex = (_a = node.attributes) === null || _a === void 0 ? void 0 : _a.findIndex((a) => {
69
+ const attrIndex = (_b = node.attributes) === null || _b === void 0 ? void 0 : _b.findIndex((a) => {
68
70
  if (a.type === 'JSXSpreadAttribute') {
69
71
  return false;
70
72
  }
@@ -74,7 +76,7 @@ const updateSequenceProps = async ({ input, nodePath, key, value, defaultValue,
74
76
  return a.name.name === key;
75
77
  });
76
78
  const attr = attrIndex !== undefined && attrIndex !== -1
77
- ? (_b = node.attributes) === null || _b === void 0 ? void 0 : _b[attrIndex]
79
+ ? (_c = node.attributes) === null || _c === void 0 ? void 0 : _c[attrIndex]
78
80
  : undefined;
79
81
  if (attr && attr.type !== 'JSXSpreadAttribute' && attr.value) {
80
82
  const printed = recast.print(attr.value).code;
@@ -116,11 +118,12 @@ const updateSequenceProps = async ({ input, nodePath, key, value, defaultValue,
116
118
  try {
117
119
  prettier = await Promise.resolve().then(() => __importStar(require('prettier')));
118
120
  }
119
- catch (_c) {
121
+ catch (_e) {
120
122
  return {
121
123
  output: finalFile,
122
124
  oldValueString,
123
125
  formatted: false,
126
+ logLine,
124
127
  };
125
128
  }
126
129
  const { format, resolveConfig, resolveConfigFile } = prettier;
@@ -135,6 +138,7 @@ const updateSequenceProps = async ({ input, nodePath, key, value, defaultValue,
135
138
  output: finalFile,
136
139
  oldValueString,
137
140
  formatted: false,
141
+ logLine,
138
142
  };
139
143
  }
140
144
  prettierConfig = await resolveConfig(configFilePath);
@@ -144,6 +148,7 @@ const updateSequenceProps = async ({ input, nodePath, key, value, defaultValue,
144
148
  output: finalFile,
145
149
  oldValueString,
146
150
  formatted: false,
151
+ logLine,
147
152
  };
148
153
  }
149
154
  const prettified = await format(finalFile, {
@@ -156,6 +161,7 @@ const updateSequenceProps = async ({ input, nodePath, key, value, defaultValue,
156
161
  output: prettified,
157
162
  oldValueString,
158
163
  formatted: true,
164
+ logLine,
159
165
  };
160
166
  };
161
167
  exports.updateSequenceProps = updateSequenceProps;
@@ -5,6 +5,7 @@ const add_render_1 = require("./routes/add-render");
5
5
  const apply_codemod_1 = require("./routes/apply-codemod");
6
6
  const apply_visual_control_change_1 = require("./routes/apply-visual-control-change");
7
7
  const cancel_render_1 = require("./routes/cancel-render");
8
+ const delete_jsx_node_1 = require("./routes/delete-jsx-node");
8
9
  const delete_static_file_1 = require("./routes/delete-static-file");
9
10
  const install_dependency_1 = require("./routes/install-dependency");
10
11
  const open_in_file_explorer_1 = require("./routes/open-in-file-explorer");
@@ -37,6 +38,7 @@ exports.allApiRoutes = {
37
38
  '/api/subscribe-to-sequence-props': subscribe_to_sequence_props_1.subscribeToSequenceProps,
38
39
  '/api/unsubscribe-from-sequence-props': unsubscribe_from_sequence_props_1.unsubscribeFromSequenceProps,
39
40
  '/api/save-sequence-props': save_sequence_props_1.saveSequencePropsHandler,
41
+ '/api/delete-jsx-node': delete_jsx_node_1.deleteJsxNodeHandler,
40
42
  '/api/update-available': update_available_1.handleUpdate,
41
43
  '/api/project-info': project_info_1.projectInfoHandler,
42
44
  '/api/delete-static-file': delete_static_file_1.deleteStaticFileHandler,
@@ -0,0 +1,5 @@
1
+ export declare const formatLogFileLocation: ({ remotionRoot, absolutePath, line, }: {
2
+ remotionRoot: string;
3
+ absolutePath: string;
4
+ line: number;
5
+ }) => string;
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.formatLogFileLocation = void 0;
7
+ const node_path_1 = __importDefault(require("node:path"));
8
+ const formatLogFileLocation = ({ remotionRoot, absolutePath, line, }) => {
9
+ return `${node_path_1.default.relative(remotionRoot, absolutePath)}:${line}`;
10
+ };
11
+ exports.formatLogFileLocation = formatLogFileLocation;
@@ -40,14 +40,35 @@ exports.applyVisualControlHandler = void 0;
40
40
  const node_fs_1 = require("node:fs");
41
41
  const node_path_1 = __importDefault(require("node:path"));
42
42
  const renderer_1 = require("@remotion/renderer");
43
+ const recast = __importStar(require("recast"));
43
44
  const parse_ast_1 = require("../../codemods/parse-ast");
44
45
  const recast_mods_1 = require("../../codemods/recast-mods");
45
46
  const file_watcher_1 = require("../../file-watcher");
46
- const make_link_1 = require("../../hyperlinks/make-link");
47
+ const format_log_file_location_1 = require("../format-log-file-location");
47
48
  const live_events_1 = require("../live-events");
48
49
  const undo_stack_1 = require("../undo-stack");
49
50
  const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
50
51
  const log_update_1 = require("./log-update");
52
+ const getVisualControlChangeLine = (file, changeId) => {
53
+ let line = 1;
54
+ recast.types.visit(file.program, {
55
+ visitCallExpression(callPath) {
56
+ var _a;
57
+ var _b;
58
+ const { node } = callPath;
59
+ if (node.callee.type === 'Identifier' &&
60
+ node.callee.name === 'visualControl') {
61
+ const firstArg = node.arguments[0];
62
+ if ((firstArg === null || firstArg === void 0 ? void 0 : firstArg.type) === 'StringLiteral' && firstArg.value === changeId) {
63
+ line = (_b = (_a = node.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== null && _b !== void 0 ? _b : 1;
64
+ return false;
65
+ }
66
+ }
67
+ this.traverse(callPath);
68
+ },
69
+ });
70
+ return line;
71
+ };
51
72
  const applyVisualControlHandler = async ({ input: { fileName, changes }, remotionRoot, logLevel }) => {
52
73
  renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[apply-visual-control] Received request for ${fileName} with ${changes.length} changes`);
53
74
  const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
@@ -57,6 +78,7 @@ const applyVisualControlHandler = async ({ input: { fileName, changes }, remotio
57
78
  }
58
79
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
59
80
  const ast = (0, parse_ast_1.parseAst)(fileContents);
81
+ const logLine = changes.length > 0 ? getVisualControlChangeLine(ast, changes[0].id) : 1;
60
82
  const { newAst, changesMade } = (0, recast_mods_1.applyCodemod)({
61
83
  file: ast,
62
84
  codeMod: {
@@ -94,11 +116,13 @@ const applyVisualControlHandler = async ({ input: { fileName, changes }, remotio
94
116
  oldContents: fileContents,
95
117
  logLevel,
96
118
  remotionRoot,
119
+ logLine,
97
120
  description: {
98
121
  undoMessage: 'Undid visual control change',
99
122
  redoMessage: 'Redid visual control change',
100
123
  },
101
124
  entryType: 'visual-control',
125
+ suppressHmrOnFileRestore: true,
102
126
  });
103
127
  (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
104
128
  (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
@@ -115,13 +139,12 @@ const applyVisualControlHandler = async ({ input: { fileName, changes }, remotio
115
139
  })),
116
140
  });
117
141
  });
118
- const locationLabel = `${fileRelativeToRoot}`;
119
- const fileLink = (0, make_link_1.makeHyperlink)({
120
- url: `file://${absolutePath}`,
121
- text: locationLabel,
122
- fallback: locationLabel,
142
+ const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
143
+ remotionRoot,
144
+ absolutePath,
145
+ line: logLine,
123
146
  });
124
- renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${fileLink}:`)} Applied visual control changes`);
147
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}:`)} Applied visual control changes`);
125
148
  if (!formatted) {
126
149
  (0, log_update_1.warnAboutPrettierOnce)(logLevel);
127
150
  }
@@ -0,0 +1,3 @@
1
+ import type { DeleteJsxNodeRequest, DeleteJsxNodeResponse } from '@remotion/studio-shared';
2
+ import type { ApiHandler } from '../api-types';
3
+ export declare const deleteJsxNodeHandler: ApiHandler<DeleteJsxNodeRequest, DeleteJsxNodeResponse>;
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.deleteJsxNodeHandler = void 0;
7
+ const node_fs_1 = require("node:fs");
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const renderer_1 = require("@remotion/renderer");
10
+ const delete_jsx_node_1 = require("../../codemods/delete-jsx-node");
11
+ const file_watcher_1 = require("../../file-watcher");
12
+ const format_log_file_location_1 = require("../format-log-file-location");
13
+ const undo_stack_1 = require("../undo-stack");
14
+ const log_update_1 = require("./log-update");
15
+ const deleteJsxNodeHandler = async ({ input: { fileName, nodePath }, remotionRoot, logLevel }) => {
16
+ try {
17
+ renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[delete-jsx-node] Received request for fileName="${fileName}"`);
18
+ const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
19
+ const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
20
+ if (fileRelativeToRoot.startsWith('..')) {
21
+ throw new Error('Cannot modify a file outside the project');
22
+ }
23
+ const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
24
+ const { output, formatted, nodeLabel, logLine } = await (0, delete_jsx_node_1.deleteJsxNode)({
25
+ input: fileContents,
26
+ nodePath,
27
+ });
28
+ (0, undo_stack_1.pushToUndoStack)({
29
+ filePath: absolutePath,
30
+ oldContents: fileContents,
31
+ logLevel,
32
+ remotionRoot,
33
+ logLine,
34
+ description: {
35
+ undoMessage: `Undid deletion of ${nodeLabel}`,
36
+ redoMessage: `Redid deletion of ${nodeLabel}`,
37
+ },
38
+ entryType: 'delete-jsx-node',
39
+ suppressHmrOnFileRestore: false,
40
+ });
41
+ (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
42
+ (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output);
43
+ const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
44
+ remotionRoot,
45
+ absolutePath,
46
+ line: logLine,
47
+ });
48
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}:`)} Deleted ${nodeLabel}`);
49
+ if (!formatted) {
50
+ (0, log_update_1.warnAboutPrettierOnce)(logLevel);
51
+ }
52
+ renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[delete-jsx-node] Wrote ${fileRelativeToRoot}${formatted ? ' (formatted)' : ''}`);
53
+ (0, undo_stack_1.printUndoHint)(logLevel);
54
+ return {
55
+ success: true,
56
+ };
57
+ }
58
+ catch (err) {
59
+ return {
60
+ success: false,
61
+ reason: err.message,
62
+ stack: err.stack,
63
+ };
64
+ }
65
+ };
66
+ exports.deleteJsxNodeHandler = deleteJsxNodeHandler;
@@ -6,9 +6,9 @@ export declare const formatPropChange: ({ key, oldValueString, newValueString, d
6
6
  newValueString: string;
7
7
  defaultValueString: string | null;
8
8
  }) => string;
9
- export declare const logUpdate: ({ absolutePath, fileRelativeToRoot, key, oldValueString, newValueString, defaultValueString, formatted, logLevel, }: {
10
- absolutePath: string;
9
+ export declare const logUpdate: ({ fileRelativeToRoot, line, key, oldValueString, newValueString, defaultValueString, formatted, logLevel, }: {
11
10
  fileRelativeToRoot: string;
11
+ line: number;
12
12
  key: string;
13
13
  oldValueString: string;
14
14
  newValueString: string;
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.logUpdate = exports.formatPropChange = exports.normalizeQuotes = exports.warnAboutPrettierOnce = void 0;
4
4
  const renderer_1 = require("@remotion/renderer");
5
- const make_link_1 = require("../../hyperlinks/make-link");
6
5
  let warnedAboutPrettier = false;
7
6
  const warnAboutPrettierOnce = (logLevel) => {
8
7
  if (warnedAboutPrettier) {
@@ -85,20 +84,15 @@ const formatPropChange = ({ key, oldValueString, newValueString, defaultValueStr
85
84
  return `${removedBg(formatNestedProp(parentKey, childKey, oldValueString))} \u2192 ${addedBg(formatNestedProp(parentKey, childKey, newValueString))}`;
86
85
  };
87
86
  exports.formatPropChange = formatPropChange;
88
- const logUpdate = ({ absolutePath, fileRelativeToRoot, key, oldValueString, newValueString, defaultValueString, formatted, logLevel, }) => {
89
- const locationLabel = `${fileRelativeToRoot}`;
90
- const fileLink = (0, make_link_1.makeHyperlink)({
91
- url: `file://${absolutePath}`,
92
- text: locationLabel,
93
- fallback: locationLabel,
94
- });
87
+ const logUpdate = ({ fileRelativeToRoot, line, key, oldValueString, newValueString, defaultValueString, formatted, logLevel, }) => {
88
+ const locationLabel = `${fileRelativeToRoot}:${line}`;
95
89
  const propChange = (0, exports.formatPropChange)({
96
90
  key,
97
91
  oldValueString: (0, exports.normalizeQuotes)(oldValueString),
98
92
  newValueString: (0, exports.normalizeQuotes)(newValueString),
99
93
  defaultValueString: defaultValueString !== null ? (0, exports.normalizeQuotes)(defaultValueString) : null,
100
94
  });
101
- renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${fileLink}:`)} ${propChange}`);
95
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}:`)} ${propChange}`);
102
96
  if (!formatted) {
103
97
  (0, exports.warnAboutPrettierOnce)(logLevel);
104
98
  }
@@ -22,7 +22,7 @@ const saveSequencePropsHandler = async ({ input: { fileName, nodePath, key, valu
22
22
  throw new Error('Cannot modify a file outside the project');
23
23
  }
24
24
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
25
- const { output, oldValueString, formatted } = await (0, update_sequence_props_1.updateSequenceProps)({
25
+ const { output, oldValueString, formatted, logLine } = await (0, update_sequence_props_1.updateSequenceProps)({
26
26
  input: fileContents,
27
27
  nodePath,
28
28
  key,
@@ -52,18 +52,20 @@ const saveSequencePropsHandler = async ({ input: { fileName, nodePath, key, valu
52
52
  oldContents: fileContents,
53
53
  logLevel,
54
54
  remotionRoot,
55
+ logLine,
55
56
  description: {
56
57
  undoMessage: `Undid ${undoPropChange}`,
57
58
  redoMessage: `Redid ${redoPropChange}`,
58
59
  },
59
60
  entryType: 'sequence-props',
61
+ suppressHmrOnFileRestore: true,
60
62
  });
61
63
  (0, undo_stack_1.suppressUndoStackInvalidation)(absolutePath);
62
64
  (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(absolutePath);
63
65
  (0, file_watcher_1.writeFileAndNotifyFileWatchers)(absolutePath, output);
64
66
  (0, log_update_1.logUpdate)({
65
- absolutePath,
66
67
  fileRelativeToRoot,
68
+ line: logLine,
67
69
  key,
68
70
  oldValueString,
69
71
  newValueString,
@@ -1,15 +1,11 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.updateDefaultPropsHandler = void 0;
7
4
  const node_fs_1 = require("node:fs");
8
- const node_path_1 = __importDefault(require("node:path"));
9
5
  const renderer_1 = require("@remotion/renderer");
10
6
  const update_default_props_1 = require("../../codemods/update-default-props");
11
7
  const file_watcher_1 = require("../../file-watcher");
12
- const make_link_1 = require("../../hyperlinks/make-link");
8
+ const format_log_file_location_1 = require("../format-log-file-location");
13
9
  const project_info_1 = require("../project-info");
14
10
  const undo_stack_1 = require("../undo-stack");
15
11
  const watch_ignore_next_change_1 = require("../watch-ignore-next-change");
@@ -24,6 +20,10 @@ const updateDefaultPropsHandler = async ({ input: { compositionId, defaultProps,
24
20
  }
25
21
  (0, can_update_default_props_1.checkIfTypeScriptFile)(projectInfo.rootFile);
26
22
  const fileContents = (0, node_fs_1.readFileSync)(projectInfo.rootFile, 'utf-8');
23
+ const logLine = (0, update_default_props_1.getCompositionDefaultPropsLine)({
24
+ input: fileContents,
25
+ compositionId,
26
+ });
27
27
  const { output, formatted } = await (0, update_default_props_1.updateDefaultProps)({
28
28
  compositionId,
29
29
  input: fileContents,
@@ -35,23 +35,23 @@ const updateDefaultPropsHandler = async ({ input: { compositionId, defaultProps,
35
35
  oldContents: fileContents,
36
36
  logLevel,
37
37
  remotionRoot,
38
+ logLine,
38
39
  description: {
39
40
  undoMessage: `Undid default props update for "${compositionId}"`,
40
41
  redoMessage: `Redid default props update for "${compositionId}"`,
41
42
  },
42
43
  entryType: 'default-props',
44
+ suppressHmrOnFileRestore: true,
43
45
  });
44
46
  (0, undo_stack_1.suppressUndoStackInvalidation)(projectInfo.rootFile);
45
47
  (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(projectInfo.rootFile);
46
48
  (0, file_watcher_1.writeFileAndNotifyFileWatchers)(projectInfo.rootFile, output);
47
- const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, projectInfo.rootFile);
48
- const locationLabel = `${fileRelativeToRoot}`;
49
- const fileLink = (0, make_link_1.makeHyperlink)({
50
- url: `file://${projectInfo.rootFile}`,
51
- text: locationLabel,
52
- fallback: locationLabel,
49
+ const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
50
+ remotionRoot,
51
+ absolutePath: projectInfo.rootFile,
52
+ line: logLine,
53
53
  });
54
- renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${fileLink}:`)} Updated default props for "${compositionId}"`);
54
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}:`)} Updated default props for "${compositionId}"`);
55
55
  if (!formatted) {
56
56
  (0, log_update_1.warnAboutPrettierOnce)(logLevel);
57
57
  }
@@ -3,28 +3,43 @@ export interface UndoEntryDescription {
3
3
  undoMessage: string;
4
4
  redoMessage: string;
5
5
  }
6
- type UndoEntryType = 'visual-control' | 'default-props' | 'sequence-props';
6
+ type UndoEntryType = 'visual-control' | 'default-props' | 'sequence-props' | 'delete-jsx-node';
7
7
  type UndoEntry = {
8
8
  filePath: string;
9
9
  oldContents: string;
10
+ /** 1-based source line for terminal/IDE file links (e.g. path:line). */
11
+ logLine: number;
10
12
  description: UndoEntryDescription;
13
+ /** When true, undo/redo file restores call `suppressBundlerUpdateForFile` (skip HMR refresh). */
14
+ suppressHmrOnFileRestore: boolean;
11
15
  } & ({
12
16
  entryType: 'visual-control';
13
17
  } | {
14
18
  entryType: 'default-props';
15
19
  } | {
16
20
  entryType: 'sequence-props';
21
+ } | {
22
+ entryType: 'delete-jsx-node';
17
23
  });
18
- export declare function pushToUndoStack({ filePath, oldContents, logLevel, remotionRoot, description, entryType }: {
24
+ export declare function pushToUndoStack({ filePath, oldContents, logLevel, remotionRoot, logLine, description, entryType, suppressHmrOnFileRestore }: {
19
25
  filePath: string;
20
26
  oldContents: string;
21
27
  logLevel: LogLevel;
22
28
  remotionRoot: string;
29
+ logLine: number;
23
30
  description: UndoEntryDescription;
24
31
  entryType: UndoEntryType;
32
+ suppressHmrOnFileRestore: boolean;
25
33
  }): void;
26
34
  export declare function printUndoHint(logLevel: LogLevel): void;
27
- export declare function pushToRedoStack(filePath: string, oldContents: string, description: UndoEntryDescription, entryType: UndoEntryType): void;
35
+ export declare function pushToRedoStack({ filePath, oldContents, logLine, description, entryType, suppressHmrOnFileRestore }: {
36
+ filePath: string;
37
+ oldContents: string;
38
+ logLine: number;
39
+ description: UndoEntryDescription;
40
+ entryType: UndoEntryType;
41
+ suppressHmrOnFileRestore: boolean;
42
+ }): void;
28
43
  export declare function suppressUndoStackInvalidation(filePath: string): void;
29
44
  export declare function popUndo(): {
30
45
  success: true;
@@ -1,7 +1,4 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.pushToUndoStack = pushToUndoStack;
7
4
  exports.printUndoHint = printUndoHint;
@@ -12,12 +9,11 @@ exports.popRedo = popRedo;
12
9
  exports.getUndoStack = getUndoStack;
13
10
  exports.getRedoStack = getRedoStack;
14
11
  const node_fs_1 = require("node:fs");
15
- const node_path_1 = __importDefault(require("node:path"));
16
12
  const renderer_1 = require("@remotion/renderer");
17
13
  const parse_ast_1 = require("../codemods/parse-ast");
18
14
  const read_visual_control_values_1 = require("../codemods/read-visual-control-values");
19
15
  const file_watcher_1 = require("../file-watcher");
20
- const make_link_1 = require("../hyperlinks/make-link");
16
+ const format_log_file_location_1 = require("./format-log-file-location");
21
17
  const live_events_1 = require("./live-events");
22
18
  const watch_ignore_next_change_1 = require("./watch-ignore-next-change");
23
19
  const MAX_ENTRIES = 100;
@@ -39,10 +35,17 @@ function broadcastState() {
39
35
  });
40
36
  });
41
37
  }
42
- function pushToUndoStack({ filePath, oldContents, logLevel, remotionRoot, description, entryType, }) {
38
+ function pushToUndoStack({ filePath, oldContents, logLevel, remotionRoot, logLine, description, entryType, suppressHmrOnFileRestore, }) {
43
39
  storedLogLevel = logLevel;
44
40
  storedRemotionRoot = remotionRoot;
45
- undoStack.push({ filePath, oldContents, description, entryType });
41
+ undoStack.push({
42
+ filePath,
43
+ oldContents,
44
+ logLine,
45
+ description,
46
+ entryType,
47
+ suppressHmrOnFileRestore,
48
+ });
46
49
  if (undoStack.length > MAX_ENTRIES) {
47
50
  undoStack.shift();
48
51
  }
@@ -58,8 +61,15 @@ function printUndoHint(logLevel) {
58
61
  renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.gray(`Tip: ${shortcut} in Studio to undo`));
59
62
  }
60
63
  }
61
- function pushToRedoStack(filePath, oldContents, description, entryType) {
62
- redoStack.push({ filePath, oldContents, description, entryType });
64
+ function pushToRedoStack({ filePath, oldContents, logLine, description, entryType, suppressHmrOnFileRestore, }) {
65
+ redoStack.push({
66
+ filePath,
67
+ oldContents,
68
+ logLine,
69
+ description,
70
+ entryType,
71
+ suppressHmrOnFileRestore,
72
+ });
63
73
  if (redoStack.length > MAX_ENTRIES) {
64
74
  redoStack.shift();
65
75
  }
@@ -156,16 +166,15 @@ function emitVisualControlChanges(fileContents) {
156
166
  // File might not contain visual controls or might not be parseable
157
167
  }
158
168
  }
159
- function logFileAction(action, filePath) {
160
- const locationLabel = storedRemotionRoot
161
- ? node_path_1.default.relative(storedRemotionRoot, filePath)
162
- : filePath;
163
- const fileLink = (0, make_link_1.makeHyperlink)({
164
- url: `file://${filePath}`,
165
- text: locationLabel,
166
- fallback: locationLabel,
167
- });
168
- renderer_1.RenderInternals.Log.info({ indent: false, logLevel: storedLogLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${fileLink}:`)} ${action}`);
169
+ function logFileAction(action, filePath, logLine) {
170
+ const locationLabel = storedRemotionRoot !== null
171
+ ? (0, format_log_file_location_1.formatLogFileLocation)({
172
+ remotionRoot: storedRemotionRoot,
173
+ absolutePath: filePath,
174
+ line: logLine,
175
+ })
176
+ : `${filePath}:${logLine}`;
177
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel: storedLogLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}:`)} ${action}`);
169
178
  }
170
179
  function popUndo() {
171
180
  const entry = undoStack.pop();
@@ -176,14 +185,18 @@ function popUndo() {
176
185
  redoStack.push({
177
186
  filePath: entry.filePath,
178
187
  oldContents: currentContents,
188
+ logLine: entry.logLine,
179
189
  description: entry.description,
180
190
  entryType: entry.entryType,
191
+ suppressHmrOnFileRestore: entry.suppressHmrOnFileRestore,
181
192
  });
182
193
  suppressUndoStackInvalidation(entry.filePath);
183
- (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(entry.filePath);
194
+ if (entry.suppressHmrOnFileRestore) {
195
+ (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(entry.filePath);
196
+ }
184
197
  (0, file_watcher_1.writeFileAndNotifyFileWatchers)(entry.filePath, entry.oldContents);
185
198
  renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel: storedLogLevel }, renderer_1.RenderInternals.chalk.gray(`Undo: restored ${entry.filePath} (undo: ${undoStack.length}, redo: ${redoStack.length})`));
186
- logFileAction(entry.description.undoMessage, entry.filePath);
199
+ logFileAction(entry.description.undoMessage, entry.filePath, entry.logLine);
187
200
  if (entry.entryType === 'visual-control') {
188
201
  emitVisualControlChanges(entry.oldContents);
189
202
  }
@@ -200,14 +213,18 @@ function popRedo() {
200
213
  undoStack.push({
201
214
  filePath: entry.filePath,
202
215
  oldContents: currentContents,
216
+ logLine: entry.logLine,
203
217
  description: entry.description,
204
218
  entryType: entry.entryType,
219
+ suppressHmrOnFileRestore: entry.suppressHmrOnFileRestore,
205
220
  });
206
221
  suppressUndoStackInvalidation(entry.filePath);
207
- (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(entry.filePath);
222
+ if (entry.suppressHmrOnFileRestore) {
223
+ (0, watch_ignore_next_change_1.suppressBundlerUpdateForFile)(entry.filePath);
224
+ }
208
225
  (0, file_watcher_1.writeFileAndNotifyFileWatchers)(entry.filePath, entry.oldContents);
209
226
  renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel: storedLogLevel }, renderer_1.RenderInternals.chalk.gray(`Redo: restored ${entry.filePath} (undo: ${undoStack.length}, redo: ${redoStack.length})`));
210
- logFileAction(entry.description.redoMessage, entry.filePath);
227
+ logFileAction(entry.description.redoMessage, entry.filePath, entry.logLine);
211
228
  if (entry.entryType === 'visual-control') {
212
229
  emitVisualControlChanges(entry.oldContents);
213
230
  }
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/studio-server"
4
4
  },
5
5
  "name": "@remotion/studio-server",
6
- "version": "4.0.443",
6
+ "version": "4.0.445",
7
7
  "description": "Run a Remotion Studio with a server backend",
8
8
  "main": "dist",
9
9
  "sideEffects": false,
@@ -27,11 +27,11 @@
27
27
  "@babel/parser": "7.24.1",
28
28
  "semver": "7.5.3",
29
29
  "prettier": "3.8.1",
30
- "remotion": "4.0.443",
30
+ "remotion": "4.0.445",
31
31
  "recast": "0.23.11",
32
- "@remotion/bundler": "4.0.443",
33
- "@remotion/renderer": "4.0.443",
34
- "@remotion/studio-shared": "4.0.443",
32
+ "@remotion/bundler": "4.0.445",
33
+ "@remotion/renderer": "4.0.445",
34
+ "@remotion/studio-shared": "4.0.445",
35
35
  "memfs": "3.4.3",
36
36
  "source-map": "0.7.3",
37
37
  "open": "^8.4.2"
@@ -41,7 +41,7 @@
41
41
  "react": "19.2.3",
42
42
  "@babel/types": "7.24.0",
43
43
  "@types/semver": "^7.3.4",
44
- "@remotion/eslint-config-internal": "4.0.443",
44
+ "@remotion/eslint-config-internal": "4.0.445",
45
45
  "eslint": "9.19.0",
46
46
  "@types/node": "20.12.14",
47
47
  "@typescript/native-preview": "7.0.0-dev.20260217.1"