mirror of
https://github.com/aljazceru/opencode.git
synced 2025-12-25 03:34:22 +01:00
52 lines
2.0 KiB
TypeScript
52 lines
2.0 KiB
TypeScript
export function getCharacterOffsetInLine(lineElement: Element, targetNode: Node, offset: number): number {
|
|
const r = document.createRange()
|
|
r.selectNodeContents(lineElement)
|
|
r.setEnd(targetNode, offset)
|
|
return r.toString().length
|
|
}
|
|
|
|
export function getNodeOffsetInLine(lineElement: Element, charIndex: number): { node: Node; offset: number } | null {
|
|
const walker = document.createTreeWalker(lineElement, NodeFilter.SHOW_TEXT, null)
|
|
let remaining = Math.max(0, charIndex)
|
|
let lastText: Node | null = null
|
|
let lastLen = 0
|
|
let node: Node | null
|
|
while ((node = walker.nextNode())) {
|
|
const len = node.textContent?.length || 0
|
|
lastText = node
|
|
lastLen = len
|
|
if (remaining <= len) return { node, offset: remaining }
|
|
remaining -= len
|
|
}
|
|
if (lastText) return { node: lastText, offset: lastLen }
|
|
if (lineElement.firstChild) return { node: lineElement.firstChild, offset: 0 }
|
|
return null
|
|
}
|
|
|
|
export function getSelectionInContainer(
|
|
container: HTMLElement,
|
|
): { sl: number; sch: number; el: number; ech: number } | null {
|
|
const s = window.getSelection()
|
|
if (!s || s.rangeCount === 0) return null
|
|
const r = s.getRangeAt(0)
|
|
const sc = r.startContainer
|
|
const ec = r.endContainer
|
|
const getLineElement = (n: Node) =>
|
|
(n.nodeType === Node.TEXT_NODE ? (n.parentElement as Element) : (n as Element))?.closest(".line")
|
|
const sle = getLineElement(sc)
|
|
const ele = getLineElement(ec)
|
|
if (!sle || !ele) return null
|
|
if (!container.contains(sle as Node) || !container.contains(ele as Node)) return null
|
|
const cc = container.querySelector("code") as HTMLElement | null
|
|
if (!cc) return null
|
|
const lines = Array.from(cc.querySelectorAll(".line"))
|
|
const sli = lines.indexOf(sle as Element)
|
|
const eli = lines.indexOf(ele as Element)
|
|
if (sli === -1 || eli === -1) return null
|
|
const sl = sli + 1
|
|
const el = eli + 1
|
|
const sch = getCharacterOffsetInLine(sle as Element, sc, r.startOffset)
|
|
const ech = getCharacterOffsetInLine(ele as Element, ec, r.endOffset)
|
|
return { sl, sch, el, ech }
|
|
}
|