import { parseSVG } from 'svg-path-parser'; import { transformBlend, transformEffects, transformLayoutAttributes, transformProportion, transformSceneNode, transformStrokesFromVector } from '@plugin/transformers/partials'; import { translateFills } from '@plugin/translators/fills'; import { translateCommands, translateWindingRule } from '@plugin/translators/vectors'; import { PathShape } from '@ui/lib/types/shapes/pathShape'; export const transformVectorPaths = (node: VectorNode, baseRotation: number): PathShape[] => { const pathShapes = node.vectorPaths .filter((vectorPath, index) => { return ( nodeHasFills(node, vectorPath, (node.vectorNetwork.regions ?? [])[index]) || node.strokes.length > 0 ); }) .map((vectorPath, index) => transformVectorPath(node, vectorPath, (node.vectorNetwork.regions ?? [])[index], baseRotation) ); const geometryShapes = node.fillGeometry .filter( geometry => !node.vectorPaths.find( vectorPath => normalizePath(vectorPath.data) === normalizePath(geometry.data) ) ) .map(geometry => transformVectorPath(node, geometry, undefined, baseRotation)); 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, baseRotation: number ): PathShape => { const normalizedPaths = parseSVG(vectorPath.data); return { type: 'path', name: 'svg-path', content: translateCommands(node, normalizedPaths, baseRotation), fills: vectorPath.windingRule === 'NONE' ? [] : translateFills(vectorRegion?.fills ?? node.fills), svgAttrs: { fillRule: translateWindingRule(vectorPath.windingRule) }, constraintsH: 'scale', constraintsV: 'scale', ...transformStrokesFromVector(node, normalizedPaths, vectorRegion), ...transformEffects(node), ...transformSceneNode(node), ...transformBlend(node), ...transformProportion(node), ...transformLayoutAttributes(node) }; };