Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/305438
Change subject: WIP: Function to rebase a transaction onto another ...................................................................... WIP: Function to rebase a transaction onto another Change-Id: I2c83056b24e45edb35aceb78f8bf066866e6563f --- M src/dm/ve.dm.Transaction.js 1 file changed, 128 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/38/305438/1 diff --git a/src/dm/ve.dm.Transaction.js b/src/dm/ve.dm.Transaction.js index 1b510fc..2cc0f26 100644 --- a/src/dm/ve.dm.Transaction.js +++ b/src/dm/ve.dm.Transaction.js @@ -1535,3 +1535,131 @@ } return offset; }; + +/** + * Rebase this to happen after other + * + * @param {other} Transaction that acts on the document in the same start state as this + * @returns {other|null} + */ +ve.dm.Transaction.prototype.rebaseOnto( other ) { + var i, len, r, range, opEnd, + changedRanges = other.getChangedRanges(), + // changedRange pointer + r = 0, + // cumulative range length diff + diff = 0, + tx = this.clone(); + + opLoop: + for ( i = 0, len = tx.operations.length; i < len; i++ ) { + op = tx.operations[ i ]; + while ( true ) { + if ( r >= changedRanges.length ) { + op.start += diff; + continue opLoop; + } + range = changedRanges[ r ]; + if ( range.end < op.start ) { + diff += range.diff; + r++; + continue; + } + break; + } + // Else op.start <= range.end + + opEnd = ( op.type === 'replace' ? op.remove : op.type === 'retain' ? op.length : 1 ); + if ( opEnd < range.start ) { + op.start += diff; + continue; + } + // Else [ range.start, range.end ] overlaps with [ op.start, op.end ] + + if ( op.type === 'retain' && op.start <= range.start && opEnd >= range.end ) { + op.start += diff; + op.length += range.diff; + } + + // Else conflict + debugger; + console.log( 'Conflict:', [ range.start, range.end ], [ op.start, opEnd ] ); + return null; + } + return tx; +}; + + +/** + * @returns {Object[]} List of { start: x, end: x, diff: x } sorted by start + */ +ve.dm.Transaction.prototype.getChangedRanges = function () { + var i, len, op, + // List of { start: x, end: x, diff: x } + changedRanges = [], + // Number of annotation changes in force + annotating = 0, + // Data pointer + d = 0, + // Cumulative range length diff + diff = 0, + // Data pointer at the start of this run of annotation changes + annStart = null, + // Length diff at the start of this run of annotation changes + annStartDiff = null; + + for ( i = 0, len = this.operations.length; i < len; i++ ) { + op = this.operations[ i ]; + if ( op.type === 'retain' ) { + d += op.length; + } else if ( op.type === 'replaceMetadata' ) { + // Mark the current item as modified + if ( !annotating ) { + changedRanges.push( { + start: d, + end: d + 1, + diff: 0 + } ); + } + } else if ( op.type === 'replace' ) { + if ( !annotating ) { + changedRanges.push( { + start: d, + end: d + op.remove.length, + diff: op.insert.length - op.remove.length + } ); + } + d += op.remove.length; + diff += op.insert.length - op.remove.length; + } else if ( op.type === 'attribute' ) { + if ( !annotating ) { + changedRanges.push( { + start: d, + end: d + 1, + diff: 0 + } ); + } + } else if ( op.type === 'annotate' && ob.bias === 'start' ) { + if ( !annotating ) { + annStart = d; + annStartDiff = diff; + } + annotating++; + } else if ( op.type === 'annotate' && ob.bias === 'stop' ) { + annotating--; + if ( !annotating ) { + changedRanges.push( { + start: annStart, + end: d, + diff: diff - annStartDiff + } ); + annStart = null; + annStartDiff = null; + } + } else { + debugger; + throw new Error( 'Weird operator', op ); + } + } + return changedRanges; +}; -- To view, visit https://gerrit.wikimedia.org/r/305438 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I2c83056b24e45edb35aceb78f8bf066866e6563f Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec <da...@troi.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits