@kgdiff/viewer 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +52 -2
- package/dist/compute-loader.d.ts +13 -0
- package/dist/compute-loader.d.ts.map +1 -0
- package/dist/compute-loader.js +46 -0
- package/dist/compute-loader.js.map +1 -0
- package/dist/compute.d.ts +8 -0
- package/dist/compute.d.ts.map +1 -0
- package/dist/compute.js +8 -0
- package/dist/compute.js.map +1 -0
- package/dist/controller.d.ts +199 -0
- package/dist/controller.d.ts.map +1 -0
- package/dist/controller.js +1254 -0
- package/dist/controller.js.map +1 -0
- package/dist/dom.d.ts +32 -0
- package/dist/dom.d.ts.map +1 -0
- package/dist/dom.js +105 -0
- package/dist/dom.js.map +1 -0
- package/dist/element.d.ts +43 -0
- package/dist/element.d.ts.map +1 -0
- package/dist/element.js +656 -0
- package/dist/element.js.map +1 -0
- package/dist/framing.d.ts +45 -0
- package/dist/framing.d.ts.map +1 -0
- package/dist/framing.js +107 -0
- package/dist/framing.js.map +1 -0
- package/dist/hash-sync.d.ts +18 -0
- package/dist/hash-sync.d.ts.map +1 -0
- package/dist/hash-sync.js +45 -0
- package/dist/hash-sync.js.map +1 -0
- package/dist/i18n.d.ts +222 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/i18n.js +434 -0
- package/dist/i18n.js.map +1 -0
- package/dist/icons.d.ts +37 -0
- package/dist/icons.d.ts.map +1 -0
- package/dist/icons.js +36 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.d.ts +151 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/keyboard.d.ts +64 -0
- package/dist/keyboard.d.ts.map +1 -0
- package/dist/keyboard.js +95 -0
- package/dist/keyboard.js.map +1 -0
- package/dist/list-model.d.ts +35 -0
- package/dist/list-model.d.ts.map +1 -0
- package/dist/list-model.js +70 -0
- package/dist/list-model.js.map +1 -0
- package/dist/payload.d.ts +10 -0
- package/dist/payload.d.ts.map +1 -0
- package/dist/payload.js +138 -0
- package/dist/payload.js.map +1 -0
- package/dist/pipeline.d.ts +31 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/pipeline.js +122 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/prefs.d.ts +18 -0
- package/dist/prefs.d.ts.map +1 -0
- package/dist/prefs.js +38 -0
- package/dist/prefs.js.map +1 -0
- package/dist/registry.d.ts +3 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +3 -0
- package/dist/registry.js.map +1 -0
- package/dist/renderer-port.d.ts +14 -0
- package/dist/renderer-port.d.ts.map +1 -0
- package/dist/renderer-port.js +16 -0
- package/dist/renderer-port.js.map +1 -0
- package/dist/replay.d.ts +55 -0
- package/dist/replay.d.ts.map +1 -0
- package/dist/replay.js +147 -0
- package/dist/replay.js.map +1 -0
- package/dist/review-store.d.ts +30 -0
- package/dist/review-store.d.ts.map +1 -0
- package/dist/review-store.js +120 -0
- package/dist/review-store.js.map +1 -0
- package/dist/search.d.ts +25 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +90 -0
- package/dist/search.js.map +1 -0
- package/dist/standalone/kgdiff-viewer-compute.js +1 -0
- package/dist/standalone/kgdiff-viewer.js +5 -0
- package/dist/standalone-compute.d.ts +2 -0
- package/dist/standalone-compute.d.ts.map +1 -0
- package/dist/standalone-compute.js +8 -0
- package/dist/standalone-compute.js.map +1 -0
- package/dist/standalone.d.ts +2 -0
- package/dist/standalone.d.ts.map +1 -0
- package/dist/standalone.js +18 -0
- package/dist/standalone.js.map +1 -0
- package/dist/styles.d.ts +11 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +622 -0
- package/dist/styles.js.map +1 -0
- package/dist/text-diff.d.ts +44 -0
- package/dist/text-diff.d.ts.map +1 -0
- package/dist/text-diff.js +261 -0
- package/dist/text-diff.js.map +1 -0
- package/dist/ui/context.d.ts +32 -0
- package/dist/ui/context.d.ts.map +1 -0
- package/dist/ui/context.js +49 -0
- package/dist/ui/context.js.map +1 -0
- package/dist/ui/detail.d.ts +9 -0
- package/dist/ui/detail.d.ts.map +1 -0
- package/dist/ui/detail.js +609 -0
- package/dist/ui/detail.js.map +1 -0
- package/dist/ui/header.d.ts +14 -0
- package/dist/ui/header.d.ts.map +1 -0
- package/dist/ui/header.js +195 -0
- package/dist/ui/header.js.map +1 -0
- package/dist/ui/popovers.d.ts +20 -0
- package/dist/ui/popovers.d.ts.map +1 -0
- package/dist/ui/popovers.js +180 -0
- package/dist/ui/popovers.js.map +1 -0
- package/dist/ui/sidebar.d.ts +25 -0
- package/dist/ui/sidebar.d.ts.map +1 -0
- package/dist/ui/sidebar.js +609 -0
- package/dist/ui/sidebar.js.map +1 -0
- package/dist/ui/stage.d.ts +18 -0
- package/dist/ui/stage.d.ts.map +1 -0
- package/dist/ui/stage.js +664 -0
- package/dist/ui/stage.js.map +1 -0
- package/package.json +58 -3
- package/src/compute-loader.ts +58 -0
- package/src/compute.ts +7 -0
- package/src/controller.ts +1393 -0
- package/src/dom.ts +131 -0
- package/src/element.ts +697 -0
- package/src/framing.ts +150 -0
- package/src/hash-sync.ts +54 -0
- package/src/i18n.ts +467 -0
- package/src/icons.ts +48 -0
- package/src/index.ts +171 -0
- package/src/keyboard.ts +128 -0
- package/src/list-model.ts +86 -0
- package/src/payload.ts +165 -0
- package/src/pipeline.ts +179 -0
- package/src/prefs.ts +55 -0
- package/src/registry.ts +2 -0
- package/src/renderer-port.ts +31 -0
- package/src/replay.ts +163 -0
- package/src/review-store.ts +125 -0
- package/src/search.ts +113 -0
- package/src/standalone-compute.ts +8 -0
- package/src/standalone.ts +18 -0
- package/src/styles.ts +633 -0
- package/src/text-diff.ts +263 -0
- package/src/ui/context.ts +70 -0
- package/src/ui/detail.ts +929 -0
- package/src/ui/header.ts +278 -0
- package/src/ui/popovers.ts +251 -0
- package/src/ui/sidebar.ts +752 -0
- package/src/ui/stage.ts +853 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Myers O((N+M)·D) sequence diff for the detail panel: character-level name diffs, word-level
|
|
3
|
+
* attribute diffs and set changes read as edits. Small, deterministic, no dependencies.
|
|
4
|
+
*/
|
|
5
|
+
export type DiffOp = 'equal' | 'insert' | 'delete';
|
|
6
|
+
export interface DiffSegment {
|
|
7
|
+
readonly op: DiffOp;
|
|
8
|
+
readonly text: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Edit script between `a` and `b` (Myers 1986, greedy forward search with a trace for the
|
|
12
|
+
* backtrack). Deletions come before insertions within a change. Common prefix / suffix are
|
|
13
|
+
* stripped first, so typical edits cost O(N + M). Inputs larger than the `MAX_D` budget fall
|
|
14
|
+
* back to a single replace of the differing middle.
|
|
15
|
+
*/
|
|
16
|
+
export declare function diffSequences<T>(a: readonly T[], b: readonly T[]): {
|
|
17
|
+
op: DiffOp;
|
|
18
|
+
items: T[];
|
|
19
|
+
}[];
|
|
20
|
+
/**
|
|
21
|
+
* Merge short equal runs sandwiched between changes into the changes ("semantic cleanup"),
|
|
22
|
+
* so that `高管任职 → 董监高任职` reads as one replaced prefix rather than confetti.
|
|
23
|
+
*/
|
|
24
|
+
export declare function cleanupSemantic(segs: readonly DiffSegment[], minEqual?: number): DiffSegment[];
|
|
25
|
+
/** Character (code point) diff with semantic cleanup. */
|
|
26
|
+
export declare function diffChars(a: string, b: string): DiffSegment[];
|
|
27
|
+
export declare function tokenize(text: string): string[];
|
|
28
|
+
/** Word-level diff (CJK per character). */
|
|
29
|
+
export declare function diffWords(a: string, b: string): DiffSegment[];
|
|
30
|
+
/** Rebuild the old (`equal` + `delete`) or new (`equal` + `insert`) text from a diff. */
|
|
31
|
+
export declare function sideOf(segs: readonly DiffSegment[], side: 'before' | 'after'): string;
|
|
32
|
+
/** A set change read as edits: removed → added pairs, and the items left over. */
|
|
33
|
+
export interface PairedItems {
|
|
34
|
+
readonly pairs: readonly (readonly [removed: string, added: string])[];
|
|
35
|
+
readonly removed: readonly string[];
|
|
36
|
+
readonly added: readonly string[];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Read a set change (synonyms, types, parents, list values) as edits: a lone removal and a lone
|
|
40
|
+
* addition pair up (`老赖 → 失信人`); otherwise removals and additions sharing at least half
|
|
41
|
+
* their characters pair up, closest first. Pairs keep the order of `removed`.
|
|
42
|
+
*/
|
|
43
|
+
export declare function pairItems(removed: readonly string[], added: readonly string[]): PairedItems;
|
|
44
|
+
//# sourceMappingURL=text-diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-diff.d.ts","sourceRoot":"","sources":["../src/text-diff.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEnD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAKD;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,CAAC,EAAE,EAAE,CAAC,EAAE,SAAS,CAAC,EAAE,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,EAAE,CAAA;CAAE,EAAE,CAoB/F;AAoGD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,EAAE,QAAQ,SAAI,GAAG,WAAW,EAAE,CA4BzF;AAOD,yDAAyD;AACzD,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,CAE7D;AASD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE/C;AAED,2CAA2C;AAC3C,wBAAgB,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,WAAW,EAAE,CAE7D;AAED,yFAAyF;AACzF,wBAAgB,MAAM,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,GAAG,MAAM,CAKrF;AAED,kFAAkF;AAClF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,SAAS,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;IACvE,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAcD;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,WAAW,CA6B3F"}
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Myers O((N+M)·D) sequence diff for the detail panel: character-level name diffs, word-level
|
|
3
|
+
* attribute diffs and set changes read as edits. Small, deterministic, no dependencies.
|
|
4
|
+
*/
|
|
5
|
+
/** Above this edit distance the diff degrades to "common prefix / suffix + replace". */
|
|
6
|
+
const MAX_D = 1024;
|
|
7
|
+
/**
|
|
8
|
+
* Edit script between `a` and `b` (Myers 1986, greedy forward search with a trace for the
|
|
9
|
+
* backtrack). Deletions come before insertions within a change. Common prefix / suffix are
|
|
10
|
+
* stripped first, so typical edits cost O(N + M). Inputs larger than the `MAX_D` budget fall
|
|
11
|
+
* back to a single replace of the differing middle.
|
|
12
|
+
*/
|
|
13
|
+
export function diffSequences(a, b) {
|
|
14
|
+
let start = 0;
|
|
15
|
+
while (start < a.length && start < b.length && a[start] === b[start])
|
|
16
|
+
start++;
|
|
17
|
+
let endA = a.length;
|
|
18
|
+
let endB = b.length;
|
|
19
|
+
while (endA > start && endB > start && a[endA - 1] === b[endB - 1]) {
|
|
20
|
+
endA--;
|
|
21
|
+
endB--;
|
|
22
|
+
}
|
|
23
|
+
const out = [];
|
|
24
|
+
const push = (op, item) => {
|
|
25
|
+
const last = out[out.length - 1];
|
|
26
|
+
if (last !== undefined && last.op === op)
|
|
27
|
+
last.items.push(item);
|
|
28
|
+
else
|
|
29
|
+
out.push({ op, items: [item] });
|
|
30
|
+
};
|
|
31
|
+
for (let i = 0; i < start; i++)
|
|
32
|
+
push('equal', a[i]);
|
|
33
|
+
const middle = myers(a.slice(start, endA), b.slice(start, endB));
|
|
34
|
+
for (const [op, item] of middle)
|
|
35
|
+
push(op, item);
|
|
36
|
+
for (let i = endA; i < a.length; i++)
|
|
37
|
+
push('equal', a[i]);
|
|
38
|
+
return normalizeOrder(out);
|
|
39
|
+
}
|
|
40
|
+
function myers(a, b) {
|
|
41
|
+
const n = a.length;
|
|
42
|
+
const m = b.length;
|
|
43
|
+
if (n === 0)
|
|
44
|
+
return b.map((x) => ['insert', x]);
|
|
45
|
+
if (m === 0)
|
|
46
|
+
return a.map((x) => ['delete', x]);
|
|
47
|
+
const max = n + m;
|
|
48
|
+
const limit = Math.min(max, MAX_D);
|
|
49
|
+
const offset = max;
|
|
50
|
+
const v = new Int32Array(2 * max + 2);
|
|
51
|
+
const trace = [];
|
|
52
|
+
let found = -1;
|
|
53
|
+
for (let d = 0; d <= limit; d++) {
|
|
54
|
+
// State after step d − 1; the backtrack reads k ± 1 for |k| ≤ d, i.e. offsets [−d, d].
|
|
55
|
+
trace.push(v.slice(offset - d, offset + d + 1));
|
|
56
|
+
for (let k = -d; k <= d; k += 2) {
|
|
57
|
+
let x;
|
|
58
|
+
if (k === -d || (k !== d && v[offset + k - 1] < v[offset + k + 1])) {
|
|
59
|
+
x = v[offset + k + 1];
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
x = v[offset + k - 1] + 1;
|
|
63
|
+
}
|
|
64
|
+
let y = x - k;
|
|
65
|
+
while (x < n && y < m && a[x] === b[y]) {
|
|
66
|
+
x++;
|
|
67
|
+
y++;
|
|
68
|
+
}
|
|
69
|
+
v[offset + k] = x;
|
|
70
|
+
if (x >= n && y >= m) {
|
|
71
|
+
found = d;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
if (found >= 0)
|
|
76
|
+
break;
|
|
77
|
+
}
|
|
78
|
+
if (found < 0) {
|
|
79
|
+
return [
|
|
80
|
+
...a.map((x) => ['delete', x]),
|
|
81
|
+
...b.map((x) => ['insert', x]),
|
|
82
|
+
];
|
|
83
|
+
}
|
|
84
|
+
// Backtrack.
|
|
85
|
+
const ops = [];
|
|
86
|
+
let x = n;
|
|
87
|
+
let y = m;
|
|
88
|
+
for (let d = found; d > 0; d--) {
|
|
89
|
+
const vd = trace[d];
|
|
90
|
+
const at = (kk) => vd[kk + d];
|
|
91
|
+
const k = x - y;
|
|
92
|
+
const down = k === -d || (k !== d && at(k - 1) < at(k + 1));
|
|
93
|
+
const prevK = down ? k + 1 : k - 1;
|
|
94
|
+
const prevX = at(prevK);
|
|
95
|
+
const prevY = prevX - prevK;
|
|
96
|
+
while (x > prevX && y > prevY) {
|
|
97
|
+
ops.push(['equal', a[x - 1]]);
|
|
98
|
+
x--;
|
|
99
|
+
y--;
|
|
100
|
+
}
|
|
101
|
+
if (down)
|
|
102
|
+
ops.push(['insert', b[y - 1]]);
|
|
103
|
+
else
|
|
104
|
+
ops.push(['delete', a[x - 1]]);
|
|
105
|
+
x = prevX;
|
|
106
|
+
y = prevY;
|
|
107
|
+
}
|
|
108
|
+
while (x > 0 && y > 0) {
|
|
109
|
+
ops.push(['equal', a[x - 1]]);
|
|
110
|
+
x--;
|
|
111
|
+
y--;
|
|
112
|
+
}
|
|
113
|
+
return ops.reverse();
|
|
114
|
+
}
|
|
115
|
+
/** Within each run of changes, deletions first, then insertions (stable, readable). */
|
|
116
|
+
function normalizeOrder(segs) {
|
|
117
|
+
const out = [];
|
|
118
|
+
let del = [];
|
|
119
|
+
let ins = [];
|
|
120
|
+
const flush = () => {
|
|
121
|
+
if (del.length)
|
|
122
|
+
out.push({ op: 'delete', items: del });
|
|
123
|
+
if (ins.length)
|
|
124
|
+
out.push({ op: 'insert', items: ins });
|
|
125
|
+
del = [];
|
|
126
|
+
ins = [];
|
|
127
|
+
};
|
|
128
|
+
for (const s of segs) {
|
|
129
|
+
if (s.op === 'equal') {
|
|
130
|
+
flush();
|
|
131
|
+
out.push(s);
|
|
132
|
+
continue;
|
|
133
|
+
}
|
|
134
|
+
const run = s.op === 'delete' ? del : ins;
|
|
135
|
+
for (const item of s.items)
|
|
136
|
+
run.push(item);
|
|
137
|
+
}
|
|
138
|
+
flush();
|
|
139
|
+
return out;
|
|
140
|
+
}
|
|
141
|
+
function join(segs) {
|
|
142
|
+
return segs.map((s) => ({ op: s.op, text: s.items.join('') }));
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Merge short equal runs sandwiched between changes into the changes ("semantic cleanup"),
|
|
146
|
+
* so that `高管任职 → 董监高任职` reads as one replaced prefix rather than confetti.
|
|
147
|
+
*/
|
|
148
|
+
export function cleanupSemantic(segs, minEqual = 3) {
|
|
149
|
+
const out = [];
|
|
150
|
+
let del = '';
|
|
151
|
+
let ins = '';
|
|
152
|
+
const flush = () => {
|
|
153
|
+
if (del)
|
|
154
|
+
out.push({ op: 'delete', text: del });
|
|
155
|
+
if (ins)
|
|
156
|
+
out.push({ op: 'insert', text: ins });
|
|
157
|
+
del = '';
|
|
158
|
+
ins = '';
|
|
159
|
+
};
|
|
160
|
+
for (let i = 0; i < segs.length; i++) {
|
|
161
|
+
const s = segs[i];
|
|
162
|
+
if (s.op === 'delete')
|
|
163
|
+
del += s.text;
|
|
164
|
+
else if (s.op === 'insert')
|
|
165
|
+
ins += s.text;
|
|
166
|
+
else {
|
|
167
|
+
const inner = i > 0 && i < segs.length - 1 && (del !== '' || ins !== '');
|
|
168
|
+
const short = [...s.text].length < minEqual && s.text.trim().length <= minEqual;
|
|
169
|
+
if (inner && short && hasChangeAfter(segs, i)) {
|
|
170
|
+
del += s.text;
|
|
171
|
+
ins += s.text;
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
flush();
|
|
175
|
+
out.push(s);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
flush();
|
|
180
|
+
return out;
|
|
181
|
+
}
|
|
182
|
+
function hasChangeAfter(segs, i) {
|
|
183
|
+
const next = segs[i + 1];
|
|
184
|
+
return next !== undefined && next.op !== 'equal';
|
|
185
|
+
}
|
|
186
|
+
/** Character (code point) diff with semantic cleanup. */
|
|
187
|
+
export function diffChars(a, b) {
|
|
188
|
+
return cleanupSemantic(join(diffSequences(Array.from(a), Array.from(b))));
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Tokens for word diffs: whitespace runs, words (letters / digits / `_'-`), single CJK
|
|
192
|
+
* characters (CJK has no spaces), single punctuation marks.
|
|
193
|
+
*/
|
|
194
|
+
const TOKEN = /\s+|[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]|[\p{L}\p{N}\p{M}_'’-]+|[^\s]/gu;
|
|
195
|
+
export function tokenize(text) {
|
|
196
|
+
return text.match(TOKEN) ?? [];
|
|
197
|
+
}
|
|
198
|
+
/** Word-level diff (CJK per character). */
|
|
199
|
+
export function diffWords(a, b) {
|
|
200
|
+
return cleanupSemantic(join(diffSequences(tokenize(a), tokenize(b))), 2);
|
|
201
|
+
}
|
|
202
|
+
/** Rebuild the old (`equal` + `delete`) or new (`equal` + `insert`) text from a diff. */
|
|
203
|
+
export function sideOf(segs, side) {
|
|
204
|
+
const skip = side === 'before' ? 'insert' : 'delete';
|
|
205
|
+
let s = '';
|
|
206
|
+
for (const seg of segs)
|
|
207
|
+
if (seg.op !== skip)
|
|
208
|
+
s += seg.text;
|
|
209
|
+
return s;
|
|
210
|
+
}
|
|
211
|
+
/** Below this share of common characters a removal and an addition stay apart. */
|
|
212
|
+
const PAIR_MIN = 0.5;
|
|
213
|
+
/** Above this many removal × addition candidates, only a lone pair is paired. */
|
|
214
|
+
const PAIR_MAX_CANDIDATES = 400;
|
|
215
|
+
/** 2 · common code points / total code points. */
|
|
216
|
+
function closeness(a, b) {
|
|
217
|
+
let common = 0;
|
|
218
|
+
for (const s of diffSequences(a, b))
|
|
219
|
+
if (s.op === 'equal')
|
|
220
|
+
common += s.items.length;
|
|
221
|
+
return (2 * common) / (a.length + b.length);
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Read a set change (synonyms, types, parents, list values) as edits: a lone removal and a lone
|
|
225
|
+
* addition pair up (`老赖 → 失信人`); otherwise removals and additions sharing at least half
|
|
226
|
+
* their characters pair up, closest first. Pairs keep the order of `removed`.
|
|
227
|
+
*/
|
|
228
|
+
export function pairItems(removed, added) {
|
|
229
|
+
const found = [];
|
|
230
|
+
if (removed.length === 1 && added.length === 1)
|
|
231
|
+
found.push([1, 0, 0]);
|
|
232
|
+
else if (removed.length * added.length <= PAIR_MAX_CANDIDATES) {
|
|
233
|
+
const as = added.map((x) => Array.from(x));
|
|
234
|
+
removed.forEach((r, i) => {
|
|
235
|
+
const rs = Array.from(r);
|
|
236
|
+
as.forEach((a, j) => {
|
|
237
|
+
const score = closeness(rs, a);
|
|
238
|
+
if (score >= PAIR_MIN)
|
|
239
|
+
found.push([score, i, j]);
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
found.sort((x, y) => y[0] - x[0] || x[1] - y[1] || x[2] - y[2]);
|
|
243
|
+
}
|
|
244
|
+
const usedR = new Set();
|
|
245
|
+
const usedA = new Set();
|
|
246
|
+
const pairs = [];
|
|
247
|
+
for (const [, i, j] of found) {
|
|
248
|
+
if (usedR.has(i) || usedA.has(j))
|
|
249
|
+
continue;
|
|
250
|
+
usedR.add(i);
|
|
251
|
+
usedA.add(j);
|
|
252
|
+
pairs.push([i, j]);
|
|
253
|
+
}
|
|
254
|
+
pairs.sort((x, y) => x[0] - y[0]);
|
|
255
|
+
return {
|
|
256
|
+
pairs: pairs.map(([i, j]) => [removed[i], added[j]]),
|
|
257
|
+
removed: removed.filter((_, i) => !usedR.has(i)),
|
|
258
|
+
added: added.filter((_, j) => !usedA.has(j)),
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=text-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-diff.js","sourceRoot":"","sources":["../src/text-diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What UI components share: the controller, the current translator and element-level actions
|
|
3
|
+
* (attribute-reflected preferences, sidebar, popovers).
|
|
4
|
+
*/
|
|
5
|
+
import type { AttrValue, HunkKind, Locale } from '@kgdiff/core';
|
|
6
|
+
import type { ChangeFamily, PaletteName, SceneHunk } from '@kgdiff/scene';
|
|
7
|
+
import type { ViewerController } from '../controller.js';
|
|
8
|
+
import type { Translator } from '../i18n.js';
|
|
9
|
+
import type { ThemePreference, ViewerMode } from '../index.js';
|
|
10
|
+
export interface UiContext {
|
|
11
|
+
readonly controller: ViewerController;
|
|
12
|
+
readonly tr: () => Translator;
|
|
13
|
+
setMode(mode: ViewerMode): void;
|
|
14
|
+
setThemePreference(pref: ThemePreference): void;
|
|
15
|
+
setPalette(palette: PaletteName): void;
|
|
16
|
+
setLocale(locale: Locale): void;
|
|
17
|
+
toggleSidebar(open?: boolean): void;
|
|
18
|
+
sidebarOpen(): boolean;
|
|
19
|
+
toggleMenu(open?: boolean): void;
|
|
20
|
+
openHelp(): void;
|
|
21
|
+
focusSearch(): void;
|
|
22
|
+
/** Root of the shadow tree (for focus management). */
|
|
23
|
+
readonly root: ShadowRoot;
|
|
24
|
+
}
|
|
25
|
+
/** One-character glyph of a hunk (docs/interaction.md §Change list): `+ − ~ ⇄ ⊕ ⑂`. */
|
|
26
|
+
export declare function hunkGlyph(kind: HunkKind, family: ChangeFamily): string;
|
|
27
|
+
export declare function sceneHunkGlyph(h: SceneHunk): string;
|
|
28
|
+
/** Single-line display form of an attribute value. */
|
|
29
|
+
export declare function formatValue(value: AttrValue | undefined): string;
|
|
30
|
+
/** Items of a list-like value (arrays of scalars), else null. */
|
|
31
|
+
export declare function listItems(value: AttrValue | undefined): string[] | null;
|
|
32
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/ui/context.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,KAAK,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE/D,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,UAAU,EAAE,gBAAgB,CAAC;IACtC,QAAQ,CAAC,EAAE,EAAE,MAAM,UAAU,CAAC;IAC9B,OAAO,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IAChC,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAAC;IAChD,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IACvC,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,aAAa,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACpC,WAAW,IAAI,OAAO,CAAC;IACvB,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IACjC,QAAQ,IAAI,IAAI,CAAC;IACjB,WAAW,IAAI,IAAI,CAAC;IACpB,sDAAsD;IACtD,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;CAC3B;AAED,uFAAuF;AACvF,wBAAgB,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAiBtE;AAED,wBAAgB,cAAc,CAAC,CAAC,EAAE,SAAS,GAAG,MAAM,CAEnD;AAED,sDAAsD;AACtD,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,CAOhE;AAED,iEAAiE;AACjE,wBAAgB,SAAS,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,MAAM,EAAE,GAAG,IAAI,CAQvE"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/** One-character glyph of a hunk (docs/interaction.md §Change list): `+ − ~ ⇄ ⊕ ⑂`. */
|
|
2
|
+
export function hunkGlyph(kind, family) {
|
|
3
|
+
switch (kind) {
|
|
4
|
+
case 'add':
|
|
5
|
+
return '+';
|
|
6
|
+
case 'remove':
|
|
7
|
+
return '−';
|
|
8
|
+
case 'merge':
|
|
9
|
+
return '⊕';
|
|
10
|
+
case 'split':
|
|
11
|
+
return '⑂';
|
|
12
|
+
case 'relations':
|
|
13
|
+
return '⇄';
|
|
14
|
+
case 'modify':
|
|
15
|
+
return family === 'structure' ? '⇄' : family === 'identity' ? '≡' : '~';
|
|
16
|
+
default:
|
|
17
|
+
return '~';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function sceneHunkGlyph(h) {
|
|
21
|
+
return hunkGlyph(h.kind, h.family);
|
|
22
|
+
}
|
|
23
|
+
/** Single-line display form of an attribute value. */
|
|
24
|
+
export function formatValue(value) {
|
|
25
|
+
if (value === undefined)
|
|
26
|
+
return '';
|
|
27
|
+
if (value === null)
|
|
28
|
+
return 'null';
|
|
29
|
+
if (typeof value === 'string')
|
|
30
|
+
return value;
|
|
31
|
+
if (typeof value === 'number' || typeof value === 'boolean')
|
|
32
|
+
return String(value);
|
|
33
|
+
if (Array.isArray(value))
|
|
34
|
+
return value.map((v) => formatValue(v)).join(', ');
|
|
35
|
+
return JSON.stringify(value);
|
|
36
|
+
}
|
|
37
|
+
/** Items of a list-like value (arrays of scalars), else null. */
|
|
38
|
+
export function listItems(value) {
|
|
39
|
+
if (!Array.isArray(value))
|
|
40
|
+
return null;
|
|
41
|
+
const out = [];
|
|
42
|
+
for (const v of value) {
|
|
43
|
+
if (typeof v === 'object' && v !== null)
|
|
44
|
+
return null;
|
|
45
|
+
out.push(formatValue(v));
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/ui/context.ts"],"names":[],"mappings":"AA0BA,uFAAuF;AACvF,MAAM,UAAU,SAAS,CAAC,IAAc,EAAE,MAAoB;IAC5D,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,KAAK;YACR,OAAO,GAAG,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,GAAG,CAAC;QACb,KAAK,OAAO;YACV,OAAO,GAAG,CAAC;QACb,KAAK,OAAO;YACV,OAAO,GAAG,CAAC;QACb,KAAK,WAAW;YACd,OAAO,GAAG,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,MAAM,KAAK,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;QAC1E;YACE,OAAO,GAAG,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,CAAY;IACzC,OAAO,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;AACrC,CAAC;AAED,sDAAsD;AACtD,MAAM,UAAU,WAAW,CAAC,KAA4B;IACtD,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACnC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,MAAM,CAAC;IAClC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IAClF,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAc,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1F,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,SAAS,CAAC,KAA4B;IACpD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,CAAC,IAAI,KAA6B,EAAE,CAAC;QAC9C,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACrD,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Topic } from '../controller.js';
|
|
2
|
+
import { type UiContext } from './context.js';
|
|
3
|
+
export declare class Detail {
|
|
4
|
+
#private;
|
|
5
|
+
readonly el: HTMLElement;
|
|
6
|
+
constructor(ctx: UiContext);
|
|
7
|
+
update(topics: ReadonlySet<Topic>): void;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=detail.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detail.d.ts","sourceRoot":"","sources":["../../src/ui/detail.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAI9C,OAAO,EAA0C,KAAK,SAAS,EAAE,MAAM,cAAc,CAAC;AAoItF,qBAAa,MAAM;;IACjB,QAAQ,CAAC,EAAE,EAAE,WAAW,CAAC;IAUzB,YAAY,GAAG,EAAE,SAAS,EAIzB;IAED,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,KAAK,CAAC,GAAG,IAAI,CAWvC;CAyuBF"}
|