import { Arr } from '@ephox/katamari'; import { SugarElement } from '../../api/node/SugarElement'; import * as Node from '../../api/node/SugarNode'; import * as SelectorFilter from '../../api/search/SelectorFilter'; import * as Selectors from '../../api/search/Selectors'; import type { SimSelection } from '../../api/selection/SimSelection'; import * as NativeRange from '../core/NativeRange'; import * as SelectionDirection from '../core/SelectionDirection'; const withinContainer = (win: Window, ancestor: SugarElement, outerRange: Range, selector: string): SugarElement[] => { const innerRange = NativeRange.create(win); const ancestorArray = Selectors.is(ancestor, selector) ? [ ancestor ] : []; const elements = ancestorArray.concat(SelectorFilter.descendants(ancestor, selector)); return Arr.filter(elements, (elem) => { // Mutate the selection to save creating new ranges each time NativeRange.selectNodeContentsUsing(innerRange, elem); return NativeRange.isWithin(outerRange, innerRange); }); }; const find = (win: Window, selection: SimSelection, selector: string): SugarElement[] => { // Reverse the selection if it is RTL when doing the comparison const outerRange = SelectionDirection.asLtrRange(win, selection); const ancestor = SugarElement.fromDom(outerRange.commonAncestorContainer); // Note, this might need to change when we have to start looking for non elements. return Node.isElement(ancestor) ? withinContainer(win, ancestor, outerRange, selector) : []; }; export { find };