module import { Node , Element , hasChildren , isDocument , Document } from 'domhandler' ; import type { Cheerio } from '../cheerio' ; import * as select from 'cheerio-select' ; import { domEach , isTag , isCheerio } from '../utils' ; import { contains } from '../static' ; import { getChildren , getSiblings , nextElementSibling , prevElementSibling , uniqueSort , } from 'domutils' ; import type { FilterFunction , AcceptedFilters } from '../types' ; const reSiblingSelector = /^\s*[~+]/ ; category example param selectorOrHaystack returns see https export function find < T extends Node > ( this , selectorOrHaystack ? ) { if ( ! selectorOrHaystack ) { return this . _make ( [ ] ) ; } const context = this . toArray ( ) ; if ( typeof selectorOrHaystack !== 'string' ) { const haystack = isCheerio ( selectorOrHaystack ) ? selectorOrHaystack . toArray ( ) : [ selectorOrHaystack ] ; return this . _make ( haystack . filter ( ( elem ) => context . some ( ( node ) => contains ( node , elem ) ) ) ) ; } const elems = reSiblingSelector . test ( selectorOrHaystack ) ? context : this . children ( ) . toArray ( ) ; const options = { context , root : this . _root ?. [ 0 ] , xmlMode : this . options . xmlMode , } ; return this . _make ( select . select ( selectorOrHaystack , elems , options ) ) ; } private param matchMap returns function _getMatcher < P > ( matchMap ) { return function ( fn , ... postFns ) { return function < T extends Node > ( this , selector ? ) : Cheerio < Element > { let matched = matchMap ( fn , this ) ; if ( selector ) { matched = filterArray ( matched , selector , this . options . xmlMode , this . _root ?. [ 0 ] ) ; } return this . _make ( this . length > 1 && matched . length > 1 ? postFns . reduce ( ( elems , fn ) => fn ( elems ) , matched ) : matched ) ; } ; } ; } /** Matcher that adds multiple elements for each entry in the input. */ const _matcher = _getMatcher ( ( fn , elems ) => { const ret = [ ] ; for ( let i = 0 ; i < elems . length ; i ++ ) { const value = fn ( elems [ i ] ) ; ret . push ( value ) ; } return new Array < Element > ( ) . concat ( ... ret ) ; } ) ; /** Matcher that adds at most one element for each entry in the input. */ const _singleMatcher = _getMatcher ( ( fn , elems ) => { const ret = [ ] ; for ( let i = 0 ; i < elems . length ; i ++ ) { const value = fn ( elems [ i ] ) ; if ( value !== null ) { ret . push ( value ) ; } } return ret ; } ) ; returns function _matchUntil ( nextElem , ... postFns ) { let matches = null ; const innerMatcher = _getMatcher ( ( nextElem , elems ) => { const matched = [ ] ; domEach ( elems , ( elem ) => { for ( let next ; ( next = nextElem ( elem ) ) ; elem = next ) { if ( matches ?. ( next , matched . length ) ) break ; matched . push ( next ) ; } } ) ; return matched ; } ) ( nextElem , ... postFns ) ; return function < T extends Node > ( this , selector ? , filterSelector ? ) : Cheerio < Element > { matches = typeof selector === 'string' ? ( elem ) => select . is ( elem , selector , this . options ) : selector ? getFilterFn ( selector ) : null ; const ret = innerMatcher . call ( this , filterSelector ) ; matches = null ; return ret ; } ; } function _removeDuplicates < T extends Node > ( elems ) { return Array . from ( new Set < T > ( elems ) ) ; } category example param selector returns see https export const parent = _singleMatcher ( ( { parent } ) => ( parent && ! isDocument ( parent ) ? ( parent as Element ) : null ) , _removeDuplicates ) ; category example param selector returns see https export const parents = _matcher ( ( elem ) => { const matched = [ ] ; while ( elem . parent && ! isDocument ( elem . parent ) ) { matched . push ( elem . parent as Element ) ; elem = elem . parent ; } return matched ; } , uniqueSort , ( elems ) => elems . reverse ( ) ) ; category example param selector param filterSelector returns see https export const parentsUntil = _matchUntil ( ( { parent } ) => ( parent && ! isDocument ( parent ) ? ( parent as Element ) : null ) , uniqueSort , ( elems ) => elems . reverse ( ) ) ; category example param selector returns see https export function closest < T extends Node > ( this , selector ? ) { const set = [ ] ; if ( ! selector ) { return this . _make ( set ) ; } const selectOpts = { xmlMode : this . options . xmlMode , root : this . _root ?. [ 0 ] , } ; const selectFn = typeof selector === 'string' ? ( elem ) => select . is ( elem , selector , selectOpts ) : getFilterFn ( selector ) ; domEach ( this , ( elem ) => { while ( elem && isTag ( elem ) ) { if ( selectFn ( elem , 0 ) ) { if ( ! set . includes ( elem ) ) { set . push ( elem ) ; } break ; } elem = elem . parent ; } } ) ; return this . _make ( set ) ; } category example param selector returns see https export const next = _singleMatcher ( ( elem ) => nextElementSibling ( elem ) ) ; category example param selector returns see https export const nextAll = _matcher ( ( elem ) => { const matched = [ ] ; while ( elem . next ) { elem = elem . next ; if ( isTag ( elem ) ) matched . push ( elem ) ; } return matched ; } , _removeDuplicates ) ; category example param selector param filterSelector returns see https export const nextUntil = _matchUntil ( ( el ) => nextElementSibling ( el ) , _removeDuplicates ) ; category example param selector returns see https export const prev = _singleMatcher ( ( elem ) => prevElementSibling ( elem ) ) ; category example param selector returns see https export const prevAll = _matcher ( ( elem ) => { const matched = [ ] ; while ( elem . prev ) { elem = elem . prev ; if ( isTag ( elem ) ) matched . push ( elem ) ; } return matched ; } , _removeDuplicates ) ; category example param selector param filterSelector returns see https export const prevUntil = _matchUntil ( ( el ) => prevElementSibling ( el ) , _removeDuplicates ) ; category example param selector returns see https export const siblings = _matcher ( ( elem ) => getSiblings ( elem ) . filter ( ( el ) : el is Element => isTag ( el ) && el !== elem ) , uniqueSort ) ; category example param selector returns see https export const children = _matcher ( ( elem ) => getChildren ( elem ) . filter ( isTag ) , _removeDuplicates ) ; category example returns see https export function contents < T extends Node > ( this ) { const elems = this . toArray ( ) . reduce < Node [ ] > ( ( newElems , elem ) => hasChildren ( elem ) ? newElems . concat ( elem . children ) : newElems , [ ] ) ; return this . _make ( elems ) ; } category example param fn returns see https export function each < T > ( this , fn ) { let i = 0 ; const len = this . length ; while ( i < len && fn . call ( this [ i ] , i , this [ i ] ) !== false ) ++ i ; return this ; } category example param fn returns see https export function map < T , M > ( this , fn ) { let elems = [ ] ; for ( let i = 0 ; i < this . length ; i ++ ) { const el = this [ i ] ; const val = fn . call ( el , i , el ) ; if ( val != null ) { elems = elems . concat ( val ) ; } } return this . _make ( elems ) ; } param match returns function getFilterFn < T > ( match ) { if ( typeof match === 'function' ) { return ( el , i ) => ( match as FilterFunction < T > ) . call ( el , i , el ) ; } if ( isCheerio < T > ( match ) ) { return ( el ) => Array . prototype . includes . call ( match , el ) ; } return function ( el ) { return match === el ; } ; } category example param match returns see https export function filter < T , S extends T > ( this , match ) ; category example example param match - Value to look for, following the rules above. See
 *    AcceptedFilters .
 *  returns see https export function filter < T , S extends AcceptedFilters < T > > ( this , match ) ; export function filter < T > ( this , match ) { return this . _make < unknown > ( filterArray ( this . toArray ( ) , match , this . options . xmlMode , this . _root ?. [ 0 ] ) ) ; } export function filterArray < T > ( nodes , match , xmlMode ? , root ? ) { return typeof match === 'string' ? select . filter ( match , nodes as unknown as Node [ ] , { xmlMode , root } ) : nodes . filter ( getFilterFn < T > ( match ) ) ; } category param selector returns see https export function is < T > ( this , selector ? ) { const nodes = this . toArray ( ) ; return typeof selector === 'string' ? select . some ( ( nodes as unknown as Node [ ] ) . filter ( isTag ) , selector , this . options ) : selector ? nodes . some ( getFilterFn < T > ( selector ) ) : false ; } category example example param match param container returns see https export function not < T extends Node > ( this , match ) { let nodes = this . toArray ( ) ; if ( typeof match === 'string' ) { const matches = new Set < Node > ( select . filter ( match , nodes , this . options ) ) ; nodes = nodes . filter ( ( el ) => ! matches . has ( el ) ) ; } else { const filterFn = getFilterFn ( match ) ; nodes = nodes . filter ( ( el , i ) => ! filterFn ( el , i ) ) ; } return this . _make ( nodes ) ; } category example example param selectorOrHaystack returns see https export function has ( this , selectorOrHaystack ) { return this . filter ( typeof selectorOrHaystack === 'string' ? `:has(${ selectorOrHaystack })` : ( _ , el ) => this . _make ( el ) . find ( selectorOrHaystack ) . length > 0 ) ; } category example returns see https export function first < T extends Node > ( this ) { return this . length > 1 ? this . _make ( this [ 0 ] ) : this ; } category example returns see https export function last < T > ( this ) { return this . length > 0 ? this . _make ( this [ this . length - 1 ] ) : this ; } category example param i returns see https export function eq < T > ( this , i ) { i = + i ; if ( i === 0 && this . length <= 1 ) return this ; if ( i < 0 ) i = this . length + i ; return this . _make ( this [ i ] ?? [ ] ) ; } category example param i returns see https export function get < T > ( this , i ) ; category example returns see https export function get < T > ( this ) ; export function get < T > ( this , i ? ) { if ( i == null ) { return this . toArray ( ) ; } return this [ i < 0 ? this . length + i : i ] ; } example returns export function toArray < T > ( this ) { return Array . prototype . slice . call ( this ) ; } category example param selectorOrNeedle returns see https export function index < T extends Node > ( this , selectorOrNeedle ? ) { let $haystack ; let needle ; if ( selectorOrNeedle == null ) { $haystack = this . parent ( ) . children ( ) ; needle = this [ 0 ] ; } else if ( typeof selectorOrNeedle === 'string' ) { $haystack = this . _make < Node > ( selectorOrNeedle ) ; needle = this [ 0 ] ; } else { $haystack = this ; needle = isCheerio ( selectorOrNeedle ) ? selectorOrNeedle [ 0 ] : selectorOrNeedle ; } return Array . prototype . indexOf . call ( $haystack , needle ) ; } category example param start param end returns see https export function slice < T > ( this , start ? , end ? ) { return this . _make ( Array . prototype . slice . call ( this , start , end ) ) ; } category example returns see https export function end < T > ( this ) { return this . prevObject ?? this . _make ( [ ] ) ; } category example param other param context returns see https export function add < S extends Node , T extends Node > ( this , other , context ? ) { const selection = this . _make ( other , context ) ; const contents = uniqueSort ( [ ... this . get ( ) , ... selection . get ( ) ] ) ; return this . _make ( contents ) ; } category example param selector returns see https export function addBack < T extends Node > ( this , selector ? ) { return this . prevObject ? this . add ( selector ? this . prevObject . filter ( selector ) : this . prevObject ) : this ; }