mirror of
https://github.com/aljazceru/opencode.git
synced 2026-02-05 16:14:33 +01:00
feat: add desktop/web app package (#2606)
Co-authored-by: adamdotdevin <2363879+adamdottv@users.noreply.github.com> Co-authored-by: Adam <2363879+adamdotdevin@users.noreply.github.com> Co-authored-by: GitHub Action <action@github.com>
This commit is contained in:
41
packages/app/src/utils/binary.ts
Normal file
41
packages/app/src/utils/binary.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
export namespace Binary {
|
||||
export function search<T>(array: T[], id: string, compare: (item: T) => string): { found: boolean; index: number } {
|
||||
let left = 0
|
||||
let right = array.length - 1
|
||||
|
||||
while (left <= right) {
|
||||
const mid = Math.floor((left + right) / 2)
|
||||
const midId = compare(array[mid])
|
||||
|
||||
if (midId === id) {
|
||||
return { found: true, index: mid }
|
||||
} else if (midId < id) {
|
||||
left = mid + 1
|
||||
} else {
|
||||
right = mid - 1
|
||||
}
|
||||
}
|
||||
|
||||
return { found: false, index: left }
|
||||
}
|
||||
|
||||
export function insert<T>(array: T[], item: T, compare: (item: T) => string): T[] {
|
||||
const id = compare(item)
|
||||
let left = 0
|
||||
let right = array.length
|
||||
|
||||
while (left < right) {
|
||||
const mid = Math.floor((left + right) / 2)
|
||||
const midId = compare(array[mid])
|
||||
|
||||
if (midId < id) {
|
||||
left = mid + 1
|
||||
} else {
|
||||
right = mid
|
||||
}
|
||||
}
|
||||
|
||||
array.splice(left, 0, item)
|
||||
return array
|
||||
}
|
||||
}
|
||||
51
packages/app/src/utils/dom.ts
Normal file
51
packages/app/src/utils/dom.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
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 }
|
||||
}
|
||||
2
packages/app/src/utils/index.ts
Normal file
2
packages/app/src/utils/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from "./path"
|
||||
export * from "./dom"
|
||||
9
packages/app/src/utils/path.ts
Normal file
9
packages/app/src/utils/path.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export function getFilename(path: string) {
|
||||
const parts = path.split("/")
|
||||
return parts[parts.length - 1]
|
||||
}
|
||||
|
||||
export function getFileExtension(path: string) {
|
||||
const parts = path.split(".")
|
||||
return parts[parts.length - 1]
|
||||
}
|
||||
Reference in New Issue
Block a user