mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-19 14:13:34 +01:00
Changeset: Turn builder()
into a real class
This commit is contained in:
parent
d3d2090ca5
commit
a1c4382386
8 changed files with 101 additions and 98 deletions
|
@ -43,6 +43,7 @@
|
|||
generator function (combined with `serializeOps()`).
|
||||
* `appendATextToAssembler()`: Deprecated in favor of the new `opsFromAText()`
|
||||
generator function.
|
||||
* `builder()`: Deprecated in favor of the new `Builder` class.
|
||||
* `newOp()`: Deprecated in favor of the new `Op` class.
|
||||
|
||||
# 1.8.16
|
||||
|
|
|
@ -538,7 +538,7 @@ exports.restoreRevision = async (padID, rev) => {
|
|||
};
|
||||
|
||||
// create a new changeset with a helper builder object
|
||||
const builder = Changeset.builder(oldText.length);
|
||||
const builder = new Changeset.Builder(oldText.length);
|
||||
|
||||
// assemble each line into the builder
|
||||
eachAttribRun(atext.attribs, (start, end, attribs) => {
|
||||
|
|
|
@ -759,7 +759,7 @@ const _correctMarkersInPad = (atext, apool) => {
|
|||
// create changeset that removes these bad markers
|
||||
offset = 0;
|
||||
|
||||
const builder = Changeset.builder(text.length);
|
||||
const builder = new Changeset.Builder(text.length);
|
||||
|
||||
badMarkers.forEach((pos) => {
|
||||
builder.keepText(text.substring(offset, pos));
|
||||
|
|
|
@ -64,7 +64,7 @@ exports.setPadHTML = async (pad, html) => {
|
|||
const newAttribs = `${result.lineAttribs.join('|1+1')}|1+1`;
|
||||
|
||||
// create a new changeset with a helper builder object
|
||||
const builder = Changeset.builder(1);
|
||||
const builder = new Changeset.Builder(1);
|
||||
|
||||
// assemble each line into the builder
|
||||
let textIndex = 0;
|
||||
|
|
|
@ -69,7 +69,7 @@ PadDiff.prototype._createClearAuthorship = async function (rev) {
|
|||
const atext = await this._pad.getInternalRevisionAText(rev);
|
||||
|
||||
// build clearAuthorship changeset
|
||||
const builder = Changeset.builder(atext.text.length);
|
||||
const builder = new Changeset.Builder(atext.text.length);
|
||||
builder.keepText(atext.text, [['author', '']], this._pad.pool);
|
||||
const changeset = builder.toString();
|
||||
|
||||
|
@ -262,7 +262,7 @@ PadDiff.prototype._createDeletionChangeset = function (cs, startAText, apool) {
|
|||
let curLineNextOp = new Changeset.Op('+');
|
||||
|
||||
const unpacked = Changeset.unpack(cs);
|
||||
const builder = Changeset.builder(unpacked.newLen);
|
||||
const builder = new Changeset.Builder(unpacked.newLen);
|
||||
|
||||
const consumeAttribRuns = (numChars, func /* (len, attribs, endsLine)*/) => {
|
||||
if (!curLineOps || curLineOpsLine !== curLine) {
|
||||
|
|
|
@ -125,7 +125,7 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
* @param attribs an array of attributes
|
||||
*/
|
||||
_setAttributesOnRangeByLine(row, startCol, endCol, attribs) {
|
||||
const builder = Changeset.builder(this.rep.lines.totalWidth());
|
||||
const builder = new Changeset.Builder(this.rep.lines.totalWidth());
|
||||
ChangesetUtils.buildKeepToStartOfRange(this.rep, builder, [row, startCol]);
|
||||
ChangesetUtils.buildKeepRange(
|
||||
this.rep, builder, [row, startCol], [row, endCol], attribs, this.rep.apool);
|
||||
|
@ -285,7 +285,7 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
*/
|
||||
setAttributeOnLine(lineNum, attributeName, attributeValue) {
|
||||
let loc = [0, 0];
|
||||
const builder = Changeset.builder(this.rep.lines.totalWidth());
|
||||
const builder = new Changeset.Builder(this.rep.lines.totalWidth());
|
||||
const hasMarker = this.lineHasMarker(lineNum);
|
||||
|
||||
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 0]));
|
||||
|
@ -314,7 +314,7 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
|||
* @param attributeValue if given only attributes with equal value will be removed
|
||||
*/
|
||||
removeAttributeOnLine(lineNum, attributeName, attributeValue) {
|
||||
const builder = Changeset.builder(this.rep.lines.totalWidth());
|
||||
const builder = new Changeset.Builder(this.rep.lines.totalWidth());
|
||||
const hasMarker = this.lineHasMarker(lineNum);
|
||||
let found = false;
|
||||
|
||||
|
|
|
@ -1915,98 +1915,100 @@ exports.attribsAttributeValue = (attribs, key, pool) => {
|
|||
|
||||
/**
|
||||
* Incrementally builds a Changeset.
|
||||
*
|
||||
* @typedef {object} Builder
|
||||
* @property {Function} insert -
|
||||
* @property {Function} keep -
|
||||
* @property {Function} keepText -
|
||||
* @property {Function} remove -
|
||||
* @property {Function} toString -
|
||||
*/
|
||||
class Builder {
|
||||
/**
|
||||
* @param {number} oldLen - Old length
|
||||
*/
|
||||
constructor(oldLen) {
|
||||
this._oldLen = oldLen;
|
||||
this._ops = [];
|
||||
this._charBank = exports.stringAssembler();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} N - Number of characters to keep.
|
||||
* @param {number} L - Number of newlines among the `N` characters. If positive, the last
|
||||
* character must be a newline.
|
||||
* @param {(string|Attribute[])} attribs - Either [[key1,value1],[key2,value2],...] or '*0*1...'
|
||||
* (no pool needed in latter case).
|
||||
* @param {?AttributePool} pool - Attribute pool, only required if `attribs` is a list of
|
||||
* attribute key, value pairs.
|
||||
* @returns {Builder} this
|
||||
*/
|
||||
keep(N, L, attribs, pool) {
|
||||
const o = new Op('=');
|
||||
o.attribs = typeof attribs === 'string'
|
||||
? attribs : new AttributeMap(pool).update(attribs || []).toString();
|
||||
o.chars = N;
|
||||
o.lines = (L || 0);
|
||||
this._ops.push(o);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text - Text to keep.
|
||||
* @param {(string|Attribute[])} attribs - Either [[key1,value1],[key2,value2],...] or '*0*1...'
|
||||
* (no pool needed in latter case).
|
||||
* @param {?AttributePool} pool - Attribute pool, only required if `attribs` is a list of
|
||||
* attribute key, value pairs.
|
||||
* @returns {Builder} this
|
||||
*/
|
||||
keepText(text, attribs, pool) {
|
||||
this._ops.push(...opsFromText('=', text, attribs, pool));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} text - Text to insert.
|
||||
* @param {(string|Attribute[])} attribs - Either [[key1,value1],[key2,value2],...] or '*0*1...'
|
||||
* (no pool needed in latter case).
|
||||
* @param {?AttributePool} pool - Attribute pool, only required if `attribs` is a list of
|
||||
* attribute key, value pairs.
|
||||
* @returns {Builder} this
|
||||
*/
|
||||
insert(text, attribs, pool) {
|
||||
this._ops.push(...opsFromText('+', text, attribs, pool));
|
||||
this._charBank.append(text);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} N - Number of characters to remove.
|
||||
* @param {number} L - Number of newlines among the `N` characters. If positive, the last
|
||||
* character must be a newline.
|
||||
* @returns {Builder} this
|
||||
*/
|
||||
remove(N, L) {
|
||||
const o = new Op('-');
|
||||
o.attribs = '';
|
||||
o.chars = N;
|
||||
o.lines = (L || 0);
|
||||
this._ops.push(o);
|
||||
return this;
|
||||
}
|
||||
|
||||
toString() {
|
||||
/** @type {number} */
|
||||
let lengthChange;
|
||||
const serializedOps = exports.serializeOps((function* () {
|
||||
lengthChange = yield* exports.canonicalizeOps(this._ops, true);
|
||||
}).call(this));
|
||||
const newLen = this._oldLen + lengthChange;
|
||||
return exports.pack(this._oldLen, newLen, serializedOps, this._charBank.toString());
|
||||
}
|
||||
}
|
||||
exports.Builder = Builder;
|
||||
|
||||
/**
|
||||
* @deprecated Use the `Builder` class instead.
|
||||
* @param {number} oldLen - Old length
|
||||
* @returns {Builder}
|
||||
*/
|
||||
exports.builder = (oldLen) => {
|
||||
const ops = [];
|
||||
const charBank = exports.stringAssembler();
|
||||
|
||||
const self = {
|
||||
/**
|
||||
* @param {number} N - Number of characters to keep.
|
||||
* @param {number} L - Number of newlines among the `N` characters. If positive, the last
|
||||
* character must be a newline.
|
||||
* @param {(string|Attribute[])} attribs - Either [[key1,value1],[key2,value2],...] or '*0*1...'
|
||||
* (no pool needed in latter case).
|
||||
* @param {?AttributePool} pool - Attribute pool, only required if `attribs` is a list of
|
||||
* attribute key, value pairs.
|
||||
* @returns {Builder} this
|
||||
*/
|
||||
keep: (N, L, attribs, pool) => {
|
||||
const o = new Op('=');
|
||||
o.attribs = typeof attribs === 'string'
|
||||
? attribs : new AttributeMap(pool).update(attribs || []).toString();
|
||||
o.chars = N;
|
||||
o.lines = (L || 0);
|
||||
ops.push(o);
|
||||
return self;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} text - Text to keep.
|
||||
* @param {(string|Attribute[])} attribs - Either [[key1,value1],[key2,value2],...] or '*0*1...'
|
||||
* (no pool needed in latter case).
|
||||
* @param {?AttributePool} pool - Attribute pool, only required if `attribs` is a list of
|
||||
* attribute key, value pairs.
|
||||
* @returns {Builder} this
|
||||
*/
|
||||
keepText: (text, attribs, pool) => {
|
||||
ops.push(...opsFromText('=', text, attribs, pool));
|
||||
return self;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {string} text - Text to insert.
|
||||
* @param {(string|Attribute[])} attribs - Either [[key1,value1],[key2,value2],...] or '*0*1...'
|
||||
* (no pool needed in latter case).
|
||||
* @param {?AttributePool} pool - Attribute pool, only required if `attribs` is a list of
|
||||
* attribute key, value pairs.
|
||||
* @returns {Builder} this
|
||||
*/
|
||||
insert: (text, attribs, pool) => {
|
||||
ops.push(...opsFromText('+', text, attribs, pool));
|
||||
charBank.append(text);
|
||||
return self;
|
||||
},
|
||||
|
||||
/**
|
||||
* @param {number} N - Number of characters to remove.
|
||||
* @param {number} L - Number of newlines among the `N` characters. If positive, the last
|
||||
* character must be a newline.
|
||||
* @returns {Builder} this
|
||||
*/
|
||||
remove: (N, L) => {
|
||||
const o = new Op('-');
|
||||
o.attribs = '';
|
||||
o.chars = N;
|
||||
o.lines = (L || 0);
|
||||
ops.push(o);
|
||||
return self;
|
||||
},
|
||||
|
||||
toString: () => {
|
||||
/** @type {number} */
|
||||
let lengthChange;
|
||||
const serializedOps = exports.serializeOps((function* () {
|
||||
lengthChange = yield* exports.canonicalizeOps(ops, true);
|
||||
})());
|
||||
const newLen = oldLen + lengthChange;
|
||||
return exports.pack(oldLen, newLen, serializedOps, charBank.toString());
|
||||
},
|
||||
};
|
||||
|
||||
return self;
|
||||
padutils.warnDeprecated(
|
||||
'Changeset.builder() is deprecated; use the Changeset.Builder class instead');
|
||||
return new Builder(oldLen);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2107,7 +2109,7 @@ exports.inverse = (cs, lines, alines, pool) => {
|
|||
let curLineNextOp = new Op('+');
|
||||
|
||||
const unpacked = exports.unpack(cs);
|
||||
const builder = exports.builder(unpacked.newLen);
|
||||
const builder = new Builder(unpacked.newLen);
|
||||
|
||||
const consumeAttribRuns = (numChars, func /* (len, attribs, endsLine)*/) => {
|
||||
if (!curLineOps || curLineOpsLine !== curLine) {
|
||||
|
|
|
@ -170,7 +170,7 @@ function Ace2Inner(editorInfo, cssManagers) {
|
|||
// CCCCCCCCCCCCCCCCCCCC\n
|
||||
// CCCC\n
|
||||
// end[0]: <CCC end[1] CCC>-------\n
|
||||
const builder = Changeset.builder(rep.lines.totalWidth());
|
||||
const builder = new Changeset.Builder(rep.lines.totalWidth());
|
||||
ChangesetUtils.buildKeepToStartOfRange(rep, builder, start);
|
||||
ChangesetUtils.buildRemoveRange(rep, builder, start, end);
|
||||
builder.insert(newText, [
|
||||
|
@ -1272,7 +1272,7 @@ function Ace2Inner(editorInfo, cssManagers) {
|
|||
if (shouldIndent && /[[(:{]\s*$/.exec(prevLineText)) {
|
||||
theIndent += THE_TAB;
|
||||
}
|
||||
const cs = Changeset.builder(rep.lines.totalWidth()).keep(
|
||||
const cs = new Changeset.Builder(rep.lines.totalWidth()).keep(
|
||||
rep.lines.offsetOfIndex(lineNum), lineNum).insert(
|
||||
theIndent, [
|
||||
['author', thisAuthor],
|
||||
|
@ -1746,7 +1746,7 @@ function Ace2Inner(editorInfo, cssManagers) {
|
|||
const spliceStartLineStart = rep.lines.offsetOfIndex(spliceStartLine);
|
||||
|
||||
const startBuilder = () => {
|
||||
const builder = Changeset.builder(oldLen);
|
||||
const builder = new Changeset.Builder(oldLen);
|
||||
builder.keep(spliceStartLineStart, spliceStartLine);
|
||||
builder.keep(spliceStart - spliceStartLineStart);
|
||||
return builder;
|
||||
|
@ -2297,7 +2297,7 @@ function Ace2Inner(editorInfo, cssManagers) {
|
|||
|
||||
// 3-renumber every list item of the same level from the beginning, level 1
|
||||
// IMPORTANT: never skip a level because there imbrication may be arbitrary
|
||||
const builder = Changeset.builder(rep.lines.totalWidth());
|
||||
const builder = new Changeset.Builder(rep.lines.totalWidth());
|
||||
let loc = [0, 0];
|
||||
const applyNumberList = (line, level) => {
|
||||
// init
|
||||
|
|
Loading…
Reference in a new issue