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 306x 306x 306x 102x 102x 5x 5x 102x 204x 204x 306x 968x 968x 968x 248x 32x 2x 30x 216x 246x 968x 968x 968x 306x | 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; } |