summaryrefslogtreecommitdiff
path: root/frontend/src/lib/draftGuard.ts
blob: d6a5222b41c00f0adc6d5d85b6caf7057c828c7e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import { diffLines, diffWordsWithSpace } from 'diff';

export interface DiffStats {
  added: number;
  removed: number;
}

export function unifiedDiffStats(before: string, after: string): DiffStats {
  const parts = diffLines(before, after);
  let added = 0;
  let removed = 0;
  for (const p of parts) {
    if (p.added) added += p.value.replace(/\n$/, '').split('\n').length;
    else if (p.removed) removed += p.value.replace(/\n$/, '').split('\n').length;
  }
  return { added, removed };
}

export interface ServerDraft {
  generation: number;
  code: string;
}

export interface ConflictVerdict {
  stale: boolean;
  serverEqualsLocal: boolean;
  localDirty: boolean;
}

export class ConflictResolver {
  constructor(private local: { generation: number; code: string }) {}

  onServerState(server: ServerDraft, lastKnownGeneration: number): ConflictVerdict {
    const stale = server.generation !== lastKnownGeneration && lastKnownGeneration !== null;
    const serverEqualsLocal = server.generation === this.local.generation && server.code === this.local.code;
    return { stale, serverEqualsLocal, localDirty: true };
  }

  retryPlan(server: ServerDraft): { generation: number; code: string } {
    return { generation: server.generation, code: this.local.code };
  }
}

export function wordDiff(before: string, after: string) {
  return diffWordsWithSpace(before, after);
}