import { Arr, Optional } from '@ephox/katamari'; import type { Gene } from '../api/Gene'; import * as Properties from './Properties'; import * as Up from './Up'; const extract = (item: Gene): string[] => { const { id } = item; const rest = item.children && item.children.length > 0 ? Arr.bind(item.children, extract) : []; return [ id ].concat(rest); }; // TODO: This is broken. See TINY-6501, but the gist is that the behaviour of this function should match // https://developer.mozilla.org/en-US/docs/Web/API/Node/compareDocumentPosition and it doesn't. const comparePosition = (item: Gene, other: Gene): number => { // horribly inefficient const top = Up.top(item); const all = extract(top); const itemIndex = Arr.findIndex(all, (x) => { return item.id === x; }); const otherIndex = Arr.findIndex(all, (x) => { return other.id === x; }); return itemIndex.bind((iIndex) => { return otherIndex.map((oIndex): number => { if (iIndex < oIndex) { return 4; } else { return 2; } }); }).getOr(0); }; const prevSibling = (item: Gene): Optional => { const parent = Properties.parent(item); const kin = parent.map(Properties.children).getOr([]); const itemIndex = Arr.findIndex(kin, (x) => { return item.id === x.id; }); return itemIndex.bind((iIndex) => { return iIndex > 0 ? Optional.some(kin[iIndex - 1]) : Optional.none(); }); }; const nextSibling = (item: Gene): Optional => { const parent = Properties.parent(item); const kin = parent.map(Properties.children).getOr([]); const itemIndex = Arr.findIndex(kin, (x) => { return item.id === x.id; }); return itemIndex.bind((iIndex) => { return iIndex < kin.length - 1 ? Optional.some(kin[iIndex + 1]) : Optional.none(); }); }; export { comparePosition, prevSibling, nextSibling };