export function resolveLink ( element ) { const parentScanState = { element , iterationAllowed : 3 , } ; while ( parentScanState . element && parentScanState . iterationAllowed ) { if ( parentScanState . element . nodeType === Node . ELEMENT_NODE && ( "tagName" in parentScanState . element && parentScanState . element . tagName . toLowerCase ( ) === "a" ) ) { parentScanState . link = true ; break ; } parentScanState . element = parentScanState . element . parentNode ; parentScanState . iterationAllowed -- ; } const result = { element : parentScanState . element as Element , link : parentScanState . link , } ; if ( ! result . link ) { return result ; } result . href = ( result . element as HTMLLinkElement ) . href ; return result ; } export function isInput ( el ) { return el . tagName === "INPUT" ; } export function isTextarea ( el ) { return el . tagName === "TEXTAREA" ; } export function isContentEditable ( el ) { return el . hasAttribute ( "contenteditable" ) ; } export function isContentEditableDeep ( el ) { let value = false ; while ( el && ! value ) { value = "tagName" in el && isContentEditable ( el ) ; el = el . parentNode ; } return value ; } export function isPasswordInput ( el ) { return ( isInput ( el ) && String ( el . getAttribute ( "type" ) ) . toLowerCase ( ) === "password" ) ; } export function isWritable ( el ) { const writableInput = ( ( isInput ( el ) || isTextarea ( el ) ) && ! el . disabled && ! el . hasAttribute ( "disabled" ) && ! el . readOnly && ! el . hasAttribute ( "readonly" ) ) ; return writableInput || isContentEditableDeep ( el ) ; }