/
change-details.ts
70 lines (57 loc) · 1.59 KB
/
change-details.ts
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
import IMask from "./holder";
export
type ChangeDetailsOptions = Pick<ChangeDetails,
| 'inserted'
| 'tailShift'
| 'rawInserted'
| 'skip'
>;
/** Provides details of changing model value */
export default
class ChangeDetails {
/** Inserted symbols */
declare inserted: string;
/** Additional offset if any changes occurred before tail */
declare tailShift: number;
/** Raw inserted is used by dynamic mask */
declare rawInserted: string;
/** Can skip chars */
declare skip: boolean;
static normalize (prep: string | [string, ChangeDetails]): [string, ChangeDetails] {
return Array.isArray(prep) ? prep : [
prep,
new ChangeDetails(),
];
}
constructor (details?: Partial<ChangeDetailsOptions>) {
Object.assign(this, {
inserted: '',
rawInserted: '',
tailShift: 0,
skip: false,
}, details);
}
/** Aggregate changes */
aggregate (details: ChangeDetails): this {
this.inserted += details.inserted;
this.rawInserted += details.rawInserted;
this.tailShift += details.tailShift;
this.skip = this.skip || details.skip;
return this;
}
/** Total offset considering all changes */
get offset (): number {
return this.tailShift + this.inserted.length;
}
get consumed (): boolean {
return Boolean(this.rawInserted) || this.skip;
}
equals (details: ChangeDetails): boolean {
return this.inserted === details.inserted &&
this.tailShift === details.tailShift &&
this.rawInserted === details.rawInserted &&
this.skip === details.skip
;
}
}
IMask.ChangeDetails = ChangeDetails;