import isEmpty from 'lodash/isEmpty' ; import get from 'lodash/get' ; import resolveIntersection from './resolveIntersection' ; import { iAst , IAstItem , iAttr , IAstElement } from './Parse' ; import { INoteTextHighlightInfo } from './Note/type' ; import { getCustomValue } from './customAttrValue' ; import { customAttr , customTag , customSplitAttr , customRowKey , customSelectedAttr , } from './constants' ; export interface IType { type : 'start' | 'end' ; uuid : string | number ; i : number ; } export interface ICustomData { d : ICustomD ; u : any ; m : string ; } export interface ICustomD { uuid : string | number ; start : number ; end : number ; [ x ] : any ; } const getElementHTML = ( item ) => { if ( item . type === 'element' ) { const { tagName , attributes , children } = item ; const attrStr = isEmpty ( attributes ) ? '' : ' ' + attributes . map ( attr => { const { value , name } = attr ; return value ? `${ name }="${ value }"` : name ; } ) . join ( ' ' ) ; const child = getAstToHTML ( children ) ; return `<${ tagName }${ attrStr }>${ child }</${ tagName }>` ; } else if ( item . type === 'text' ) { return item . content ; } throw new Error ( '解析类型错误' ) ; } ; const getAstToHTML = ( ast ) : string => { if ( isEmpty ( ast ) ) return '' ; return ast . map ( item => { return getElementHTML ( item ) ; } ) . join ( '' ) ; } ; const getLastAst = ( astItem , path ) : IAstItem => { if ( astItem . isCustom ) return astItem ; return get ( astItem , path ) || get ( astItem . children , path ) || astItem ; } ; const translateAstNodes = ( ast , options ? ) => { const { tagName = customTag , splitAttrName = customSplitAttr , attrName = customAttr , selectedAttr = customSelectedAttr , rowKey = customRowKey , modeClassNames = { } , } = getCustomValue ( ) ; const translateNodeList = [ ] ; if ( ! options || isEmpty ( options ) ) return ; options . forEach ( ( optionItem , index ) => { const { list , mode } = optionItem ; const uuid = optionItem [ rowKey ] ; if ( ! Array . isArray ( list ) || ! list . length ) return ; list . forEach ( item => { const node = item . level . reduce ( getLastAst , ast ) ; const { type , content , attributes } = node ; if ( type === 'text' || ( type === 'element' && attributes . find ( ( item ) => item . name === attrName ) ) ) { const parentNode = node . parent ; if ( ! parentNode ) return ; let cNode = node ; if ( ! node . isCustom ) { cNode = { attributes : [ { name : attrName , value : 'true' , } , ] , isCustom : true , custom : { list : [ { d : item , m : mode , u : uuid } ] , node , } , children : [ ] , parent : node . parent , tagName , type : 'element' , } ; translateNodeList . push ( cNode ) ; const index = parentNode . children . findIndex ( item => item === node ) ; if ( index !== - 1 ) { parentNode . children . splice ( index , 1 , cNode ) ; } } else { cNode . custom . list . push ( { d : item , m : mode , u : uuid } ) ; } } } ) ; } ) ; translateNodeList . forEach ( item => { const { list , node } = item . custom ; const content = node . content ; const filterData = list . filter ( ( item ) => { const { start , end , text } = item . d ; const comparisonText = content . slice ( start , end ) ; return comparisonText === text ; } ) ; const children = resolveIntersection ( filterData , content ) . map ( item => { const { start , end , text , options } = item ; const content = text ; if ( isEmpty ( options ) ) { return { content , type : 'text' , } ; } const ref = { children : [ ] } ; const lastNode = options . reduce ( ( parent , option ) => { const { uuid , mode } = option ; const item = { type : 'element' , tagName , parent : null , attributes : [ { name : 'class' , value : mode ? modeClassNames [ mode ] : '' , } , { name : splitAttrName , value : 'true' , } , { name : selectedAttr , value : uuid , } , ] , children : [ ] , } ; parent . children . push ( item ) ; return item ; } , ref ) ; lastNode . children . push ( { content , type : 'text' , } ) ; return ref . children [ 0 ] ; } ) ; item . children . push ( ... children ) ; } ) ; } ; const getJSON = ( ast , list ? ) => { translateAstNodes ( ast , list ) ; return ast ; } ; export default getJSON ;