import { Arr, Fun, type Optional } from '@ephox/katamari'; import * as Compare from '../dom/Compare'; import type { SugarElement } from '../node/SugarElement'; import * as PredicateFind from './PredicateFind'; import * as SelectorFilter from './SelectorFilter'; import * as SelectorFind from './SelectorFind'; import * as Traverse from './Traverse'; export interface AddressInAncestor { readonly ancestor: SugarElement; readonly descendants: ReadonlyArray>; readonly element: SugarElement; readonly index: number; } export interface AddressInParent { readonly parent: SugarElement

; readonly children: ReadonlyArray>; readonly element: SugarElement; readonly index: number; } const inAncestor = (ancestor: SugarElement, descendants: SugarElement[], element: SugarElement, index: number): AddressInAncestor => ({ ancestor, descendants, element, index }); const inParent = (parent: SugarElement

, children: SugarElement[], element: SugarElement, index: number): AddressInParent => ({ parent, children, element, index }); const childOf = (element: SugarElement, ancestor: SugarElement): Optional> => PredicateFind.closest(element, (elem) => Traverse.parent(elem).exists((parent) => Compare.eq(parent, ancestor))); const indexInParent = (element: SugarElement): Optional> => Traverse.parent(element).bind((parent) => { const children = Traverse.children(parent); return indexOf(children, element).map((index) => inParent(parent, children, element, index)); }); const indexOf = (elements: SugarElement[], element: SugarElement): Optional => Arr.findIndex(elements, Fun.curry(Compare.eq, element)); const selectorsInParent = (element: SugarElement, selector: string): Optional> => Traverse.parent(element).bind((parent) => { const children = SelectorFilter.children(parent, selector); return indexOf(children, element).map((index) => inParent(parent, children, element, index)); }); const descendantsInAncestor = (element: SugarElement, ancestorSelector: string, descendantSelector: string): Optional> => SelectorFind.closest(element, ancestorSelector).bind((ancestor) => { const descendants = SelectorFilter.descendants(ancestor, descendantSelector); return indexOf(descendants, element).map((index) => inAncestor(ancestor, descendants, element, index)); }); export { childOf, indexOf, indexInParent, selectorsInParent, descendantsInAncestor };