import { IDocument , ITagNode } from 'svg-vdom' ; import { filterPrimitiveElements , transferFunctionElements } from '../const/definitions' ; import { hasProp } from '../utils/has-prop' ; import { getAnimateAttr } from '../xml/get-animate-attr' ; const feFuncAttr = [ 'tableValues' , 'slope' , 'intercept' , 'amplitude' , 'exponent' , 'offset' ] ; const feTypeNeed = { identity : [ ] , table : [ 'tableValues' ] , discrete : [ 'tableValues' ] , linear : [ 'slope' , 'intercept' ] , gamma : [ 'amplitude' , 'exponent' , 'offset' ] , } ; const checkFeAttrs = ( type , rmAttrs ) => { if ( hasProp ( feTypeNeed , type ) ) { feTypeNeed [ type as keyof typeof feTypeNeed ] . forEach ( val => { const index = rmAttrs . indexOf ( val ) ; if ( index !== - 1 ) { rmAttrs . splice ( index , 1 ) ; } } ) ; } } ; export const shortenFilter = async ( dom ) : Promise < void > => new Promise ( resolve => { const filterTags = dom . querySelectorAll ( [ 'filter' ] . concat ( filterPrimitiveElements , transferFunctionElements ) . join ( ',' ) ) as ITagNode [ ] ; filterTags . forEach ( node => { if ( filterPrimitiveElements . includes ( node . nodeName ) || node . nodeName === 'filter' ) { const width = node . getAttribute ( 'width' ) ; const height = node . getAttribute ( 'height' ) ; if ( ( width && parseFloat ( width ) <= 0 ) || ( height && parseFloat ( height ) <= 0 ) ) { node . remove ( ) ; return ; } } if ( node . nodeName === 'filter' ) { let hasFilterSub = false ; node . childNodes . forEach ( subNode => { if ( filterPrimitiveElements . includes ( subNode . nodeName ) ) { hasFilterSub = true ; } } ) ; if ( ! hasFilterSub ) { node . remove ( ) ; return ; } } if ( node . nodeName === 'feComponentTransfer' ) { const funcUnique = new Set < string > ( ) ; for ( let i = node . childNodes . length ; i -- ; ) { const childNode = node . childNodes [ i ] ; if ( funcUnique . has ( childNode . nodeName ) ) { childNode . remove ( ) ; continue ; } if ( transferFunctionElements . includes ( childNode . nodeName ) ) { funcUnique . add ( childNode . nodeName ) ; } } } if ( transferFunctionElements . includes ( node . nodeName ) ) { const type = node . getAttribute ( 'type' ) || '' ; const animateAttrs = getAnimateAttr ( node ) . filter ( item => item . attributeName === 'type' ) ; if ( ! type && ! animateAttrs . length ) { node . remove ( ) ; return ; } const rmAttrs = feFuncAttr . slice ( ) ; checkFeAttrs ( type , rmAttrs ) ; animateAttrs . forEach ( item => { item . values . forEach ( val => { checkFeAttrs ( val , rmAttrs ) ; } ) ; } ) ; rmAttrs . forEach ( attr => { node . removeAttribute ( attr ) ; } ) ; } } ) ; resolve ( ) ; } ) ;