mirror of
https://github.com/penpot/penpot-exporter-figma-plugin.git
synced 2024-12-22 05:33:02 -05:00
Boolean Groups (#115)
* wip * wip * fixes * changeset * fixes * fixes * fixes * fixes * minor fixes * minor fixes
This commit is contained in:
parent
aafb9cf342
commit
36afc6da55
14 changed files with 139 additions and 8 deletions
5
.changeset/dry-pumas-warn.md
Normal file
5
.changeset/dry-pumas-warn.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"penpot-exporter": minor
|
||||
---
|
||||
|
||||
Added support for boolean groups
|
|
@ -1,3 +1,4 @@
|
|||
export * from './transformBooleanNode';
|
||||
export * from './transformDocumentNode';
|
||||
export * from './transformEllipseNode';
|
||||
export * from './transformFrameNode';
|
||||
|
|
33
plugin-src/transformers/transformBooleanNode.ts
Normal file
33
plugin-src/transformers/transformBooleanNode.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
import {
|
||||
transformBlend,
|
||||
transformChildren,
|
||||
transformDimensionAndPosition,
|
||||
transformEffects,
|
||||
transformFills,
|
||||
transformProportion,
|
||||
transformSceneNode,
|
||||
transformStrokes
|
||||
} from '@plugin/transformers/partials';
|
||||
import { translateBoolType } from '@plugin/translators';
|
||||
|
||||
import { BoolShape } from '@ui/lib/types/shapes/boolShape';
|
||||
|
||||
export const transformBooleanNode = async (
|
||||
node: BooleanOperationNode,
|
||||
baseX: number,
|
||||
baseY: number
|
||||
): Promise<BoolShape> => {
|
||||
return {
|
||||
type: 'bool',
|
||||
name: node.name,
|
||||
boolType: translateBoolType(node.booleanOperation),
|
||||
...(await transformChildren(node, baseX, baseY)),
|
||||
...(await transformFills(node)),
|
||||
...transformEffects(node),
|
||||
...(await transformStrokes(node)),
|
||||
...transformDimensionAndPosition(node, baseX, baseY),
|
||||
...transformSceneNode(node),
|
||||
...transformBlend(node),
|
||||
...transformProportion(node)
|
||||
};
|
||||
};
|
|
@ -1,6 +1,7 @@
|
|||
import { PenpotNode } from '@ui/lib/types/penpotNode';
|
||||
|
||||
import {
|
||||
transformBooleanNode,
|
||||
transformEllipseNode,
|
||||
transformFrameNode,
|
||||
transformGroupNode,
|
||||
|
@ -33,6 +34,8 @@ export const transformSceneNode = async (
|
|||
case 'POLYGON':
|
||||
case 'LINE':
|
||||
return await transformPathNode(node, baseX, baseY);
|
||||
case 'BOOLEAN_OPERATION':
|
||||
return await transformBooleanNode(node, baseX, baseY);
|
||||
}
|
||||
|
||||
console.error(`Unsupported node type: ${node.type}`);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
export * from './translateBlendMode';
|
||||
export * from './translateBlurEffects';
|
||||
export * from './translateBoolType';
|
||||
export * from './translateShadowEffects';
|
||||
export * from './translateStrokes';
|
||||
|
|
15
plugin-src/translators/translateBoolType.ts
Normal file
15
plugin-src/translators/translateBoolType.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { BoolOperations } from '@ui/lib/types/shapes/boolShape';
|
||||
|
||||
type BooleanOperation = 'UNION' | 'INTERSECT' | 'SUBTRACT' | 'EXCLUDE';
|
||||
export const translateBoolType = (booleanOperation: BooleanOperation): BoolOperations => {
|
||||
switch (booleanOperation) {
|
||||
case 'EXCLUDE':
|
||||
return 'exclude';
|
||||
case 'INTERSECT':
|
||||
return 'intersection';
|
||||
case 'SUBTRACT':
|
||||
return 'difference';
|
||||
case 'UNION':
|
||||
return 'union';
|
||||
}
|
||||
};
|
22
ui-src/converters/createPenpotBool.ts
Normal file
22
ui-src/converters/createPenpotBool.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { createPenpotItem } from '@ui/converters/createPenpotItem';
|
||||
import { PenpotFile } from '@ui/lib/types/penpotFile';
|
||||
import { BoolShape } from '@ui/lib/types/shapes/boolShape';
|
||||
import { translateFillGradients, translateUiBlendMode, translateUiBoolType } from '@ui/translators';
|
||||
|
||||
export const createPenpotBool = (
|
||||
file: PenpotFile,
|
||||
{ type, fills, boolType, blendMode, children = [], ...rest }: BoolShape
|
||||
) => {
|
||||
file.addBool({
|
||||
fills: translateFillGradients(fills),
|
||||
blendMode: translateUiBlendMode(blendMode),
|
||||
boolType: translateUiBoolType(boolType),
|
||||
...rest
|
||||
});
|
||||
|
||||
for (const child of children) {
|
||||
createPenpotItem(file, child);
|
||||
}
|
||||
|
||||
file.closeBool();
|
||||
};
|
|
@ -3,6 +3,7 @@ import { PenpotNode } from '@ui/lib/types/penpotNode';
|
|||
|
||||
import {
|
||||
createPenpotArtboard,
|
||||
createPenpotBool,
|
||||
createPenpotCircle,
|
||||
createPenpotGroup,
|
||||
createPenpotPath,
|
||||
|
@ -24,5 +25,7 @@ export const createPenpotItem = (file: PenpotFile, node: PenpotNode) => {
|
|||
return createPenpotPath(file, node);
|
||||
case 'text':
|
||||
return createPenpotText(file, node);
|
||||
case 'bool':
|
||||
return createPenpotBool(file, node);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
export * from './createPenpotArtboard';
|
||||
export * from './createPenpotBool';
|
||||
export * from './createPenpotCircle';
|
||||
export * from './createPenpotFile';
|
||||
export * from './createPenpotGroup';
|
||||
|
|
|
@ -32,6 +32,6 @@ export interface PenpotFile {
|
|||
// lookupShape(shapeId: string): void;
|
||||
// updateObject(id: string, object: any): void;
|
||||
// deleteObject(id: string): void;
|
||||
asMap(): unknown;
|
||||
// asMap(): unknown;
|
||||
export(): void;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { BoolShape } from '@ui/lib/types/shapes/boolShape';
|
||||
import { CircleShape } from '@ui/lib/types/shapes/circleShape';
|
||||
import { FrameShape } from '@ui/lib/types/shapes/frameShape';
|
||||
import { GroupShape } from '@ui/lib/types/shapes/groupShape';
|
||||
|
@ -5,4 +6,11 @@ import { PathShape } from '@ui/lib/types/shapes/pathShape';
|
|||
import { RectShape } from '@ui/lib/types/shapes/rectShape';
|
||||
import { TextShape } from '@ui/lib/types/shapes/textShape';
|
||||
|
||||
export type PenpotNode = FrameShape | GroupShape | PathShape | RectShape | CircleShape | TextShape;
|
||||
export type PenpotNode =
|
||||
| FrameShape
|
||||
| GroupShape
|
||||
| PathShape
|
||||
| RectShape
|
||||
| CircleShape
|
||||
| TextShape
|
||||
| BoolShape;
|
||||
|
|
|
@ -1,23 +1,39 @@
|
|||
import { LayoutChildAttributes } from '@ui/lib/types/shapes/layout';
|
||||
import { PathContent } from '@ui/lib/types/shapes/pathShape';
|
||||
import { ShapeAttributes, ShapeBaseAttributes } from '@ui/lib/types/shapes/shape';
|
||||
import { Children } from '@ui/lib/types/utils/children';
|
||||
import { Point } from '@ui/lib/types/utils/point';
|
||||
import { Uuid } from '@ui/lib/types/utils/uuid';
|
||||
|
||||
export const BOOL_DIFFERENCE: unique symbol = Symbol.for('difference');
|
||||
export const BOOL_UNION: unique symbol = Symbol.for('union');
|
||||
export const BOOL_INTERSECTION: unique symbol = Symbol.for('intersection');
|
||||
export const BOOL_EXCLUDE: unique symbol = Symbol.for('exclude');
|
||||
|
||||
export type BoolOperations =
|
||||
| 'difference'
|
||||
| 'union'
|
||||
| 'intersection'
|
||||
| 'exclude'
|
||||
| typeof BOOL_DIFFERENCE
|
||||
| typeof BOOL_UNION
|
||||
| typeof BOOL_INTERSECTION
|
||||
| typeof BOOL_EXCLUDE;
|
||||
|
||||
export type BoolShape = ShapeBaseAttributes &
|
||||
ShapeAttributes &
|
||||
BoolAttributes &
|
||||
LayoutChildAttributes;
|
||||
LayoutChildAttributes &
|
||||
Children;
|
||||
|
||||
type BoolAttributes = {
|
||||
type?: 'bool';
|
||||
shapes?: Uuid[];
|
||||
boolType: string; // @TODO: in Penpot this is of type :keyword. check if it makes sense
|
||||
boolContent: BoolContent[];
|
||||
boolType: BoolOperations;
|
||||
boolContent?: BoolContent[];
|
||||
};
|
||||
|
||||
type BoolContent = {
|
||||
command: string; // @TODO: in Penpot this is of type :keyword. check if it makes sense
|
||||
relative?: boolean;
|
||||
prevPos?: Point;
|
||||
params?: { [keyword: string]: number }; // @TODO: in Penpot this is of type :keyword. check if it makes sense
|
||||
};
|
||||
} & PathContent;
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
export * from './translateFillGradients';
|
||||
export * from './translatePathContent';
|
||||
export * from './translateUiBlendMode';
|
||||
export * from './translateUiBoolType';
|
||||
|
|
22
ui-src/translators/translateUiBoolType.ts
Normal file
22
ui-src/translators/translateUiBoolType.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import {
|
||||
BOOL_DIFFERENCE,
|
||||
BOOL_EXCLUDE,
|
||||
BOOL_INTERSECTION,
|
||||
BOOL_UNION,
|
||||
BoolOperations
|
||||
} from '@ui/lib/types/shapes/boolShape';
|
||||
|
||||
export const translateUiBoolType = (booleanOperation: BoolOperations): BoolOperations => {
|
||||
switch (booleanOperation) {
|
||||
case 'union':
|
||||
return BOOL_UNION;
|
||||
case 'exclude':
|
||||
return BOOL_EXCLUDE;
|
||||
case 'difference':
|
||||
return BOOL_DIFFERENCE;
|
||||
case 'intersection':
|
||||
return BOOL_INTERSECTION;
|
||||
}
|
||||
|
||||
throw new Error(`Unsupported boolean operation: ${String(booleanOperation)}`);
|
||||
};
|
Loading…
Reference in a new issue