Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | 1x 1x 406x 406x 406x 90x 90x 5x 5x 90x 316x 316x 406x 1184x 1184x 1184x 386x 42x 2x 40x 344x 384x 1184x 1184x 1184x 406x | import { isNodeOfType } from 'roosterjs-content-model-dom';
/**
* @internal
*
* Get the path of the node relative to rootNode.
* The path of the node is an array of integer indices into the childNodes of the given node.
*
* The node path will be what the node path will be on a _normalized_ dom
* (e.g. empty text nodes will be ignored and adjacent text nodes will be concatenated)
*
* @param rootNode the node the path will be relative to
* @param position the position to get indexes from. Follows the same semantics
* as selectionRange (if node is of type Text, it is an offset into the text of that node.
* If node is of type Element, it is the index of a child in that Element node.)
*/
export function getPath(node: Node | null, offset: number, rootNode: Node): number[] {
const result: number[] = [];
let parent: Node | null;
Iif (!node || !rootNode.contains(node)) {
return result;
}
if (isNodeOfType(node, 'TEXT_NODE')) {
parent = node.parentNode;
while (node.previousSibling && isNodeOfType(node.previousSibling, 'TEXT_NODE')) {
offset += node.previousSibling.nodeValue?.length || 0;
node = node.previousSibling;
}
result.unshift(offset);
} else {
parent = node;
node = node.childNodes[offset];
}
do {
offset = 0;
let isPreviousText = false;
for (let c: Node | null = parent?.firstChild || null; c && c != node; c = c.nextSibling) {
if (isNodeOfType(c, 'TEXT_NODE')) {
if (c.nodeValue?.length === 0 || isPreviousText) {
continue;
}
isPreviousText = true;
} else {
isPreviousText = false;
}
offset++;
}
result.unshift(offset);
node = parent;
parent = parent?.parentNode || null;
} while (node && node != rootNode);
return result;
}
|