import { IPathItem } from '../../typings' ; import { APOS_LARGE , APOS_LEN , APOS_SWEEP } from '../const' ; import { numberSequence } from '../const/syntax' ; import { parseNumberList } from '../utils/parse-numberlist' ; import { parseArc } from './parse-arc' ; const pathReg = new RegExp ( `([mzlhvcsqta])\\s*((?:${ numberSequence })?)(.*?)(?=[mzlhvcsqta]|$)` , 'gim' ) ; export const parsePath = ( str ) : IPathItem [ ] [ ] => { const result = [ ] ; let temp = [ ] ; pathReg . lastIndex = 0 ; let match = pathReg . exec ( str ) ; outer : while ( match !== null ) { const type = match [ 1 ] . toLowerCase ( ) ; if ( ! temp . length && type !== 'm' ) { return result ; } let val = [ ] ; if ( match [ 2 ] ) { val = type === 'a' ? parseArc ( match [ 2 ] ) : parseNumberList ( match [ 2 ] ) ; } switch ( type ) { case 'm' : if ( temp . length ) { result . push ( temp ) ; temp = [ ] ; } if ( val . length % 2 !== 0 ) { if ( val . length > 2 ) { temp . push ( { type : match [ 1 ] , val : val . slice ( 0 , val . length - 1 ) , } ) ; } break outer ; } break ; case 'l' : case 't' : if ( val . length % 2 !== 0 ) { if ( val . length > 2 ) { temp . push ( { type : match [ 1 ] , val : val . slice ( 0 , val . length - 1 ) , } ) ; } break outer ; } break ; case 'z' : if ( val . length ) { temp . push ( { type : match [ 1 ] , val : [ ] , } ) ; break outer ; } break ; case 's' : case 'q' : if ( val . length % 4 !== 0 ) { if ( val . length > 4 ) { temp . push ( { type : match [ 1 ] , val : val . slice ( 0 , val . length - val . length % 4 ) , } ) ; } break outer ; } break ; case 'c' : if ( val . length % 6 !== 0 ) { if ( val . length > 6 ) { temp . push ( { type : match [ 1 ] , val : val . slice ( 0 , val . length - val . length % 6 ) , } ) ; } break outer ; } break ; case 'a' : { const _val = [ ] ; val . every ( ( v , i ) => { if ( ( i % APOS_LEN === APOS_LARGE || i % APOS_LEN === APOS_SWEEP ) && v !== 0 && v !== 1 ) { return false ; } _val . push ( v ) ; return true ; } ) ; if ( _val . length % APOS_LEN !== 0 ) { if ( _val . length > APOS_LEN ) { temp . push ( { type : match [ 1 ] , val : _val . slice ( 0 , _val . length - _val . length % APOS_LEN ) , } ) ; } break outer ; } break ; } default : break ; } if ( type !== 'z' && ! val . length ) { break outer ; } temp . push ( { type : match [ 1 ] , val , } ) ; if ( match [ 3 ] && ! /^\s*,?\s*$/ . test ( match [ 3 ] ) ) { break ; } match = pathReg . exec ( str ) ; } result . push ( temp ) ; return result ; } ;