import Component from "../components/component" ; import Block from "../components/block" ; import Editor from "../editor" ; import StructureType from "../const/structure-type" ; import Inline from "../components/inline" ; import ComponentType from "../const/component-type" ; import { nextTick } from ".." ; const getWrapDom = ( containDocument , id ) : HTMLElement | null => { let element = containDocument . getElementById ( id ) ; if ( element ?. dataset . inList ) { return element ! . parentElement ! ; } return element ; } ; const getParentDom = ( containDocument , id ) : HTMLElement | null => { let element = containDocument . getElementById ( id ) ; if ( element ?. dataset . type === ComponentType . table ) { return element ! . children [ 0 ] as HTMLElement ; } return element ; } ; const recallQueue = [ ] ; const handleRecallQueue = ( editor ) => { let containDocument = editor . mountedDocument ; while ( recallQueue . length ) { const [ afterComId , newDom , parentDom ] = recallQueue . pop ( ) ! ; let afterDom = getWrapDom ( containDocument , afterComId ) ; if ( afterDom ) { parentDom . insertBefore ( newDom , afterDom ) ; } else { recallQueue . unshift ( [ afterComId , newDom , parentDom ] ) ; } } } ; let inLoop = false ; const updateComponent = ( editor , ... componentList ) => { if ( ! editor . mountedDocument ) return ; componentList . sort ( ( each ) => ( each . structureType === StructureType . structure ? - 1 : 1 ) ) . forEach ( ( each ) => update ( editor , each ) ) ; handleRecallQueue ( editor ) ; if ( ! inLoop ) { inLoop = true ; nextTick ( ( ) => { inLoop = false ; document . dispatchEvent ( new Event ( "editorChange" ) ) ; } ) ; } } ; const update = ( editor , component ) => { if ( component . type === ComponentType . article ) return ; let containDocument = editor . mountedDocument ; let oldDom = getWrapDom ( containDocument , component . id ) ; if ( ! component . parent ) { if ( oldDom ) { oldDom . remove ( ) ; } return ; } let inList = component . parent . type === ComponentType . list ; let newDom = component . render ( editor . contentView ) ; if ( inList ) { newDom = editor . contentView . buildListItem ( component . render ( editor . contentView ) , component . structureType ) ; } if ( oldDom === newDom ) { return ; } if ( component instanceof Inline ) { if ( oldDom ) { oldDom . replaceWith ( newDom ) ; } else if ( component . parent ) { update ( editor , component . parent ) ; } return ; } if ( component instanceof Block ) { if ( oldDom ) { if ( component . active ) { oldDom ?. replaceWith ( newDom ) ; } else { oldDom ?. remove ( ) ; } return ; } let parentComponent = component . parent ; let parentDom = getParentDom ( containDocument , parentComponent . id ) ; if ( ! parentDom ) { return ; } let index = parentComponent . findChildrenIndex ( component ) ; if ( index === parentComponent . getSize ( ) - 1 ) { parentDom . appendChild ( newDom ) ; } else { let afterComId = parentComponent . getChild ( index + 1 ) . id ; let afterDom = getWrapDom ( containDocument , afterComId ) ; if ( afterDom ) { parentDom . insertBefore ( newDom , afterDom ) ; } else { recallQueue . push ( [ afterComId , newDom , parentDom ] ) ; } } } } ; export default updateComponent ;