summaryrefslogtreecommitdiffhomepage
path: root/packages/ui/src/pierre/diff-selection.ts
diff options
context:
space:
mode:
authorAdam <[email protected]>2026-02-26 18:23:04 -0600
committerGitHub <[email protected]>2026-02-26 18:23:04 -0600
commitfc52e4b2d3a41efde772e6de8fb2e01f27821701 (patch)
treecf23af294a00a10e55f230232585344c111f0bb9 /packages/ui/src/pierre/diff-selection.ts
parent9a6bfeb782766099d4ce3a98bb9e7b4e79f8bfe6 (diff)
downloadopencode-fc52e4b2d3a41efde772e6de8fb2e01f27821701.tar.gz
opencode-fc52e4b2d3a41efde772e6de8fb2e01f27821701.zip
feat(app): better diff/code comments (#14621)
Co-authored-by: adamelmore <[email protected]> Co-authored-by: David Hill <[email protected]>
Diffstat (limited to 'packages/ui/src/pierre/diff-selection.ts')
-rw-r--r--packages/ui/src/pierre/diff-selection.ts71
1 files changed, 71 insertions, 0 deletions
diff --git a/packages/ui/src/pierre/diff-selection.ts b/packages/ui/src/pierre/diff-selection.ts
new file mode 100644
index 000000000..bc008b1b2
--- /dev/null
+++ b/packages/ui/src/pierre/diff-selection.ts
@@ -0,0 +1,71 @@
+import { type SelectedLineRange } from "@pierre/diffs"
+
+export type DiffSelectionSide = "additions" | "deletions"
+
+export function findDiffSide(node: HTMLElement): DiffSelectionSide {
+ const line = node.closest("[data-line], [data-alt-line]")
+ if (line instanceof HTMLElement) {
+ const type = line.dataset.lineType
+ if (type === "change-deletion") return "deletions"
+ if (type === "change-addition" || type === "change-additions") return "additions"
+ }
+
+ const code = node.closest("[data-code]")
+ if (!(code instanceof HTMLElement)) return "additions"
+ return code.hasAttribute("data-deletions") ? "deletions" : "additions"
+}
+
+export function diffLineIndex(split: boolean, node: HTMLElement) {
+ const raw = node.dataset.lineIndex
+ if (!raw) return
+
+ const values = raw
+ .split(",")
+ .map((x) => parseInt(x, 10))
+ .filter((x) => !Number.isNaN(x))
+ if (values.length === 0) return
+ if (!split) return values[0]
+ if (values.length === 2) return values[1]
+ return values[0]
+}
+
+export function diffRowIndex(root: ShadowRoot, split: boolean, line: number, side: DiffSelectionSide | undefined) {
+ const rows = Array.from(root.querySelectorAll(`[data-line="${line}"], [data-alt-line="${line}"]`)).filter(
+ (node): node is HTMLElement => node instanceof HTMLElement,
+ )
+ if (rows.length === 0) return
+
+ const target = side ?? "additions"
+ for (const row of rows) {
+ if (findDiffSide(row) === target) return diffLineIndex(split, row)
+ if (parseInt(row.dataset.altLine ?? "", 10) === line) return diffLineIndex(split, row)
+ }
+}
+
+export function fixDiffSelection(root: ShadowRoot | undefined, range: SelectedLineRange | null) {
+ if (!range) return range
+ if (!root) return
+
+ const diffs = root.querySelector("[data-diff]")
+ if (!(diffs instanceof HTMLElement)) return
+
+ const split = diffs.dataset.diffType === "split"
+ const start = diffRowIndex(root, split, range.start, range.side)
+ const end = diffRowIndex(root, split, range.end, range.endSide ?? range.side)
+
+ if (start === undefined || end === undefined) {
+ if (root.querySelector("[data-line], [data-alt-line]") == null) return
+ return null
+ }
+ if (start <= end) return range
+
+ const side = range.endSide ?? range.side
+ const swapped: SelectedLineRange = {
+ start: range.end,
+ end: range.start,
+ }
+
+ if (side) swapped.side = side
+ if (range.endSide && range.side) swapped.endSide = range.side
+ return swapped
+}