mirror of
https://github.com/open-webui/open-webui.git
synced 2026-10-18 04:43:55 +00:00
refac
This commit is contained in:
parent
1595c20130
commit
10ce0d2365
2 changed files with 50 additions and 21 deletions
|
|
@ -6,6 +6,48 @@ export const diffEditorConfig: DiffConfig = { timeout: 100 };
|
|||
|
||||
export type MergeDirection = 'to-working' | 'to-proposal';
|
||||
|
||||
// Match rows by the text preserved inside a chunk, not their ordinal position.
|
||||
export function changedLinePairs(a: Text, b: Text, chunk: Chunk): [number, number][] {
|
||||
const candidates = new Map<number, Map<number, { a: number; b: number; weight: number }>>();
|
||||
let fromA = chunk.fromA;
|
||||
let fromB = chunk.fromB;
|
||||
for (let index = 0; index <= chunk.changes.length; index++) {
|
||||
const change = chunk.changes[index];
|
||||
const endA = change ? chunk.fromA + change.fromA : Math.min(chunk.toA, a.length);
|
||||
const endB = change ? chunk.fromB + change.fromB : Math.min(chunk.toB, b.length);
|
||||
while (fromA < endA && fromB < endB) {
|
||||
const lineA = a.lineAt(fromA),
|
||||
lineB = b.lineAt(fromB);
|
||||
const length = Math.min(endA - fromA, endB - fromB, lineA.to - fromA, lineB.to - fromB);
|
||||
const weight = a.sliceString(fromA, fromA + length).replace(/\s/g, '').length;
|
||||
if (weight) {
|
||||
let row = candidates.get(lineA.from);
|
||||
if (!row) candidates.set(lineA.from, (row = new Map()));
|
||||
const pair = row.get(lineB.from) ?? { a: lineA.from, b: lineB.from, weight: 0 };
|
||||
pair.weight += weight;
|
||||
row.set(lineB.from, pair);
|
||||
}
|
||||
fromA += length || 1;
|
||||
fromB += length || 1;
|
||||
}
|
||||
if (change) {
|
||||
fromA = chunk.fromA + change.toA;
|
||||
fromB = chunk.fromB + change.toB;
|
||||
}
|
||||
}
|
||||
const bestA = new Map<number, { a: number; b: number; weight: number }>();
|
||||
const bestB = new Map<number, { a: number; b: number; weight: number }>();
|
||||
for (const row of candidates.values()) {
|
||||
for (const pair of row.values()) {
|
||||
if (pair.weight > (bestA.get(pair.a)?.weight ?? 0)) bestA.set(pair.a, pair);
|
||||
if (pair.weight > (bestB.get(pair.b)?.weight ?? 0)) bestB.set(pair.b, pair);
|
||||
}
|
||||
}
|
||||
return [...bestA.values()]
|
||||
.filter((pair) => bestB.get(pair.b) === pair)
|
||||
.map((pair) => [pair.a, pair.b]);
|
||||
}
|
||||
|
||||
export function changedLineCounts(a: Text, b: Text, chunks: readonly Chunk[]) {
|
||||
const count = (doc: Text, side: 'A' | 'B') => {
|
||||
let total = 0;
|
||||
|
|
|
|||
|
|
@ -7,16 +7,19 @@ import {
|
|||
type DecorationSet
|
||||
} from '@codemirror/view';
|
||||
import type { Chunk } from '@codemirror/merge';
|
||||
import { changedLinePairs } from './diffEditor';
|
||||
|
||||
export function pairedLinePosition(a: Text, b: Text, chunks: readonly Chunk[], position: number) {
|
||||
let offset = 0;
|
||||
for (const chunk of chunks) {
|
||||
if (position < chunk.fromA) break;
|
||||
if (position < chunk.toA) {
|
||||
const row = a.lineAt(position).number - a.lineAt(chunk.fromA).number;
|
||||
const start = b.lineAt(Math.min(chunk.fromB, b.length)).number;
|
||||
const end = b.lineAt(Math.min(Math.max(chunk.fromB, chunk.toB - 1), b.length)).number;
|
||||
return b.line(Math.min(start + row, end)).from;
|
||||
const pairs = changedLinePairs(a, b, chunk);
|
||||
const line = a.lineAt(position).from;
|
||||
return (
|
||||
(pairs.find(([from]) => from >= line) ?? pairs.at(-1))?.[1] ??
|
||||
Math.min(chunk.fromB, b.length)
|
||||
);
|
||||
}
|
||||
offset = chunk.toB - chunk.toA;
|
||||
}
|
||||
|
|
@ -128,23 +131,7 @@ export function alignChangedLines(a: EditorView, b: EditorView, chunks: readonly
|
|||
align(posA, posB);
|
||||
}
|
||||
if (!chunk) break;
|
||||
if (chunk.fromA < chunk.toA && chunk.fromB < chunk.toB) {
|
||||
const lineA = a.state.doc.lineAt(chunk.fromA).number,
|
||||
lineB = b.state.doc.lineAt(chunk.fromB).number;
|
||||
let row = Math.max(
|
||||
0,
|
||||
a.state.doc.lineAt(a.viewport.from).number - lineA,
|
||||
b.state.doc.lineAt(b.viewport.from).number - lineB
|
||||
);
|
||||
while (lineA + row <= a.state.doc.lines && lineB + row <= b.state.doc.lines) {
|
||||
const posA = a.state.doc.line(lineA + row).from,
|
||||
posB = b.state.doc.line(lineB + row).from;
|
||||
if (posA >= chunk.toA || posB >= chunk.toB || posA > a.viewport.to || posB > b.viewport.to)
|
||||
break;
|
||||
align(posA, posB);
|
||||
row++;
|
||||
}
|
||||
}
|
||||
for (const [posA, posB] of changedLinePairs(a.state.doc, b.state.doc, chunk)) align(posA, posB);
|
||||
fromA = chunk.toA;
|
||||
fromB = chunk.toB;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue