@remotion/studio-server 4.0.431 → 4.0.433
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/update-nested-prop.d.ts +11 -0
- package/dist/codemods/update-nested-prop.js +156 -0
- package/dist/codemods/update-sequence-props.d.ts +5 -4
- package/dist/codemods/update-sequence-props.js +90 -63
- package/dist/preview-server/routes/can-update-sequence-props.d.ts +12 -3
- package/dist/preview-server/routes/can-update-sequence-props.js +143 -26
- package/dist/preview-server/routes/log-update.d.ts +10 -0
- package/dist/preview-server/routes/log-update.js +73 -0
- package/dist/preview-server/routes/save-sequence-props.js +14 -12
- package/dist/preview-server/routes/subscribe-to-sequence-props.js +1 -2
- package/dist/preview-server/routes/unsubscribe-from-sequence-props.js +2 -3
- package/dist/preview-server/sequence-props-watchers.d.ts +4 -6
- package/dist/preview-server/sequence-props-watchers.js +23 -17
- package/package.json +6 -6
- package/dist/codemods/apply-component-visual-control.d.ts +0 -8
- package/dist/codemods/apply-component-visual-control.js +0 -92
- package/dist/preview-server/routes/apply-component-visual-control-change.d.ts +0 -3
- package/dist/preview-server/routes/apply-component-visual-control-change.js +0 -38
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { JSXOpeningElement } from '@babel/types';
|
|
2
|
+
import type { ExpressionKind } from 'ast-types/lib/gen/kinds';
|
|
3
|
+
export declare const parseValueExpression: (value: unknown) => ExpressionKind;
|
|
4
|
+
export declare const updateNestedProp: ({ node, parentKey, childKey, value, defaultValue, isDefault, }: {
|
|
5
|
+
node: JSXOpeningElement;
|
|
6
|
+
parentKey: string;
|
|
7
|
+
childKey: string;
|
|
8
|
+
value: unknown;
|
|
9
|
+
defaultValue: unknown;
|
|
10
|
+
isDefault: boolean;
|
|
11
|
+
}) => string;
|
|
@@ -0,0 +1,156 @@
|
|
|
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.updateNestedProp = exports.parseValueExpression = void 0;
|
|
37
|
+
const studio_shared_1 = require("@remotion/studio-shared");
|
|
38
|
+
const recast = __importStar(require("recast"));
|
|
39
|
+
const parse_ast_1 = require("./parse-ast");
|
|
40
|
+
const b = recast.types.builders;
|
|
41
|
+
const parseValueExpression = (value) => {
|
|
42
|
+
return (0, parse_ast_1.parseAst)(`a = ${(0, studio_shared_1.stringifyDefaultProps)({ props: value, enumPaths: [] })}`)
|
|
43
|
+
.program.body[0].expression.right;
|
|
44
|
+
};
|
|
45
|
+
exports.parseValueExpression = parseValueExpression;
|
|
46
|
+
const findJsxAttribute = (attributes, name) => {
|
|
47
|
+
const attrIndex = attributes.findIndex((a) => {
|
|
48
|
+
if (a.type === 'JSXSpreadAttribute') {
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
if (a.name.type === 'JSXNamespacedName') {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
return a.name.name === name;
|
|
55
|
+
});
|
|
56
|
+
const found = attrIndex !== -1 ? attributes[attrIndex] : undefined;
|
|
57
|
+
return {
|
|
58
|
+
attrIndex,
|
|
59
|
+
attr: found && found.type === 'JSXAttribute'
|
|
60
|
+
? found
|
|
61
|
+
: undefined,
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
const findObjectProperty = (objExpr, propertyName) => {
|
|
65
|
+
const propIndex = objExpr.properties.findIndex((p) => p.type === 'ObjectProperty' &&
|
|
66
|
+
((p.key.type === 'Identifier' &&
|
|
67
|
+
p.key.name === propertyName) ||
|
|
68
|
+
(p.key.type === 'StringLiteral' &&
|
|
69
|
+
p.key.value === propertyName)));
|
|
70
|
+
return {
|
|
71
|
+
propIndex,
|
|
72
|
+
prop: propIndex !== -1
|
|
73
|
+
? objExpr.properties[propIndex]
|
|
74
|
+
: undefined,
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
const getObjectExpression = (attr) => {
|
|
78
|
+
const { value } = attr;
|
|
79
|
+
if (!value || value.type !== 'JSXExpressionContainer') {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
const container = value;
|
|
83
|
+
if (container.expression.type !== 'ObjectExpression') {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
return container.expression;
|
|
87
|
+
};
|
|
88
|
+
const getOldValueString = ({ attr, childKey, defaultValue, }) => {
|
|
89
|
+
if (attr) {
|
|
90
|
+
const objExpr = getObjectExpression(attr);
|
|
91
|
+
if (objExpr) {
|
|
92
|
+
const { prop } = findObjectProperty(objExpr, childKey);
|
|
93
|
+
if (prop) {
|
|
94
|
+
return recast.print(prop.value).code;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (defaultValue !== null) {
|
|
99
|
+
return JSON.stringify(defaultValue);
|
|
100
|
+
}
|
|
101
|
+
return '';
|
|
102
|
+
};
|
|
103
|
+
const removeNestedProp = ({ attr, attrIndex, attributes, childKey, }) => {
|
|
104
|
+
if (!attr) {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const objExpr = getObjectExpression(attr);
|
|
108
|
+
if (!objExpr) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const { propIndex } = findObjectProperty(objExpr, childKey);
|
|
112
|
+
if (propIndex !== -1) {
|
|
113
|
+
objExpr.properties.splice(propIndex, 1);
|
|
114
|
+
}
|
|
115
|
+
if (objExpr.properties.length === 0 && attrIndex !== -1) {
|
|
116
|
+
attributes.splice(attrIndex, 1);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
const setNestedProp = ({ attr, attributes, parentKey, childKey, value, }) => {
|
|
120
|
+
const parsedValue = (0, exports.parseValueExpression)(value);
|
|
121
|
+
if (attr) {
|
|
122
|
+
const objExpr = getObjectExpression(attr);
|
|
123
|
+
if (objExpr) {
|
|
124
|
+
const { prop } = findObjectProperty(objExpr, childKey);
|
|
125
|
+
if (prop) {
|
|
126
|
+
prop.value = parsedValue;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
objExpr.properties.push(b.objectProperty(b.identifier(childKey), parsedValue));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
const objExpr = b.objectExpression([
|
|
135
|
+
b.objectProperty(b.identifier(childKey), parsedValue),
|
|
136
|
+
]);
|
|
137
|
+
const newAttr = b.jsxAttribute(b.jsxIdentifier(parentKey), b.jsxExpressionContainer(objExpr));
|
|
138
|
+
attributes.push(newAttr);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
const updateNestedProp = ({ node, parentKey, childKey, value, defaultValue, isDefault, }) => {
|
|
142
|
+
if (!node.attributes) {
|
|
143
|
+
node.attributes = [];
|
|
144
|
+
}
|
|
145
|
+
const { attributes } = node;
|
|
146
|
+
const { attrIndex, attr } = findJsxAttribute(attributes, parentKey);
|
|
147
|
+
const oldValueString = getOldValueString({ attr, childKey, defaultValue });
|
|
148
|
+
if (isDefault) {
|
|
149
|
+
removeNestedProp({ attr, attrIndex, attributes, childKey });
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
setNestedProp({ attr, attributes, parentKey, childKey, value });
|
|
153
|
+
}
|
|
154
|
+
return oldValueString;
|
|
155
|
+
};
|
|
156
|
+
exports.updateNestedProp = updateNestedProp;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare const updateSequenceProps: ({ input,
|
|
1
|
+
import type { SequenceNodePath } from '@remotion/studio-shared';
|
|
2
|
+
export declare const updateSequenceProps: ({ input, nodePath, key, value, defaultValue, prettierConfigOverride, }: {
|
|
3
3
|
input: string;
|
|
4
|
-
|
|
4
|
+
nodePath: SequenceNodePath;
|
|
5
5
|
key: string;
|
|
6
6
|
value: unknown;
|
|
7
|
-
enumPaths: EnumPath[];
|
|
8
7
|
defaultValue: unknown;
|
|
8
|
+
prettierConfigOverride?: Record<string, unknown> | null | undefined;
|
|
9
9
|
}) => Promise<{
|
|
10
10
|
output: string;
|
|
11
11
|
oldValueString: string;
|
|
12
|
+
formatted: boolean;
|
|
12
13
|
}>;
|
|
@@ -34,63 +34,73 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
36
|
exports.updateSequenceProps = void 0;
|
|
37
|
-
const studio_shared_1 = require("@remotion/studio-shared");
|
|
38
37
|
const recast = __importStar(require("recast"));
|
|
38
|
+
const can_update_sequence_props_1 = require("../preview-server/routes/can-update-sequence-props");
|
|
39
39
|
const parse_ast_1 = require("./parse-ast");
|
|
40
|
-
const
|
|
40
|
+
const update_nested_prop_1 = require("./update-nested-prop");
|
|
41
|
+
const b = recast.types.builders;
|
|
42
|
+
const updateSequenceProps = async ({ input, nodePath, key, value, defaultValue, prettierConfigOverride, }) => {
|
|
43
|
+
var _a, _b;
|
|
41
44
|
const ast = (0, parse_ast_1.parseAst)(input);
|
|
42
|
-
let found = false;
|
|
43
45
|
let oldValueString = '';
|
|
44
46
|
const isDefault = defaultValue !== null &&
|
|
45
47
|
JSON.stringify(value) === JSON.stringify(defaultValue);
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
oldValueString =
|
|
69
|
-
printed.startsWith('{') && printed.endsWith('}')
|
|
70
|
-
? printed.slice(1, -1)
|
|
71
|
-
: printed;
|
|
72
|
-
}
|
|
73
|
-
else if (attr && attr.type !== 'JSXSpreadAttribute' && !attr.value) {
|
|
74
|
-
// JSX shorthand like `loop` (no value) is implicitly `true`
|
|
75
|
-
oldValueString = 'true';
|
|
48
|
+
const dotIndex = key.indexOf('.');
|
|
49
|
+
const isNested = dotIndex !== -1;
|
|
50
|
+
const parentKey = isNested ? key.slice(0, dotIndex) : key;
|
|
51
|
+
const childKey = isNested ? key.slice(dotIndex + 1) : '';
|
|
52
|
+
const node = (0, can_update_sequence_props_1.findJsxElementAtNodePath)(ast, nodePath);
|
|
53
|
+
if (!node) {
|
|
54
|
+
throw new Error('Could not find a JSX element at the specified line to update');
|
|
55
|
+
}
|
|
56
|
+
if (isNested) {
|
|
57
|
+
oldValueString = (0, update_nested_prop_1.updateNestedProp)({
|
|
58
|
+
node,
|
|
59
|
+
parentKey,
|
|
60
|
+
childKey,
|
|
61
|
+
value,
|
|
62
|
+
defaultValue,
|
|
63
|
+
isDefault,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
const attrIndex = (_a = node.attributes) === null || _a === void 0 ? void 0 : _a.findIndex((a) => {
|
|
68
|
+
if (a.type === 'JSXSpreadAttribute') {
|
|
69
|
+
return false;
|
|
76
70
|
}
|
|
77
|
-
|
|
78
|
-
|
|
71
|
+
if (a.name.type === 'JSXNamespacedName') {
|
|
72
|
+
return false;
|
|
79
73
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
74
|
+
return a.name.name === key;
|
|
75
|
+
});
|
|
76
|
+
const attr = attrIndex !== undefined && attrIndex !== -1
|
|
77
|
+
? (_b = node.attributes) === null || _b === void 0 ? void 0 : _b[attrIndex]
|
|
78
|
+
: undefined;
|
|
79
|
+
if (attr && attr.type !== 'JSXSpreadAttribute' && attr.value) {
|
|
80
|
+
const printed = recast.print(attr.value).code;
|
|
81
|
+
// Strip JSX expression container braces, e.g. "{30}" -> "30"
|
|
82
|
+
oldValueString =
|
|
83
|
+
printed.startsWith('{') && printed.endsWith('}')
|
|
84
|
+
? printed.slice(1, -1)
|
|
85
|
+
: printed;
|
|
86
|
+
}
|
|
87
|
+
else if (attr && attr.type !== 'JSXSpreadAttribute' && !attr.value) {
|
|
88
|
+
// JSX shorthand like `loop` (no value) is implicitly `true`
|
|
89
|
+
oldValueString = 'true';
|
|
90
|
+
}
|
|
91
|
+
else if (!attr && defaultValue !== null) {
|
|
92
|
+
oldValueString = JSON.stringify(defaultValue);
|
|
93
|
+
}
|
|
94
|
+
if (isDefault) {
|
|
95
|
+
if (attr && attr.type !== 'JSXSpreadAttribute' && node.attributes) {
|
|
96
|
+
node.attributes.splice(attrIndex, 1);
|
|
86
97
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
: recast.types.builders.jsxExpressionContainer(parsed);
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
const parsed = (0, update_nested_prop_1.parseValueExpression)(value);
|
|
101
|
+
const newValue = value === true ? null : b.jsxExpressionContainer(parsed);
|
|
92
102
|
if (!attr || attr.type === 'JSXSpreadAttribute') {
|
|
93
|
-
const newAttr =
|
|
103
|
+
const newAttr = b.jsxAttribute(b.jsxIdentifier(key), newValue);
|
|
94
104
|
if (!node.attributes) {
|
|
95
105
|
node.attributes = [];
|
|
96
106
|
}
|
|
@@ -99,36 +109,53 @@ const updateSequenceProps = async ({ input, targetLine, key, value, enumPaths, d
|
|
|
99
109
|
else {
|
|
100
110
|
attr.value = newValue;
|
|
101
111
|
}
|
|
102
|
-
|
|
103
|
-
return this.traverse(path);
|
|
104
|
-
},
|
|
105
|
-
});
|
|
106
|
-
if (!found) {
|
|
107
|
-
throw new Error('Could not find a JSX element at the specified line to update');
|
|
112
|
+
}
|
|
108
113
|
}
|
|
114
|
+
const finalFile = (0, parse_ast_1.serializeAst)(ast);
|
|
109
115
|
let prettier = null;
|
|
110
116
|
try {
|
|
111
117
|
prettier = await Promise.resolve().then(() => __importStar(require('prettier')));
|
|
112
118
|
}
|
|
113
|
-
catch (
|
|
114
|
-
|
|
119
|
+
catch (_c) {
|
|
120
|
+
return {
|
|
121
|
+
output: finalFile,
|
|
122
|
+
oldValueString,
|
|
123
|
+
formatted: false,
|
|
124
|
+
};
|
|
115
125
|
}
|
|
116
126
|
const { format, resolveConfig, resolveConfigFile } = prettier;
|
|
117
|
-
|
|
118
|
-
if (
|
|
119
|
-
|
|
127
|
+
let prettierConfig;
|
|
128
|
+
if (prettierConfigOverride !== undefined) {
|
|
129
|
+
prettierConfig = prettierConfigOverride;
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
const configFilePath = await resolveConfigFile();
|
|
133
|
+
if (!configFilePath) {
|
|
134
|
+
return {
|
|
135
|
+
output: finalFile,
|
|
136
|
+
oldValueString,
|
|
137
|
+
formatted: false,
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
prettierConfig = await resolveConfig(configFilePath);
|
|
120
141
|
}
|
|
121
|
-
const prettierConfig = await resolveConfig(configFilePath);
|
|
122
142
|
if (!prettierConfig) {
|
|
123
|
-
|
|
143
|
+
return {
|
|
144
|
+
output: finalFile,
|
|
145
|
+
oldValueString,
|
|
146
|
+
formatted: false,
|
|
147
|
+
};
|
|
124
148
|
}
|
|
125
|
-
const finalFile = (0, parse_ast_1.serializeAst)(ast);
|
|
126
149
|
const prettified = await format(finalFile, {
|
|
127
150
|
...prettierConfig,
|
|
128
151
|
filepath: 'test.tsx',
|
|
129
152
|
plugins: [],
|
|
130
|
-
endOfLine: '
|
|
153
|
+
endOfLine: 'lf',
|
|
131
154
|
});
|
|
132
|
-
return {
|
|
155
|
+
return {
|
|
156
|
+
output: prettified,
|
|
157
|
+
oldValueString,
|
|
158
|
+
formatted: true,
|
|
159
|
+
};
|
|
133
160
|
};
|
|
134
161
|
exports.updateSequenceProps = updateSequenceProps;
|
|
@@ -1,8 +1,17 @@
|
|
|
1
|
-
import type { Expression } from '@babel/types';
|
|
2
|
-
import type { CanUpdateSequencePropsResponse } from '@remotion/studio-shared';
|
|
1
|
+
import type { Expression, File, JSXOpeningElement } from '@babel/types';
|
|
2
|
+
import type { CanUpdateSequencePropsResponse, SequenceNodePath } from '@remotion/studio-shared';
|
|
3
3
|
export declare const isStaticValue: (node: Expression) => boolean;
|
|
4
4
|
export declare const extractStaticValue: (node: Expression) => unknown;
|
|
5
|
-
export declare const
|
|
5
|
+
export declare const findJsxElementAtNodePath: (ast: File, nodePath: SequenceNodePath) => JSXOpeningElement | null;
|
|
6
|
+
export declare const lineColumnToNodePath: (ast: File, targetLine: number) => SequenceNodePath | null;
|
|
7
|
+
export declare const computeSequencePropsStatusFromContent: (fileContents: string, nodePath: SequenceNodePath, keys: string[]) => CanUpdateSequencePropsResponse;
|
|
8
|
+
export declare const computeSequencePropsStatus: ({ fileName, nodePath, keys, remotionRoot, }: {
|
|
9
|
+
fileName: string;
|
|
10
|
+
nodePath: SequenceNodePath;
|
|
11
|
+
keys: string[];
|
|
12
|
+
remotionRoot: string;
|
|
13
|
+
}) => CanUpdateSequencePropsResponse;
|
|
14
|
+
export declare const computeSequencePropsStatusByLine: ({ fileName, line, keys, remotionRoot, }: {
|
|
6
15
|
fileName: string;
|
|
7
16
|
line: number;
|
|
8
17
|
keys: string[];
|
|
@@ -36,7 +36,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
37
|
};
|
|
38
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.computeSequencePropsStatus = exports.extractStaticValue = exports.isStaticValue = void 0;
|
|
39
|
+
exports.computeSequencePropsStatusByLine = exports.computeSequencePropsStatus = exports.computeSequencePropsStatusFromContent = exports.lineColumnToNodePath = exports.findJsxElementAtNodePath = exports.extractStaticValue = exports.isStaticValue = void 0;
|
|
40
40
|
const node_fs_1 = require("node:fs");
|
|
41
41
|
const node_path_1 = __importDefault(require("node:path"));
|
|
42
42
|
const recast = __importStar(require("recast"));
|
|
@@ -151,21 +151,146 @@ const getPropsStatus = (jsxElement) => {
|
|
|
151
151
|
}
|
|
152
152
|
return props;
|
|
153
153
|
};
|
|
154
|
-
const
|
|
155
|
-
|
|
154
|
+
const getNodePathForRecastPath = (
|
|
155
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
156
|
+
recastPath) => {
|
|
157
|
+
const segments = [];
|
|
158
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
159
|
+
let current = recastPath;
|
|
160
|
+
while (current && current.parentPath) {
|
|
161
|
+
segments.unshift(current.name);
|
|
162
|
+
current = current.parentPath;
|
|
163
|
+
}
|
|
164
|
+
// Recast paths start with "root" which doesn't correspond to a real AST property
|
|
165
|
+
if (segments.length > 0 && segments[0] === 'root') {
|
|
166
|
+
return segments.slice(1);
|
|
167
|
+
}
|
|
168
|
+
return segments;
|
|
169
|
+
};
|
|
170
|
+
const findJsxElementAtNodePath = (ast, nodePath) => {
|
|
171
|
+
let current = new recast.types.NodePath(ast);
|
|
172
|
+
for (const segment of nodePath) {
|
|
173
|
+
current = current.get(segment);
|
|
174
|
+
if (current.value === null || current.value === undefined) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (recast.types.namedTypes.JSXOpeningElement.check(current.value)) {
|
|
179
|
+
return current.value;
|
|
180
|
+
}
|
|
181
|
+
return null;
|
|
182
|
+
};
|
|
183
|
+
exports.findJsxElementAtNodePath = findJsxElementAtNodePath;
|
|
184
|
+
const lineColumnToNodePath = (ast, targetLine) => {
|
|
185
|
+
let foundPath = null;
|
|
156
186
|
recast.types.visit(ast, {
|
|
157
|
-
visitJSXOpeningElement(
|
|
158
|
-
const { node } =
|
|
187
|
+
visitJSXOpeningElement(p) {
|
|
188
|
+
const { node } = p;
|
|
159
189
|
if (node.loc && node.loc.start.line === targetLine) {
|
|
160
|
-
|
|
190
|
+
foundPath = getNodePathForRecastPath(p);
|
|
161
191
|
return false;
|
|
162
192
|
}
|
|
163
|
-
return this.traverse(
|
|
193
|
+
return this.traverse(p);
|
|
164
194
|
},
|
|
165
195
|
});
|
|
166
|
-
return
|
|
196
|
+
return foundPath;
|
|
197
|
+
};
|
|
198
|
+
exports.lineColumnToNodePath = lineColumnToNodePath;
|
|
199
|
+
const PIXEL_VALUE_REGEX = /^-?\d+(\.\d+)?px$/;
|
|
200
|
+
const isSupportedTranslateValue = (value) => {
|
|
201
|
+
const parts = value.split(/\s+/);
|
|
202
|
+
if (parts.length === 1 || parts.length === 2) {
|
|
203
|
+
return parts.every((part) => PIXEL_VALUE_REGEX.test(part));
|
|
204
|
+
}
|
|
205
|
+
return false;
|
|
206
|
+
};
|
|
207
|
+
const validateStyleValue = (childKey, value) => {
|
|
208
|
+
if (childKey === 'translate' && typeof value === 'string') {
|
|
209
|
+
return isSupportedTranslateValue(value);
|
|
210
|
+
}
|
|
211
|
+
return true;
|
|
212
|
+
};
|
|
213
|
+
const getNestedPropStatus = (jsxElement, parentKey, childKey) => {
|
|
214
|
+
const attr = jsxElement.attributes.find((a) => a.type !== 'JSXSpreadAttribute' &&
|
|
215
|
+
a.name.type !== 'JSXNamespacedName' &&
|
|
216
|
+
a.name.name === parentKey);
|
|
217
|
+
if (!attr || !attr.value) {
|
|
218
|
+
// Parent attribute doesn't exist, nested prop can be added
|
|
219
|
+
return { canUpdate: true, codeValue: undefined };
|
|
220
|
+
}
|
|
221
|
+
if (attr.value.type !== 'JSXExpressionContainer') {
|
|
222
|
+
return { canUpdate: false, reason: 'computed' };
|
|
223
|
+
}
|
|
224
|
+
const { expression } = attr.value;
|
|
225
|
+
if (expression.type === 'JSXEmptyExpression' ||
|
|
226
|
+
expression.type !== 'ObjectExpression') {
|
|
227
|
+
// Parent is not an object literal (e.g. style={myStyles})
|
|
228
|
+
return { canUpdate: false, reason: 'computed' };
|
|
229
|
+
}
|
|
230
|
+
const objExpr = expression;
|
|
231
|
+
const prop = objExpr.properties.find((p) => p.type === 'ObjectProperty' &&
|
|
232
|
+
((p.key.type === 'Identifier' && p.key.name === childKey) ||
|
|
233
|
+
(p.key.type === 'StringLiteral' && p.key.value === childKey)));
|
|
234
|
+
if (!prop) {
|
|
235
|
+
// Property not set in the object, can be added
|
|
236
|
+
return { canUpdate: true, codeValue: undefined };
|
|
237
|
+
}
|
|
238
|
+
const propValue = prop.value;
|
|
239
|
+
if (!(0, exports.isStaticValue)(propValue)) {
|
|
240
|
+
return { canUpdate: false, reason: 'computed' };
|
|
241
|
+
}
|
|
242
|
+
const codeValue = (0, exports.extractStaticValue)(propValue);
|
|
243
|
+
if (!validateStyleValue(childKey, codeValue)) {
|
|
244
|
+
return { canUpdate: false, reason: 'computed' };
|
|
245
|
+
}
|
|
246
|
+
return { canUpdate: true, codeValue };
|
|
247
|
+
};
|
|
248
|
+
const computeSequencePropsStatusFromContent = (fileContents, nodePath, keys) => {
|
|
249
|
+
const ast = (0, parse_ast_1.parseAst)(fileContents);
|
|
250
|
+
const jsxElement = (0, exports.findJsxElementAtNodePath)(ast, nodePath);
|
|
251
|
+
if (!jsxElement) {
|
|
252
|
+
throw new Error('Could not find a JSX element at the specified location');
|
|
253
|
+
}
|
|
254
|
+
const allProps = getPropsStatus(jsxElement);
|
|
255
|
+
const filteredProps = {};
|
|
256
|
+
for (const key of keys) {
|
|
257
|
+
const dotIndex = key.indexOf('.');
|
|
258
|
+
if (dotIndex !== -1) {
|
|
259
|
+
filteredProps[key] = getNestedPropStatus(jsxElement, key.slice(0, dotIndex), key.slice(dotIndex + 1));
|
|
260
|
+
}
|
|
261
|
+
else if (key in allProps) {
|
|
262
|
+
filteredProps[key] = allProps[key];
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
filteredProps[key] = { canUpdate: true, codeValue: undefined };
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
canUpdate: true,
|
|
270
|
+
props: filteredProps,
|
|
271
|
+
nodePath,
|
|
272
|
+
};
|
|
273
|
+
};
|
|
274
|
+
exports.computeSequencePropsStatusFromContent = computeSequencePropsStatusFromContent;
|
|
275
|
+
const computeSequencePropsStatus = ({ fileName, nodePath, keys, remotionRoot, }) => {
|
|
276
|
+
try {
|
|
277
|
+
const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
|
|
278
|
+
const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
|
|
279
|
+
if (fileRelativeToRoot.startsWith('..')) {
|
|
280
|
+
throw new Error('Cannot read a file outside the project');
|
|
281
|
+
}
|
|
282
|
+
const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
|
|
283
|
+
return (0, exports.computeSequencePropsStatusFromContent)(fileContents, nodePath, keys);
|
|
284
|
+
}
|
|
285
|
+
catch (err) {
|
|
286
|
+
return {
|
|
287
|
+
canUpdate: false,
|
|
288
|
+
reason: err.message,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
167
291
|
};
|
|
168
|
-
|
|
292
|
+
exports.computeSequencePropsStatus = computeSequencePropsStatus;
|
|
293
|
+
const computeSequencePropsStatusByLine = ({ fileName, line, keys, remotionRoot, }) => {
|
|
169
294
|
try {
|
|
170
295
|
const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
|
|
171
296
|
const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
|
|
@@ -174,24 +299,16 @@ const computeSequencePropsStatus = ({ fileName, line, keys, remotionRoot, }) =>
|
|
|
174
299
|
}
|
|
175
300
|
const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
|
|
176
301
|
const ast = (0, parse_ast_1.parseAst)(fileContents);
|
|
177
|
-
const
|
|
178
|
-
if (!
|
|
302
|
+
const resolvedNodePath = (0, exports.lineColumnToNodePath)(ast, line);
|
|
303
|
+
if (!resolvedNodePath) {
|
|
179
304
|
throw new Error('Could not find a JSX element at the specified location');
|
|
180
305
|
}
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
else {
|
|
188
|
-
filteredProps[key] = { canUpdate: true, codeValue: undefined };
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
return {
|
|
192
|
-
canUpdate: true,
|
|
193
|
-
props: filteredProps,
|
|
194
|
-
};
|
|
306
|
+
return (0, exports.computeSequencePropsStatus)({
|
|
307
|
+
fileName,
|
|
308
|
+
nodePath: resolvedNodePath,
|
|
309
|
+
keys,
|
|
310
|
+
remotionRoot,
|
|
311
|
+
});
|
|
195
312
|
}
|
|
196
313
|
catch (err) {
|
|
197
314
|
return {
|
|
@@ -200,4 +317,4 @@ const computeSequencePropsStatus = ({ fileName, line, keys, remotionRoot, }) =>
|
|
|
200
317
|
};
|
|
201
318
|
}
|
|
202
319
|
};
|
|
203
|
-
exports.
|
|
320
|
+
exports.computeSequencePropsStatusByLine = computeSequencePropsStatusByLine;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const logUpdate: ({ absolutePath, fileRelativeToRoot, key, oldValueString, newValueString, defaultValueString, formatted, logLevel, }: {
|
|
2
|
+
absolutePath: string;
|
|
3
|
+
fileRelativeToRoot: string;
|
|
4
|
+
key: string;
|
|
5
|
+
oldValueString: string;
|
|
6
|
+
newValueString: string;
|
|
7
|
+
defaultValueString: string | null;
|
|
8
|
+
formatted: boolean;
|
|
9
|
+
logLevel: "error" | "info" | "trace" | "verbose" | "warn";
|
|
10
|
+
}) => void;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logUpdate = void 0;
|
|
4
|
+
const renderer_1 = require("@remotion/renderer");
|
|
5
|
+
const make_link_1 = require("../../hyperlinks/make-link");
|
|
6
|
+
let warnedAboutPrettier = false;
|
|
7
|
+
const normalizeQuotes = (str) => {
|
|
8
|
+
if (str.length >= 2 &&
|
|
9
|
+
((str.startsWith("'") && str.endsWith("'")) ||
|
|
10
|
+
(str.startsWith('"') && str.endsWith('"')))) {
|
|
11
|
+
return `'${str.slice(1, -1)}'`;
|
|
12
|
+
}
|
|
13
|
+
return str;
|
|
14
|
+
};
|
|
15
|
+
const formatValueChange = ({ oldValueString, newValueString, defaultValueString, }) => {
|
|
16
|
+
// Changed to default value (prop gets deleted) → show only old value in red
|
|
17
|
+
if (defaultValueString !== null && newValueString === defaultValueString) {
|
|
18
|
+
return renderer_1.RenderInternals.chalk.red(oldValueString);
|
|
19
|
+
}
|
|
20
|
+
// Changed from default value (prop gets added) → show only new value in green
|
|
21
|
+
if (defaultValueString !== null && oldValueString === defaultValueString) {
|
|
22
|
+
return renderer_1.RenderInternals.chalk.green(newValueString);
|
|
23
|
+
}
|
|
24
|
+
return `${renderer_1.RenderInternals.chalk.red(oldValueString)} \u2192 ${renderer_1.RenderInternals.chalk.green(newValueString)}`;
|
|
25
|
+
};
|
|
26
|
+
const formatPropChange = ({ key, oldValueString, newValueString, defaultValueString, }) => {
|
|
27
|
+
const isResetToDefault = defaultValueString !== null && newValueString === defaultValueString;
|
|
28
|
+
const isChangeFromDefault = defaultValueString !== null && oldValueString === defaultValueString;
|
|
29
|
+
const valueChange = formatValueChange({
|
|
30
|
+
oldValueString,
|
|
31
|
+
newValueString,
|
|
32
|
+
defaultValueString,
|
|
33
|
+
});
|
|
34
|
+
const dotIndex = key.indexOf('.');
|
|
35
|
+
if (dotIndex === -1) {
|
|
36
|
+
if (isResetToDefault) {
|
|
37
|
+
return renderer_1.RenderInternals.chalk.red(`${key}={${oldValueString}}`);
|
|
38
|
+
}
|
|
39
|
+
if (isChangeFromDefault) {
|
|
40
|
+
return renderer_1.RenderInternals.chalk.green(`${key}={${newValueString}}`);
|
|
41
|
+
}
|
|
42
|
+
return `${key}={${valueChange}}`;
|
|
43
|
+
}
|
|
44
|
+
const parentKey = key.slice(0, dotIndex);
|
|
45
|
+
const childKey = key.slice(dotIndex + 1);
|
|
46
|
+
if (isResetToDefault) {
|
|
47
|
+
return `${parentKey}={{${renderer_1.RenderInternals.chalk.red(`${childKey}: ${oldValueString}`)}}}`;
|
|
48
|
+
}
|
|
49
|
+
if (isChangeFromDefault) {
|
|
50
|
+
return `${parentKey}={{${renderer_1.RenderInternals.chalk.green(`${childKey}: ${newValueString}`)}}}`;
|
|
51
|
+
}
|
|
52
|
+
return `${parentKey}={{${childKey}: ${valueChange}}}`;
|
|
53
|
+
};
|
|
54
|
+
const logUpdate = ({ absolutePath, fileRelativeToRoot, key, oldValueString, newValueString, defaultValueString, formatted, logLevel, }) => {
|
|
55
|
+
const locationLabel = `${fileRelativeToRoot}`;
|
|
56
|
+
const fileLink = (0, make_link_1.makeHyperlink)({
|
|
57
|
+
url: `file://${absolutePath}`,
|
|
58
|
+
text: locationLabel,
|
|
59
|
+
fallback: locationLabel,
|
|
60
|
+
});
|
|
61
|
+
const propChange = formatPropChange({
|
|
62
|
+
key,
|
|
63
|
+
oldValueString: normalizeQuotes(oldValueString),
|
|
64
|
+
newValueString: normalizeQuotes(newValueString),
|
|
65
|
+
defaultValueString: defaultValueString !== null ? normalizeQuotes(defaultValueString) : null,
|
|
66
|
+
});
|
|
67
|
+
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(`${fileLink}:`)} ${propChange}`);
|
|
68
|
+
if (!formatted && !warnedAboutPrettier) {
|
|
69
|
+
warnedAboutPrettier = true;
|
|
70
|
+
renderer_1.RenderInternals.Log.warn({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.yellow('Could not format with Prettier. File will need to be formatted manually.'));
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
exports.logUpdate = logUpdate;
|
|
@@ -6,11 +6,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.saveSequencePropsHandler = void 0;
|
|
7
7
|
const node_fs_1 = require("node:fs");
|
|
8
8
|
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
-
const renderer_1 = require("@remotion/renderer");
|
|
10
9
|
const update_sequence_props_1 = require("../../codemods/update-sequence-props");
|
|
11
|
-
const make_link_1 = require("../../hyperlinks/make-link");
|
|
12
10
|
const hmr_suppression_1 = require("../hmr-suppression");
|
|
13
|
-
const
|
|
11
|
+
const log_update_1 = require("./log-update");
|
|
12
|
+
const saveSequencePropsHandler = async ({ input: { fileName, nodePath, key, value, defaultValue }, remotionRoot, logLevel, }) => {
|
|
14
13
|
try {
|
|
15
14
|
const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
|
|
16
15
|
const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
|
|
@@ -18,24 +17,27 @@ const saveSequencePropsHandler = async ({ input: { fileName, line, column, key,
|
|
|
18
17
|
throw new Error('Cannot modify a file outside the project');
|
|
19
18
|
}
|
|
20
19
|
const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
|
|
21
|
-
const { output, oldValueString } = await (0, update_sequence_props_1.updateSequenceProps)({
|
|
20
|
+
const { output, oldValueString, formatted } = await (0, update_sequence_props_1.updateSequenceProps)({
|
|
22
21
|
input: fileContents,
|
|
23
|
-
|
|
22
|
+
nodePath,
|
|
24
23
|
key,
|
|
25
24
|
value: JSON.parse(value),
|
|
26
|
-
enumPaths,
|
|
27
25
|
defaultValue: defaultValue !== null ? JSON.parse(defaultValue) : null,
|
|
28
26
|
});
|
|
29
27
|
(0, hmr_suppression_1.suppressHmrForFile)(absolutePath);
|
|
30
28
|
(0, node_fs_1.writeFileSync)(absolutePath, output);
|
|
31
29
|
const newValueString = JSON.stringify(JSON.parse(value));
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
const parsedDefault = defaultValue !== null ? JSON.parse(defaultValue) : null;
|
|
31
|
+
(0, log_update_1.logUpdate)({
|
|
32
|
+
absolutePath,
|
|
33
|
+
fileRelativeToRoot,
|
|
34
|
+
key,
|
|
35
|
+
oldValueString,
|
|
36
|
+
newValueString,
|
|
37
|
+
defaultValueString: parsedDefault !== null ? JSON.stringify(parsedDefault) : null,
|
|
38
|
+
formatted,
|
|
39
|
+
logLevel,
|
|
37
40
|
});
|
|
38
|
-
renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, renderer_1.RenderInternals.chalk.blueBright(`${fileLink} updated: ${key} ${oldValueString} \u2192 ${newValueString}`));
|
|
39
41
|
return {
|
|
40
42
|
success: true,
|
|
41
43
|
};
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.subscribeToSequenceProps = void 0;
|
|
4
4
|
const sequence_props_watchers_1 = require("../sequence-props-watchers");
|
|
5
|
-
const subscribeToSequenceProps = ({ input: { fileName, line,
|
|
5
|
+
const subscribeToSequenceProps = ({ input: { fileName, line, keys, clientId }, remotionRoot }) => {
|
|
6
6
|
const result = (0, sequence_props_watchers_1.subscribeToSequencePropsWatchers)({
|
|
7
7
|
fileName,
|
|
8
8
|
line,
|
|
9
|
-
column,
|
|
10
9
|
keys,
|
|
11
10
|
remotionRoot,
|
|
12
11
|
clientId,
|
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.unsubscribeFromSequenceProps = void 0;
|
|
4
4
|
const sequence_props_watchers_1 = require("../sequence-props-watchers");
|
|
5
|
-
const unsubscribeFromSequenceProps = ({ input: { fileName,
|
|
5
|
+
const unsubscribeFromSequenceProps = ({ input: { fileName, nodePath, clientId }, remotionRoot }) => {
|
|
6
6
|
(0, sequence_props_watchers_1.unsubscribeFromSequencePropsWatchers)({
|
|
7
7
|
fileName,
|
|
8
|
-
|
|
9
|
-
column,
|
|
8
|
+
nodePath,
|
|
10
9
|
remotionRoot,
|
|
11
10
|
clientId,
|
|
12
11
|
});
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import type { CanUpdateSequencePropsResponse } from '@remotion/studio-shared';
|
|
2
|
-
export declare const subscribeToSequencePropsWatchers: ({ fileName, line,
|
|
1
|
+
import type { CanUpdateSequencePropsResponse, SequenceNodePath } from '@remotion/studio-shared';
|
|
2
|
+
export declare const subscribeToSequencePropsWatchers: ({ fileName, line, keys, remotionRoot, clientId, }: {
|
|
3
3
|
fileName: string;
|
|
4
4
|
line: number;
|
|
5
|
-
column: number;
|
|
6
5
|
keys: string[];
|
|
7
6
|
remotionRoot: string;
|
|
8
7
|
clientId: string;
|
|
9
8
|
}) => CanUpdateSequencePropsResponse;
|
|
10
|
-
export declare const unsubscribeFromSequencePropsWatchers: ({ fileName,
|
|
9
|
+
export declare const unsubscribeFromSequencePropsWatchers: ({ fileName, nodePath, remotionRoot, clientId, }: {
|
|
11
10
|
fileName: string;
|
|
12
|
-
|
|
13
|
-
column: number;
|
|
11
|
+
nodePath: SequenceNodePath;
|
|
14
12
|
remotionRoot: string;
|
|
15
13
|
clientId: string;
|
|
16
14
|
}) => void;
|
|
@@ -9,23 +9,28 @@ const file_watcher_1 = require("../file-watcher");
|
|
|
9
9
|
const live_events_1 = require("./live-events");
|
|
10
10
|
const can_update_sequence_props_1 = require("./routes/can-update-sequence-props");
|
|
11
11
|
const sequencePropsWatchers = {};
|
|
12
|
-
const makeWatcherKey = ({ absolutePath,
|
|
13
|
-
return `${absolutePath}:${
|
|
12
|
+
const makeWatcherKey = ({ absolutePath, nodePath, }) => {
|
|
13
|
+
return `${absolutePath}:${JSON.stringify(nodePath)}`;
|
|
14
14
|
};
|
|
15
|
-
const subscribeToSequencePropsWatchers = ({ fileName, line,
|
|
15
|
+
const subscribeToSequencePropsWatchers = ({ fileName, line, keys, remotionRoot, clientId, }) => {
|
|
16
16
|
var _a;
|
|
17
17
|
const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
if ((_a = sequencePropsWatchers[clientId]) === null || _a === void 0 ? void 0 : _a[watcherKey]) {
|
|
21
|
-
sequencePropsWatchers[clientId][watcherKey].unwatch();
|
|
22
|
-
}
|
|
23
|
-
const initialResult = (0, can_update_sequence_props_1.computeSequencePropsStatus)({
|
|
18
|
+
// Initial lookup by line+column to resolve the nodePath
|
|
19
|
+
const initialResult = (0, can_update_sequence_props_1.computeSequencePropsStatusByLine)({
|
|
24
20
|
fileName,
|
|
25
21
|
line,
|
|
26
22
|
keys,
|
|
27
23
|
remotionRoot,
|
|
28
24
|
});
|
|
25
|
+
if (!initialResult.canUpdate) {
|
|
26
|
+
return initialResult;
|
|
27
|
+
}
|
|
28
|
+
const { nodePath } = initialResult;
|
|
29
|
+
const watcherKey = makeWatcherKey({ absolutePath, nodePath });
|
|
30
|
+
// Unwatch any existing watcher for the same key
|
|
31
|
+
if ((_a = sequencePropsWatchers[clientId]) === null || _a === void 0 ? void 0 : _a[watcherKey]) {
|
|
32
|
+
sequencePropsWatchers[clientId][watcherKey].unwatch();
|
|
33
|
+
}
|
|
29
34
|
const { unwatch } = (0, file_watcher_1.installFileWatcher)({
|
|
30
35
|
file: absolutePath,
|
|
31
36
|
onChange: (type) => {
|
|
@@ -34,7 +39,7 @@ const subscribeToSequencePropsWatchers = ({ fileName, line, column, keys, remoti
|
|
|
34
39
|
}
|
|
35
40
|
const result = (0, can_update_sequence_props_1.computeSequencePropsStatus)({
|
|
36
41
|
fileName,
|
|
37
|
-
|
|
42
|
+
nodePath,
|
|
38
43
|
keys,
|
|
39
44
|
remotionRoot,
|
|
40
45
|
});
|
|
@@ -42,8 +47,7 @@ const subscribeToSequencePropsWatchers = ({ fileName, line, column, keys, remoti
|
|
|
42
47
|
listener.sendEventToClient({
|
|
43
48
|
type: 'sequence-props-updated',
|
|
44
49
|
fileName,
|
|
45
|
-
|
|
46
|
-
column,
|
|
50
|
+
nodePath,
|
|
47
51
|
result,
|
|
48
52
|
});
|
|
49
53
|
});
|
|
@@ -56,14 +60,16 @@ const subscribeToSequencePropsWatchers = ({ fileName, line, column, keys, remoti
|
|
|
56
60
|
return initialResult;
|
|
57
61
|
};
|
|
58
62
|
exports.subscribeToSequencePropsWatchers = subscribeToSequencePropsWatchers;
|
|
59
|
-
const unsubscribeFromSequencePropsWatchers = ({ fileName,
|
|
60
|
-
var _a;
|
|
63
|
+
const unsubscribeFromSequencePropsWatchers = ({ fileName, nodePath, remotionRoot, clientId, }) => {
|
|
61
64
|
const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
|
|
62
|
-
const watcherKey = makeWatcherKey({ absolutePath,
|
|
63
|
-
if (!sequencePropsWatchers[clientId]
|
|
65
|
+
const watcherKey = makeWatcherKey({ absolutePath, nodePath });
|
|
66
|
+
if (!sequencePropsWatchers[clientId] ||
|
|
67
|
+
!sequencePropsWatchers[clientId][watcherKey]) {
|
|
68
|
+
// eslint-disable-next-line no-console
|
|
69
|
+
console.warn(`Unexpected: unsubscribe for sequence props watcher that does not exist (clientId=${clientId}, key=${watcherKey})`);
|
|
64
70
|
return;
|
|
65
71
|
}
|
|
66
|
-
|
|
72
|
+
sequencePropsWatchers[clientId][watcherKey].unwatch();
|
|
67
73
|
delete sequencePropsWatchers[clientId][watcherKey];
|
|
68
74
|
};
|
|
69
75
|
exports.unsubscribeFromSequencePropsWatchers = unsubscribeFromSequencePropsWatchers;
|
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.
|
|
6
|
+
"version": "4.0.433",
|
|
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.
|
|
30
|
+
"remotion": "4.0.433",
|
|
31
31
|
"recast": "0.23.11",
|
|
32
|
-
"@remotion/bundler": "4.0.
|
|
33
|
-
"@remotion/renderer": "4.0.
|
|
34
|
-
"@remotion/studio-shared": "4.0.
|
|
32
|
+
"@remotion/bundler": "4.0.433",
|
|
33
|
+
"@remotion/renderer": "4.0.433",
|
|
34
|
+
"@remotion/studio-shared": "4.0.433",
|
|
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.
|
|
44
|
+
"@remotion/eslint-config-internal": "4.0.433",
|
|
45
45
|
"eslint": "9.19.0",
|
|
46
46
|
"@types/node": "20.12.14",
|
|
47
47
|
"@typescript/native-preview": "7.0.0-dev.20260217.1"
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import type { File } from '@babel/types';
|
|
2
|
-
import { type ApplyComponentVisualControlCodemod } from '@remotion/studio-shared';
|
|
3
|
-
import type { ApplyCodeModReturnType, Change } from './recast-mods';
|
|
4
|
-
export declare const applyComponentVisualControl: ({ file, transformation, changesMade, }: {
|
|
5
|
-
file: File;
|
|
6
|
-
transformation: ApplyComponentVisualControlCodemod;
|
|
7
|
-
changesMade: Change[];
|
|
8
|
-
}) => ApplyCodeModReturnType;
|
|
@@ -1,92 +0,0 @@
|
|
|
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.applyComponentVisualControl = void 0;
|
|
37
|
-
const studio_shared_1 = require("@remotion/studio-shared");
|
|
38
|
-
const recast = __importStar(require("recast"));
|
|
39
|
-
const parse_ast_1 = require("./parse-ast");
|
|
40
|
-
const applyComponentVisualControl = ({ file, transformation, changesMade, }) => {
|
|
41
|
-
recast.types.visit(file.program, {
|
|
42
|
-
visitJSXOpeningElement(path) {
|
|
43
|
-
var _a;
|
|
44
|
-
const { node } = path;
|
|
45
|
-
if (node.name.type !== 'JSXIdentifier' ||
|
|
46
|
-
node.name.name !== transformation.componentName) {
|
|
47
|
-
return this.traverse(path);
|
|
48
|
-
}
|
|
49
|
-
if (((_a = node.loc) === null || _a === void 0 ? void 0 : _a.start.line) !== transformation.line) {
|
|
50
|
-
return this.traverse(path);
|
|
51
|
-
}
|
|
52
|
-
const attributes = node.attributes;
|
|
53
|
-
if (!attributes) {
|
|
54
|
-
return this.traverse(path);
|
|
55
|
-
}
|
|
56
|
-
for (const change of transformation.changes) {
|
|
57
|
-
const parsed = (0, parse_ast_1.parseAst)(`a = ${(0, studio_shared_1.stringifyDefaultProps)({ props: JSON.parse(change.newValueSerialized), enumPaths: change.enumPaths })}`).program.body[0].expression.right;
|
|
58
|
-
const existingAttr = attributes.find((attr) => attr.type === 'JSXAttribute' &&
|
|
59
|
-
attr.name.type === 'JSXIdentifier' &&
|
|
60
|
-
attr.name.name === change.propName);
|
|
61
|
-
if (existingAttr && existingAttr.type === 'JSXAttribute') {
|
|
62
|
-
existingAttr.value = {
|
|
63
|
-
type: 'JSXExpressionContainer',
|
|
64
|
-
expression: parsed,
|
|
65
|
-
};
|
|
66
|
-
changesMade.push({
|
|
67
|
-
description: `Updated prop ${change.propName} on ${transformation.componentName}`,
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
else {
|
|
71
|
-
attributes.push({
|
|
72
|
-
type: 'JSXAttribute',
|
|
73
|
-
name: {
|
|
74
|
-
type: 'JSXIdentifier',
|
|
75
|
-
name: change.propName,
|
|
76
|
-
},
|
|
77
|
-
value: {
|
|
78
|
-
type: 'JSXExpressionContainer',
|
|
79
|
-
expression: parsed,
|
|
80
|
-
},
|
|
81
|
-
});
|
|
82
|
-
changesMade.push({
|
|
83
|
-
description: `Added prop ${change.propName} to ${transformation.componentName}`,
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
return false;
|
|
88
|
-
},
|
|
89
|
-
});
|
|
90
|
-
return { newAst: file, changesMade };
|
|
91
|
-
};
|
|
92
|
-
exports.applyComponentVisualControl = applyComponentVisualControl;
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import type { ApplyComponentVisualControlRequest, ApplyComponentVisualControlResponse } from '@remotion/studio-shared';
|
|
2
|
-
import type { ApiHandler } from '../api-types';
|
|
3
|
-
export declare const applyComponentVisualControlHandler: ApiHandler<ApplyComponentVisualControlRequest, ApplyComponentVisualControlResponse>;
|
|
@@ -1,38 +0,0 @@
|
|
|
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.applyComponentVisualControlHandler = void 0;
|
|
7
|
-
const node_fs_1 = require("node:fs");
|
|
8
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
-
const parse_ast_1 = require("../../codemods/parse-ast");
|
|
10
|
-
const recast_mods_1 = require("../../codemods/recast-mods");
|
|
11
|
-
const applyComponentVisualControlHandler = ({ input: { fileName, componentName, line, column, changes }, remotionRoot }) => {
|
|
12
|
-
const absolutePath = node_path_1.default.resolve(remotionRoot, fileName);
|
|
13
|
-
const fileRelativeToRoot = node_path_1.default.relative(remotionRoot, absolutePath);
|
|
14
|
-
if (fileRelativeToRoot.startsWith('..')) {
|
|
15
|
-
throw new Error('Cannot apply component visual control change to a file outside the project');
|
|
16
|
-
}
|
|
17
|
-
const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
|
|
18
|
-
const ast = (0, parse_ast_1.parseAst)(fileContents);
|
|
19
|
-
const { newAst, changesMade } = (0, recast_mods_1.applyCodemod)({
|
|
20
|
-
file: ast,
|
|
21
|
-
codeMod: {
|
|
22
|
-
type: 'apply-component-visual-control',
|
|
23
|
-
componentName,
|
|
24
|
-
line,
|
|
25
|
-
column,
|
|
26
|
-
changes,
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
|
-
if (changesMade.length === 0) {
|
|
30
|
-
throw new Error('No changes were made to the file');
|
|
31
|
-
}
|
|
32
|
-
const output = (0, parse_ast_1.serializeAst)(newAst);
|
|
33
|
-
(0, node_fs_1.writeFileSync)(absolutePath, output);
|
|
34
|
-
return Promise.resolve({
|
|
35
|
-
success: true,
|
|
36
|
-
});
|
|
37
|
-
};
|
|
38
|
-
exports.applyComponentVisualControlHandler = applyComponentVisualControlHandler;
|