in packages/dom/src/normalize-range.ts [70:113]
export function normalizeRange(range: Range, scope?: Range): TextRange {
const document = ownerDocument(range);
const walker = document.createTreeWalker(document, NodeFilter.SHOW_TEXT, {
acceptNode(node: Text) {
return !scope || scope.intersectsNode(node)
? NodeFilter.FILTER_ACCEPT
: NodeFilter.FILTER_REJECT;
},
});
let [startContainer, startOffset] = snapBoundaryPointToTextNode(
range.startContainer,
range.startOffset,
);
// If we point at the end of a text node, move to the start of the next one.
// The step is repeated to skip over empty text nodes.
walker.currentNode = startContainer;
while (startOffset === startContainer.length && walker.nextNode()) {
startContainer = walker.currentNode as Text;
startOffset = 0;
}
// Set the range’s start; note this might move its end too.
range.setStart(startContainer, startOffset);
let [endContainer, endOffset] = snapBoundaryPointToTextNode(
range.endContainer,
range.endOffset,
);
// If we point at the start of a text node, move to the end of the previous one.
// The step is repeated to skip over empty text nodes.
walker.currentNode = endContainer;
while (endOffset === 0 && walker.previousNode()) {
endContainer = walker.currentNode as Text;
endOffset = endContainer.length;
}
// Set the range’s end; note this might move its start too.
range.setEnd(endContainer, endOffset);
return range as TextRange;
}