mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-21 07:56:16 -04:00
Changeset.js: refine comments
This commit is contained in:
parent
55c47efd4c
commit
395cbc01bb
1 changed files with 44 additions and 10 deletions
|
@ -525,6 +525,9 @@ exports.mergingOpAssembler = () => {
|
||||||
// ops immediately after it.
|
// ops immediately after it.
|
||||||
let bufOpAdditionalCharsAfterNewline = 0;
|
let bufOpAdditionalCharsAfterNewline = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {boolean} [isEndDocument]
|
||||||
|
*/
|
||||||
const flush = (isEndDocument) => {
|
const flush = (isEndDocument) => {
|
||||||
if (!bufOp.opcode) return;
|
if (!bufOp.opcode) return;
|
||||||
if (isEndDocument && bufOp.opcode === '=' && !bufOp.attribs) {
|
if (isEndDocument && bufOp.opcode === '=' && !bufOp.attribs) {
|
||||||
|
@ -803,7 +806,7 @@ class TextLinesMutator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates if curLine is already in the splice. This is necessary because the last element in
|
* Indicates if curLine is already in the splice. This is necessary because the last element in
|
||||||
* curSplice is curLine when this line is currently worked on (e.g. when skipping are inserting).
|
* curSplice is curLine when this line is currently worked on (e.g. when skipping or inserting).
|
||||||
*
|
*
|
||||||
* TODO(doc) why aren't removals considered?
|
* TODO(doc) why aren't removals considered?
|
||||||
*
|
*
|
||||||
|
@ -831,7 +834,7 @@ class TextLinesMutator {
|
||||||
* It will skip some newlines by putting them into the splice.
|
* It will skip some newlines by putting them into the splice.
|
||||||
*
|
*
|
||||||
* @param {number} L -
|
* @param {number} L -
|
||||||
* @param {boolean} includeInSplice - indicates if attributes are present
|
* @param {boolean} includeInSplice - Indicates that attributes are present.
|
||||||
*/
|
*/
|
||||||
skipLines(L, includeInSplice) {
|
skipLines(L, includeInSplice) {
|
||||||
if (!L) return;
|
if (!L) return;
|
||||||
|
@ -960,7 +963,7 @@ class TextLinesMutator {
|
||||||
/** @type {string} */
|
/** @type {string} */
|
||||||
const theLine = this._curSplice[sline];
|
const theLine = this._curSplice[sline];
|
||||||
const lineCol = this._curCol;
|
const lineCol = this._curCol;
|
||||||
// insert the first new line
|
// Insert the chars up to `curCol` and the first new line.
|
||||||
this._curSplice[sline] = theLine.substring(0, lineCol) + newLines[0];
|
this._curSplice[sline] = theLine.substring(0, lineCol) + newLines[0];
|
||||||
this._curLine++;
|
this._curLine++;
|
||||||
newLines.splice(0, 1);
|
newLines.splice(0, 1);
|
||||||
|
@ -976,9 +979,8 @@ class TextLinesMutator {
|
||||||
this._curLine += newLines.length;
|
this._curLine += newLines.length;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// there are no additional lines
|
// There are no additional lines. Although the line is put into splice, curLine is not
|
||||||
// although the line is put into splice, curLine is not increased, because
|
// increased because there may be more chars in the line (newline is not reached).
|
||||||
// there may be more chars in the line (newline is not reached)
|
|
||||||
const sline = this._putCurLineInSplice();
|
const sline = this._putCurLineInSplice();
|
||||||
if (!this._curSplice[sline]) {
|
if (!this._curSplice[sline]) {
|
||||||
const err = new Error(
|
const err = new Error(
|
||||||
|
@ -1277,6 +1279,13 @@ exports.applyToAttribution = (cs, astr, pool) => {
|
||||||
return applyZip(astr, unpacked.ops, (op1, op2) => slicerZipperFunc(op1, op2, pool));
|
return applyZip(astr, unpacked.ops, (op1, op2) => slicerZipperFunc(op1, op2, pool));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies a changeset to an array of attribute lines.
|
||||||
|
*
|
||||||
|
* @param {string} cs - The encoded changeset.
|
||||||
|
* @param {Array<string>} lines - Attribute lines. Modified in place.
|
||||||
|
* @param {AttributePool} pool - Attribute pool.
|
||||||
|
*/
|
||||||
exports.mutateAttributionLines = (cs, lines, pool) => {
|
exports.mutateAttributionLines = (cs, lines, pool) => {
|
||||||
const unpacked = exports.unpack(cs);
|
const unpacked = exports.unpack(cs);
|
||||||
const csOps = exports.deserializeOps(unpacked.ops);
|
const csOps = exports.deserializeOps(unpacked.ops);
|
||||||
|
@ -1286,26 +1295,47 @@ exports.mutateAttributionLines = (cs, lines, pool) => {
|
||||||
// treat the attribution lines as text lines, mutating a line at a time
|
// treat the attribution lines as text lines, mutating a line at a time
|
||||||
const mut = new TextLinesMutator(lines);
|
const mut = new TextLinesMutator(lines);
|
||||||
|
|
||||||
/** @type {?Generator<Op>} */
|
/**
|
||||||
|
* The Ops in the current line from `lines`.
|
||||||
|
*
|
||||||
|
* @type {?Generator<Op>}
|
||||||
|
*/
|
||||||
let lineOps = null;
|
let lineOps = null;
|
||||||
let lineOpsNext = null;
|
let lineOpsNext = null;
|
||||||
|
|
||||||
const lineOpsHasNext = () => lineOpsNext && !lineOpsNext.done;
|
const lineOpsHasNext = () => lineOpsNext && !lineOpsNext.done;
|
||||||
|
/**
|
||||||
|
* Returns false if we are on the last attribute line in `lines` and there is no additional op in
|
||||||
|
* that line.
|
||||||
|
*
|
||||||
|
* @returns {boolean} True if there are more ops to go through.
|
||||||
|
*/
|
||||||
const isNextMutOp = () => lineOpsHasNext() || mut.hasMore();
|
const isNextMutOp = () => lineOpsHasNext() || mut.hasMore();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {Op} The next Op from `lineIter`. If there are no more Ops, `lineIter` is reset to
|
||||||
|
* iterate over the next line, which is consumed from `mut`. If there are no more lines,
|
||||||
|
* returns a null Op.
|
||||||
|
*/
|
||||||
const nextMutOp = () => {
|
const nextMutOp = () => {
|
||||||
if (!lineOpsHasNext() && mut.hasMore()) {
|
if (!lineOpsHasNext() && mut.hasMore()) {
|
||||||
|
// There are more attribute lines in `lines` to do AND either we just started so `lineIter` is
|
||||||
|
// still null or there are no more ops in current `lineIter`.
|
||||||
const line = mut.removeLines(1);
|
const line = mut.removeLines(1);
|
||||||
lineOps = exports.deserializeOps(line);
|
lineOps = exports.deserializeOps(line);
|
||||||
lineOpsNext = lineOps.next();
|
lineOpsNext = lineOps.next();
|
||||||
}
|
}
|
||||||
if (!lineOpsHasNext()) return new Op();
|
if (!lineOpsHasNext()) return new Op(); // No more ops and no more lines.
|
||||||
const op = lineOpsNext.value;
|
const op = lineOpsNext.value;
|
||||||
lineOpsNext = lineOps.next();
|
lineOpsNext = lineOps.next();
|
||||||
return op;
|
return op;
|
||||||
};
|
};
|
||||||
let lineAssem = null;
|
let lineAssem = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends an op to `lineAssem`. In case `lineAssem` includes one single newline, adds it to the
|
||||||
|
* `lines` mutator.
|
||||||
|
*/
|
||||||
const outputMutOp = (op) => {
|
const outputMutOp = (op) => {
|
||||||
if (!lineAssem) {
|
if (!lineAssem) {
|
||||||
lineAssem = exports.mergingOpAssembler();
|
lineAssem = exports.mergingOpAssembler();
|
||||||
|
@ -1322,6 +1352,7 @@ exports.mutateAttributionLines = (cs, lines, pool) => {
|
||||||
let attOp = new Op();
|
let attOp = new Op();
|
||||||
while (csOp.opcode || !csOpsNext.done || attOp.opcode || isNextMutOp()) {
|
while (csOp.opcode || !csOpsNext.done || attOp.opcode || isNextMutOp()) {
|
||||||
if (!csOp.opcode && !csOpsNext.done) {
|
if (!csOp.opcode && !csOpsNext.done) {
|
||||||
|
// coOp done, but more ops in cs.
|
||||||
csOp = csOpsNext.value;
|
csOp = csOpsNext.value;
|
||||||
csOpsNext = csOps.next();
|
csOpsNext = csOps.next();
|
||||||
}
|
}
|
||||||
|
@ -1329,18 +1360,21 @@ exports.mutateAttributionLines = (cs, lines, pool) => {
|
||||||
break; // done
|
break; // done
|
||||||
} else if (csOp.opcode === '=' && csOp.lines > 0 && !csOp.attribs && !attOp.opcode &&
|
} else if (csOp.opcode === '=' && csOp.lines > 0 && !csOp.attribs && !attOp.opcode &&
|
||||||
!lineAssem && !lineOpsHasNext()) {
|
!lineAssem && !lineOpsHasNext()) {
|
||||||
// skip multiple lines; this is what makes small changes not order of the document size
|
// Skip multiple lines without attributes; this is what makes small changes not order of the
|
||||||
|
// document size.
|
||||||
mut.skipLines(csOp.lines);
|
mut.skipLines(csOp.lines);
|
||||||
csOp.opcode = '';
|
csOp.opcode = '';
|
||||||
} else if (csOp.opcode === '+') {
|
} else if (csOp.opcode === '+') {
|
||||||
const opOut = copyOp(csOp);
|
const opOut = copyOp(csOp);
|
||||||
if (csOp.lines > 1) {
|
if (csOp.lines > 1) {
|
||||||
|
// Copy the first line from `csOp` to `opOut`.
|
||||||
const firstLineLen = csBank.indexOf('\n', csBankIndex) + 1 - csBankIndex;
|
const firstLineLen = csBank.indexOf('\n', csBankIndex) + 1 - csBankIndex;
|
||||||
csOp.chars -= firstLineLen;
|
csOp.chars -= firstLineLen;
|
||||||
csOp.lines--;
|
csOp.lines--;
|
||||||
opOut.lines = 1;
|
opOut.lines = 1;
|
||||||
opOut.chars = firstLineLen;
|
opOut.chars = firstLineLen;
|
||||||
} else {
|
} else {
|
||||||
|
// Either one or no newlines in '+' `csOp`, copy to `opOut` and reset `csOp`.
|
||||||
csOp.opcode = '';
|
csOp.opcode = '';
|
||||||
}
|
}
|
||||||
outputMutOp(opOut);
|
outputMutOp(opOut);
|
||||||
|
@ -1758,7 +1792,7 @@ exports.copyAText = (atext1, atext2) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert AText to a series of operations.
|
* Convert AText to a series of operations. Strips final newline.
|
||||||
*
|
*
|
||||||
* @param {AText} atext - The AText to convert.
|
* @param {AText} atext - The AText to convert.
|
||||||
* @yields {Op}
|
* @yields {Op}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue