0
Fork 0
mirror of https://github.com/penpot/penpot-exporter-figma-plugin.git synced 2024-12-22 13:43:03 -05:00

Instances Overrides (#166)

* wip

* added support for overrides

* fixes
This commit is contained in:
Alex Sánchez 2024-06-17 09:58:23 +02:00 committed by GitHub
parent 2f11c5f090
commit 4591369e3c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 274 additions and 10 deletions

View file

@ -0,0 +1,5 @@
---
"penpot-exporter": minor
---
Added support for instances overrides

View file

@ -0,0 +1,13 @@
class OverridesLibrary {
private overrides: Map<string, NodeChangeProperty[]> = new Map();
public register(nodeId: string, overrides: NodeChangeProperty[]): void {
this.overrides.set(nodeId, overrides);
}
public get(nodeId: string): NodeChangeProperty[] | undefined {
return this.overrides.get(nodeId);
}
}
export const overridesLibrary = new OverridesLibrary();

View file

@ -7,6 +7,7 @@ export * from './transformEffects';
export * from './transformFigmaIds'; export * from './transformFigmaIds';
export * from './transformFills'; export * from './transformFills';
export * from './transformLayout'; export * from './transformLayout';
export * from './transformOverrides';
export * from './transformProportion'; export * from './transformProportion';
export * from './transformRotationAndPosition'; export * from './transformRotationAndPosition';
export * from './transformSceneNode'; export * from './transformSceneNode';

View file

@ -0,0 +1,23 @@
import { overridesLibrary } from '@plugin/OverridesLibrary';
import { syncAttributes } from '@plugin/utils/syncAttributes';
import { SyncGroups } from '@ui/lib/types/utils/syncGroups';
export const transformOverrides = (node: SceneNode) => {
const overrides = overridesLibrary.get(node.id);
if (!overrides) {
return {};
}
const touched: SyncGroups[] = [];
overrides.forEach(override => {
if (syncAttributes[override]) {
touched.push(...syncAttributes[override]);
}
});
return {
touched
};
};

View file

@ -6,6 +6,7 @@ import {
transformFigmaIds, transformFigmaIds,
transformFills, transformFills,
transformLayoutAttributes, transformLayoutAttributes,
transformOverrides,
transformProportion, transformProportion,
transformRotationAndPosition, transformRotationAndPosition,
transformSceneNode, transformSceneNode,
@ -33,6 +34,7 @@ export const transformBooleanNode = async (
...transformSceneNode(node), ...transformSceneNode(node),
...transformBlend(node), ...transformBlend(node),
...transformProportion(node), ...transformProportion(node),
...transformLayoutAttributes(node) ...transformLayoutAttributes(node),
...transformOverrides(node)
}; };
}; };

View file

@ -6,6 +6,7 @@ import {
transformFigmaIds, transformFigmaIds,
transformFills, transformFills,
transformLayoutAttributes, transformLayoutAttributes,
transformOverrides,
transformProportion, transformProportion,
transformRotationAndPosition, transformRotationAndPosition,
transformSceneNode, transformSceneNode,
@ -28,6 +29,7 @@ export const transformEllipseNode = (node: EllipseNode, baseRotation: number): C
...transformBlend(node), ...transformBlend(node),
...transformProportion(node), ...transformProportion(node),
...transformLayoutAttributes(node), ...transformLayoutAttributes(node),
...transformConstraints(node) ...transformConstraints(node),
...transformOverrides(node)
}; };
}; };

View file

@ -9,6 +9,7 @@ import {
transformFigmaIds, transformFigmaIds,
transformFills, transformFills,
transformLayoutAttributes, transformLayoutAttributes,
transformOverrides,
transformProportion, transformProportion,
transformRotationAndPosition, transformRotationAndPosition,
transformSceneNode, transformSceneNode,
@ -63,6 +64,7 @@ export const transformFrameNode = async (
...frameSpecificAttributes, ...frameSpecificAttributes,
...transformDimension(node), ...transformDimension(node),
...(await transformChildren(node, rotation)), ...(await transformChildren(node, rotation)),
...transformSceneNode(node) ...transformSceneNode(node),
...transformOverrides(node)
}; };
}; };

View file

@ -3,6 +3,7 @@ import {
transformDimension, transformDimension,
transformEffects, transformEffects,
transformFigmaIds, transformFigmaIds,
transformOverrides,
transformRotationAndPosition, transformRotationAndPosition,
transformSceneNode transformSceneNode
} from '@plugin/transformers/partials'; } from '@plugin/transformers/partials';
@ -19,7 +20,8 @@ export const transformGroupNode = async (
...transformGroupNodeLike(node, baseRotation), ...transformGroupNodeLike(node, baseRotation),
...transformEffects(node), ...transformEffects(node),
...transformBlend(node), ...transformBlend(node),
...(await transformChildren(node, baseRotation)) ...(await transformChildren(node, baseRotation)),
...transformOverrides(node)
}; };
}; };

View file

@ -1,3 +1,4 @@
import { overridesLibrary } from '@plugin/OverridesLibrary';
import { remoteComponentLibrary } from '@plugin/RemoteComponentLibrary'; import { remoteComponentLibrary } from '@plugin/RemoteComponentLibrary';
import { import {
transformAutoLayout, transformAutoLayout,
@ -10,6 +11,7 @@ import {
transformFigmaIds, transformFigmaIds,
transformFills, transformFills,
transformLayoutAttributes, transformLayoutAttributes,
transformOverrides,
transformProportion, transformProportion,
transformRotationAndPosition, transformRotationAndPosition,
transformSceneNode, transformSceneNode,
@ -32,6 +34,12 @@ export const transformInstanceNode = async (
registerExternalComponents(mainComponent); registerExternalComponents(mainComponent);
} }
if (node.overrides.length > 0) {
node.overrides.forEach(override =>
overridesLibrary.register(override.id, override.overriddenFields)
);
}
return { return {
type: 'instance', type: 'instance',
name: node.name, name: node.name,
@ -51,7 +59,8 @@ export const transformInstanceNode = async (
...transformRotationAndPosition(node, baseRotation), ...transformRotationAndPosition(node, baseRotation),
...transformConstraints(node), ...transformConstraints(node),
...transformAutoLayout(node), ...transformAutoLayout(node),
...(await transformChildren(node, node.rotation + baseRotation)) ...(await transformChildren(node, node.rotation + baseRotation)),
...transformOverrides(node)
}; };
}; };

View file

@ -4,6 +4,7 @@ import {
transformEffects, transformEffects,
transformFigmaIds, transformFigmaIds,
transformLayoutAttributes, transformLayoutAttributes,
transformOverrides,
transformProportion, transformProportion,
transformSceneNode, transformSceneNode,
transformStrokes transformStrokes
@ -30,6 +31,7 @@ export const transformLineNode = (node: LineNode, baseRotation: number): PathSha
...transformBlend(node), ...transformBlend(node),
...transformProportion(node), ...transformProportion(node),
...transformLayoutAttributes(node), ...transformLayoutAttributes(node),
...transformConstraints(node) ...transformConstraints(node),
...transformOverrides(node)
}; };
}; };

View file

@ -5,6 +5,7 @@ import {
transformFigmaIds, transformFigmaIds,
transformFills, transformFills,
transformLayoutAttributes, transformLayoutAttributes,
transformOverrides,
transformProportion, transformProportion,
transformSceneNode, transformSceneNode,
transformStrokes transformStrokes
@ -29,6 +30,7 @@ export const transformPathNode = (
...transformBlend(node), ...transformBlend(node),
...transformProportion(node), ...transformProportion(node),
...transformLayoutAttributes(node), ...transformLayoutAttributes(node),
...transformConstraints(node) ...transformConstraints(node),
...transformOverrides(node)
}; };
}; };

View file

@ -7,6 +7,7 @@ import {
transformFigmaIds, transformFigmaIds,
transformFills, transformFills,
transformLayoutAttributes, transformLayoutAttributes,
transformOverrides,
transformProportion, transformProportion,
transformRotationAndPosition, transformRotationAndPosition,
transformSceneNode, transformSceneNode,
@ -30,6 +31,7 @@ export const transformRectangleNode = (node: RectangleNode, baseRotation: number
...transformProportion(node), ...transformProportion(node),
...transformLayoutAttributes(node), ...transformLayoutAttributes(node),
...transformCornerRadius(node), ...transformCornerRadius(node),
...transformConstraints(node) ...transformConstraints(node),
...transformOverrides(node)
}; };
}; };

View file

@ -5,6 +5,7 @@ import {
transformEffects, transformEffects,
transformFigmaIds, transformFigmaIds,
transformLayoutAttributes, transformLayoutAttributes,
transformOverrides,
transformProportion, transformProportion,
transformRotationAndPosition, transformRotationAndPosition,
transformSceneNode, transformSceneNode,
@ -28,6 +29,7 @@ export const transformTextNode = (node: TextNode, baseRotation: number): TextSha
...transformProportion(node), ...transformProportion(node),
...transformLayoutAttributes(node), ...transformLayoutAttributes(node),
...transformStrokes(node), ...transformStrokes(node),
...transformConstraints(node) ...transformConstraints(node),
...transformOverrides(node)
}; };
}; };

