import { Declaration , Rule , StyleRules } from 'css' ; import { NodeType , parseSelector } from 'svg-vdom' ; import { IDom , ITag } from '../../typings/node' ; import { IStyleObj } from '../../typings/style' ; import { importantReg } from '../const/regs' ; import { regularAttr } from '../const/regular-attr' ; import { parseStyle } from '../style/parse' ; import { getSelectorPriority , overrideAble } from '../style/seletor-priority' ; import { styleToValue } from '../style/style-to-value' ; import { valueIsEqual } from '../xml/attr-is-equal' ; import { parseStyleTree } from '../xml/parse-style-tree' ; export const rmImportant = async ( dom ) : Promise < void > => new Promise ( resolve => { parseStyleTree ( dom ) ; if ( dom . stylesheet ) { ( dom . stylesheet . stylesheet as StyleRules ) . rules . forEach ( ( styleRule ) => { if ( styleRule . type === 'rule' && styleRule . declarations && styleRule . selectors ) { const importantMap = new Map < string , Declaration > ( ) ; styleRule . declarations . forEach ( ( ruleItem ) => { if ( ruleItem . property && ruleItem . value ) { if ( importantReg . test ( ruleItem . value ) ) { importantMap . set ( ruleItem . property , ruleItem ) ; } } } ) ; if ( importantMap . size ) { for ( let si = styleRule . selectors . length ; si -- ; ) { const selector = parseSelector ( styleRule . selectors [ si ] ) [ 0 ] ; const selectorPriority = getSelectorPriority ( selector ) ; const nodes = dom . querySelectorAll ( selector ) as ITag [ ] ; if ( nodes . length ) { nodes . forEach ( node => { const nodeStyles = node . styles as IStyleObj ; for ( const [ key , decl ] of importantMap ) { if ( nodeStyles [ key ] . from === 'styletag' && valueIsEqual ( regularAttr [ key ] , nodeStyles [ key ] . value , ( decl . value as string ) . replace ( importantReg , '' ) ) ) { if ( nodeStyles [ key ] . overrideList . some ( ovr => ovr . from === 'inline' || ( ( ovr . important || overrideAble ( ovr . selectorPriority , selectorPriority ) ) && ! valueIsEqual ( regularAttr [ key ] , ovr . value , decl . value as string ) ) ) ) { importantMap . delete ( key ) ; } } } } ) ; } } for ( const decl of importantMap . values ( ) ) { decl . value = ( decl . value as string ) . replace ( importantReg , '' ) ; } } } } ) ; } parseStyleTree ( dom ) ; const tags = dom . querySelectorAll ( NodeType . Tag ) as ITag [ ] ; tags . forEach ( node => { if ( node . hasAttribute ( 'style' ) ) { const nodeStyles = node . styles as IStyleObj ; const styleList = parseStyle ( node . getAttribute ( 'style' ) as string ) ; styleList . forEach ( style => { if ( style . important ) { if ( ( nodeStyles [ style . fullname ] . overrideList as Array < { important ? : boolean ; value : string ; } > ) . every ( ovr => ! ovr . important || valueIsEqual ( regularAttr [ style . fullname ] , ovr . value , style . value ) ) ) { style . important = false ; } } } ) ; node . setAttribute ( 'style' , styleToValue ( styleList ) ) ; } } ) ; resolve ( ) ; } ) ;