summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src/utils
diff options
context:
space:
mode:
authorDax <[email protected]>2025-09-15 03:28:08 -0400
committerGitHub <[email protected]>2025-09-15 03:28:08 -0400
commit725104572e2b6d64dcfc145d4748124186427c7b (patch)
treedaf5b26437fd267bc41848e0578ed13d1b43bb52 /packages/app/src/utils
parent4954edf8aeb5b8b395fc4f4e91b7fe36cfab212d (diff)
downloadopencode-725104572e2b6d64dcfc145d4748124186427c7b.tar.gz
opencode-725104572e2b6d64dcfc145d4748124186427c7b.zip
feat: add desktop/web app package (#2606)
Co-authored-by: adamdotdevin <[email protected]> Co-authored-by: Adam <[email protected]> Co-authored-by: GitHub Action <[email protected]>
Diffstat (limited to 'packages/app/src/utils')
-rw-r--r--packages/app/src/utils/binary.ts41
-rw-r--r--packages/app/src/utils/dom.ts51
-rw-r--r--packages/app/src/utils/index.ts2
-rw-r--r--packages/app/src/utils/path.ts9
4 files changed, 103 insertions, 0 deletions
diff --git a/packages/app/src/utils/binary.ts b/packages/app/src/utils/binary.ts
new file mode 100644
index 000000000..3d8f61851
--- /dev/null
+++ b/packages/app/src/utils/binary.ts
@@ -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
+ }
+}
diff --git a/packages/app/src/utils/dom.ts b/packages/app/src/utils/dom.ts
new file mode 100644
index 000000000..4f3724c7c
--- /dev/null
+++ b/packages/app/src/utils/dom.ts
@@ -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 }
+}
diff --git a/packages/app/src/utils/index.ts b/packages/app/src/utils/index.ts
new file mode 100644
index 000000000..ae89e4417
--- /dev/null
+++ b/packages/app/src/utils/index.ts
@@ -0,0 +1,2 @@
+export * from "./path"
+export * from "./dom"
diff --git a/packages/app/src/utils/path.ts b/packages/app/src/utils/path.ts
new file mode 100644
index 000000000..d6a066e80
--- /dev/null
+++ b/packages/app/src/utils/path.ts
@@ -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]
+}