main
js 71 lines 1.57 KB
Raw
1 /**
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 * @flow
8 */
9
10 import {TEXT_NODE} from './HTMLNodeType';
11
12 /**
13 * Given any node return the first leaf node without children.
14 *
15 * @param {DOMElement|DOMTextNode} node
16 * @return {DOMElement|DOMTextNode}
17 */
18 function getLeafNode(node: ?(Node | Element)) {
19 while (node && node.firstChild) {
20 node = node.firstChild;
21 }
22 return node;
23 }
24
25 /**
26 * Get the next sibling within a container. This will walk up the
27 * DOM if a node's siblings have been exhausted.
28 *
29 * @param {DOMElement|DOMTextNode} node
30 * @return {?DOMElement|DOMTextNode}
31 */
32 function getSiblingNode(node: ?(Node | Element)) {
33 while (node) {
34 if (node.nextSibling) {
35 return node.nextSibling;
36 }
37 node = node.parentNode;
38 }
39 }
40
41 /**
42 * Get object describing the nodes which contain characters at offset.
43 *
44 * @param {DOMElement|DOMTextNode} root
45 * @param {number} offset
46 * @return {?object}
47 */
48 function getNodeForCharacterOffset(root: Element, offset: number): ?Object {
49 let node = getLeafNode(root);
50 let nodeStart = 0;
51 let nodeEnd = 0;
52
53 while (node) {
54 if (node.nodeType === TEXT_NODE) {
55 nodeEnd = nodeStart + node.textContent.length;
56
57 if (nodeStart <= offset && nodeEnd >= offset) {
58 return {
59 node: node,
60 offset: offset - nodeStart,
61 };
62 }
63
64 nodeStart = nodeEnd;
65 }
66
67 node = getLeafNode(getSiblingNode(node));
68 }
69 }
70
71 export default getNodeForCharacterOffset;