import { NodeType } from 'svg-vdom' ; import { IRuleOption } from '../../typings' ; import { IDom , ITag } from '../../typings/node' ; import { needUnitInStyle } from '../const/definitions' ; import { regularAttr } from '../const/regular-attr' ; import { regularTag } from '../const/regular-tag' ; import { numberFullMatch } from '../const/syntax' ; import { cantTrans } from '../style/cant-trans' ; import { checkGeometry } from '../style/check-geometry' ; import { parseStyle } from '../style/parse' ; import { styleToValue } from '../style/style-to-value' ; import { hasProp } from '../utils/has-prop' ; import { parseStyleTree } from '../xml/parse-style-tree' ; const STYLE_LEN = 8 ; const checkTrans = ( attrObj ) => { let stylelen = STYLE_LEN ; Object . entries ( attrObj ) . forEach ( ( [ key , val ] ) => { if ( ! needUnitInStyle . includes ( key ) || ! numberFullMatch . test ( val . value ) || + val . value === 0 ) { stylelen -= 2 ; } } ) ; return stylelen ; } ; interface IStyleAttrObj { [ prop ] : { value : string ; fromStyle ? : boolean ; onlyCss ? : boolean ; } ; } const checkAttr = ( node , dom , browsers ) => { parseStyleTree ( dom ) ; const attrObj = { } ; const tagDefine = regularTag [ node . nodeName ] ; const nodeStyle = node . styles ; for ( let i = node . attributes . length ; i -- ; ) { const attr = node . attributes [ i ] ; const attrDefine = regularAttr [ attr . fullname ] ; if ( attr . fullname === 'style' ) { const styleList = parseStyle ( attr . value ) ; for ( let si = styleList . length ; si -- ; ) { const styleItem = styleList [ si ] ; const styleDefine = regularAttr [ styleItem . fullname ] ; const onlyCss = ( nodeStyle && nodeStyle [ styleItem . fullname ] && nodeStyle [ styleItem . fullname ] . override ) || ( ! styleDefine . couldBeStyle && ! checkGeometry ( node . nodeName , styleItem . fullname , browsers ) ) || cantTrans ( tagDefine , styleItem . fullname ) ; attrObj [ styleItem . fullname ] = { value : styleItem . value , fromStyle : true , onlyCss , } ; } } else if ( attrDefine . couldBeStyle || checkGeometry ( node . nodeName , attr . fullname , browsers ) ) { if ( cantTrans ( tagDefine , attr . fullname ) ) { continue ; } if ( ! hasProp ( attrObj , attr . fullname ) ) { attrObj [ attr . fullname ] = { value : attr . value , } ; } } } return attrObj ; } ; export const shortenStyleAttr = async ( dom , { browsers , } ) : Promise < void > => new Promise ( resolve => { const tags = dom . querySelectorAll ( NodeType . Tag ) as ITag [ ] ; tags . forEach ( node => { const attrObj = checkAttr ( node , dom , browsers ) ; const transLen = checkTrans ( attrObj ) ; if ( Object . values ( attrObj ) . some ( val => val . onlyCss ) || transLen < 0 ) { Object . entries ( attrObj ) . forEach ( ( [ key , val ] ) => { if ( ! val . onlyCss ) { node . removeAttribute ( key ) ; } } ) ; node . setAttribute ( 'style' , styleToValue ( Object . keys ( attrObj ) . reverse ( ) . map ( key => { let value = attrObj [ key ] . value ; if ( needUnitInStyle . includes ( key ) && numberFullMatch . test ( value ) && + value !== 0 ) { value += 'px' ; } return { name : key , fullname : key , value , } ; } ) ) ) ; } else { node . removeAttribute ( 'style' ) ; Object . keys ( attrObj ) . reverse ( ) . forEach ( name => { let value = attrObj [ name ] . value ; if ( needUnitInStyle . includes ( name ) && ! numberFullMatch . test ( value ) ) { value = value . replace ( /(?<=\d)px$/ , '' ) ; } node . setAttribute ( name , value ) ; } ) ; } } ) ; resolve ( ) ; } ) ;