MCPcopy Create free account
hub / github.com/editablejs/editable / toEditorPoint

Function toEditorPoint

packages/editor/src/plugin/editable.ts:898–1003  ·  view source on GitHub ↗

* Find a Editor point from a DOM selection's `offsetNode` and `domOffset`.

(
    editor: Editor,
    domPoint: DOMPoint,
    options: {
      exactMatch: T
      suppressThrow: T
    },
  )

Source from the content-addressed store, hash-verified

896 * Find a Editor point from a DOM selection's `offsetNode` and `domOffset`.
897 */
898 toEditorPoint<T extends boolean>(
899 editor: Editor,
900 domPoint: DOMPoint,
901 options: {
902 exactMatch: T
903 suppressThrow: T
904 },
905 ): T extends true ? Point | null : Point {
906 const { exactMatch, suppressThrow } = options
907 const [nearestNode, nearestOffset] = exactMatch ? domPoint : normalizeDOMPoint(domPoint)
908 const parentNode = nearestNode.parentNode as DOMElement
909 let textNode: DOMElement | null = null
910 let offset = 0
911
912 if (parentNode) {
913 const editorEl = Editable.toDOMNode(editor, editor)
914 const potentialVoidNode = parentNode.closest(`[${DATA_EDITABLE_VOID}]`)
915 // Need to ensure that the closest void node is actually a void node
916 // within this editor, and not a void node within some parent editor. This can happen
917 // if this editor is within a void node of another editor ("nested editors", like in
918 // the "Editable Voids" example on the docs site).
919 const voidNode =
920 potentialVoidNode && editorEl.contains(potentialVoidNode) ? potentialVoidNode : null
921 let leafNode = parentNode.closest(`[${DATA_EDITABLE_LEAF}]`)
922 let offsetNode: DOMElement | null = null
923
924 // Calculate how far into the text node the `nearestNode` is, so that we
925 // can determine what the offset relative to the text node is.
926 if (leafNode) {
927 textNode = leafNode.closest(`[${DATA_EDITABLE_NODE}="text"]`)
928
929 if (textNode) {
930 const window = Editable.getWindow(editor)
931 const range = window.document.createRange()
932 range.setStart(textNode, 0)
933 range.setEnd(nearestNode, nearestOffset)
934
935 const contents = range.cloneContents()
936 const removals = [
937 ...Array.prototype.slice.call(
938 contents.querySelectorAll(`[${DATA_EDITABLE_ZERO_WIDTH}]`),
939 ),
940 ]
941
942 removals.forEach(el => {
943 el!.parentNode!.removeChild(el)
944 })
945
946 // COMPAT: Edge has a bug where Range.prototype.toString() will
947 // convert \n into \r\n. The bug causes a loop when slate-react
948 // attempts to reposition its cursor to match the native position. Use
949 // textContent.length instead.
950 // https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/10291116/
951 offset = contents.textContent!.length
952 offsetNode = textNode
953 }
954 } else if (voidNode) {
955 // For void nodes, the element with the offset key will be a cousin, not an

Callers

nothing calls this directly

Calls 1

normalizeDOMPointFunction · 0.90

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…