@remotion/studio-server 4.0.529 → 4.0.530
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-composition-to-file.d.ts +7 -0
- package/dist/codemods/add-composition-to-file.js +63 -0
- package/dist/codemods/apply-codemod-to-file.js +6 -1
- package/dist/codemods/update-keyframes/update-keyframes.d.ts +3 -3
- package/dist/codemods/update-keyframes/update-keyframes.js +1 -1
- package/dist/codemods/update-sequence-props/update-sequence-props.js +1 -1
- package/dist/helpers/get-local-package-override.d.ts +5 -0
- package/dist/helpers/get-local-package-override.js +39 -0
- package/dist/helpers/resolve-composition-component.d.ts +2 -1
- package/dist/helpers/resolve-composition-component.js +66 -15
- package/dist/index.d.ts +5 -0
- package/dist/index.js +3 -0
- package/dist/preview-server/api-routes.js +32 -12
- package/dist/preview-server/element-install-state.js +10 -2
- package/dist/preview-server/routes/add-composition.d.ts +3 -0
- package/dist/preview-server/routes/add-composition.js +97 -0
- package/dist/preview-server/routes/add-folder.d.ts +3 -0
- package/dist/preview-server/routes/add-folder.js +107 -0
- package/dist/preview-server/routes/add-keyframes.d.ts +2 -2
- package/dist/preview-server/routes/add-keyframes.js +49 -6
- package/dist/preview-server/routes/can-update-sequence-props.js +27 -5
- package/dist/preview-server/routes/delete-composition.d.ts +3 -0
- package/dist/preview-server/routes/delete-composition.js +104 -0
- package/dist/preview-server/routes/delete-nodes.d.ts +3 -0
- package/dist/preview-server/routes/delete-nodes.js +142 -0
- package/dist/preview-server/routes/duplicate-composition.d.ts +3 -0
- package/dist/preview-server/routes/duplicate-composition.js +114 -0
- package/dist/preview-server/routes/duplicate-nodes.d.ts +3 -0
- package/dist/preview-server/routes/duplicate-nodes.js +123 -0
- package/dist/preview-server/routes/insert-basic-captions.js +2 -1
- package/dist/preview-server/routes/insert-composition-element.d.ts +3 -0
- package/dist/preview-server/routes/insert-composition-element.js +236 -0
- package/dist/preview-server/routes/insert-element.js +26 -19
- package/dist/preview-server/routes/install-dependency.js +10 -1
- package/dist/preview-server/routes/move-composition.d.ts +3 -0
- package/dist/preview-server/routes/move-composition.js +148 -0
- package/dist/preview-server/routes/move-folder.d.ts +3 -0
- package/dist/preview-server/routes/move-folder.js +151 -0
- package/dist/preview-server/routes/precompose-jsx-nodes.d.ts +3 -0
- package/dist/preview-server/routes/precompose-jsx-nodes.js +209 -0
- package/dist/preview-server/routes/rename-composition.d.ts +3 -0
- package/dist/preview-server/routes/rename-composition.js +105 -0
- package/dist/preview-server/routes/rename-folder.d.ts +3 -0
- package/dist/preview-server/routes/rename-folder.js +111 -0
- package/dist/preview-server/routes/reorder-sequence.js +7 -2
- package/dist/preview-server/routes/replace-video-source.js +7 -2
- package/dist/preview-server/routes/save-sequence-props.js +6 -3
- package/dist/preview-server/routes/split-sequences.d.ts +3 -0
- package/dist/preview-server/routes/split-sequences.js +122 -0
- package/dist/preview-server/routes/split-video-from-audio.js +6 -1
- package/dist/preview-server/routes/unwrap-folder.d.ts +3 -0
- package/dist/preview-server/routes/unwrap-folder.js +107 -0
- package/dist/preview-server/routes/update-composition-metadata.d.ts +3 -0
- package/dist/preview-server/routes/update-composition-metadata.js +110 -0
- package/dist/preview-server/routes/wrap-node.d.ts +3 -0
- package/dist/preview-server/routes/wrap-node.js +108 -0
- package/dist/preview-server/studio-protocol/handle-discovery.js +3 -10
- package/dist/preview-server/studio-protocol/handle-install.js +0 -3
- package/dist/preview-server/undo-stack.d.ts +1 -1
- package/dist/preview-server/undo-stack.js +6 -0
- package/dist/start-studio.js +1 -1
- package/package.json +8 -8
|
@@ -0,0 +1,114 @@
|
|
|
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.duplicateCompositionHandler = void 0;
|
|
7
|
+
const node_fs_1 = require("node:fs");
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const codemods_1 = require("@remotion/codemods");
|
|
10
|
+
const renderer_1 = require("@remotion/renderer");
|
|
11
|
+
const file_watcher_1 = require("../../file-watcher");
|
|
12
|
+
const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
|
|
13
|
+
const format_log_file_location_1 = require("../format-log-file-location");
|
|
14
|
+
const project_info_1 = require("../project-info");
|
|
15
|
+
const undo_stack_1 = require("../undo-stack");
|
|
16
|
+
const can_update_default_props_1 = require("./can-update-default-props");
|
|
17
|
+
const source_file_write_queue_1 = require("./source-file-write-queue");
|
|
18
|
+
const duplicateCompositionHandler = ({ input: request, logLevel, remotionRoot, entryPoint }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
|
|
19
|
+
var _a, _b;
|
|
20
|
+
var _c, _d, _e, _f, _g, _h;
|
|
21
|
+
try {
|
|
22
|
+
let filePath;
|
|
23
|
+
if ((_a = request.symbolicatedStack) === null || _a === void 0 ? void 0 : _a.originalFileName) {
|
|
24
|
+
filePath = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
|
|
25
|
+
remotionRoot,
|
|
26
|
+
fileName: request.symbolicatedStack.originalFileName,
|
|
27
|
+
action: 'duplicate a composition in',
|
|
28
|
+
}).absolutePath;
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
const { rootFile } = await (0, project_info_1.getProjectInfo)(remotionRoot, entryPoint);
|
|
32
|
+
if (rootFile === null) {
|
|
33
|
+
throw new Error('Cannot find the Remotion root file');
|
|
34
|
+
}
|
|
35
|
+
filePath = rootFile;
|
|
36
|
+
}
|
|
37
|
+
(0, can_update_default_props_1.checkIfTypeScriptFile)(filePath);
|
|
38
|
+
const result = (0, codemods_1.duplicateComposition)({
|
|
39
|
+
project: {
|
|
40
|
+
files: { [filePath]: (0, node_fs_1.readFileSync)(filePath, 'utf-8') },
|
|
41
|
+
rootDir: node_path_1.default.dirname(filePath),
|
|
42
|
+
},
|
|
43
|
+
compositionFile: filePath,
|
|
44
|
+
compositionId: request.idToDuplicate,
|
|
45
|
+
newId: request.newId,
|
|
46
|
+
tag: request.tag,
|
|
47
|
+
metadata: {
|
|
48
|
+
width: (_c = request.newWidth) !== null && _c !== void 0 ? _c : undefined,
|
|
49
|
+
height: (_d = request.newHeight) !== null && _d !== void 0 ? _d : undefined,
|
|
50
|
+
fps: request.tag === 'Still' ? undefined : ((_e = request.newFps) !== null && _e !== void 0 ? _e : undefined),
|
|
51
|
+
durationInFrames: request.tag === 'Still'
|
|
52
|
+
? undefined
|
|
53
|
+
: ((_f = request.newDurationInFrames) !== null && _f !== void 0 ? _f : undefined),
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
for (const change of result.changes) {
|
|
57
|
+
const currentContents = (0, node_fs_1.existsSync)(change.filePath)
|
|
58
|
+
? (0, node_fs_1.readFileSync)(change.filePath, 'utf-8')
|
|
59
|
+
: null;
|
|
60
|
+
if (currentContents !== change.previousContents) {
|
|
61
|
+
throw new Error(`Source changed before duplicating composition: ${change.filePath}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (result.changes.length > 0) {
|
|
65
|
+
const logLine = (_g = (_b = request.symbolicatedStack) === null || _b === void 0 ? void 0 : _b.originalLineNumber) !== null && _g !== void 0 ? _g : 1;
|
|
66
|
+
(0, undo_stack_1.pushTransactionToUndoStack)({
|
|
67
|
+
snapshots: result.changes.map((change) => ({
|
|
68
|
+
filePath: change.filePath,
|
|
69
|
+
oldContents: change.previousContents,
|
|
70
|
+
newContents: change.nextContents,
|
|
71
|
+
logLine: change.filePath === filePath ? logLine : 1,
|
|
72
|
+
nodePathRemappings: null,
|
|
73
|
+
})),
|
|
74
|
+
logLevel,
|
|
75
|
+
remotionRoot,
|
|
76
|
+
description: {
|
|
77
|
+
undoMessage: `↩️ Duplication of composition "${request.idToDuplicate}" to "${request.newId}"`,
|
|
78
|
+
redoMessage: `↪️ Duplication of composition "${request.idToDuplicate}" to "${request.newId}"`,
|
|
79
|
+
},
|
|
80
|
+
entryType: 'duplicate-composition',
|
|
81
|
+
suppressHmrOnFileRestore: false,
|
|
82
|
+
undoRedoNavigation: request.undoRedoNavigation,
|
|
83
|
+
});
|
|
84
|
+
for (const change of result.changes) {
|
|
85
|
+
if (change.nextContents === null) {
|
|
86
|
+
throw new Error('Duplicating a composition cannot remove source files');
|
|
87
|
+
}
|
|
88
|
+
(0, undo_stack_1.suppressUndoStackInvalidation)(change.filePath);
|
|
89
|
+
(0, file_watcher_1.writeFileAndNotifyFileWatchers)({
|
|
90
|
+
file: change.filePath,
|
|
91
|
+
content: change.nextContents,
|
|
92
|
+
originatorClientId: undefined,
|
|
93
|
+
metadata: null,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
|
|
97
|
+
remotionRoot,
|
|
98
|
+
absolutePath: filePath,
|
|
99
|
+
line: logLine,
|
|
100
|
+
});
|
|
101
|
+
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright(locationLabel)} Duplicated composition "${request.idToDuplicate}" to "${request.newId}"`);
|
|
102
|
+
(0, undo_stack_1.printUndoHint)(logLevel);
|
|
103
|
+
}
|
|
104
|
+
return { success: true, nodePathMutation: null };
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
return {
|
|
108
|
+
success: false,
|
|
109
|
+
reason: error instanceof Error ? error.message : String(error),
|
|
110
|
+
stack: error instanceof Error ? ((_h = error.stack) !== null && _h !== void 0 ? _h : '') : '',
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
exports.duplicateCompositionHandler = duplicateCompositionHandler;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.duplicateNodesHandler = void 0;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const codemods_1 = require("@remotion/codemods");
|
|
6
|
+
const renderer_1 = require("@remotion/renderer");
|
|
7
|
+
const file_watcher_1 = require("../../file-watcher");
|
|
8
|
+
const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
|
|
9
|
+
const format_log_file_location_1 = require("../format-log-file-location");
|
|
10
|
+
const sequence_node_path_mutation_1 = require("../sequence-node-path-mutation");
|
|
11
|
+
const undo_stack_1 = require("../undo-stack");
|
|
12
|
+
const source_file_write_queue_1 = require("./source-file-write-queue");
|
|
13
|
+
const duplicateNodesHandler = ({ input: { nodes }, remotionRoot, logLevel }) => {
|
|
14
|
+
return (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
|
|
15
|
+
var _a;
|
|
16
|
+
try {
|
|
17
|
+
if (nodes.length === 0) {
|
|
18
|
+
throw new Error('No JSX nodes were specified for duplication');
|
|
19
|
+
}
|
|
20
|
+
renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[duplicate-nodes] Received request to duplicate ${nodes.length} JSX node${nodes.length === 1 ? '' : 's'}`);
|
|
21
|
+
const itemsByFileName = new Map();
|
|
22
|
+
for (const item of nodes) {
|
|
23
|
+
const fileItems = (_a = itemsByFileName.get(item.fileName)) !== null && _a !== void 0 ? _a : [];
|
|
24
|
+
fileItems.push(item);
|
|
25
|
+
itemsByFileName.set(item.fileName, fileItems);
|
|
26
|
+
}
|
|
27
|
+
const updates = await Promise.all([...itemsByFileName.entries()].map(async ([fileName, fileItems]) => {
|
|
28
|
+
var _a;
|
|
29
|
+
var _b;
|
|
30
|
+
const { absolutePath, fileRelativeToRoot } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
|
|
31
|
+
remotionRoot,
|
|
32
|
+
fileName,
|
|
33
|
+
action: 'modify',
|
|
34
|
+
});
|
|
35
|
+
const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
|
|
36
|
+
const result = await (0, codemods_1.duplicateNodes)({
|
|
37
|
+
project: {
|
|
38
|
+
files: { [absolutePath]: fileContents },
|
|
39
|
+
rootDir: remotionRoot,
|
|
40
|
+
},
|
|
41
|
+
nodes: fileItems.map((item) => ({
|
|
42
|
+
filePath: absolutePath,
|
|
43
|
+
nodePath: item.nodePath,
|
|
44
|
+
})),
|
|
45
|
+
});
|
|
46
|
+
const output = (_b = (_a = result.changes[0]) === null || _a === void 0 ? void 0 : _a.nextContents) !== null && _b !== void 0 ? _b : fileContents;
|
|
47
|
+
const { nodeLabels, logLines } = result.editDetails[0];
|
|
48
|
+
const nodePathRemappings = result.nodePathRemappings.map(({ oldNodePath, newNodePath, oldJsxName, newJsxName }) => ({
|
|
49
|
+
oldNodePath,
|
|
50
|
+
newNodePath,
|
|
51
|
+
oldJsxName,
|
|
52
|
+
newJsxName,
|
|
53
|
+
}));
|
|
54
|
+
return {
|
|
55
|
+
absolutePath,
|
|
56
|
+
fileRelativeToRoot,
|
|
57
|
+
fileContents,
|
|
58
|
+
logLine: Math.min(...logLines),
|
|
59
|
+
nodeLabels,
|
|
60
|
+
nodePathRemappings,
|
|
61
|
+
output,
|
|
62
|
+
};
|
|
63
|
+
}));
|
|
64
|
+
const nodePathMutation = (0, sequence_node_path_mutation_1.broadcastSequenceNodePathMutation)(updates.map((update) => ({
|
|
65
|
+
absolutePath: update.absolutePath,
|
|
66
|
+
remappings: update.nodePathRemappings,
|
|
67
|
+
})), null);
|
|
68
|
+
const duplicatedNodeDescription = nodes.length === 1
|
|
69
|
+
? updates[0].nodeLabels[0]
|
|
70
|
+
: `${nodes.length} JSX nodes`;
|
|
71
|
+
(0, undo_stack_1.pushTransactionToUndoStack)({
|
|
72
|
+
snapshots: updates.map((update) => ({
|
|
73
|
+
filePath: update.absolutePath,
|
|
74
|
+
oldContents: update.fileContents,
|
|
75
|
+
newContents: null,
|
|
76
|
+
logLine: update.logLine,
|
|
77
|
+
nodePathRemappings: update.nodePathRemappings,
|
|
78
|
+
})),
|
|
79
|
+
logLevel,
|
|
80
|
+
remotionRoot,
|
|
81
|
+
description: {
|
|
82
|
+
undoMessage: `↩️ Duplication of ${duplicatedNodeDescription}`,
|
|
83
|
+
redoMessage: `↪️ Duplication of ${duplicatedNodeDescription}`,
|
|
84
|
+
},
|
|
85
|
+
entryType: 'duplicate-nodes',
|
|
86
|
+
suppressHmrOnFileRestore: false,
|
|
87
|
+
undoRedoNavigation: null,
|
|
88
|
+
});
|
|
89
|
+
for (const update of updates) {
|
|
90
|
+
(0, undo_stack_1.suppressUndoStackInvalidation)(update.absolutePath);
|
|
91
|
+
(0, file_watcher_1.writeFileAndNotifyFileWatchers)({
|
|
92
|
+
file: update.absolutePath,
|
|
93
|
+
content: update.output,
|
|
94
|
+
originatorClientId: undefined,
|
|
95
|
+
metadata: { skipSequencePropsUpdate: true },
|
|
96
|
+
});
|
|
97
|
+
const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
|
|
98
|
+
remotionRoot,
|
|
99
|
+
absolutePath: update.absolutePath,
|
|
100
|
+
line: update.logLine,
|
|
101
|
+
});
|
|
102
|
+
const fileDescription = update.nodeLabels.length === 1
|
|
103
|
+
? update.nodeLabels[0]
|
|
104
|
+
: `${update.nodeLabels.length} JSX nodes`;
|
|
105
|
+
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}`)} Duplicated ${fileDescription}`);
|
|
106
|
+
renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[duplicate-nodes] Wrote ${update.fileRelativeToRoot}`);
|
|
107
|
+
}
|
|
108
|
+
(0, undo_stack_1.printUndoHint)(logLevel);
|
|
109
|
+
return {
|
|
110
|
+
success: true,
|
|
111
|
+
nodePathMutation,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
return {
|
|
116
|
+
success: false,
|
|
117
|
+
reason: err.message,
|
|
118
|
+
stack: err.stack,
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
exports.duplicateNodesHandler = duplicateNodesHandler;
|
|
@@ -11,7 +11,7 @@ const sequence_node_path_mutation_1 = require("../sequence-node-path-mutation");
|
|
|
11
11
|
const undo_stack_1 = require("../undo-stack");
|
|
12
12
|
const source_file_write_queue_1 = require("./source-file-write-queue");
|
|
13
13
|
const { basicCaptionsElementSource, getBasicCaptionsElementFile, insertBasicCaptions, } = codemods_1.CodemodsInternals;
|
|
14
|
-
const insertBasicCaptionsHandler = ({ input: { fileName, nodePath, captions, durationInFrames }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(() => {
|
|
14
|
+
const insertBasicCaptionsHandler = ({ input: { fileName, nodePath, captions, durationInFrames, premountFor }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(() => {
|
|
15
15
|
var _a;
|
|
16
16
|
try {
|
|
17
17
|
const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
|
|
@@ -49,6 +49,7 @@ const insertBasicCaptionsHandler = ({ input: { fileName, nodePath, captions, dur
|
|
|
49
49
|
nodePath,
|
|
50
50
|
captions,
|
|
51
51
|
durationInFrames,
|
|
52
|
+
premountFor,
|
|
52
53
|
importPath: elementFile.importPath,
|
|
53
54
|
});
|
|
54
55
|
const nodePathMutation = (0, sequence_node_path_mutation_1.broadcastSequenceNodePathMutation)([{ absolutePath, remappings: nodePathRemappings }], null);
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type InsertCompositionElementRequest, type InsertCompositionElementResponse } from '@remotion/studio-shared';
|
|
2
|
+
import type { ApiHandler } from '../api-types';
|
|
3
|
+
export declare const insertCompositionElementHandler: ApiHandler<InsertCompositionElementRequest, InsertCompositionElementResponse>;
|
|
@@ -0,0 +1,236 @@
|
|
|
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.insertCompositionElementHandler = void 0;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const renderer_1 = require("@remotion/renderer");
|
|
9
|
+
const studio_protocol_1 = require("@remotion/studio-protocol");
|
|
10
|
+
const studio_shared_1 = require("@remotion/studio-shared");
|
|
11
|
+
const file_watcher_1 = require("../../file-watcher");
|
|
12
|
+
const resolve_composition_component_1 = require("../../helpers/resolve-composition-component");
|
|
13
|
+
const format_log_file_location_1 = require("../format-log-file-location");
|
|
14
|
+
const sequence_node_path_mutation_1 = require("../sequence-node-path-mutation");
|
|
15
|
+
const undo_stack_1 = require("../undo-stack");
|
|
16
|
+
const source_file_write_queue_1 = require("./source-file-write-queue");
|
|
17
|
+
const validateDimension = (name, value) => {
|
|
18
|
+
if (!Number.isFinite(value) || value < 1) {
|
|
19
|
+
throw new Error(`${name} must be a positive number`);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
const validatePosition = (position) => {
|
|
23
|
+
if (position === null) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (!Number.isFinite(position.x) || !Number.isFinite(position.y)) {
|
|
27
|
+
throw new Error('Position must be finite');
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
const isInsideRemotionRoot = ({ fileName, remotionRoot, }) => {
|
|
31
|
+
const relativePath = node_path_1.default.relative(remotionRoot, fileName);
|
|
32
|
+
return !relativePath.startsWith('..') && !node_path_1.default.isAbsolute(relativePath);
|
|
33
|
+
};
|
|
34
|
+
const hasParentDirectorySegment = (fileName) => {
|
|
35
|
+
return fileName.split('/').includes('..');
|
|
36
|
+
};
|
|
37
|
+
const validateCompositionFile = ({ compositionFile, remotionRoot, }) => {
|
|
38
|
+
if (!compositionFile ||
|
|
39
|
+
compositionFile.includes('\0') ||
|
|
40
|
+
compositionFile.includes('\\') ||
|
|
41
|
+
compositionFile.startsWith('/') ||
|
|
42
|
+
hasParentDirectorySegment(compositionFile)) {
|
|
43
|
+
throw new Error('Unsupported composition file');
|
|
44
|
+
}
|
|
45
|
+
const resolved = node_path_1.default.resolve(remotionRoot, compositionFile);
|
|
46
|
+
if (!isInsideRemotionRoot({ fileName: resolved, remotionRoot })) {
|
|
47
|
+
throw new Error('Unsupported composition file');
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const validateElement = (element, remotionRoot) => {
|
|
51
|
+
validatePosition(element.position);
|
|
52
|
+
if (element.type === 'solid') {
|
|
53
|
+
validateDimension('width', element.width);
|
|
54
|
+
validateDimension('height', element.height);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (element.type === 'svg') {
|
|
58
|
+
if (typeof element.markup !== 'string' || element.markup.trim() === '') {
|
|
59
|
+
throw new Error('SVG markup must be a non-empty string');
|
|
60
|
+
}
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if (element.type === 'asset') {
|
|
64
|
+
if (element.srcType === 'remote') {
|
|
65
|
+
if (!(0, studio_shared_1.isUrl)(element.src)) {
|
|
66
|
+
throw new Error('Remote asset source must be a URL');
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
else if (!element.src || element.src.includes('\\')) {
|
|
70
|
+
throw new Error('Asset path must be a static file path');
|
|
71
|
+
}
|
|
72
|
+
if (element.dimensions) {
|
|
73
|
+
validateDimension('width', element.dimensions.width);
|
|
74
|
+
validateDimension('height', element.dimensions.height);
|
|
75
|
+
}
|
|
76
|
+
if (element.durationInFrames !== null) {
|
|
77
|
+
validateDimension('durationInFrames', element.durationInFrames);
|
|
78
|
+
}
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (element.type === 'component') {
|
|
82
|
+
if (!studio_protocol_1.StudioProtocolInternals.isComponentIdentifier(element.componentName)) {
|
|
83
|
+
throw new Error('Unsupported component name');
|
|
84
|
+
}
|
|
85
|
+
if (!studio_protocol_1.StudioProtocolInternals.isComponentIdentifier(element.importName)) {
|
|
86
|
+
throw new Error('Unsupported component import name');
|
|
87
|
+
}
|
|
88
|
+
if (!studio_protocol_1.StudioProtocolInternals.isComponentImportPath(element.importPath)) {
|
|
89
|
+
throw new Error('Unsupported component import path');
|
|
90
|
+
}
|
|
91
|
+
if (!studio_protocol_1.StudioProtocolInternals.areComponentProps(element.props)) {
|
|
92
|
+
throw new Error('Unsupported component props');
|
|
93
|
+
}
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (element.type === 'composition') {
|
|
97
|
+
if (typeof element.compositionId !== 'string' || !element.compositionId) {
|
|
98
|
+
throw new Error('Unsupported composition ID');
|
|
99
|
+
}
|
|
100
|
+
if (typeof element.compositionFile !== 'string') {
|
|
101
|
+
throw new Error('Unsupported composition file');
|
|
102
|
+
}
|
|
103
|
+
validateCompositionFile({
|
|
104
|
+
compositionFile: element.compositionFile,
|
|
105
|
+
remotionRoot,
|
|
106
|
+
});
|
|
107
|
+
validateDimension('width', element.width);
|
|
108
|
+
validateDimension('height', element.height);
|
|
109
|
+
validateDimension('durationInFrames', element.durationInFrames);
|
|
110
|
+
const parsedProps = JSON.parse(element.serializedResolvedPropsWithCustomSchema);
|
|
111
|
+
if (typeof parsedProps !== 'object' ||
|
|
112
|
+
parsedProps === null ||
|
|
113
|
+
Array.isArray(parsedProps)) {
|
|
114
|
+
throw new Error('Resolved composition props must be an object');
|
|
115
|
+
}
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
throw new Error('Unsupported element type');
|
|
119
|
+
};
|
|
120
|
+
const getElementLabel = (element) => {
|
|
121
|
+
if (element.type === 'solid') {
|
|
122
|
+
return '<Solid>';
|
|
123
|
+
}
|
|
124
|
+
if (element.type === 'svg') {
|
|
125
|
+
return '<Interactive.Svg>';
|
|
126
|
+
}
|
|
127
|
+
if (element.type === 'asset') {
|
|
128
|
+
if (element.assetType === 'image') {
|
|
129
|
+
return '<CanvasImage>';
|
|
130
|
+
}
|
|
131
|
+
if (element.assetType === 'video') {
|
|
132
|
+
return '<Video>';
|
|
133
|
+
}
|
|
134
|
+
if (element.assetType === 'gif') {
|
|
135
|
+
return '<Gif>';
|
|
136
|
+
}
|
|
137
|
+
if (element.assetType === 'animated-image') {
|
|
138
|
+
return '<AnimatedImage>';
|
|
139
|
+
}
|
|
140
|
+
if (element.assetType === 'audio') {
|
|
141
|
+
return '<Audio>';
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
if (element.type === 'component') {
|
|
145
|
+
return `<${element.componentName}>`;
|
|
146
|
+
}
|
|
147
|
+
if (element.type === 'composition') {
|
|
148
|
+
return `composition "${element.compositionId}"`;
|
|
149
|
+
}
|
|
150
|
+
throw new Error('Unsupported element type');
|
|
151
|
+
};
|
|
152
|
+
const insertCompositionElementHandler = ({ input: { compositionFile, compositionId, element, from, premountFor }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
|
|
153
|
+
try {
|
|
154
|
+
validateElement(element, remotionRoot);
|
|
155
|
+
if (from !== null &&
|
|
156
|
+
(!Number.isInteger(from) || !Number.isFinite(from) || from < 0)) {
|
|
157
|
+
throw new Error('from must be a non-negative integer');
|
|
158
|
+
}
|
|
159
|
+
if (premountFor !== null &&
|
|
160
|
+
(!Number.isInteger(premountFor) || premountFor < 0)) {
|
|
161
|
+
throw new Error('premountFor must be a non-negative integer');
|
|
162
|
+
}
|
|
163
|
+
const elementLabel = getElementLabel(element);
|
|
164
|
+
renderer_1.RenderInternals.Log.trace({ indent: false, logLevel }, `[insert-composition-element] Received request for compositionFile="${compositionFile}" compositionId="${compositionId}" element="${element.type}"`);
|
|
165
|
+
const { fileName, source, oldContents, output, insertedNodePath, logLine, nodePathRemappings, } = await (0, resolve_composition_component_1.insertJsxElementIntoComposition)({
|
|
166
|
+
remotionRoot,
|
|
167
|
+
compositionFile,
|
|
168
|
+
compositionId,
|
|
169
|
+
element,
|
|
170
|
+
from,
|
|
171
|
+
premountFor,
|
|
172
|
+
prettierConfigOverride: null,
|
|
173
|
+
sourceFileOverrides: null,
|
|
174
|
+
});
|
|
175
|
+
const nodePathMutation = (0, sequence_node_path_mutation_1.broadcastSequenceNodePathMutation)([
|
|
176
|
+
{
|
|
177
|
+
absolutePath: fileName,
|
|
178
|
+
remappings: nodePathRemappings,
|
|
179
|
+
},
|
|
180
|
+
], insertedNodePath === null
|
|
181
|
+
? null
|
|
182
|
+
: {
|
|
183
|
+
absolutePath: fileName,
|
|
184
|
+
compositionId,
|
|
185
|
+
nodePath: insertedNodePath,
|
|
186
|
+
});
|
|
187
|
+
if (insertedNodePath === null) {
|
|
188
|
+
renderer_1.RenderInternals.Log.warn({ indent: false, logLevel }, 'Could not determine the inserted JSX element node path. Skipping automatic selection.');
|
|
189
|
+
}
|
|
190
|
+
(0, undo_stack_1.pushToUndoStack)({
|
|
191
|
+
filePath: fileName,
|
|
192
|
+
oldContents,
|
|
193
|
+
newContents: output,
|
|
194
|
+
logLevel,
|
|
195
|
+
remotionRoot,
|
|
196
|
+
logLine,
|
|
197
|
+
description: {
|
|
198
|
+
undoMessage: `↩️ Added ${elementLabel}`,
|
|
199
|
+
redoMessage: `↪️ Added ${elementLabel}`,
|
|
200
|
+
},
|
|
201
|
+
entryType: 'insert-composition-element',
|
|
202
|
+
suppressHmrOnFileRestore: false,
|
|
203
|
+
nodePathRemappings,
|
|
204
|
+
});
|
|
205
|
+
(0, undo_stack_1.suppressUndoStackInvalidation)(fileName);
|
|
206
|
+
(0, file_watcher_1.writeFileAndNotifyFileWatchers)({
|
|
207
|
+
file: fileName,
|
|
208
|
+
content: output,
|
|
209
|
+
originatorClientId: undefined,
|
|
210
|
+
metadata: { skipSequencePropsUpdate: true },
|
|
211
|
+
});
|
|
212
|
+
const locationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
|
|
213
|
+
remotionRoot,
|
|
214
|
+
absolutePath: fileName,
|
|
215
|
+
line: logLine,
|
|
216
|
+
});
|
|
217
|
+
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright(`${locationLabel}`)} Added ${elementLabel}`);
|
|
218
|
+
renderer_1.RenderInternals.Log.verbose({ indent: false, logLevel }, `[insert-composition-element] Wrote ${source}`);
|
|
219
|
+
(0, undo_stack_1.printUndoHint)(logLevel);
|
|
220
|
+
return {
|
|
221
|
+
success: true,
|
|
222
|
+
insertedNodePath: insertedNodePath === null
|
|
223
|
+
? null
|
|
224
|
+
: { absolutePath: fileName, nodePath: insertedNodePath },
|
|
225
|
+
nodePathMutation,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
catch (err) {
|
|
229
|
+
return {
|
|
230
|
+
success: false,
|
|
231
|
+
reason: err.message,
|
|
232
|
+
stack: err.stack,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
exports.insertCompositionElementHandler = insertCompositionElementHandler;
|
|
@@ -8,10 +8,11 @@ const node_fs_1 = require("node:fs");
|
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
9
|
const renderer_1 = require("@remotion/renderer");
|
|
10
10
|
const studio_protocol_1 = require("@remotion/studio-protocol");
|
|
11
|
-
const
|
|
11
|
+
const add_composition_to_file_1 = require("../../codemods/add-composition-to-file");
|
|
12
12
|
const file_watcher_1 = require("../../file-watcher");
|
|
13
13
|
const open_file_for_writing_without_symlinks_1 = require("../../helpers/open-file-for-writing-without-symlinks");
|
|
14
14
|
const resolve_composition_component_1 = require("../../helpers/resolve-composition-component");
|
|
15
|
+
const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
|
|
15
16
|
const format_log_file_location_1 = require("../format-log-file-location");
|
|
16
17
|
const project_info_1 = require("../project-info");
|
|
17
18
|
const sequence_node_path_mutation_1 = require("../sequence-node-path-mutation");
|
|
@@ -32,7 +33,7 @@ const hasExpectedFileState = ({ expected, actual, }) => {
|
|
|
32
33
|
}
|
|
33
34
|
return actual.sourceHash === expected.sourceHash;
|
|
34
35
|
};
|
|
35
|
-
const insertElementHandler = async ({ input: { compositionFile, compositionId, element, installationName, expectedFileState, from, position, overwriteExisting, undoRedoNavigation, newComposition, }, entryPoint, remotionRoot, logLevel, publicDir, }) => {
|
|
36
|
+
const insertElementHandler = async ({ input: { compositionFile, compositionId, element, installationName, expectedFileState, from, premountFor, position, overwriteExisting, undoRedoNavigation, newComposition, }, entryPoint, remotionRoot, logLevel, publicDir, }) => {
|
|
36
37
|
var _a;
|
|
37
38
|
let resolvedAssets;
|
|
38
39
|
try {
|
|
@@ -52,8 +53,8 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
|
|
|
52
53
|
};
|
|
53
54
|
}
|
|
54
55
|
return (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
|
|
55
|
-
var _a, _b, _c, _d, _e;
|
|
56
|
-
var
|
|
56
|
+
var _a, _b, _c, _d, _e, _f;
|
|
57
|
+
var _g, _h, _j, _k;
|
|
57
58
|
const createdAssets = [];
|
|
58
59
|
const changedSources = [];
|
|
59
60
|
let undoEntryPushed = false;
|
|
@@ -86,11 +87,15 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
|
|
|
86
87
|
let compositionCreation = null;
|
|
87
88
|
let sourceFileOverrides = null;
|
|
88
89
|
if (newComposition !== null) {
|
|
89
|
-
if (newComposition.
|
|
90
|
+
if (newComposition.options.newId !== compositionId) {
|
|
90
91
|
throw new Error('New composition ID does not match installation target');
|
|
91
92
|
}
|
|
92
|
-
const registrationFilePath = newComposition.symbolicatedStack
|
|
93
|
-
? (0,
|
|
93
|
+
const registrationFilePath = ((_b = newComposition.symbolicatedStack) === null || _b === void 0 ? void 0 : _b.originalFileName)
|
|
94
|
+
? (0, resolve_file_inside_project_1.resolveFileInsideProject)({
|
|
95
|
+
remotionRoot,
|
|
96
|
+
fileName: newComposition.symbolicatedStack.originalFileName,
|
|
97
|
+
action: 'add a composition to',
|
|
98
|
+
}).absolutePath
|
|
94
99
|
: (await (0, project_info_1.getProjectInfo)(remotionRoot, entryPoint)).rootFile;
|
|
95
100
|
if (registrationFilePath === null) {
|
|
96
101
|
throw new Error('Cannot find file for composition in project');
|
|
@@ -99,17 +104,18 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
|
|
|
99
104
|
if (node_path_1.default.resolve(remotionRoot, compositionFile) !== registrationFilePath) {
|
|
100
105
|
throw new Error('New composition source does not match installation target');
|
|
101
106
|
}
|
|
102
|
-
const componentFilePath = node_path_1.default.join(node_path_1.default.dirname(registrationFilePath), `${newComposition.
|
|
107
|
+
const componentFilePath = node_path_1.default.join(node_path_1.default.dirname(registrationFilePath), `${newComposition.options.componentName}.tsx`);
|
|
103
108
|
if ((0, node_fs_1.existsSync)(componentFilePath)) {
|
|
104
109
|
throw new Error(`Cannot create ${node_path_1.default.relative(remotionRoot, componentFilePath)} because it already exists`);
|
|
105
110
|
}
|
|
106
111
|
const registrationFileOldContents = (0, node_fs_1.readFileSync)(registrationFilePath, 'utf-8');
|
|
107
|
-
const codemodResult = await (0,
|
|
112
|
+
const codemodResult = await (0, add_composition_to_file_1.addCompositionToFile)({
|
|
108
113
|
filePath: registrationFilePath,
|
|
109
|
-
|
|
114
|
+
options: newComposition.options,
|
|
115
|
+
remotionRoot,
|
|
110
116
|
});
|
|
111
|
-
const registrationFileNewContents = (
|
|
112
|
-
const componentFileContents = (
|
|
117
|
+
const registrationFileNewContents = (_g = (_c = codemodResult.changes.find((change) => change.filePath === registrationFilePath)) === null || _c === void 0 ? void 0 : _c.nextContents) !== null && _g !== void 0 ? _g : registrationFileOldContents;
|
|
118
|
+
const componentFileContents = (_d = codemodResult.changes.find((change) => change.filePath === componentFilePath)) === null || _d === void 0 ? void 0 : _d.nextContents;
|
|
113
119
|
if (componentFileContents === null ||
|
|
114
120
|
componentFileContents === undefined) {
|
|
115
121
|
throw new Error('Could not create the composition component');
|
|
@@ -191,7 +197,7 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
|
|
|
191
197
|
importName: plan.componentName,
|
|
192
198
|
importPath: plan.importPath,
|
|
193
199
|
props: [
|
|
194
|
-
...Object.entries((
|
|
200
|
+
...Object.entries((_h = element.initialProps) !== null && _h !== void 0 ? _h : {}).map(([name, value]) => ({ name, value })),
|
|
195
201
|
...(componentOwnsSequence && element.durationInFrames !== null
|
|
196
202
|
? [
|
|
197
203
|
{
|
|
@@ -207,6 +213,7 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
|
|
|
207
213
|
position: componentOwnsSequence ? position : null,
|
|
208
214
|
},
|
|
209
215
|
from: componentOwnsSequence ? from : null,
|
|
216
|
+
premountFor,
|
|
210
217
|
prettierConfigOverride: null,
|
|
211
218
|
wrapInSequence: componentOwnsSequence
|
|
212
219
|
? null
|
|
@@ -282,7 +289,7 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
|
|
|
282
289
|
try {
|
|
283
290
|
(0, node_fs_1.unlinkSync)(asset.absolutePath);
|
|
284
291
|
}
|
|
285
|
-
catch (
|
|
292
|
+
catch (_l) {
|
|
286
293
|
// Keep the original write error.
|
|
287
294
|
}
|
|
288
295
|
throw error;
|
|
@@ -321,7 +328,7 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
|
|
|
321
328
|
filePath: compositionCreation.registrationFilePath,
|
|
322
329
|
oldContents: compositionCreation.registrationFileOldContents,
|
|
323
330
|
newContents: compositionCreation.registrationFileNewContents,
|
|
324
|
-
logLine: (
|
|
331
|
+
logLine: (_j = (_e = newComposition === null || newComposition === void 0 ? void 0 : newComposition.symbolicatedStack) === null || _e === void 0 ? void 0 : _e.originalLineNumber) !== null && _j !== void 0 ? _j : 1,
|
|
325
332
|
nodePathRemappings: null,
|
|
326
333
|
},
|
|
327
334
|
]),
|
|
@@ -355,7 +362,7 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
|
|
|
355
362
|
undoMessage: `↩️ Installation of ${element.displayName} into composition "${compositionId}"`,
|
|
356
363
|
redoMessage: `↪️ Installation of ${element.displayName} into composition "${compositionId}"`,
|
|
357
364
|
},
|
|
358
|
-
entryType: 'insert-
|
|
365
|
+
entryType: 'insert-composition-element',
|
|
359
366
|
suppressHmrOnFileRestore: false,
|
|
360
367
|
undoRedoNavigation,
|
|
361
368
|
});
|
|
@@ -390,7 +397,7 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
|
|
|
390
397
|
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${(0, source_file_write_queue_1.getCodemodTimingPrefix)(logLevel)}${renderer_1.RenderInternals.chalk.blueBright((0, format_log_file_location_1.formatLogFileLocation)({
|
|
391
398
|
remotionRoot,
|
|
392
399
|
absolutePath: compositionCreation.registrationFilePath,
|
|
393
|
-
line: (
|
|
400
|
+
line: (_k = (_f = newComposition.symbolicatedStack) === null || _f === void 0 ? void 0 : _f.originalLineNumber) !== null && _k !== void 0 ? _k : 1,
|
|
394
401
|
}))} Created composition "${compositionId}"`);
|
|
395
402
|
}
|
|
396
403
|
const compositionLocationLabel = (0, format_log_file_location_1.formatLogFileLocation)({
|
|
@@ -434,7 +441,7 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
|
|
|
434
441
|
});
|
|
435
442
|
}
|
|
436
443
|
}
|
|
437
|
-
catch (
|
|
444
|
+
catch (_m) {
|
|
438
445
|
// Preserve subsequent user changes and the original installation error.
|
|
439
446
|
}
|
|
440
447
|
}
|
|
@@ -444,7 +451,7 @@ const insertElementHandler = async ({ input: { compositionFile, compositionId, e
|
|
|
444
451
|
(0, node_fs_1.unlinkSync)(asset.absolutePath);
|
|
445
452
|
}
|
|
446
453
|
}
|
|
447
|
-
catch (
|
|
454
|
+
catch (_o) {
|
|
448
455
|
// Preserve subsequent user changes and the original installation error.
|
|
449
456
|
}
|
|
450
457
|
}
|