module import { Node , NodeWithChildren , Element , Text , hasChildren } from 'domhandler' ; import { update as updateDOM } from '../parse' ; import { text as staticText } from '../static' ; import { domEach , cloneDom , isTag , isHtml , isCheerio } from '../utils' ; import { removeElement } from 'domutils' ; import type { Cheerio } from '../cheerio' ; import type { BasicAcceptedElems , AcceptedElems } from '../types' ; private category param elem param clone returns export function _makeDomArray < T extends Node > ( this , elem ? , clone ? ) { if ( elem == null ) { return [ ] ; } if ( isCheerio ( elem ) ) { return clone ? cloneDom ( elem . get ( ) ) : elem . get ( ) ; } if ( Array . isArray ( elem ) ) { return elem . reduce < Node [ ] > ( ( newElems , el ) => newElems . concat ( this . _makeDomArray ( el , clone ) ) , [ ] ) ; } if ( typeof elem === 'string' ) { return this . _parse ( elem , this . options , false ) . children ; } return clone ? cloneDom ( [ elem ] ) : [ elem ] ; } function _insert ( concatenator ) { return function < T extends Node > ( this , ... elems ) { const lastIdx = this . length - 1 ; return domEach ( this , ( el , i ) => { if ( ! hasChildren ( el ) ) return ; const domSrc = typeof elems [ 0 ] === 'function' ? elems [ 0 ] . call ( el , i , this . _render ( el . children ) ) : ( elems as Node [ ] ) ; const dom = this . _makeDomArray ( domSrc , i < lastIdx ) ; concatenator ( dom , el . children , el ) ; } ) ; } ; } private category param array param spliceIdx param spliceCount param newElems param parent returns function uniqueSplice ( array , spliceIdx , spliceCount , newElems , parent ) { const spliceArgs = [ spliceIdx , spliceCount , ... newElems , ] ; const prev = spliceIdx === 0 ? null : array [ spliceIdx - 1 ] ; const next = spliceIdx + spliceCount >= array . length ? null : array [ spliceIdx + spliceCount ] ; for ( let idx = 0 ; idx < newElems . length ; ++ idx ) { const node = newElems [ idx ] ; const oldParent = node . parent ; if ( oldParent ) { const prevIdx = oldParent . children . indexOf ( node ) ; if ( prevIdx > - 1 ) { oldParent . children . splice ( prevIdx , 1 ) ; if ( parent === oldParent && spliceIdx > prevIdx ) { spliceArgs [ 0 ] -- ; } } } node . parent = parent ; if ( node . prev ) { node . prev . next = node . next ?? null ; } if ( node . next ) { node . next . prev = node . prev ?? null ; } node . prev = idx === 0 ? prev : newElems [ idx - 1 ] ; node . next = idx === newElems . length - 1 ? next : newElems [ idx + 1 ] ; } if ( prev ) { prev . next = newElems [ 0 ] ; } if ( next ) { next . prev = newElems [ newElems . length - 1 ] ; } return array . splice ( ... spliceArgs ) ; } category example param target returns see https export function appendTo < T extends Node > ( this , target ) { const appendTarget = isCheerio ( target ) ? target : this . _make ( target ) ; appendTarget . append ( this ) ; return this ; } category example param target returns see https export function prependTo < T extends Node > ( this , target ) { const prependTarget = isCheerio ( target ) ? target : this . _make ( target ) ; prependTarget . prepend ( this ) ; return this ; } category example see https export const append = _insert ( ( dom , children , parent ) => { uniqueSplice ( children , children . length , 0 , dom , parent ) ; } ) ; category example see https export const prepend = _insert ( ( dom , children , parent ) => { uniqueSplice ( children , 0 , 0 , dom , parent ) ; } ) ; function _wrap ( insert ) { return function < T extends Node > ( this , wrapper ) { const lastIdx = this . length - 1 ; const lastParent = this . parents ( ) . last ( ) ; for ( let i = 0 ; i < this . length ; i ++ ) { const el = this [ i ] ; const wrap = typeof wrapper === 'function' ? wrapper . call ( el , i , el ) : typeof wrapper === 'string' && ! isHtml ( wrapper ) ? lastParent . find ( wrapper ) . clone ( ) : wrapper ; const [ wrapperDom ] = this . _makeDomArray ( wrap , i < lastIdx ) ; if ( ! wrapperDom || ! hasChildren ( wrapperDom ) ) continue ; let elInsertLocation = wrapperDom ; let j = 0 ; while ( j < elInsertLocation . children . length ) { const child = elInsertLocation . children [ j ] ; if ( isTag ( child ) ) { elInsertLocation = child ; j = 0 ; } else { j ++ ; } } insert ( el , elInsertLocation , [ wrapperDom ] ) ; } return this ; } ; } category example param wrapper see https export const wrap = _wrap ( ( el , elInsertLocation , wrapperDom ) => { const { parent } = el ; if ( ! parent ) return ; const siblings = parent . children ; const index = siblings . indexOf ( el ) ; updateDOM ( [ el ] , elInsertLocation ) ; uniqueSplice ( siblings , index , 0 , wrapperDom , parent ) ; } ) ; category example param wrapper returns see https export const wrapInner = _wrap ( ( el , elInsertLocation , wrapperDom ) => { if ( ! hasChildren ( el ) ) return ; updateDOM ( el . children , elInsertLocation ) ; updateDOM ( wrapperDom , el ) ; } ) ; category example example param selector returns see https export function unwrap < T extends Node > ( this , selector ? ) { this . parent ( selector ) . not ( 'body' ) . each ( ( _ , el ) => { this . _make ( el ) . replaceWith ( el . children ) ; } ) ; return this ; } category example example param wrapper returns see https export function wrapAll < T extends Node > ( this , wrapper ) { const el = this [ 0 ] ; if ( el ) { const wrap = this . _make ( typeof wrapper === 'function' ? wrapper . call ( el , 0 , el ) : wrapper ) . insertBefore ( el ) ; let elInsertLocation ; for ( let i = 0 ; i < wrap . length ; i ++ ) { if ( wrap [ i ] . type === 'tag' ) elInsertLocation = wrap [ i ] as Element ; } let j = 0 ; while ( elInsertLocation && j < elInsertLocation . children . length ) { const child = elInsertLocation . children [ j ] ; if ( child . type === 'tag' ) { elInsertLocation = child as Element ; j = 0 ; } else { j ++ ; } } if ( elInsertLocation ) this . _make ( elInsertLocation ) . append ( this ) ; } return this ; } category example param content returns see https export function after < T extends Node > ( this , ... elems ) { const lastIdx = this . length - 1 ; return domEach ( this , ( el , i ) => { const { parent } = el ; if ( ! hasChildren ( el ) || ! parent ) { return ; } const siblings = parent . children ; const index = siblings . indexOf ( el ) ; if ( index < 0 ) return ; const domSrc = typeof elems [ 0 ] === 'function' ? elems [ 0 ] . call ( el , i , this . _render ( el . children ) ) : ( elems as Node [ ] ) ; const dom = this . _makeDomArray ( domSrc , i < lastIdx ) ; uniqueSplice ( siblings , index + 1 , 0 , dom , parent ) ; } ) ; } category example param target returns see https export function insertAfter < T extends Node > ( this , target ) { if ( typeof target === 'string' ) { target = this . _make < Node > ( target ) ; } this . remove ( ) ; const clones = [ ] ; this . _makeDomArray ( target ) . forEach ( ( el ) => { const clonedSelf = this . clone ( ) . toArray ( ) ; const { parent } = el ; if ( ! parent ) { return ; } const siblings = parent . children ; const index = siblings . indexOf ( el ) ; if ( index < 0 ) return ; uniqueSplice ( siblings , index + 1 , 0 , clonedSelf , parent ) ; clones . push ( ... clonedSelf ) ; } ) ; return this . _make ( clones ) ; } category example param content returns see https export function before < T extends Node > ( this , ... elems ) { const lastIdx = this . length - 1 ; return domEach ( this , ( el , i ) => { const { parent } = el ; if ( ! hasChildren ( el ) || ! parent ) { return ; } const siblings = parent . children ; const index = siblings . indexOf ( el ) ; if ( index < 0 ) return ; const domSrc = typeof elems [ 0 ] === 'function' ? elems [ 0 ] . call ( el , i , this . _render ( el . children ) ) : ( elems as Node [ ] ) ; const dom = this . _makeDomArray ( domSrc , i < lastIdx ) ; uniqueSplice ( siblings , index , 0 , dom , parent ) ; } ) ; } category example param target returns see https export function insertBefore < T extends Node > ( this , target ) { const targetArr = this . _make < Node > ( target ) ; this . remove ( ) ; const clones = [ ] ; domEach ( targetArr , ( el ) => { const clonedSelf = this . clone ( ) . toArray ( ) ; const { parent } = el ; if ( ! parent ) { return ; } const siblings = parent . children ; const index = siblings . indexOf ( el ) ; if ( index < 0 ) return ; uniqueSplice ( siblings , index , 0 , clonedSelf , parent ) ; clones . push ( ... clonedSelf ) ; } ) ; return this . _make ( clones ) ; } category example param selector returns see https export function remove < T extends Node > ( this , selector ? ) { const elems = selector ? this . filter ( selector ) : this ; domEach ( elems , ( el ) => { removeElement ( el ) ; el . prev = el . next = el . parent = null ; } ) ; return this ; } category example param content returns see https export function replaceWith < T extends Node > ( this , content ) { return domEach ( this , ( el , i ) => { const { parent } = el ; if ( ! parent ) { return ; } const siblings = parent . children ; const cont = typeof content === 'function' ? content . call ( el , i , el ) : content ; const dom = this . _makeDomArray ( cont ) ; updateDOM ( dom , null ) ; const index = siblings . indexOf ( el ) ; uniqueSplice ( siblings , index , 1 , dom , parent ) ; if ( ! dom . includes ( el ) ) { el . parent = el . prev = el . next = null ; } } ) ; } category example returns see https export function empty < T extends Node > ( this ) { return domEach ( this , ( el ) => { if ( ! hasChildren ( el ) ) return ; el . children . forEach ( ( child ) => { child . next = child . prev = child . parent = null ; } ) ; el . children . length = 0 ; } ) ; } category example param str returns see https export function html < T extends Node > ( this ) ; export function html < T extends Node > ( this , str ) ; export function html < T extends Node > ( this , str ? ) { if ( str === undefined ) { const el = this [ 0 ] ; if ( ! el || ! hasChildren ( el ) ) return null ; return this . _render ( el . children ) ; } const opts = { ... this . options , context : null as NodeWithChildren | null } ; return domEach ( this , ( el ) => { if ( ! hasChildren ( el ) ) return ; el . children . forEach ( ( child ) => { child . next = child . prev = child . parent = null ; } ) ; opts . context = el ; const content = isCheerio ( str ) ? str . toArray ( ) : this . _parse ( `${ str }` , opts , false ) . children ; updateDOM ( content , el ) ; } ) ; } category returns export function toString < T extends Node > ( this ) { return this . _render ( this ) ; } category example param str returns see https export function text < T extends Node > ( this ) ; export function text < T extends Node > ( this , str ) ; export function text < T extends Node > ( this , str ? ) { if ( str === undefined ) { return staticText ( this ) ; } if ( typeof str === 'function' ) { return domEach ( this , ( el , i ) => this . _make ( el ) . text ( str . call ( el , i , staticText ( [ el ] ) ) ) ) ; } return domEach ( this , ( el ) => { if ( ! hasChildren ( el ) ) return ; el . children . forEach ( ( child ) => { child . next = child . prev = child . parent = null ; } ) ; const textNode = new Text ( `${ str }` ) ; updateDOM ( textNode , el ) ; } ) ; } category example returns see https export function clone < T extends Node > ( this ) { return this . _make ( cloneDom ( this . get ( ) ) ) ; }