import { isElementMatch } from "./isElementMatch" ; import { Cue , Evaluator , Rect } from "./types" ; let evaluator ; try { evaluator = require ( "playwright-evaluator" ) ; console . log ( evaluator ) ; } catch ( e ) { } function shouldSkipForTextMatching ( element ) { return element . nodeName === "SCRIPT" || element . nodeName === "STYLE" || ( document . head && document . head . contains ( element ) ) ; } export function elementText ( root ) { let value = "" ; if ( ! shouldSkipForTextMatching ( root ) ) { if ( root instanceof HTMLInputElement && ( root . type === "submit" || root . type === "button" ) ) { value = root . value ; } else { for ( let child = root . firstChild ; child ; child = child . nextSibling ) { if ( child . nodeType === Node . ELEMENT_NODE ) value += elementText ( child as Element ) ; else if ( child . nodeType === Node . TEXT_NODE ) value += child . nodeValue || "" ; if ( value . length > 100 ) break ; } if ( ( root as Element ) . shadowRoot ) value += elementText ( ( root as Element ) . shadowRoot ! ) ; } } return value ; } export const buildSelectorForCues = ( cues ) : string => { const levels = [ ... new Set ( cues . map ( ( cue ) => cue . level ) ) ] ; levels . sort ( ( a , b ) => a - b ) ; const parts = [ ] ; let useMultipleEngines = true ; levels . forEach ( ( level ) => { const cuesForLevel = cues . filter ( ( cue ) => cue . level === level ) ; const textCues = cuesForLevel . filter ( ( cue ) => cue . type === "text" ) ; if ( textCues . length === 1 ) { parts . push ( `text=${ textCues [ 0 ] . value }` ) ; useMultipleEngines = true ; return ; } cuesForLevel . sort ( ( a , b ) => { if ( a . type === "modifier" ) return 1 ; if ( b . type === "modifier" ) return - 1 ; if ( a . type === "tag" ) return - 1 ; if ( b . type === "tag" ) return 1 ; return 0 ; } ) ; const cssSelector = cuesForLevel . map ( ( cue ) => ( cue . type === "text" ? `:has-text("${ cue . value }")` : cue . value ) ) . join ( "" ) ; parts . push ( cssSelector ) ; } ) ; return useMultipleEngines ? parts . join ( " >> " ) : parts . join ( " " ) ; } ; export const buildElementText = ( element ) : string => { const text = elementText ( element ) . replace ( /\s+/g , " " ) . trim ( ) ; return text . length > 100 ? "" : text ; } ; export const evaluatorQuerySelector = ( selector , root ? ) : HTMLElement | null => { return evaluator . querySelector ( selector , root || document ) ; } ; export const isSelectorMatch = ( selector , target , rectCache ) : boolean => { try { const matchedElement = evaluatorQuerySelector ( selector , target . ownerDocument ! ) ; return ! ! matchedElement && isElementMatch ( matchedElement , target , rectCache ) ; } catch ( err ) { console . error ( err ) ; return false ; } } ;