View file

@ -1,6 +1,7 @@
import { import {
transformConstraints, transformConstraints,
transformFigmaIds, transformFigmaIds,
transformOverrides,
transformVectorPaths transformVectorPaths
} from '@plugin/transformers/partials'; } from '@plugin/transformers/partials';
@ -26,7 +27,8 @@ export const transformVectorNode = (
...children[0], ...children[0],
name: node.name, name: node.name,
...transformFigmaIds(node), ...transformFigmaIds(node),
...transformConstraints(node) ...transformConstraints(node),
...transformOverrides(node)
}; };
} }
@ -34,6 +36,7 @@ export const transformVectorNode = (
...transformGroupNodeLike(node, baseRotation), ...transformGroupNodeLike(node, baseRotation),
...transformFigmaIds(node), ...transformFigmaIds(node),
...transformConstraints(node), ...transformConstraints(node),
...transformOverrides(node),
children children
}; };
}; };

View file

@ -0,0 +1,150 @@
import { SyncGroups } from '@ui/lib/types/utils/syncGroups';
export type SyncAttributes = {
[key in NodeChangeProperty]: SyncGroups[];
};
export const syncAttributes: SyncAttributes = {
name: [':name-group'],
fills: [':fill-group'],
backgrounds: [':fill-group'],
fillStyleId: [':fill-group'],
backgroundStyleId: [':fill-group'],
textBackground: [':fill-group'],
visible: [':visibility-group'],
locked: [':modifiable-group'],
fontName: [':text-font-group', ':content-group'],
fontSize: [':text-font-group', ':content-group'],
textCase: [':text-font-group', ':content-group'],
textDecoration: [':text-font-group', ':content-group'],
textStyleId: [':text-font-group', ':content-group'],
characters: [':text-display-group', ':content-group'],
styledTextSegments: [':text-display-group', ':content-group'],
lineHeight: [':text-display-group', ':content-group'],
leadingTrim: [':text-display-group', ':content-group'],
paragraphIndent: [':text-display-group', ':content-group'],
paragraphSpacing: [':text-display-group', ':content-group'],
listSpacing: [':text-display-group', ':content-group'],
hangingPunctuation: [':text-display-group', ':content-group'],
hangingList: [':text-display-group', ':content-group'],
letterSpacing: [':text-display-group', ':content-group'],
textAlignHorizontal: [':text-display-group', ':content-group'],
textAlignVertical: [':text-display-group', ':content-group'],
textAutoResize: [':text-display-group', ':content-group'],
text: [':text-display-group', ':content-group'],
strokes: [':stroke-group'],
strokeWeight: [':stroke-group'],
strokeAlign: [':stroke-group'],
strokeCap: [':stroke-group'],
strokeJoin: [':stroke-group'],
strokeMiterLimit: [':stroke-group'],
dashPattern: [':stroke-group'],
strokeStyleId: [':stroke-group'],
stokeTopWeight: [':stroke-group'],
strokeBottomWeight: [':stroke-group'],
strokeLeftWeight: [':stroke-group'],
strokeRightWeight: [':stroke-group'],
connectorStartStrokeCap: [':stroke-group'],
connectorEndStrokeCap: [':stroke-group'],
innerRadius: [':radius-group'],
topLeftRadius: [':radius-group'],
topRightRadius: [':radius-group'],
bottomLeftRadius: [':radius-group'],
bottomRightRadius: [':radius-group'],
cornerRadius: [':radius-group'],
cornerSmoothing: [':radius-group'],
vectorNetwork: [':geometry-group'],
pointCount: [':geometry-group'],
width: [':geometry-group'],
height: [':geometry-group'],
guides: [':geometry-group'],
arcData: [':geometry-group'],
constrainProportions: [':geometry-group'],
handleMirroring: [':geometry-group'],
relativeTransform: [':geometry-group'],
x: [':geometry-group'],
y: [':geometry-group'],
rotation: [':geometry-group'],
type: [':geometry-group'],
shapeType: [':geometry-group'],
connectorStart: [':geometry-group'],
connectorEnd: [':geometry-group'],
connectorLineType: [':geometry-group'],
opacity: [':layer-effects-group'],
blendMode: [':layer-effects-group'],
effects: [':shadow-group', ':blur-group'],
effectStyleId: [':shadow-group', ':blur-group'],
isMask: [':mask-group'],
clipsContent: [':mask-group'],
maskType: [':mask-group'],
constraints: [':constraints-group'],
booleanOperation: [':bool-group'],
exportSettings: [':exports-group'],
gridStyleId: [':grids-group'],
layoutMode: [':layout-container', ':layout-flex-dir'],
layoutAlign: [':layout-align-content', ':layout-align-items'],
itemSpacing: [':layout-gap'],
paddingLeft: [':layout-padding'],
paddingTop: [':layout-padding'],
paddingRight: [':layout-padding'],
paddingBottom: [':layout-padding'],
layoutGrids: [
':layout-grid-cells',
':layout-grid-columns',
':layout-grid-dir',
':layout-grid-rows'
],
layoutWrap: [':layout-wrap-type'],
overflowDirection: [':layout-item-align-self'],
counterAxisSizingMode: [':layout-item-h-sizing'],
primaryAxisSizingMode: [':layout-item-v-sizing'],
primaryAxisAlignItems: [
':layout-item-align-self',
':layout-justify-items',
':layout-justify-content',
':layout-gap'
],
counterAxisAlignItems: [
':layout-item-align-self',
':layout-align-content',
':layout-align-items'
],
layoutGrow: [':layout-item-h-sizing'],
layoutPositioning: [':layout-item-absolute'],
itemReverseZIndex: [':layout-item-z-index'],
// @TODO: not supported yet
textTruncation: [],
minWidth: [],
minHeight: [],
maxWidth: [],
maxLines: [],
maxHeight: [],
counterAxisSpacing: [],
counterAxisAlignContent: [],
openTypeFeatures: [],
authorVisible: [],
parent: [],
pluginData: [],
autoRename: [],
overlayPositionType: [],
overlayBackgroundInteraction: [],
overlayBackground: [],
prototypeStartNode: [],
prototypeBackgrounds: [],
expanded: [],
description: [],
hyperlink: [],
mediaData: [],
reactions: [],
flowStartingPoints: [],
codeLanguage: [],
widgetSyncedState: [],
componentPropertyDefinitions: [],
componentPropertyReferences: [],
componentProperties: [],
embedData: [],
linkUnfurlData: [],
authorName: [],
code: []
};

