mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-20 23:46:14 -04:00
Feat/changeset ts (#6594)
* Migrated changeset * Added more tests. * Fixed test scopes
This commit is contained in:
parent
3dae23a1e5
commit
28e04bdf71
37 changed files with 2540 additions and 1310 deletions
73
src/static/js/MergingOpAssembler.ts
Normal file
73
src/static/js/MergingOpAssembler.ts
Normal file
|
@ -0,0 +1,73 @@
|
|||
import {OpAssembler} from "./OpAssembler";
|
||||
import Op from "./Op";
|
||||
import {clearOp, copyOp} from "./Changeset";
|
||||
|
||||
export class MergingOpAssembler {
|
||||
private assem: OpAssembler;
|
||||
private readonly bufOp: Op;
|
||||
private bufOpAdditionalCharsAfterNewline: number;
|
||||
|
||||
constructor() {
|
||||
this.assem = new OpAssembler()
|
||||
this.bufOp = new Op()
|
||||
// If we get, for example, insertions [xxx\n,yyy], those don't merge,
|
||||
// but if we get [xxx\n,yyy,zzz\n], that merges to [xxx\nyyyzzz\n].
|
||||
// This variable stores the length of yyy and any other newline-less
|
||||
// ops immediately after it.
|
||||
this.bufOpAdditionalCharsAfterNewline = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {boolean} [isEndDocument]
|
||||
*/
|
||||
flush = (isEndDocument?: boolean) => {
|
||||
if (!this.bufOp.opcode) return;
|
||||
if (isEndDocument && this.bufOp.opcode === '=' && !this.bufOp.attribs) {
|
||||
// final merged keep, leave it implicit
|
||||
} else {
|
||||
this.assem.append(this.bufOp);
|
||||
if (this.bufOpAdditionalCharsAfterNewline) {
|
||||
this.bufOp.chars = this.bufOpAdditionalCharsAfterNewline;
|
||||
this.bufOp.lines = 0;
|
||||
this.assem.append(this.bufOp);
|
||||
this.bufOpAdditionalCharsAfterNewline = 0;
|
||||
}
|
||||
}
|
||||
this.bufOp.opcode = '';
|
||||
}
|
||||
|
||||
append = (op: Op) => {
|
||||
if (op.chars <= 0) return;
|
||||
if (this.bufOp.opcode === op.opcode && this.bufOp.attribs === op.attribs) {
|
||||
if (op.lines > 0) {
|
||||
// bufOp and additional chars are all mergeable into a multi-line op
|
||||
this.bufOp.chars += this.bufOpAdditionalCharsAfterNewline + op.chars;
|
||||
this.bufOp.lines += op.lines;
|
||||
this.bufOpAdditionalCharsAfterNewline = 0;
|
||||
} else if (this.bufOp.lines === 0) {
|
||||
// both bufOp and op are in-line
|
||||
this.bufOp.chars += op.chars;
|
||||
} else {
|
||||
// append in-line text to multi-line bufOp
|
||||
this.bufOpAdditionalCharsAfterNewline += op.chars;
|
||||
}
|
||||
} else {
|
||||
this.flush();
|
||||
copyOp(op, this.bufOp);
|
||||
}
|
||||
}
|
||||
|
||||
endDocument = () => {
|
||||
this.flush(true);
|
||||
};
|
||||
|
||||
toString = () => {
|
||||
this.flush();
|
||||
return this.assem.toString();
|
||||
};
|
||||
|
||||
clear = () => {
|
||||
this.assem.clear();
|
||||
clearOp(this.bufOp);
|
||||
};
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue