mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-01-31 19:02:59 +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()`).
|
generator function (combined with `serializeOps()`).
|
||||||
* `appendATextToAssembler()`: Deprecated in favor of the new `opsFromAText()`
|
* `appendATextToAssembler()`: Deprecated in favor of the new `opsFromAText()`
|
||||||
generator function.
|
generator function.
|
||||||
|
* `builder()`: Deprecated in favor of the new `Builder` class.
|
||||||
* `newOp()`: Deprecated in favor of the new `Op` class.
|
* `newOp()`: Deprecated in favor of the new `Op` class.
|
||||||
|
|
||||||
# 1.8.16
|
# 1.8.16
|
||||||
|
|
|
@ -538,7 +538,7 @@ exports.restoreRevision = async (padID, rev) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// create a new changeset with a helper builder object
|
// 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
|
// assemble each line into the builder
|
||||||
eachAttribRun(atext.attribs, (start, end, attribs) => {
|
eachAttribRun(atext.attribs, (start, end, attribs) => {
|
||||||
|
|
|
@ -759,7 +759,7 @@ const _correctMarkersInPad = (atext, apool) => {
|
||||||
// create changeset that removes these bad markers
|
// create changeset that removes these bad markers
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
|
||||||
const builder = Changeset.builder(text.length);
|
const builder = new Changeset.Builder(text.length);
|
||||||
|
|
||||||
badMarkers.forEach((pos) => {
|
badMarkers.forEach((pos) => {
|
||||||
builder.keepText(text.substring(offset, 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`;
|
const newAttribs = `${result.lineAttribs.join('|1+1')}|1+1`;
|
||||||
|
|
||||||
// create a new changeset with a helper builder object
|
// 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
|
// assemble each line into the builder
|
||||||
let textIndex = 0;
|
let textIndex = 0;
|
||||||
|
|
|
@ -69,7 +69,7 @@ PadDiff.prototype._createClearAuthorship = async function (rev) {
|
||||||
const atext = await this._pad.getInternalRevisionAText(rev);
|
const atext = await this._pad.getInternalRevisionAText(rev);
|
||||||
|
|
||||||
// build clearAuthorship changeset
|
// 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);
|
builder.keepText(atext.text, [['author', '']], this._pad.pool);
|
||||||
const changeset = builder.toString();
|
const changeset = builder.toString();
|
||||||
|
|
||||||
|
@ -262,7 +262,7 @@ PadDiff.prototype._createDeletionChangeset = function (cs, startAText, apool) {
|
||||||
let curLineNextOp = new Changeset.Op('+');
|
let curLineNextOp = new Changeset.Op('+');
|
||||||
|
|
||||||
const unpacked = Changeset.unpack(cs);
|
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)*/) => {
|
const consumeAttribRuns = (numChars, func /* (len, attribs, endsLine)*/) => {
|
||||||
if (!curLineOps || curLineOpsLine !== curLine) {
|
if (!curLineOps || curLineOpsLine !== curLine) {
|
||||||
|
|
|
@ -125,7 +125,7 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
||||||
* @param attribs an array of attributes
|
* @param attribs an array of attributes
|
||||||
*/
|
*/
|
||||||
_setAttributesOnRangeByLine(row, startCol, endCol, attribs) {
|
_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.buildKeepToStartOfRange(this.rep, builder, [row, startCol]);
|
||||||
ChangesetUtils.buildKeepRange(
|
ChangesetUtils.buildKeepRange(
|
||||||
this.rep, builder, [row, startCol], [row, endCol], attribs, this.rep.apool);
|
this.rep, builder, [row, startCol], [row, endCol], attribs, this.rep.apool);
|
||||||
|
@ -285,7 +285,7 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
||||||
*/
|
*/
|
||||||
setAttributeOnLine(lineNum, attributeName, attributeValue) {
|
setAttributeOnLine(lineNum, attributeName, attributeValue) {
|
||||||
let loc = [0, 0];
|
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);
|
const hasMarker = this.lineHasMarker(lineNum);
|
||||||
|
|
||||||
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 0]));
|
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
|
* @param attributeValue if given only attributes with equal value will be removed
|
||||||
*/
|
*/
|
||||||
removeAttributeOnLine(lineNum, attributeName, attributeValue) {
|
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);
|
const hasMarker = this.lineHasMarker(lineNum);
|
||||||
let found = false;
|
let found = false;
|
||||||
|
|
||||||
|
|
|
@ -1915,98 +1915,100 @@ exports.attribsAttributeValue = (attribs, key, pool) => {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Incrementally builds a Changeset.
|
* 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
|
* @param {number} oldLen - Old length
|
||||||
* @returns {Builder}
|
* @returns {Builder}
|
||||||
*/
|
*/
|
||||||
exports.builder = (oldLen) => {
|
exports.builder = (oldLen) => {
|
||||||
const ops = [];
|
padutils.warnDeprecated(
|
||||||
const charBank = exports.stringAssembler();
|
'Changeset.builder() is deprecated; use the Changeset.Builder class instead');
|
||||||
|
return new Builder(oldLen);
|
||||||
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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2107,7 +2109,7 @@ exports.inverse = (cs, lines, alines, pool) => {
|
||||||
let curLineNextOp = new Op('+');
|
let curLineNextOp = new Op('+');
|
||||||
|
|
||||||
const unpacked = exports.unpack(cs);
|
const unpacked = exports.unpack(cs);
|
||||||
const builder = exports.builder(unpacked.newLen);
|
const builder = new Builder(unpacked.newLen);
|
||||||
|
|
||||||
const consumeAttribRuns = (numChars, func /* (len, attribs, endsLine)*/) => {
|
const consumeAttribRuns = (numChars, func /* (len, attribs, endsLine)*/) => {
|
||||||
if (!curLineOps || curLineOpsLine !== curLine) {
|
if (!curLineOps || curLineOpsLine !== curLine) {
|
||||||
|
|
|
@ -170,7 +170,7 @@ function Ace2Inner(editorInfo, cssManagers) {
|
||||||
// CCCCCCCCCCCCCCCCCCCC\n
|
// CCCCCCCCCCCCCCCCCCCC\n
|
||||||
// CCCC\n
|
// CCCC\n
|
||||||
// end[0]: <CCC end[1] CCC>-------\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.buildKeepToStartOfRange(rep, builder, start);
|
||||||
ChangesetUtils.buildRemoveRange(rep, builder, start, end);
|
ChangesetUtils.buildRemoveRange(rep, builder, start, end);
|
||||||
builder.insert(newText, [
|
builder.insert(newText, [
|
||||||
|
@ -1272,7 +1272,7 @@ function Ace2Inner(editorInfo, cssManagers) {
|
||||||
if (shouldIndent && /[[(:{]\s*$/.exec(prevLineText)) {
|
if (shouldIndent && /[[(:{]\s*$/.exec(prevLineText)) {
|
||||||
theIndent += THE_TAB;
|
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(
|
rep.lines.offsetOfIndex(lineNum), lineNum).insert(
|
||||||
theIndent, [
|
theIndent, [
|
||||||
['author', thisAuthor],
|
['author', thisAuthor],
|
||||||
|
@ -1746,7 +1746,7 @@ function Ace2Inner(editorInfo, cssManagers) {
|
||||||
const spliceStartLineStart = rep.lines.offsetOfIndex(spliceStartLine);
|
const spliceStartLineStart = rep.lines.offsetOfIndex(spliceStartLine);
|
||||||
|
|
||||||
const startBuilder = () => {
|
const startBuilder = () => {
|
||||||
const builder = Changeset.builder(oldLen);
|
const builder = new Changeset.Builder(oldLen);
|
||||||
builder.keep(spliceStartLineStart, spliceStartLine);
|
builder.keep(spliceStartLineStart, spliceStartLine);
|
||||||
builder.keep(spliceStart - spliceStartLineStart);
|
builder.keep(spliceStart - spliceStartLineStart);
|
||||||
return builder;
|
return builder;
|
||||||
|
@ -2297,7 +2297,7 @@ function Ace2Inner(editorInfo, cssManagers) {
|
||||||
|
|
||||||
// 3-renumber every list item of the same level from the beginning, level 1
|
// 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
|
// 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];
|
let loc = [0, 0];
|
||||||
const applyNumberList = (line, level) => {
|
const applyNumberList = (line, level) => {
|
||||||
// init
|
// init
|
||||||
|
|
Loading…
Reference in a new issue