"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var fast_diff_1 = __importDefault(require("fast-diff")); var lodash_clonedeep_1 = __importDefault(require("lodash.clonedeep")); var lodash_isequal_1 = __importDefault(require("lodash.isequal")); var AttributeMap_1 = __importDefault(require("./AttributeMap")); var Op_1 = __importDefault(require("./Op")); var NULL_CHARACTER = String.fromCharCode(0); // Placeholder char for embed in diff() var Delta = /** @class */ (function () { function Delta(ops) { // Assume we are given a well formed ops if (Array.isArray(ops)) { this.ops = ops; } else if (ops != null && Array.isArray(ops.ops)) { this.ops = ops.ops; } else { this.ops = []; } } Delta.prototype.insert = function (arg, attributes) { var newOp = {}; if (typeof arg === 'string' && arg.length === 0) { return this; } newOp.insert = arg; if (attributes != null && typeof attributes === 'object' && Object.keys(attributes).length > 0) { newOp.attributes = attributes; } return this.push(newOp); }; Delta.prototype.delete = function (length) { if (length <= 0) { return this; } return this.push({ delete: length }); }; Delta.prototype.retain = function (length, attributes) { if (length <= 0) { return this; } var newOp = { retain: length }; if (attributes != null && typeof attributes === 'object' && Object.keys(attributes).length > 0) { newOp.attributes = attributes; } return this.push(newOp); }; Delta.prototype.push = function (newOp) { var index = this.ops.length; var lastOp = this.ops[index - 1]; newOp = lodash_clonedeep_1.default(newOp); if (typeof lastOp === 'object') { if (typeof newOp.delete === 'number' && typeof lastOp.delete === 'number') { this.ops[index - 1] = { delete: lastOp.delete + newOp.delete }; return this; } // Since it does not matter if we insert before or after deleting at the same index, // always prefer to insert first if (typeof lastOp.delete === 'number' && newOp.insert != null) { index -= 1; lastOp = this.ops[index - 1]; if (typeof lastOp !== 'object') { this.ops.unshift(newOp); return this; } } if (lodash_isequal_1.default(newOp.attributes, lastOp.attributes)) { if (typeof newOp.insert === 'string' && typeof lastOp.insert === 'string') { this.ops[index - 1] = { insert: lastOp.insert + newOp.insert }; if (typeof newOp.attributes === 'object') { this.ops[index - 1].attributes = newOp.attributes; } return this; } else if (typeof newOp.retain === 'number' && typeof lastOp.retain === 'number') { this.ops[index - 1] = { retain: lastOp.retain + newOp.retain }; if (typeof newOp.attributes === 'object') { this.ops[index - 1].attributes = newOp.attributes; } return this; } } } if (index === this.ops.length) { this.ops.push(newOp); } else { this.ops.splice(index, 0, newOp); } return this; }; Delta.prototype.chop = function () { var lastOp = this.ops[this.ops.length - 1]; if (lastOp && lastOp.retain && !lastOp.attributes) { this.ops.pop(); } return this; }; Delta.prototype.filter = function (predicate) { return this.ops.filter(predicate); }; Delta.prototype.forEach = function (predicate) { this.ops.forEach(predicate); }; Delta.prototype.map = function (predicate) { return this.ops.map(predicate); }; Delta.prototype.partition = function (predicate) { var passed = []; var failed = []; this.forEach(function (op) { var target = predicate(op) ? passed : failed; target.push(op); }); return [passed, failed]; }; Delta.prototype.reduce = function (predicate, initialValue) { return this.ops.reduce(predicate, initialValue); }; Delta.prototype.changeLength = function () { return this.reduce(function (length, elem) { if (elem.insert) { return length + Op_1.default.length(elem); } else if (elem.delete) { return length - elem.delete; } return length; }, 0); }; Delta.prototype.length = function () { return this.reduce(function (length, elem) { return length + Op_1.default.length(elem); }, 0); }; Delta.prototype.slice = function (start, end) { if (start === void 0) { start = 0; } if (end === void 0) { end = Infinity; } var ops = []; var iter = Op_1.default.iterator(this.ops); var index = 0; while (index < end && iter.hasNext()) { var nextOp = void 0; if (index < start) { nextOp = iter.next(start - index); } else { nextOp = iter.next(end - index); ops.push(nextOp); } index += Op_1.default.length(nextOp); } return new Delta(ops); }; Delta.prototype.compose = function (other) { var thisIter = Op_1.default.iterator(this.ops); var otherIter = Op_1.default.iterator(other.ops); var ops = []; var firstOther = otherIter.peek(); if (firstOther != null && typeof firstOther.retain === 'number' && firstOther.attributes == null) { var firstLeft = firstOther.retain; while (thisIter.peekType() === 'insert' && thisIter.peekLength() <= firstLeft) { firstLeft -= thisIter.peekLength(); ops.push(thisIter.next()); } if (firstOther.retain - firstLeft > 0) { otherIter.next(firstOther.retain - firstLeft); } } var delta = new Delta(ops); while (thisIter.hasNext() || otherIter.hasNext()) { if (otherIter.peekType() === 'insert') { delta.push(otherIter.next()); } else if (thisIter.peekType() === 'delete') { delta.push(thisIter.next()); } else { var length_1 = Math.min(thisIter.peekLength(), otherIter.peekLength()); var thisOp = thisIter.next(length_1); var otherOp = otherIter.next(length_1); if (typeof otherOp.retain === 'number') { var newOp = {}; if (typeof thisOp.retain === 'number') { newOp.retain = length_1; } else { newOp.insert = thisOp.insert; } // Preserve null when composing with a retain, otherwise remove it for inserts var attributes = AttributeMap_1.default.compose(thisOp.attributes, otherOp.attributes, typeof thisOp.retain === 'number'); if (attributes) { newOp.attributes = attributes; } delta.push(newOp); // Optimization if rest of other is just retain if (!otherIter.hasNext() && lodash_isequal_1.default(delta.ops[delta.ops.length - 1], newOp)) { var rest = new Delta(thisIter.rest()); return delta.concat(rest).chop(); } // Other op should be delete, we could be an insert or retain // Insert + delete cancels out } else if (typeof otherOp.delete === 'number' && typeof thisOp.retain === 'number') { delta.push(otherOp); } } } return delta.chop(); }; Delta.prototype.concat = function (other) { var delta = new Delta(this.ops.slice()); if (other.ops.length > 0) { delta.push(other.ops[0]); delta.ops = delta.ops.concat(other.ops.slice(1)); } return delta; }; Delta.prototype.diff = function (other, cursor) { if (this.ops === other.ops) { return new Delta(); } var strings = [this, other].map(function (delta) { return delta .map(function (op) { if (op.insert != null) { return typeof op.insert === 'string' ? op.insert : NULL_CHARACTER; } var prep = delta === other ? 'on' : 'with'; throw new Error('diff() called ' + prep + ' non-document'); }) .join(''); }); var retDelta = new Delta(); var diffResult = fast_diff_1.default(strings[0], strings[1], cursor); var thisIter = Op_1.default.iterator(this.ops); var otherIter = Op_1.default.iterator(other.ops); diffResult.forEach(function (component) { var length = component[1].length; while (length > 0) { var opLength = 0; switch (component[0]) { case fast_diff_1.default.INSERT: opLength = Math.min(otherIter.peekLength(), length); retDelta.push(otherIter.next(opLength)); break; case fast_diff_1.default.DELETE: opLength = Math.min(length, thisIter.peekLength()); thisIter.next(opLength); retDelta.delete(opLength); break; case fast_diff_1.default.EQUAL: opLength = Math.min(thisIter.peekLength(), otherIter.peekLength(), length); var thisOp = thisIter.next(opLength); var otherOp = otherIter.next(opLength); if (lodash_isequal_1.default(thisOp.insert, otherOp.insert)) { retDelta.retain(opLength, AttributeMap_1.default.diff(thisOp.attributes, otherOp.attributes)); } else { retDelta.push(otherOp).delete(opLength); } break; } length -= opLength; } }); return retDelta.chop(); }; Delta.prototype.eachLine = function (predicate, newline) { if (newline === void 0) { newline = '\n'; } var iter = Op_1.default.iterator(this.ops); var line = new Delta(); var i = 0; while (iter.hasNext()) { if (iter.peekType() !== 'insert') { return; } var thisOp = iter.peek(); var start = Op_1.default.length(thisOp) - iter.peekLength(); var index = typeof thisOp.insert === 'string' ? thisOp.insert.indexOf(newline, start) - start : -1; if (index < 0) { line.push(iter.next()); } else if (index > 0) { line.push(iter.next(index)); } else { if (predicate(line, iter.next(1).attributes || {}, i) === false) { return; } i += 1; line = new Delta(); } } if (line.length() > 0) { predicate(line, {}, i); } }; Delta.prototype.invert = function (base) { var inverted = new Delta(); this.reduce(function (baseIndex, op) { if (op.insert) { inverted.delete(Op_1.default.length(op)); } else if (op.retain && op.attributes == null) { inverted.retain(op.retain); return baseIndex + op.retain; } else if (op.delete || (op.retain && op.attributes)) { var length_2 = (op.delete || op.retain); var slice = base.slice(baseIndex, baseIndex + length_2); slice.forEach(function (baseOp) { if (op.delete) { inverted.push(baseOp); } else if (op.retain && op.attributes) { inverted.retain(Op_1.default.length(baseOp), AttributeMap_1.default.invert(op.attributes, baseOp.attributes)); } }); return baseIndex + length_2; } return baseIndex; }, 0); return inverted.chop(); }; Delta.prototype.transform = function (arg, priority) { if (priority === void 0) { priority = false; } priority = !!priority; if (typeof arg === 'number') { return this.transformPosition(arg, priority); } var other = arg; var thisIter = Op_1.default.iterator(this.ops); var otherIter = Op_1.default.iterator(other.ops); var delta = new Delta(); while (thisIter.hasNext() || otherIter.hasNext()) { if (thisIter.peekType() === 'insert' && (priority || otherIter.peekType() !== 'insert')) { delta.retain(Op_1.default.length(thisIter.next())); } else if (otherIter.peekType() === 'insert') { delta.push(otherIter.next()); } else { var length_3 = Math.min(thisIter.peekLength(), otherIter.peekLength()); var thisOp = thisIter.next(length_3); var otherOp = otherIter.next(length_3); if (thisOp.delete) { // Our delete either makes their delete redundant or removes their retain continue; } else if (otherOp.delete) { delta.push(otherOp); } else { // We retain either their retain or insert delta.retain(length_3, AttributeMap_1.default.transform(thisOp.attributes, otherOp.attributes, priority)); } } } return delta.chop(); }; Delta.prototype.transformPosition = function (index, priority) { if (priority === void 0) { priority = false; } priority = !!priority; var thisIter = Op_1.default.iterator(this.ops); var offset = 0; while (thisIter.hasNext() && offset <= index) { var length_4 = thisIter.peekLength(); var nextType = thisIter.peekType(); thisIter.next(); if (nextType === 'delete') { index -= Math.min(length_4, index - offset); continue; } else if (nextType === 'insert' && (offset < index || !priority)) { index += length_4; } offset += length_4; } return index; }; Delta.Op = Op_1.default; Delta.AttributeMap = AttributeMap_1.default; return Delta; }()); module.exports = Delta; //# sourceMappingURL=Delta.js.map