| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051 |
- 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 }
- }
|