View file

@ -9,6 +9,7 @@ import { Point } from '@ui/lib/types/utils/point';
import { Selrect } from '@ui/lib/types/utils/selrect'; import { Selrect } from '@ui/lib/types/utils/selrect';
import { Shadow } from '@ui/lib/types/utils/shadow'; import { Shadow } from '@ui/lib/types/utils/shadow';
import { Stroke } from '@ui/lib/types/utils/stroke'; import { Stroke } from '@ui/lib/types/utils/stroke';
import { SyncGroups } from '@ui/lib/types/utils/syncGroups';
import { Uuid } from '@ui/lib/types/utils/uuid'; import { Uuid } from '@ui/lib/types/utils/uuid';
export type ShapeBaseAttributes = { export type ShapeBaseAttributes = {
@ -74,6 +75,7 @@ export type ShapeAttributes = {
shadow?: Shadow[]; shadow?: Shadow[];
blur?: Blur; blur?: Blur;
growType?: GrowType; growType?: GrowType;
touched?: SyncGroups[];
}; };
export type ShapeGeomAttributes = { export type ShapeGeomAttributes = {

View file

@ -0,0 +1,42 @@
export type SyncGroups =
| ':name-group'
| ':fill-group'
| ':content-group'
| ':visibility-group'
| ':modifiable-group'
| ':text-font-group'
| ':text-display-group'
| ':stroke-group'
| ':radius-group'
| ':geometry-group'
| ':layer-effects-group'
| ':shadow-group'
| ':blur-group'
| ':mask-group'
| ':constraints-group'
| ':bool-group'
| ':exports-group'
| ':grids-group'
| ':layout-container'
| ':layout-align-content'
| ':layout-align-items'
| ':layout-flex-dir'
| ':layout-gap'
| ':layout-justify-content'
| ':layout-justify-items'
| ':layout-wrap-type'
| ':layout-padding'
| ':layout-grid-dir'
| ':layout-grid-rows'
| ':layout-grid-columns'
| ':layout-grid-cells'
| ':layout-item-margin'
| ':layout-item-h-sizing'
| ':layout-item-v-sizing'
| ':layout-item-max-h'
| ':layout-item-min-h'
| ':layout-item-max-w'
| ':layout-item-min-w'
| ':layout-item-absolute'
| ':layout-item-z-index'
| ':layout-item-align-self';