0
Fork 0
mirror of https://github.com/penpot/penpot-exporter-figma-plugin.git synced 2024-12-22 13:43:03 -05:00
penpot-exporter-figma-plugin/plugin-src/transformers/partials/transformVectorPaths.ts
Alex Sánchez a079f168df
Analytics (#228)
* metricts-sentry

* fixes

* refactor

* mixpanel integration

* improvements

* improvements

* fixes

* changeset

* fixes

* fixes

* Update .changeset/few-scissors-sleep.md

Co-authored-by: Jordi Sala Morales <jordism91@gmail.com>

* Update manifest.json

Co-authored-by: Jordi Sala Morales <jordism91@gmail.com>

* Update vite.config.ts

Co-authored-by: Jordi Sala Morales <jordism91@gmail.com>

* fixes

* fixes

* fixes

* lint

---------

Co-authored-by: Jordi Sala Morales <jordism91@gmail.com>
2024-10-28 11:22:50 +01:00

87 lines
2.5 KiB
TypeScript

import { parseSVG } from 'svg-path-parser';
import {
transformBlend,
transformEffects,
transformLayoutAttributes,
transformProportion,
transformSceneNode,
transformStrokesFromVector,
transformVectorFills
} from '@plugin/transformers/partials';
import { translateCommands, translateWindingRule } from '@plugin/translators/vectors';
import { PathShape } from '@ui/lib/types/shapes/pathShape';
export const transformVectorPaths = (node: VectorNode): PathShape[] => {
let regions: readonly VectorRegion[] = [];
try {
regions = node.vectorNetwork?.regions ?? [];
} catch (error) {
console.warn('Could not access the vector network', node, error);
}
const strokeLength = node.strokes.length;
const pathShapes = node.vectorPaths
.filter((vectorPath, index) => {
return nodeHasFills(node, vectorPath, regions[index]) || strokeLength > 0;
})
.map((vectorPath, index) => transformVectorPath(node, vectorPath, regions[index]));
const geometryShapes = node.fillGeometry
.filter(
geometry =>
!node.vectorPaths.find(
vectorPath => normalizePath(vectorPath.data) === normalizePath(geometry.data)
)
)
.map(geometry => transformVectorPath(node, geometry, undefined));
return [...geometryShapes, ...pathShapes];
};
const normalizePath = (path: string): string => {
// Round to 2 decimal places all numbers
const str = path.replace(/(\d+\.\d+|\d+)/g, (match: string) => {
return parseFloat(match).toFixed(2);
});
// remove spaces
return str.replace(/\s/g, '');
};
const nodeHasFills = (
node: VectorNode,
vectorPath: VectorPath,
vectorRegion: VectorRegion | undefined
): boolean => {
return !!(vectorPath.windingRule !== 'NONE' && (vectorRegion?.fills || node.fills));
};
const transformVectorPath = (
node: VectorNode,
vectorPath: VectorPath,
vectorRegion: VectorRegion | undefined
): PathShape => {
const normalizedPaths = parseSVG(vectorPath.data);
return {
type: 'path',
name: 'svg-path',
content: translateCommands(node, normalizedPaths),
svgAttrs: {
fillRule: translateWindingRule(vectorPath.windingRule)
},
constraintsH: 'scale',
constraintsV: 'scale',
...transformVectorFills(node, vectorPath, vectorRegion),
...transformStrokesFromVector(node, normalizedPaths, vectorRegion),
...transformEffects(node),
...transformSceneNode(node),
...transformBlend(node),
...transformProportion(node),
...transformLayoutAttributes(node)
};
};