@remotion/studio-server 4.0.500 → 4.0.502

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/dist/codemods/update-inline-caption-patches.d.ts +1 -0
  2. package/dist/codemods/update-inline-caption-patches.js +5 -0
  3. package/dist/codemods/update-sequence-props/update-sequence-props.d.ts +2 -35
  4. package/dist/codemods/update-sequence-props/update-sequence-props.js +7 -718
  5. package/dist/helpers/css-shorthand-properties.d.ts +9 -3
  6. package/dist/helpers/css-shorthand-properties.js +16 -2
  7. package/dist/helpers/parse-border-radius-shorthand.d.ts +7 -0
  8. package/dist/helpers/parse-border-radius-shorthand.js +53 -0
  9. package/dist/helpers/resolve-composition-component.js +80 -52
  10. package/dist/preview-server/element-install-state.d.ts +16 -0
  11. package/dist/preview-server/element-install-state.js +43 -1
  12. package/dist/preview-server/handler.js +1 -1
  13. package/dist/preview-server/parse-body.d.ts +6 -1
  14. package/dist/preview-server/parse-body.js +60 -9
  15. package/dist/preview-server/routes/can-update-default-props.d.ts +1 -1
  16. package/dist/preview-server/routes/can-update-default-props.js +5 -132
  17. package/dist/preview-server/routes/can-update-sequence-props.d.ts +3 -2
  18. package/dist/preview-server/routes/can-update-sequence-props.js +130 -12
  19. package/dist/preview-server/routes/find-in-file.d.ts +1 -9
  20. package/dist/preview-server/routes/find-in-file.js +4 -17
  21. package/dist/preview-server/routes/insert-element.js +40 -20
  22. package/dist/preview-server/routes/insert-jsx-element.js +5 -5
  23. package/dist/preview-server/routes/save-sequence-props.js +73 -8
  24. package/dist/preview-server/sequence-props-watchers.js +2 -1
  25. package/dist/preview-server/studio-protocol/handle-discovery.d.ts +11 -0
  26. package/dist/preview-server/studio-protocol/handle-discovery.js +99 -0
  27. package/dist/preview-server/studio-protocol/handle-install.d.ts +10 -0
  28. package/dist/preview-server/studio-protocol/handle-install.js +139 -0
  29. package/dist/preview-server/studio-protocol/origin-policy.d.ts +10 -0
  30. package/dist/preview-server/studio-protocol/origin-policy.js +40 -0
  31. package/dist/preview-server/studio-protocol/protocol-response.d.ts +7 -0
  32. package/dist/preview-server/studio-protocol/protocol-response.js +13 -0
  33. package/dist/routes.js +14 -154
  34. package/package.json +9 -7
@@ -1,44 +1,11 @@
1
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
2
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.computeCanUpdateDefaultProps = exports.computeCanUpdateDefaultPropsFromContent = exports.checkIfTypeScriptFile = void 0;
3
+ exports.computeCanUpdateDefaultProps = exports.checkIfTypeScriptFile = exports.computeCanUpdateDefaultPropsFromContent = void 0;
37
4
  const node_fs_1 = require("node:fs");
38
- const recast = __importStar(require("recast"));
39
- const parse_ast_1 = require("../../codemods/parse-ast");
5
+ const studio_codemods_1 = require("@remotion/studio-codemods");
40
6
  const project_info_1 = require("../project-info");
