Skip to content

Commit a4c6402

Browse files
committed
Make it even faster. No more inferredAutoLayout.
1 parent c477282 commit a4c6402

3 files changed

Lines changed: 15 additions & 136 deletions

File tree

packages/backend/src/code.ts

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -26,18 +26,6 @@ let nodeCacheHits = 0;
2626
// Keep track of node names for sequential numbering
2727
const nodeNameCounters: Map<string, number> = new Map();
2828

29-
// Helper function to add parent references to all children in the node tree
30-
const addParentReferences = (node: any) => {
31-
if (node.children && node.children.length > 0) {
32-
for (const child of node.children) {
33-
// Add parent reference to the child
34-
child.parent = node;
35-
// Recursively process this child's children
36-
addParentReferences(child);
37-
}
38-
}
39-
};
40-
4129
const variableCache = new Map<string, string>();
4230

4331
const memoizedVariableToColorName = async (
@@ -171,14 +159,21 @@ function adjustChildrenOrder(node: any) {
171159
* @param jsonNode The JSON node to process
172160
* @param figmaNode The corresponding Figma node
173161
* @param settings Plugin settings
162+
* @param parentNode Optional parent node reference to set
174163
*/
175164
const processNodePair = async (
176165
jsonNode: any,
177166
figmaNode: SceneNode,
178167
settings: PluginSettings,
168+
parentNode?: any
179169
) => {
180170
if (!jsonNode.id) return;
181171

172+
// Set parent reference if parent is provided
173+
if (parentNode) {
174+
jsonNode.parent = parentNode;
175+
}
176+
182177
// Ensure node has a unique name with simple numbering
183178
const cleanName = jsonNode.name.trim();
184179

@@ -295,13 +290,6 @@ const processNodePair = async (
295290
}
296291
}
297292

298-
// Extract inferredAutoLayout if optimizeLayout is enabled
299-
if (settings.optimizeLayout && "inferredAutoLayout" in figmaNode) {
300-
jsonNode.inferredAutoLayout = JSON.parse(
301-
JSON.stringify(figmaNode.inferredAutoLayout),
302-
);
303-
}
304-
305293
// Extract component metadata from instances
306294
if ("variantProperties" in figmaNode && figmaNode.variantProperties) {
307295
jsonNode.variantProperties = figmaNode.variantProperties;
@@ -311,8 +299,8 @@ const processNodePair = async (
311299
if ("width" in figmaNode) {
312300
jsonNode.width = figmaNode.width;
313301
jsonNode.height = figmaNode.height;
314-
// jsonNode.x = figmaNode.x;
315-
// jsonNode.y = figmaNode.y;
302+
jsonNode.x = figmaNode.x;
303+
jsonNode.y = figmaNode.y;
316304
}
317305

318306
if ("rotation" in jsonNode) {
@@ -388,6 +376,7 @@ const processNodePair = async (
388376
jsonNode.children[i],
389377
figmaNode.children[i],
390378
settings,
379+
jsonNode // Pass the current node as parent for its children
391380
);
392381
}
393382

@@ -444,13 +433,6 @@ export const nodesToJSON = async (
444433
`[benchmark][inside nodesToJSON] Process node pairs: ${Date.now() - processNodesStart}ms`,
445434
);
446435

447-
const addParentStart = Date.now();
448-
// Add parent references to all children in the node tree
449-
nodeJson.forEach((node) => addParentReferences(node));
450-
console.log(
451-
`[benchmark][inside nodesToJSON] addParentReferences: ${Date.now() - addParentStart}ms`,
452-
);
453-
454436
return nodeJson;
455437
};
456438

packages/backend/src/common/commonPosition.ts

Lines changed: 5 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,97 +1,3 @@
1-
import { LayoutMode } from "types";
2-
import { parentCoordinates } from "./parentCoordinates";
3-
4-
export const commonPosition = (
5-
node: SceneNode & DimensionAndPositionMixin,
6-
): LayoutMode => {
7-
// if node is same size as height, position is not necessary
8-
9-
// detect if Frame's width is same as Child when Frame has Padding.
10-
// warning: this may return true even when false, if size is same, but position is different. However, it would be an unexpected layout.
11-
let hPadding = 0;
12-
let vPadding = 0;
13-
if (node.parent && "layoutMode" in node.parent) {
14-
hPadding = node.parent.paddingLeft + node.parent.paddingRight;
15-
vPadding = node.parent.paddingTop + node.parent.paddingBottom;
16-
}
17-
18-
if (
19-
!node.parent ||
20-
!("width" in node.parent) ||
21-
(node.width === node.parent.width - hPadding &&
22-
node.height === node.parent.height - vPadding)
23-
) {
24-
return "";
25-
}
26-
27-
// position is absolute, parent is relative
28-
// return "absolute inset-0 m-auto ";
29-
30-
const [parentX, parentY] = parentCoordinates(node.parent);
31-
32-
// if view is too small, anything will be detected; this is necessary to reduce the tolerance.
33-
let threshold = 8;
34-
if (node.width < 16 || node.height < 16) {
35-
threshold = 1;
36-
}
37-
38-
// < 4 is a threshold. If === is used, there can be rounding errors (28.002 !== 28)
39-
const centerX =
40-
Math.abs(2 * (node.x - parentX) + node.width - node.parent.width) <
41-
threshold;
42-
const centerY =
43-
Math.abs(2 * (node.y - parentY) + node.height - node.parent.height) <
44-
threshold;
45-
46-
const minX = node.x - parentX < threshold;
47-
const minY = node.y - parentY < threshold;
48-
49-
const maxX = node.parent.width - (node.x - parentX + node.width) < threshold;
50-
const maxY =
51-
node.parent.height - (node.y - parentY + node.height) < threshold;
52-
53-
// this needs to be on top, because Tailwind is incompatible with Center, so this will give preference.
54-
if (minX && minY) {
55-
// x left, y top
56-
return "TopStart";
57-
} else if (minX && maxY) {
58-
// x left, y bottom
59-
return "BottomStart";
60-
} else if (maxX && minY) {
61-
// x right, y top
62-
return "TopEnd";
63-
} else if (maxX && maxY) {
64-
// x right, y bottom
65-
return "BottomEnd";
66-
}
67-
68-
if (centerX && centerY) {
69-
return "Center";
70-
}
71-
72-
if (centerX) {
73-
if (minY) {
74-
// x center, y top
75-
return "TopCenter";
76-
}
77-
if (maxY) {
78-
// x center, y bottom
79-
return "BottomCenter";
80-
}
81-
} else if (centerY) {
82-
if (minX) {
83-
// x left, y center
84-
return "CenterStart";
85-
}
86-
if (maxX) {
87-
// x right, y center
88-
return "CenterEnd";
89-
}
90-
}
91-
92-
return "Absolute";
93-
};
94-
951
export const getCommonPositionValue = (
962
node: SceneNode,
973
): { x: number; y: number } => {
@@ -112,6 +18,10 @@ export const commonIsAbsolutePosition = (
11218
node: SceneNode,
11319
optimizeLayout: boolean,
11420
) => {
21+
if ("layoutPositioning" in node && node.layoutPositioning === "ABSOLUTE") {
22+
return true;
23+
}
24+
11525
// No position when parent is inferred auto layout.
11626
if (
11727
optimizeLayout &&
@@ -130,11 +40,7 @@ export const commonIsAbsolutePosition = (
13040
"layoutMode" in node.parent && node.parent.layoutMode === "NONE";
13141
const hasNoLayoutMode = !("layoutMode" in node.parent);
13242

133-
if (
134-
("layoutPositioning" in node && node.layoutPositioning === "ABSOLUTE") ||
135-
parentLayoutIsNone ||
136-
hasNoLayoutMode
137-
) {
43+
if (parentLayoutIsNone || hasNoLayoutMode) {
13844
return true;
13945
}
14046

packages/plugin-ui/src/codegenPreferenceOptions.ts

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,6 @@ export const preferenceOptions: LocalCodegenPreferenceOptions[] = [
99
isDefault: false,
1010
includedLanguages: ["HTML", "Tailwind"],
1111
},
12-
{
13-
itemType: "individual_select",
14-
propertyName: "optimizeLayout",
15-
label: "Optimize layout",
16-
description:
17-
"Attempt to auto-layout suitable element groups. This may increase code quality, but may not always work as expected.",
18-
isDefault: true,
19-
includedLanguages: ["HTML", "Tailwind", "Flutter", "SwiftUI"],
20-
},
2112
{
2213
itemType: "individual_select",
2314
propertyName: "roundTailwindValues",

0 commit comments

Comments
 (0)