-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
@remotion/web-renderer: Include SVG, visual testing
#5887
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
| const [x, y] = transformOrigin.split(' '); | ||
|
|
||
| return { | ||
| x: parseFloat(x), | ||
| y: parseFloat(y), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parseTransformOrigin function only splits on spaces and assumes exactly two values, but CSS transform-origin supports many formats including single values, keywords, and complex values with spaces (e.g., calc(50% + 10px) 50%), causing it to return NaN for many valid inputs.
View Details
📝 Patch Details
diff --git a/packages/web-renderer/src/parse-transform-origin.ts b/packages/web-renderer/src/parse-transform-origin.ts
index d0922da030..040b2da251 100644
--- a/packages/web-renderer/src/parse-transform-origin.ts
+++ b/packages/web-renderer/src/parse-transform-origin.ts
@@ -3,10 +3,100 @@ export const parseTransformOrigin = (transformOrigin: string) => {
return null;
}
- const [x, y] = transformOrigin.split(' ');
+ // Handle calc() expressions and other complex values by not splitting on spaces inside parentheses
+ const values = parseTransformOriginValues(transformOrigin.trim());
+
+ if (values.length === 0) {
+ return null;
+ }
+
+ // Single value: applies to horizontal, vertical defaults to center (50%)
+ if (values.length === 1) {
+ const x = parseTransformOriginValue(values[0]);
+ return {
+ x: x !== null ? x : 50, // Default to center if parsing fails
+ y: 50, // CSS spec: single value sets horizontal, vertical defaults to center
+ };
+ }
+
+ // Two values: first is horizontal, second is vertical
+ const x = parseTransformOriginValue(values[0]);
+ const y = parseTransformOriginValue(values[1]);
return {
- x: parseFloat(x),
- y: parseFloat(y),
+ x: x !== null ? x : 50,
+ y: y !== null ? y : 50,
};
};
+
+// Parse space-separated values while respecting parentheses (for calc(), etc.)
+function parseTransformOriginValues(str: string): string[] {
+ const values: string[] = [];
+ let current = '';
+ let parenDepth = 0;
+
+ for (let i = 0; i < str.length; i++) {
+ const char = str[i];
+
+ if (char === '(') {
+ parenDepth++;
+ current += char;
+ } else if (char === ')') {
+ parenDepth--;
+ current += char;
+ } else if (char === ' ' && parenDepth === 0) {
+ if (current.trim()) {
+ values.push(current.trim());
+ current = '';
+ }
+ } else {
+ current += char;
+ }
+ }
+
+ if (current.trim()) {
+ values.push(current.trim());
+ }
+
+ return values;
+}
+
+// Parse individual transform-origin value (keyword, percentage, length)
+function parseTransformOriginValue(value: string): number | null {
+ // Handle keywords
+ switch (value.toLowerCase()) {
+ case 'left':
+ case 'top':
+ return 0;
+ case 'center':
+ return 50;
+ case 'right':
+ case 'bottom':
+ return 100;
+ }
+
+ // Handle percentages
+ if (value.endsWith('%')) {
+ const num = parseFloat(value.slice(0, -1));
+ return isNaN(num) ? null : num;
+ }
+
+ // Handle pixel values (convert to percentage - this is approximate)
+ // Note: Without element dimensions, we can't convert px to % accurately
+ // For now, treat px values as if they were percentages for basic functionality
+ if (value.endsWith('px')) {
+ const num = parseFloat(value.slice(0, -2));
+ return isNaN(num) ? null : num;
+ }
+
+ // Handle calc() and other complex expressions
+ // For calc() expressions, we can't evaluate them without context
+ // Return 50% (center) as a reasonable fallback
+ if (value.startsWith('calc(')) {
+ return 50;
+ }
+
+ // Try parsing as a raw number
+ const num = parseFloat(value);
+ return isNaN(num) ? null : num;
+}
Analysis
parseTransformOrigin function returns NaN for valid CSS transform-origin values
What fails: parseTransformOrigin() in packages/web-renderer/src/parse-transform-origin.ts produces NaN values for valid CSS transform-origin inputs like single values, keywords, and calc() expressions
How to reproduce:
// Test cases that fail with current implementation:
parseTransformOrigin("center") // Returns {x: NaN, y: NaN}
parseTransformOrigin("50%") // Returns {x: 50, y: NaN}
parseTransformOrigin("calc(50% + 10px) 50%") // Returns {x: NaN, y: NaN}
parseTransformOrigin("left top") // Returns {x: NaN, y: NaN}Result: imageBitmap.transformOrigin contains NaN values in canvas drawing code (compose.ts lines 80-81, 92-93), causing incorrect transform origin calculations and visual rendering errors
Expected: Should parse all valid CSS transform-origin syntax per MDN specification - single values, keywords (left/center/right/top/bottom), percentages, and calc() expressions
@remotion/web-renderer: Include SVG@remotion/web-renderer: Include SVG, visual testing
visually, the tests are differering on ubuntu and macos. since everybody uses macos to develop, we should use macos to create references. tests only run on node >= 18, but we also test node 16. so this avoids the tests being run on anything else than macos essentially
No description provided.