41
- const can_update_sequence_props_1 = require("./can-update-sequence-props");
7
+ const studio_codemods_2 = require("@remotion/studio-codemods");
8
+ Object.defineProperty(exports, "computeCanUpdateDefaultPropsFromContent", { enumerable: true, get: function () { return studio_codemods_2.computeCanUpdateDefaultPropsFromContent; } });
42
9
  const checkIfTypeScriptFile = (file) => {
43
10
  if (!file.endsWith('.tsx') &&
44
11
  !file.endsWith('.ts') &&
@@ -48,100 +15,6 @@ const checkIfTypeScriptFile = (file) => {
48
15
  }
49
16
  };
50
17
  exports.checkIfTypeScriptFile = checkIfTypeScriptFile;
51
- const extractDefaultPropsFromSource = (input, compositionId) => {
52
- const ast = (0, parse_ast_1.parseAst)(input);
53
- let result = null;
54
- recast.types.visit(ast, {
55
- visitJSXElement(path) {
56
- var _a;
57
- const { openingElement } = path.node;
58
- const openingName = openingElement.name;
59
- if (openingName.type !== 'JSXIdentifier' &&
60
- openingName.type !== 'JSXNamespacedName') {
61
- this.traverse(path);
62
- return;
63
- }
64
- if (openingName.name !== 'Composition' && openingName.name !== 'Still') {
65
- this.traverse(path);
66
- return;
67
- }
68
- if (!((_a = openingElement.attributes) === null || _a === void 0 ? void 0 : _a.some((attr) => {
69
- if (attr.type === 'JSXSpreadAttribute') {
70
- return;
71
- }
72
- if (!attr.value) {
73
- return;
74
- }
75
- if (attr.value.type === 'JSXElement') {
76
- return;
77
- }
78
- if (attr.value.type === 'JSXExpressionContainer') {
79
- return;
80
- }
81
- if (attr.value.type === 'JSXFragment') {
82
- return;
83
- }
84
- return attr.name.name === 'id' && attr.value.value === compositionId;
85
- }))) {
86
- this.traverse(path);
87
- return;
88
- }
89
- const defaultPropsAttr = openingElement.attributes.find((attr) => {
90
- if (attr.type === 'JSXSpreadAttribute') {
91
- return;
92
- }
93
- return attr.name.name === 'defaultProps';
94
- });
95
- if (!defaultPropsAttr || defaultPropsAttr.type === 'JSXSpreadAttribute') {
96
- this.traverse(path);
97
- return;
98
- }
99
- if (!defaultPropsAttr.value ||
100
- defaultPropsAttr.value.type !== 'JSXExpressionContainer') {
101
- this.traverse(path);
102
- return;
103
- }
104
- const { expression } = defaultPropsAttr.value;
105
- if (expression.type === 'JSXEmptyExpression') {
106
- this.traverse(path);
107
- return;
108
- }
109
- if ((0, can_update_sequence_props_1.isStaticValue)(expression, {
110
- allowSpecialValues: true,
111
- })) {
112
- const value = (0, can_update_sequence_props_1.extractStaticValue)(expression, {
113
- allowSpecialValues: true,
114
- });
115
- if (value !== null &&
116
- typeof value === 'object' &&
117
- !Array.isArray(value)) {
118
- result = value;
119
- }
120
- }
121
- this.traverse(path);
122
- },
123
- });
124
- return result;
125
- };
126
- const computeCanUpdateDefaultPropsFromContent = (content, compositionId) => {
127
- try {
128
- const currentDefaultProps = extractDefaultPropsFromSource(content, compositionId);
129
- if (currentDefaultProps === null) {
130
- throw new Error(`Could not find or extract defaultProps for composition "${compositionId}"`);
131
- }
132
- return {
133
- canUpdate: true,
134
- currentDefaultProps,
135
- };
136
- }
137
- catch (err) {
138
- return {
139
- canUpdate: false,
140
- reason: err.message,
141
- };
142
- }
143
- };
144
- exports.computeCanUpdateDefaultPropsFromContent = computeCanUpdateDefaultPropsFromContent;
145
18
  const computeCanUpdateDefaultProps = async ({ compositionId, remotionRoot, entryPoint, }) => {
146
19
  try {
147
20
  const projectInfo = await (0, project_info_1.getProjectInfo)(remotionRoot, entryPoint);
@@ -150,7 +23,7 @@ const computeCanUpdateDefaultProps = async ({ compositionId, remotionRoot, entry
150
23
  }
151
24
  (0, exports.checkIfTypeScriptFile)(projectInfo.rootFile);
152
25
  const input = (0, node_fs_1.readFileSync)(projectInfo.rootFile, 'utf-8');
153
- const result = (0, exports.computeCanUpdateDefaultPropsFromContent)(input, compositionId);
26
+ const result = (0, studio_codemods_1.computeCanUpdateDefaultPropsFromContent)(input, compositionId);
154
27
  return {
155
28
  result,
156
29
  rootFile: projectInfo.rootFile,
@@ -22,7 +22,7 @@ export declare const getStaticJsxChildrenAttribute: (jsxElement: JSXOpeningEleme
22
22
  export declare const hasJsxChildrenAttribute: (jsxElement: JSXOpeningElement) => boolean;
23
23
  export declare const getStaticJsxTextContent: (jsxElement: JSXElement) => StaticJsxTextContent | null;
24
24
  export declare const findNodePathForJsxElement: (ast: File, target: JSXOpeningElement) => SequenceNodePath | null;
25
- export declare const lineColumnToNodePath: (ast: File, targetLine: number) => SequenceNodePath | null;
25
+ export declare const lineColumnToNodePath: (ast: File, targetLine: number, targetColumn?: number | undefined, fileContents?: string | undefined) => SequenceNodePath | null;
26
26
  export declare const computeSequencePropsStatusFromContent: ({ fileContents, nodePath, componentIdentity, keys, assetKeys, effects, videoConfigValues, }: {
27
27
  fileContents: string;
28
28
  nodePath: SequenceNodePath;
@@ -42,9 +42,10 @@ export declare const computeSequencePropsStatus: ({ fileName, nodePath, componen
42
42
  remotionRoot: string;
43
43
  videoConfigValues: VideoConfigValues | null;
44
44
  }) => CanUpdateSequencePropsResponseTrue;
45
- export declare const computeSequencePropsStatusFromFilenameByLine: ({ fileName, line, componentIdentity, keys, assetKeys, effects, remotionRoot, logLevel, videoConfigValues, }: {
45
+ export declare const computeSequencePropsStatusFromFilenameByLocation: ({ fileName, line, column, componentIdentity, keys, assetKeys, effects, remotionRoot, logLevel, videoConfigValues, }: {
46
46
  fileName: string;
47
47
  line: number;
48
+ column: number;
48
49
  componentIdentity: string | null;
49
50
  keys: string[];
50
51
  assetKeys?: string[] | undefined;
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.computeSequencePropsStatusFromFilenameByLine = exports.computeSequencePropsStatus = exports.computeSequencePropsStatusFromContent = exports.lineColumnToNodePath = exports.findNodePathForJsxElement = exports.getStaticJsxTextContent = exports.hasJsxChildrenAttribute = exports.getStaticJsxChildrenAttribute = exports.findJsxElementNodeAtNodePath = exports.findJsxElementAtNodePath = exports.findJsxElementPathAtNodePath = exports.getComputedStatus = exports.extractStaticValue = exports.isStaticValue = void 0;
36
+ exports.computeSequencePropsStatusFromFilenameByLocation = exports.computeSequencePropsStatus = exports.computeSequencePropsStatusFromContent = exports.lineColumnToNodePath = exports.findNodePathForJsxElement = exports.getStaticJsxTextContent = exports.hasJsxChildrenAttribute = exports.getStaticJsxChildrenAttribute = exports.findJsxElementNodeAtNodePath = exports.findJsxElementAtNodePath = exports.findJsxElementPathAtNodePath = exports.getComputedStatus = exports.extractStaticValue = exports.isStaticValue = void 0;
37
37
  const node_fs_1 = require("node:fs");
38
38
  const renderer_1 = require("@remotion/renderer");
39
39
  const studio_shared_1 = require("@remotion/studio-shared");
@@ -43,6 +43,7 @@ const parse_ast_1 = require("../../codemods/parse-ast");
43
43
  const css_shorthand_properties_1 = require("../../helpers/css-shorthand-properties");
44
44
  const get_ast_node_path_1 = require("../../helpers/get-ast-node-path");
45
45
  const import_agnostic_node_path_1 = require("../../helpers/import-agnostic-node-path");
46
+ const parse_border_radius_shorthand_1 = require("../../helpers/parse-border-radius-shorthand");
46
47
  const parse_keyframe_easing_expression_1 = require("../../helpers/parse-keyframe-easing-expression");
47
48
  const resolve_file_inside_project_1 = require("../../helpers/resolve-file-inside-project");
48
49
  const video_config_numeric_expression_1 = require("../../helpers/video-config-numeric-expression");
@@ -641,19 +642,51 @@ const findNodePathForJsxElement = (ast, target) => {
641
642
  return foundPath;
642
643
  };
643
644
  exports.findNodePathForJsxElement = findNodePathForJsxElement;
644
- const lineColumnToNodePath = (ast, targetLine) => {
645
- let foundPath = null;
645
+ const RECAST_TAB_WIDTH = 4;
646
+ const sourceColumnToRecastColumn = ({ fileContents, line, column, }) => {
647
+ const sourceLine = fileContents.split('\n')[line - 1];
648
+ if (sourceLine === undefined) {
649
+ return column;
650
+ }
651
+ let recastColumn = 0;
652
+ for (let index = 0; index < column; index++) {
653
+ if (sourceLine[index] === '\t') {
654
+ recastColumn += RECAST_TAB_WIDTH - (recastColumn % RECAST_TAB_WIDTH);
655
+ }
656
+ else {
657
+ recastColumn++;
658
+ }
659
+ }
660
+ return recastColumn;
661
+ };
662
+ const lineColumnToNodePath = (ast, targetLine, targetColumn, fileContents) => {
663
+ var _a;
664
+ const lineMatches = [];
665
+ const exactMatches = [];
666
+ const recastTargetColumn = targetColumn === undefined || fileContents === undefined
667
+ ? targetColumn
668
+ : sourceColumnToRecastColumn({
669
+ fileContents,
670
+ line: targetLine,
671
+ column: targetColumn,
672
+ });
646
673
  recast.types.visit(ast, {
647
674
  visitJSXOpeningElement(p) {
648
675
  const { node } = p;
649
676
  if (node.loc && node.loc.start.line === targetLine) {
650
- foundPath = getNodePathForRecastPath(p, ast);
651
- return false;
677
+ const nodePath = getNodePathForRecastPath(p, ast);
678
+ lineMatches.push(nodePath);
679
+ if (node.loc.start.column === recastTargetColumn) {
680
+ exactMatches.push(nodePath);
681
+ }
652
682
  }
653
683
  return this.traverse(p);
654
684
  },
655
685
  });
656
- return foundPath;
686
+ if (exactMatches.length === 1) {
687
+ return exactMatches[0];
688
+ }
689
+ return (_a = lineMatches.at(-1)) !== null && _a !== void 0 ? _a : null;
657
690
  };
658
691
  exports.lineColumnToNodePath = lineColumnToNodePath;
659
692
  const PIXEL_VALUE_REGEX = /^-?\d+(\.\d+)?px$/;
@@ -679,6 +712,70 @@ const getObjectPropertyName = (property) => {
679
712
  }
680
713
  return null;
681
714
  };
715
+ const BORDER_RADIUS_SHORTHAND = 'borderRadius';
716
+ const BORDER_RADIUS_LONGHANDS = [
717
+ 'borderTopLeftRadius',
718
+ 'borderTopRightRadius',
719
+ 'borderBottomRightRadius',
720
+ 'borderBottomLeftRadius',
721
+ ];
722
+ const BORDER_RADIUS_PROPERTIES = new Set([
723
+ BORDER_RADIUS_SHORTHAND,
724
+ ...BORDER_RADIUS_LONGHANDS,
725
+ ]);
726
+ const hasMixedBorderRadiusRepresentation = (jsxElement) => {
727
+ var _a;
728
+ const style = jsxElement.attributes.find((attribute) => attribute.type === 'JSXAttribute' &&
729
+ attribute.name.type !== 'JSXNamespacedName' &&
730
+ attribute.name.name === 'style');
731
+ if (!style ||
732
+ style.type !== 'JSXAttribute' ||
733
+ ((_a = style.value) === null || _a === void 0 ? void 0 : _a.type) !== 'JSXExpressionContainer' ||
734
+ style.value.expression.type !== 'ObjectExpression') {
735
+ return false;
736
+ }
737
+ let hasShorthand = false;
738
+ let hasLonghand = false;
739
+ for (const property of style.value.expression.properties) {
740
+ if (property.type !== 'ObjectProperty') {
741
+ continue;
742
+ }
743
+ const name = getObjectPropertyName(property);
744
+ hasShorthand || (hasShorthand = name === BORDER_RADIUS_SHORTHAND);
745
+ hasLonghand || (hasLonghand = BORDER_RADIUS_LONGHANDS.some((longhand) => longhand === name));
746
+ }
747
+ return hasShorthand && hasLonghand;
748
+ };
749
+ const getUniformBorderRadius = (value) => {
750
+ const parsed = (0, parse_border_radius_shorthand_1.parseBorderRadiusShorthand)(value);
751
+ if (!parsed) {
752
+ return null;
753
+ }
754
+ const values = Object.values(parsed);
755
+ return values.every((radius) => radius === values[0]) ? values[0] : null;
756
+ };
757
+ const getBorderRadiusShorthandStatus = ({ propValue, ast, videoConfigValues, }) => {
758
+ if ((0, exports.isStaticValue)(propValue)) {
759
+ const uniform = getUniformBorderRadius((0, exports.extractStaticValue)(propValue));
760
+ return uniform === null ? computedStatus() : staticStatus(uniform, null);
761
+ }
762
+ const numericExpression = (0, video_config_numeric_expression_1.parseVideoConfigNumericExpression)({
763
+ node: propValue,
764
+ videoConfigValues,
765
+ });
766
+ if (numericExpression !== null && numericExpression.value >= 0) {
767
+ return staticStatus(numericExpression.value, numericExpression);
768
+ }
769
+ const computed = (0, exports.getComputedStatus)(propValue, ast, videoConfigValues);
770
+ if (computed.status === 'keyframed' &&
771
+ computed.interpolationFunction === 'interpolate' &&
772
+ computed.keyframes.every((keyframe) => typeof keyframe.value === 'number' &&
773
+ Number.isFinite(keyframe.value) &&
774
+ keyframe.value >= 0)) {
775
+ return computed;
776
+ }
777
+ return computedStatus();
778
+ };
682
779
  const getNestedPropStatus = ({ jsxElement, ast, parentKey, childKey, videoConfigValues, allowSpecialValues, }) => {
683
780
  const attr = jsxElement.attributes.find((a) => a.type !== 'JSXSpreadAttribute' &&
684
781
  a.name.type !== 'JSXNamespacedName' &&
@@ -735,9 +832,6 @@ const getNestedPropStatus = ({ jsxElement, ast, parentKey, childKey, videoConfig
735
832
  const staticShorthandValue = (0, exports.extractStaticValue)(shorthandValue, {
736
833
  allowSpecialValues: false,
737
834
  });
738
- if (typeof staticShorthandValue !== 'string') {
739
- return computedStatus();
740
- }
741
835
  const parsed = cssShorthand.parse(staticShorthandValue);
742
836
  return parsed ? staticStatus(parsed[childKey], null) : computedStatus();
743
837
  }
@@ -746,6 +840,13 @@ const getNestedPropStatus = ({ jsxElement, ast, parentKey, childKey, videoConfig
746
840
  return staticStatus(undefined, null);
747
841
  }
748
842
  const propValue = prop.value;
843
+ if (parentKey === 'style' && childKey === BORDER_RADIUS_SHORTHAND) {
844
+ return getBorderRadiusShorthandStatus({
845
+ propValue,
846
+ ast,
847
+ videoConfigValues,
848
+ });
849
+ }
749
850
  const staticValueOptions = { allowSpecialValues };
750
851
  if (!(0, exports.isStaticValue)(propValue, staticValueOptions)) {
751
852
  const numericExpression = (0, video_config_numeric_expression_1.parseVideoConfigNumericExpression)({
@@ -774,7 +875,14 @@ const computeEffectsForJsx = ({ ast, jsxElement, effects, videoConfigValues, })
774
875
  const computeSequenceOnlyPropsRecord = ({ jsxElement, jsxElementNode, ast, keys, assetKeys, videoConfigValues, }) => {
775
876
  const allProps = getPropsStatus(jsxElement, ast, videoConfigValues, assetKeys);
776
877
  const filteredProps = {};
878
+ const mixedBorderRadius = hasMixedBorderRadiusRepresentation(jsxElement);
777
879
  for (const key of keys) {
880
+ if (mixedBorderRadius &&
881
+ key.startsWith('style.') &&
882
+ BORDER_RADIUS_PROPERTIES.has(key.slice('style.'.length))) {
883
+ filteredProps[key] = computedStatus();
884
+ continue;
885
+ }
778
886
  if (key === 'children') {
779
887
  const staticChildrenAttribute = (0, exports.getStaticJsxChildrenAttribute)(jsxElement);
780
888
  if (staticChildrenAttribute) {
@@ -868,7 +976,7 @@ const computeSequencePropsStatus = ({ fileName, nodePath, componentIdentity, key
868
976
  });
869
977
  };
870
978
  exports.computeSequencePropsStatus = computeSequencePropsStatus;
871
- const computeSequencePropsStatusFromFilenameByLine = ({ fileName, line, componentIdentity, keys, assetKeys = [], effects, remotionRoot, logLevel, videoConfigValues, }) => {
979
+ const computeSequencePropsStatusFromFilenameByLocation = ({ fileName, line, column, componentIdentity, keys, assetKeys = [], effects, remotionRoot, logLevel, videoConfigValues, }) => {
872
980
  try {
873
981
  const { absolutePath } = (0, resolve_file_inside_project_1.resolveFileInsideProject)({
874
982
  remotionRoot,
@@ -877,7 +985,7 @@ const computeSequencePropsStatusFromFilenameByLine = ({ fileName, line, componen
877
985
  });
878
986
  const fileContents = (0, node_fs_1.readFileSync)(absolutePath, 'utf-8');
879
987
  const ast = (0, parse_ast_1.parseAst)(fileContents);
880
- const resolvedNodePath = (0, exports.lineColumnToNodePath)(ast, line);
988
+ const resolvedNodePath = (0, exports.lineColumnToNodePath)(ast, line, column, fileContents);
881
989
  if (!resolvedNodePath) {
882
990
  return {
883
991
  status: {
@@ -909,6 +1017,16 @@ const computeSequencePropsStatusFromFilenameByLine = ({ fileName, line, componen
909
1017
  };
910
1018
  }
911
1019
  catch (err) {
1020
+ if (err instanceof jsx_component_identity_1.JsxElementIdentityMismatchError ||
1021
+ err instanceof jsx_element_not_found_at_location_error_1.JsxElementNotFoundAtLocationError) {
1022
+ return {
1023
+ status: {
1024
+ canUpdate: false,
1025
+ reason: 'not-found',
1026
+ },
1027
+ success: false,
1028
+ };
1029
+ }
912
1030
  renderer_1.RenderInternals.Log.error({ indent: false, logLevel }, err);
913
1031
  return {
914
1032
  status: {
@@ -919,4 +1037,4 @@ const computeSequencePropsStatusFromFilenameByLine = ({ fileName, line, componen
919
1037
  };
920
1038
  }
921
1039
  };
922
- exports.computeSequencePropsStatusFromFilenameByLine = computeSequencePropsStatusFromFilenameByLine;
1040
+ exports.computeSequencePropsStatusFromFilenameByLocation = computeSequencePropsStatusFromFilenameByLocation;
@@ -1,12 +1,4 @@
1
1
  import type { FindInFileRequest, FindInFileResponse } from '@remotion/studio-shared';
2
2
  import type { ApiHandler } from '../api-types';
3
- export declare const findSearchPosition: ({ contents, lineNumber, columnNumber, search, }: {
4
- contents: string;
5
- lineNumber: number;
6
- columnNumber: number;
7
- search: string;
8
- }) => {
9
- lineNumber: number;
10
- columnNumber: number;
11
- };
3
+ export { findSearchPosition } from '@remotion/studio-codemods';
12
4
  export declare const findInFileHandler: ApiHandler<FindInFileRequest, FindInFileResponse>;
@@ -6,26 +6,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.findInFileHandler = exports.findSearchPosition = void 0;
7
7
  const node_fs_1 = __importDefault(require("node:fs"));
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
- const findSearchPosition = ({ contents, lineNumber, columnNumber, search, }) => {
10
- const lines = contents.split(/\r?\n/);
11
- const startLineIndex = Math.max(0, lineNumber - 1);
12
- for (let lineIndex = startLineIndex; lineIndex < lines.length; lineIndex++) {
13
- const startColumnIndex = lineIndex === startLineIndex ? Math.max(0, columnNumber - 1) : 0;
14
- const foundColumnIndex = lines[lineIndex].indexOf(search, startColumnIndex);
15
- if (foundColumnIndex !== -1) {
16
- return {
17
- lineNumber: lineIndex + 1,
18
- columnNumber: foundColumnIndex + 1,
19
- };
20
- }
21
- }
22
- return { lineNumber, columnNumber };
23
- };
24
- exports.findSearchPosition = findSearchPosition;
9
+ const studio_codemods_1 = require("@remotion/studio-codemods");
10
+ const studio_codemods_2 = require("@remotion/studio-codemods");
11
+ Object.defineProperty(exports, "findSearchPosition", { enumerable: true, get: function () { return studio_codemods_2.findSearchPosition; } });
25
12
  const findInFileHandler = async ({ input, remotionRoot }) => {
26
13
  const { fileName, lineNumber, columnNumber, search } = input;
27
14
  const contents = await node_fs_1.default.promises.readFile(node_path_1.default.resolve(remotionRoot, fileName), 'utf-8');
28
- return (0, exports.findSearchPosition)({
15
+ return (0, studio_codemods_1.findSearchPosition)({
29
16
  contents,
30
17
  lineNumber,
31
18
  columnNumber,
@@ -6,8 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.insertElementHandler = void 0;
7
7
  const node_fs_1 = require("node:fs");
8
8
  const node_path_1 = __importDefault(require("node:path"));
9
- const drag_and_drop_1 = require("@remotion/drag-and-drop");
10
9
  const renderer_1 = require("@remotion/renderer");
10
+ const studio_protocol_1 = require("@remotion/studio-protocol");
11
11
  const file_watcher_1 = require("../../file-watcher");
12
12
  const resolve_composition_component_1 = require("../../helpers/resolve-composition-component");
13
13
  const format_log_file_location_1 = require("../format-log-file-location");
@@ -56,7 +56,7 @@ const validateDimensions = (dimensions) => {
56
56
  }
57
57
  };
58
58
  const validateElement = (element) => {
59
- if (drag_and_drop_1.DragAndDropInternals.makeElementFileNameFromSlug(element.slug) === null) {
59
+ if (studio_protocol_1.StudioProtocolInternals.makeElementFileNameFromSlug(element.slug) === null) {
60
60
  throw new Error('Element slug must produce a safe lowercase .tsx file name');
61
61
  }
62
62
  if (typeof element.sourceCode !== 'string' ||
@@ -64,12 +64,12 @@ const validateElement = (element) => {
64
64
  element.sourceCode.length > 200000) {
65
65
  throw new Error('Unsupported Element source code');
66
66
  }
67
- if (drag_and_drop_1.DragAndDropInternals.getElementComponentNameFromSourceCode(element.sourceCode) === null) {
67
+ if (studio_protocol_1.StudioProtocolInternals.getElementComponentNameFromSourceCode(element.sourceCode) === null) {
68
68
  throw new Error('Element source must export exactly one named component');
69
69
  }
70
70
  validateDimensions(element.dimensions);
71
71
  };
72
- const insertElementHandler = ({ input: { compositionFile, compositionId, element, from, position }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
72
+ const insertElementHandler = ({ input: { compositionFile, compositionId, element, from, position, overwriteExisting, }, remotionRoot, logLevel, }) => (0, source_file_write_queue_1.withSourceFileWriteQueue)(async () => {
73
73
  try {
74
74
  validateElement(element);
75
75
  validatePosition(position);
@@ -77,7 +77,7 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
77
77
  (!Number.isInteger(from) || !Number.isFinite(from) || from < 0)) {
78
78
  throw new Error('from must be a non-negative integer');
79
79
  }
80
- const componentName = drag_and_drop_1.DragAndDropInternals.getElementComponentNameFromSourceCode(element.sourceCode);
80
+ const componentName = studio_protocol_1.StudioProtocolInternals.getElementComponentNameFromSourceCode(element.sourceCode);
81
81
  if (componentName === null) {
82
82
  throw new Error('Element source must export exactly one named component');
83
83
  }
@@ -90,7 +90,7 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
90
90
  if (!location.canAddSequence) {
91
91
  throw new Error('Cannot insert Element into this composition component');
92
92
  }
93
- const derivedElementFileName = drag_and_drop_1.DragAndDropInternals.makeElementFileNameFromSlug(element.slug);
93
+ const derivedElementFileName = studio_protocol_1.StudioProtocolInternals.makeElementFileNameFromSlug(element.slug);
94
94
  if (derivedElementFileName === null) {
95
95
  throw new Error('Element slug must produce a safe lowercase .tsx file name');
96
96
  }
@@ -99,13 +99,27 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
99
99
  throw new Error('Element file must stay inside the Remotion project');
100
100
  }
101
101
  const elementFileExists = (0, node_fs_1.existsSync)(elementFileName);
102
- if (elementFileExists) {
103
- const existingSource = (0, node_fs_1.readFileSync)(elementFileName, 'utf-8');
104
- if (normalizeSourceForComparison(existingSource) !==
105
- normalizeSourceForComparison(element.sourceCode)) {
106
- throw new Error(`Element file already exists with different contents: ${derivedElementFileName}`);
107
- }
102
+ const existingElementSource = elementFileExists
103
+ ? (0, node_fs_1.readFileSync)(elementFileName, 'utf-8')
104
+ : null;
105
+ const elementSourcesDiffer = existingElementSource !== null &&
106
+ normalizeSourceForComparison(existingElementSource) !==
107
+ normalizeSourceForComparison(element.sourceCode);
108
+ if (elementSourcesDiffer && !overwriteExisting) {
109
+ return {
110
+ success: false,
111
+ type: 'file-conflict',
112
+ conflict: {
113
+ filePath: node_path_1.default
114
+ .relative(remotionRoot, elementFileName)
115
+ .split(node_path_1.default.sep)
116
+ .join('/'),
117
+ existingSource: existingElementSource,
118
+ incomingSource: element.sourceCode,
119
+ },
120
+ };
108
121
  }
122
+ const shouldWriteElementFile = !elementFileExists || elementSourcesDiffer;
109
123
  const importPath = makeRelativeImportPath({
110
124
  fromFile: location.fileName,
111
125
  toFile: elementFileName,
@@ -133,16 +147,16 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
133
147
  });
134
148
  (0, undo_stack_1.pushTransactionToUndoStack)({
135
149
  snapshots: [
136
- ...(elementFileExists
137
- ? []
138
- : [
150
+ ...(shouldWriteElementFile
151
+ ? [
139
152
  {
140
153
  filePath: elementFileName,
141
- oldContents: null,
154
+ oldContents: existingElementSource,
142
155
  newContents: element.sourceCode,
143
156
  logLine: 1,
144
157
  },
145
- ]),
158
+ ]
159
+ : []),
146
160
  {
147
161
  filePath: inserted.fileName,
148
162
  oldContents: inserted.oldContents,
@@ -159,11 +173,11 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
159
173
  entryType: 'insert-jsx-element',
160
174
  suppressHmrOnFileRestore: false,
161
175
  });
162
- if (!elementFileExists) {
176
+ if (shouldWriteElementFile) {
163
177
  (0, undo_stack_1.suppressUndoStackInvalidation)(elementFileName);
164
178
  }
165
179
  (0, undo_stack_1.suppressUndoStackInvalidation)(inserted.fileName);
166
- if (!elementFileExists) {
180
+ if (shouldWriteElementFile) {
167
181
  (0, file_watcher_1.writeFileAndNotifyFileWatchers)(elementFileName, element.sourceCode, undefined);
168
182
  }
169
183
  (0, file_watcher_1.writeFileAndNotifyFileWatchers)(inserted.fileName, inserted.output, undefined);
@@ -177,7 +191,12 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
177
191
  absolutePath: elementFileName,
178
192
  line: 1,
179
193
  });
180
- renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(elementLocationLabel)} ${elementFileExists ? 'Reused existing Element source' : 'Created Element source'}`);
194
+ const elementFileAction = elementSourcesDiffer
195
+ ? 'Overwrote existing Element source'
196
+ : elementFileExists
197
+ ? 'Reused existing Element source'
198
+ : 'Created Element source';
199
+ renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(elementLocationLabel)} ${elementFileAction}`);
181
200
  renderer_1.RenderInternals.Log.info({ indent: false, logLevel }, `${renderer_1.RenderInternals.chalk.blueBright(compositionLocationLabel)} Added <${componentName}>`);
182
201
  if (!inserted.formatted) {
183
202
  (0, log_update_1.warnAboutPrettierOnce)(logLevel);
@@ -190,6 +209,7 @@ const insertElementHandler = ({ input: { compositionFile, compositionId, element
190
209
  catch (err) {
191
210
  return {
192
211
  success: false,
212
+ type: 'error',
193
213
  reason: err.message,
194
214
  stack: err.stack,
195
215
  };
@@ -5,8 +5,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.insertJsxElementHandler = void 0;
7
7
  const node_path_1 = __importDefault(require("node:path"));
8
- const drag_and_drop_1 = require("@remotion/drag-and-drop");
9
8
  const renderer_1 = require("@remotion/renderer");
9
+ const studio_protocol_1 = require("@remotion/studio-protocol");
10
10
  const studio_shared_1 = require("@remotion/studio-shared");
11
11
  const file_watcher_1 = require("../../file-watcher");
12
12
  const resolve_composition_component_1 = require("../../helpers/resolve-composition-component");
@@ -79,16 +79,16 @@ const validateElement = (element, remotionRoot) => {
79
79
  return;
80
80
  }
81
81
  if (element.type === 'component') {
82
- if (!drag_and_drop_1.DragAndDropInternals.isComponentIdentifier(element.componentName)) {
82
+ if (!studio_protocol_1.StudioProtocolInternals.isComponentIdentifier(element.componentName)) {
83
83
  throw new Error('Unsupported component name');
84
84
  }
85
- if (!drag_and_drop_1.DragAndDropInternals.isComponentIdentifier(element.importName)) {
85
+ if (!studio_protocol_1.StudioProtocolInternals.isComponentIdentifier(element.importName)) {
86
86
  throw new Error('Unsupported component import name');
87
87
  }
88
- if (!drag_and_drop_1.DragAndDropInternals.isComponentImportPath(element.importPath)) {
88
+ if (!studio_protocol_1.StudioProtocolInternals.isComponentImportPath(element.importPath)) {
89
89
  throw new Error('Unsupported component import path');
90
90
  }
91
- if (!drag_and_drop_1.DragAndDropInternals.areComponentProps(element.props)) {
91
+ if (!studio_protocol_1.StudioProtocolInternals.areComponentProps(element.props)) {
92
92
  throw new Error('Unsupported component props');
93
93
  }
94
94
  return;