Skip to content

Commit

Permalink
Component Instances (#124)
Browse files Browse the repository at this point in the history
* wip

* wip

* wipo

* more structure

* wip

* id library wip

* wip

* main instance working

* improvements

* fix node order

* refactor

* remove not used method

* refactor

* fix component set translation

* refactor

* add changelog

* penpot lib update

---------

Co-authored-by: Jordi Sala Morales <[email protected]>
  • Loading branch information
Cenadros and jordisala1991 authored May 30, 2024
1 parent 5d4ace3 commit 7b31929
Show file tree
Hide file tree
Showing 39 changed files with 415 additions and 148 deletions.
5 changes: 5 additions & 0 deletions .changeset/stale-geckos-grab.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"penpot-exporter": minor
---

Implement component instances translation
1 change: 1 addition & 0 deletions plugin-src/transformers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from './transformDocumentNode';
export * from './transformEllipseNode';
export * from './transformFrameNode';
export * from './transformGroupNode';
export * from './transformInstanceNode';
export * from './transformPageNode';
export * from './transformPathNode';
export * from './transformRectangleNode';
Expand Down
1 change: 1 addition & 0 deletions plugin-src/transformers/partials/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export * from './transformChildren';
export * from './transformCornerRadius';
export * from './transformDimensionAndPosition';
export * from './transformEffects';
export * from './transformFigmaIds';
export * from './transformFills';
export * from './transformProportion';
export * from './transformRotationAndPosition';
Expand Down
22 changes: 22 additions & 0 deletions plugin-src/transformers/partials/transformFigmaIds.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ShapeBaseAttributes } from '@ui/lib/types/shapes/shape';

export const transformFigmaIds = (
node: SceneNode
): Pick<ShapeBaseAttributes, 'figmaId' | 'figmaRelatedId'> => {
return {
figmaId: normalizeNodeId(node.id),
figmaRelatedId: getRelatedNodeId(node.id)
};
};

const getRelatedNodeId = (nodeId: string): string | undefined => {
const ids = nodeId.split(';');

if (ids.length > 1) {
return ids.slice(1).join(';');
}
};

const normalizeNodeId = (nodeId: string): string => {
return nodeId.replace('I', '');
};
2 changes: 2 additions & 0 deletions plugin-src/transformers/transformBooleanNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
transformChildren,
transformDimensionAndPosition,
transformEffects,
transformFigmaIds,
transformFills,
transformProportion,
transformSceneNode,
Expand All @@ -21,6 +22,7 @@ export const transformBooleanNode = async (
type: 'bool',
name: node.name,
boolType: translateBoolType(node.booleanOperation),
...transformFigmaIds(node),
...(await transformChildren(node, baseX, baseY)),
...(await transformFills(node)),
...transformEffects(node),
Expand Down
2 changes: 2 additions & 0 deletions plugin-src/transformers/transformComponentNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
transformCornerRadius,
transformDimensionAndPosition,
transformEffects,
transformFigmaIds,
transformFills,
transformProportion,
transformSceneNode,
Expand All @@ -22,6 +23,7 @@ export const transformComponentNode = async (
type: 'component',
name: node.name,
path: '',
...transformFigmaIds(node),
...(await transformFills(node)),
...transformEffects(node),
...(await transformStrokes(node)),
Expand Down
2 changes: 2 additions & 0 deletions plugin-src/transformers/transformEllipseNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
transformBlend,
transformDimension,
transformEffects,
transformFigmaIds,
transformFills,
transformProportion,
transformRotationAndPosition,
Expand All @@ -19,6 +20,7 @@ export const transformEllipseNode = async (
return {
type: 'circle',
name: node.name,
...transformFigmaIds(node),
...(await transformFills(node)),
...transformEffects(node),
...(await transformStrokes(node)),
Expand Down
2 changes: 2 additions & 0 deletions plugin-src/transformers/transformFrameNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
transformCornerRadius,
transformDimensionAndPosition,
transformEffects,
transformFigmaIds,
transformFills,
transformProportion,
transformSceneNode,
Expand Down Expand Up @@ -41,6 +42,7 @@ export const transformFrameNode = async (
type: 'frame',
name: node.name,
showContent: isSectionNode(node) ? true : !node.clipsContent,
...transformFigmaIds(node),
...(await transformFills(node)),
...frameSpecificAttributes,
...(await transformChildren(node, baseX + node.x, baseY + node.y)),
Expand Down
2 changes: 2 additions & 0 deletions plugin-src/transformers/transformGroupNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
transformBlend,
transformDimensionAndPosition,
transformEffects,
transformFigmaIds,
transformSceneNode
} from '@plugin/transformers/partials';
import { transformChildren } from '@plugin/transformers/partials';
Expand All @@ -14,6 +15,7 @@ export const transformGroupNode = async (
baseY: number
): Promise<GroupShape> => {
return {
...transformFigmaIds(node),
...transformGroupNodeLike(node, baseX, baseY),
...transformEffects(node),
...transformBlend(node),
Expand Down
64 changes: 64 additions & 0 deletions plugin-src/transformers/transformInstanceNode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import {
transformBlend,
transformChildren,
transformCornerRadius,
transformDimensionAndPosition,
transformEffects,
transformFigmaIds,
transformFills,
transformProportion,
transformSceneNode,
transformStrokes
} from '@plugin/transformers/partials';

import { ComponentInstance } from '@ui/types';

export const transformInstanceNode = async (
node: InstanceNode,
baseX: number,
baseY: number
): Promise<ComponentInstance | undefined> => {
const mainComponent = await node.getMainComponentAsync();

/**
* We do not want to process component instances in the following scenarios:
*
* 1. If the component does not have a main component.
* 2. If the component does not have parent (it comes from an external design system).
* 3. If the component is inside a component set, (it is a variant component).
*/
if (
!mainComponent ||
mainComponent.parent === null ||
mainComponent.parent.type === 'COMPONENT_SET'
) {
return;
}

return {
type: 'instance',
mainComponentFigmaId: mainComponent.id,
isComponentRoot: isComponentRoot(node),
...transformFigmaIds(node),
...(await transformFills(node)),
...transformEffects(node),
...(await transformStrokes(node)),
...transformSceneNode(node),
...transformBlend(node),
...transformProportion(node),
...transformCornerRadius(node),
...transformDimensionAndPosition(node, baseX, baseY),
...(await transformChildren(node, baseX + node.x, baseY + node.y))
};
};

const isComponentRoot = (node: InstanceNode): boolean => {
let parent = node.parent;
while (parent !== null) {
if (parent.type === 'COMPONENT' || parent.type === 'INSTANCE') {
return false;
}
parent = parent.parent;
}
return true;
};
2 changes: 2 additions & 0 deletions plugin-src/transformers/transformPathNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
transformBlend,
transformDimensionAndPosition,
transformEffects,
transformFigmaIds,
transformFills,
transformProportion,
transformSceneNode,
Expand All @@ -23,6 +24,7 @@ export const transformPathNode = async (
return {
type: 'path',
name: node.name,
...transformFigmaIds(node),
...(hasFillGeometry(node) ? await transformFills(node) : []),
...(await transformStrokes(node)),
...transformEffects(node),
Expand Down
2 changes: 2 additions & 0 deletions plugin-src/transformers/transformRectangleNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
transformCornerRadius,
transformDimension,
transformEffects,
transformFigmaIds,
transformFills,
transformProportion,
transformRotationAndPosition,
Expand All @@ -20,6 +21,7 @@ export const transformRectangleNode = async (
return {
type: 'rect',
name: node.name,
...transformFigmaIds(node),
...(await transformFills(node)),
...transformEffects(node),
...(await transformStrokes(node)),
Expand Down
3 changes: 3 additions & 0 deletions plugin-src/transformers/transformSceneNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
transformEllipseNode,
transformFrameNode,
transformGroupNode,
transformInstanceNode,
transformPathNode,
transformRectangleNode,
transformTextNode,
Expand Down Expand Up @@ -39,6 +40,8 @@ export const transformSceneNode = async (
return await transformBooleanNode(node, baseX, baseY);
case 'COMPONENT':
return await transformComponentNode(node, baseX, baseY);
case 'INSTANCE':
return await transformInstanceNode(node, baseX, baseY);
}

console.error(`Unsupported node type: ${node.type}`);
Expand Down
2 changes: 2 additions & 0 deletions plugin-src/transformers/transformTextNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
transformBlend,
transformDimensionAndPosition,
transformEffects,
transformFigmaIds,
transformProportion,
transformSceneNode,
transformStrokes,
Expand All @@ -18,6 +19,7 @@ export const transformTextNode = async (
return {
type: 'text',
name: node.name,
...transformFigmaIds(node),
...(await transformText(node)),
...transformDimensionAndPosition(node, baseX, baseY),
...transformEffects(node),
Expand Down
6 changes: 4 additions & 2 deletions plugin-src/transformers/transformVectorNode.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { transformVectorPaths } from '@plugin/transformers/partials';
import { transformFigmaIds, transformVectorPaths } from '@plugin/transformers/partials';

import { GroupShape } from '@ui/lib/types/shapes/groupShape';
import { PathShape } from '@ui/lib/types/shapes/pathShape';
Expand All @@ -21,12 +21,14 @@ export const transformVectorNode = async (
if (children.length === 1) {
return {
...children[0],
name: node.name
name: node.name,
...transformFigmaIds(node)
};
}

return {
...transformGroupNodeLike(node, baseX, baseY),
...transformFigmaIds(node),
children
};
};
Loading

0 comments on commit 7b31929

Please sign in to comment.