[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: rebaser: Only apply artificial delay to submitChange events
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/405927 ) Change subject: rebaser: Only apply artificial delay to submitChange events .. rebaser: Only apply artificial delay to submitChange events For debugging, delays on welcomeNewClient and disconnect are unhelpful Change-Id: I259f0012a7c2ffe8f827d6547a195c0b08c46c65 --- M rebaser/server.js 1 file changed, 9 insertions(+), 5 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/27/405927/1 diff --git a/rebaser/server.js b/rebaser/server.js index 2bf6280..3c832af 100644 --- a/rebaser/server.js +++ b/rebaser/server.js @@ -146,10 +146,13 @@ } ); } -function addStep( docName, generatorFunc ) { - var pending = Promise.resolve( pendingForDoc.get( docName ) ), - delayPromise = wait( artificialDelay ); - pending = Promise.all( [ pending, delayPromise ] ) +function addStep( docName, generatorFunc, addDelay ) { + var pending, + parallel = [ Promise.resolve( pendingForDoc.get( docName ) ) ]; + if ( addDelay && artificialDelay > 0 ) { + parallel.push( wait( artificialDelay ) ); + } + pending = Promise.all( parallel ) .then( function () { return ve.spawn( generatorFunc ); } ) @@ -165,7 +168,8 @@ }; function handleEvent( context, eventName, data ) { - addStep( context.docName, handlers[ eventName ]( context, data ) ); + var delay = eventName === 'submitChange'; + addStep( context.docName, handlers[ eventName ]( context, data ), delay ); } function makeConnectionHandler( docName ) { -- To view, visit https://gerrit.wikimedia.org/r/405927 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I259f0012a7c2ffe8f827d6547a195c0b08c46c65 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: ve.dm.Change: Truncate stores as well as transactions on con...
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/405926 ) Change subject: ve.dm.Change: Truncate stores as well as transactions on conflict .. ve.dm.Change: Truncate stores as well as transactions on conflict Change-Id: I5e07579ded9715384875a2d83498d54a9eb0f808 --- M src/dm/ve.dm.Change.js M tests/dm/ve.dm.Change.test.js 2 files changed, 43 insertions(+), 6 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/26/405926/1 diff --git a/src/dm/ve.dm.Change.js b/src/dm/ve.dm.Change.js index 5ff3bdf..a582371 100644 --- a/src/dm/ve.dm.Change.js +++ b/src/dm/ve.dm.Change.js @@ -432,6 +432,7 @@ if ( rebases[ 0 ] === null ) { rejected = uncommitted.mostRecent( uncommitted.start + i ); transactionsB.length = i; + storesB.length = i; selectionsB = {}; break bLoop; } @@ -658,16 +659,13 @@ */ ve.dm.Change.prototype.unapplyTo = function ( surface ) { var doc = surface.documentModel, - historyLength = doc.completeHistory.length - this.getLength(), - storeLength = doc.store.getLength(); - this.stores.forEach( function ( store ) { - storeLength -= store.getLength(); - } ); + historyLength = doc.completeHistory.length - this.getLength(); this.transactions.slice().reverse().forEach( function ( tx ) { surface.change( tx.reversed() ); } ); doc.completeHistory.length = historyLength; - doc.store.truncate( storeLength ); + doc.storeLengthAtHistoryLength.length = historyLength + 1; + doc.store.truncate( doc.storeLengthAtHistoryLength[ historyLength ] ); }; /** diff --git a/tests/dm/ve.dm.Change.test.js b/tests/dm/ve.dm.Change.test.js index dc9aea1..76f5855 100644 --- a/tests/dm/ve.dm.Change.test.js +++ b/tests/dm/ve.dm.Change.test.js @@ -276,6 +276,45 @@ ); } ); +QUnit.test( 'Rebase with conflicting annotations', function ( assert ) { + var setBold, remove, result, + origData = [ { type: 'paragraph' }, 'A', { type: '/paragraph' } ], + newSurface = function () { + return new ve.dm.Surface( + ve.dm.example.createExampleDocumentFromData( origData ) + ); + }, + surface = newSurface(), + doc = surface.documentModel, + TxRemove = ve.dm.TransactionBuilder.static.newFromRemoval, + TxAnnotate = ve.dm.TransactionBuilder.static.newFromAnnotation, + b = ve.dm.example.bold, + emptyStore = new ve.dm.IndexValueStore(), + bStore = new ve.dm.IndexValueStore( [ b ] ); + + assert.expect( 3 ); + + // Canonical history: text was removed + remove = new ve.dm.Change( 1, [ TxRemove( doc, new ve.Range( 1, 2 ) ) ], [ emptyStore ], {} ); + setBold = new ve.dm.Change( 1, [ TxAnnotate( doc, new ve.Range( 1, 2 ), 'set', b ) ], [ bStore ], {} ); + result = ve.dm.Change.static.rebaseUncommittedChange( remove, setBold ); + assert.deepEqual( + result.rebased.serialize(), + new ve.dm.Change( 2, [], [], {} ).serialize(), + 'Nothing got rebased' + ); + assert.deepEqual( + result.rejected.serialize(), + setBold.serialize(), + 'setBold got rejected' + ); + assert.deepEqual( + result.transposedHistory.serialize(), + remove.serialize(), + 'remove got transposed' + ); +} ); + QUnit.test( 'Serialize/deserialize', function ( assert ) { var origData = [ { type: 'paragraph' }, 'b', 'a', 'r', { type: '/paragraph' } ], newSurface = function () { -- To view, visit https://gerrit.wikimedia.org/r/405926 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I5e07579ded9715384875a2d83498d54a9eb0f808 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Disable undo/usurp within SurfaceSynchronizer
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/405838 ) Change subject: Disable undo/usurp within SurfaceSynchronizer .. Disable undo/usurp within SurfaceSynchronizer Change-Id: Ic5dc470e444288ea41b2ed2a35fc82e078e3fe0b --- M src/dm/ve.dm.SurfaceSynchronizer.js 1 file changed, 6 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/38/405838/1 diff --git a/src/dm/ve.dm.SurfaceSynchronizer.js b/src/dm/ve.dm.SurfaceSynchronizer.js index 0f51f1b..853c4b4 100644 --- a/src/dm/ve.dm.SurfaceSynchronizer.js +++ b/src/dm/ve.dm.SurfaceSynchronizer.js @@ -27,6 +27,10 @@ // Properties this.surface = surface; + // HACK disable undo/redo + this.surface.canUndo = this.surface.canRedo = function () { + return false; + }; this.doc = surface.documentModel; this.store = this.doc.getStore(); this.authorSelections = {}; @@ -45,7 +49,8 @@ this.socket.on( 'newChange', this.onNewChange.bind( this ) ); this.socket.on( 'nameChange', this.onNameChange.bind( this ) ); this.socket.on( 'authorDisconnect', this.onAuthorDisconnect.bind( this ) ); - this.tryUsurp(); + // TODO: unbreak then re-enable usurp + // this.tryUsurp(); // Events this.doc.connect( this, { -- To view, visit https://gerrit.wikimedia.org/r/405838 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ic5dc470e444288ea41b2ed2a35fc82e078e3fe0b Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Create ve.EventEmitter with emitCatch, and use it throughout...
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/405827 ) Change subject: Create ve.EventEmitter with emitCatch, and use it throughout ve.dm .. Create ve.EventEmitter with emitCatch, and use it throughout ve.dm Bug: T185546 Change-Id: I3175a9e985d4ecffa282d9078352523bfbdf4982 --- M .jsduck/categories.json M build/modules.json M demos/ve/desktop.html M demos/ve/mobile.html M src/dm/nodes/ve.dm.TableNode.js M src/dm/nodes/ve.dm.TableRowNode.js M src/dm/nodes/ve.dm.TableSectionNode.js M src/dm/ve.dm.APIResultsProvider.js M src/dm/ve.dm.APIResultsQueue.js M src/dm/ve.dm.Document.js M src/dm/ve.dm.InternalList.js M src/dm/ve.dm.MetaItem.js M src/dm/ve.dm.MetaList.js M src/dm/ve.dm.Node.js M src/dm/ve.dm.Scalable.js M src/dm/ve.dm.Surface.js M src/dm/ve.dm.SurfaceSynchronizer.js M src/dm/ve.dm.TableMatrix.js M src/ve.Document.js A src/ve.EventEmitter.js M tests/index.html 21 files changed, 126 insertions(+), 81 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/27/405827/1 diff --git a/.jsduck/categories.json b/.jsduck/categories.json index a7b1fbe..bafa206 100644 --- a/.jsduck/categories.json +++ b/.jsduck/categories.json @@ -9,6 +9,7 @@ "ve.Range", "ve.PositionStep", "ve.SelectionState", + "ve.EventEmitter", "ve.EventSequencer", "ve.Filibuster", "ve.TriggerListener", diff --git a/build/modules.json b/build/modules.json index d808fa1..7ce11c2 100644 --- a/build/modules.json +++ b/build/modules.json @@ -249,6 +249,7 @@ }, "visualEditor.core.build": { "scripts": [ + "src/ve.EventEmitter.js", "src/ve.Range.js", "src/ve.SelectionState.js", "src/ve.Node.js", diff --git a/demos/ve/desktop.html b/demos/ve/desktop.html index f8dc64e..94cbd41 100644 --- a/demos/ve/desktop.html +++ b/demos/ve/desktop.html @@ -190,6 +190,7 @@ + diff --git a/demos/ve/mobile.html b/demos/ve/mobile.html index b5e6346..88aa00d 100644 --- a/demos/ve/mobile.html +++ b/demos/ve/mobile.html @@ -190,6 +190,7 @@ + diff --git a/src/dm/nodes/ve.dm.TableNode.js b/src/dm/nodes/ve.dm.TableNode.js index 64caa96..8a7ce63 100644 --- a/src/dm/nodes/ve.dm.TableNode.js +++ b/src/dm/nodes/ve.dm.TableNode.js @@ -65,7 +65,7 @@ * @fires cellAttributeChange */ ve.dm.TableNode.prototype.onCellAttributeChange = function ( cell ) { - this.emit( 'cellAttributeChange', cell ); + this.emitCatch( 'cellAttributeChange', cell ); }; /** @@ -113,14 +113,14 @@ * e.g., providing consecutive row indexes. * * @class - * @mixins OO.EventEmitter + * @mixins ve.EventEmitter * * @constructor * @param {ve.dm.TableNode} tableNode Table node to iterate through */ ve.dm.TableNodeCellIterator = function VeDmTableNodeCellIterator( tableNode ) { // Mixin constructors - OO.EventEmitter.call( this ); + ve.EventEmitter.call( this ); this.table = tableNode; @@ -141,7 +141,7 @@ /* Inheritance */ -OO.mixinClass( ve.dm.TableNodeCellIterator, OO.EventEmitter ); +OO.mixinClass( ve.dm.TableNodeCellIterator, ve.EventEmitter ); /* Events */ @@ -200,7 +200,7 @@ if ( sectionNode instanceof ve.dm.TableSectionNode ) { this.sectionNode = sectionNode; this.rowCount = this.sectionNode.children.length; - this.emit( 'newSection', this.sectionNode ); + this.emitCatch( 'newSection', this.sectionNode ); } else { this.nextSection(); return; @@ -229,7 +229,7 @@ if ( rowNode instanceof ve.dm.TableRowNode ) { this.rowNode = rowNode; this.cellCount = this.rowNode.children.length; - this.emit( 'newRow', this.rowNode ); + this.emitCatch( 'newRow', this.rowNode ); } else { this.nextRow(); return; diff --git a/src/dm/nodes/ve.dm.TableRowNode.js b/src/dm/nodes/ve.dm.TableRowNode.js index 6245b3a..758f582 100644 --- a/src/dm/nodes/ve.dm.TableRowNode.js +++ b/src/dm/nodes/ve.dm.TableRowNode.js @@ -92,7 +92,7 @@ * @fires cellAttributeChange */ ve.dm.TableRowNode.prototype.onCellAttributeChange = function ( cell ) { - this.emit( 'cellAttributeChange', cell ); + this.emitCatch( 'cellAttributeChange', cell ); }; /* Registration */ diff --git
[MediaWiki-commits] [Gerrit] mediawiki...VisualEditor[master]: Use ve.dm.MetaList without explicitly requiring metadata off...
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/405664 ) Change subject: Use ve.dm.MetaList without explicitly requiring metadata offset/index .. Use ve.dm.MetaList without explicitly requiring metadata offset/index For future compatibility with Ib5174b0dcba1c24f44d889e08140bee31a064011 . Change-Id: I15f252ce5d36bc0c38c5f5035e5176bf5e6d96e5 --- M modules/ve-mw/ui/pages/ve.ui.MWCategoriesPage.js 1 file changed, 14 insertions(+), 13 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor refs/changes/64/405664/1 diff --git a/modules/ve-mw/ui/pages/ve.ui.MWCategoriesPage.js b/modules/ve-mw/ui/pages/ve.ui.MWCategoriesPage.js index 8d277f9..c155613 100644 --- a/modules/ve-mw/ui/pages/ve.ui.MWCategoriesPage.js +++ b/modules/ve-mw/ui/pages/ve.ui.MWCategoriesPage.js @@ -107,13 +107,12 @@ * or undefined to go at the end */ ve.ui.MWCategoriesPage.prototype.onNewCategory = function ( item, beforeMetaItem ) { + var offset; + // Insert new metaList item if ( beforeMetaItem ) { - this.insertMetaListItem( - this.getCategoryItemForInsertion( item ), - beforeMetaItem.getOffset(), - beforeMetaItem.getIndex() - ); + offset = beforeMetaItem.getOffset(); + this.insertMetaListItem( this.getCategoryItemForInsertion( item ), offset ); } else { this.insertMetaListItem( this.getCategoryItemForInsertion( item ) ); } @@ -135,12 +134,12 @@ * @param {ve.dm.MetaItem} metaItem */ ve.ui.MWCategoriesPage.prototype.onMetaListInsert = function ( metaItem ) { + var index; + // Responsible for adding UI components if ( metaItem.element.type === 'mwCategory' ) { - this.categoryWidget.addItems( - [ this.getCategoryItemFromMetaListItem( metaItem ) ], - this.metaList.findItem( metaItem.getOffset(), metaItem.getIndex(), 'mwCategory' ) - ); + index = this.metaList.getItemsForGroup( 'mwCategory' ).indexOf( metaItem ); + this.categoryWidget.addItems( [ metaItem ], index ); } }; @@ -225,11 +224,13 @@ * Inserts a meta list item * * @param {Object} metaBase meta list insert object - * @param {number} [offset] Offset of the meta items within the document - * @param {number} [index] Index of the meta item within the group of meta items at this offset + * @param {number} [offset] Offset of the meta items within the document; default to document end */ -ve.ui.MWCategoriesPage.prototype.insertMetaListItem = function ( metaBase, offset, index ) { - this.metaList.insertMeta( metaBase, offset, index ); +ve.ui.MWCategoriesPage.prototype.insertMetaListItem = function ( metaBase, offset ) { + if ( arguments.length > 2 ) { + throw new Error( 'Old "index" argument is no longer supported' ); + } + this.metaList.insertMeta( metaBase, offset ); }; /** -- To view, visit https://gerrit.wikimedia.org/r/405664 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I15f252ce5d36bc0c38c5f5035e5176bf5e6d96e5 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Don't execute commands twice
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/395919 ) Change subject: Don't execute commands twice .. Don't execute commands twice Bug: T182270 Change-Id: Iecc15a744d9a4606f8e1c9a1d2641d0fe8191049 --- M src/ui/ve.ui.Tool.js 1 file changed, 10 insertions(+), 7 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/19/395919/1 diff --git a/src/ui/ve.ui.Tool.js b/src/ui/ve.ui.Tool.js index 0a63bd1..c07290c 100644 --- a/src/ui/ve.ui.Tool.js +++ b/src/ui/ve.ui.Tool.js @@ -114,7 +114,6 @@ contextClosePromise = surface.context.inspector.close().closed; } else { contextClosePromise = $.Deferred().resolve().promise(); - command.execute( surface ); } } if ( this.constructor.static.deactivateOnSelect ) { @@ -123,12 +122,16 @@ // if the promise is slow. this.setActive( false ); } - contextClosePromise.done( function () { - if ( !command.execute( surface ) ) { - // If the command fails, ensure the tool is not active - tool.setActive( false ); - } - } ); + if ( contextClosePromise ) { + // N.B. If contextClosePromise is already resolved, then the handler is called + // before the call to .done returns + contextClosePromise.done( function () { + if ( !command.execute( surface ) ) { + // If the command fails, ensure the tool is not active + tool.setActive( false ); + } + } ); + } }; /** -- To view, visit https://gerrit.wikimedia.org/r/395919 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Iecc15a744d9a4606f8e1c9a1d2641d0fe8191049 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Destroy CE nodes on removal by onSplice
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/393436 ) Change subject: Destroy CE nodes on removal by onSplice .. Destroy CE nodes on removal by onSplice Bug: T179574 Change-Id: Ic858711456bb786f0c1c9d6cfc4e26e11be283ac --- M src/ce/ve.ce.BranchNode.js 1 file changed, 2 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/36/393436/1 diff --git a/src/ce/ve.ce.BranchNode.js b/src/ce/ve.ce.BranchNode.js index b1a3131..82adcf0 100644 --- a/src/ce/ve.ce.BranchNode.js +++ b/src/ce/ve.ce.BranchNode.js @@ -203,6 +203,8 @@ removals[ i ].setLive( false ); removals[ i ].detach(); removals[ i ].$element.detach(); + // And fare thee weel a while + removals[ i ].destroy(); } if ( args.length >= 3 ) { if ( index > 0 ) { -- To view, visit https://gerrit.wikimedia.org/r/393436 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ic858711456bb786f0c1c9d6cfc4e26e11be283ac Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: WIP: [BREAKING CHANGE] Refactor ve.dm.MetaList
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/387511 ) Change subject: WIP: [BREAKING CHANGE] Refactor ve.dm.MetaList .. WIP: [BREAKING CHANGE] Refactor ve.dm.MetaList Change-Id: I3fb657ffaabec47fd0b14a54576fc957afed5cc4 --- M src/dm/ve.dm.MetaList.js M src/ve.Node.js 2 files changed, 55 insertions(+), 107 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/11/387511/1 diff --git a/src/dm/ve.dm.MetaList.js b/src/dm/ve.dm.MetaList.js index 69d3716..4e28e75 100644 --- a/src/dm/ve.dm.MetaList.js +++ b/src/dm/ve.dm.MetaList.js @@ -11,31 +11,22 @@ * @mixins OO.EventEmitter * * @constructor - * @param {ve.dm.Surface} surface Surface model + * @param {ve.dm.Document} document Document model */ -ve.dm.MetaList = function VeDmMetaList( surface ) { - var i, metadata, item; - +ve.dm.MetaList = function VeDmMetaList( document ) { // Mixin constructors OO.EventEmitter.call( this ); - // Properties - this.surface = surface; - this.document = surface.getDocument(); - // A sparse array of meta items in document order + this.document = document; + + // Sorted array of attached ve.dm.MetaItem nodes in document order this.items = []; + *** TODO: group-related stuff *** - // Event handlers - this.document.connect( this, { transact: 'onTransact' } ); - - // Populate from document - metadata = this.document.getMetadata(); - for ( i in metadata ) { - if ( Object.prototype.hasOwnProperty.call( metadata, i ) ) { - item = metadata[ i ]; - this.items[ i ] = item; - } - } + this.document.connect( this, { + nodeAttached: 'onNodeAttached', + nodeDetached: 'onNodeDetached' + } ); }; /* Inheritance */ @@ -52,100 +43,37 @@ /** * @event remove * @param {ve.dm.MetaItem} item Item that was removed - * @param {number} offset Linear model offset that the item was at */ /* Methods */ /** - * Event handler for transactions on the document. - * - * When a transaction occurs, update this list to account for it: - * - insert items for new metadata that was inserted - * - remove items for metadata that was removed - * - translate offsets and recompute indices for metadata that has shifted - * - * @param {ve.dm.Transaction} tx Transaction that was applied to the document - * @fires insert - * @fires remove + * If a ve.dm.MetaItem was attached, insert it into items in document order */ -ve.dm.MetaList.prototype.onTransact = function ( tx ) { - var i, len, op, - newPosition = 0; - for ( i = 0, len = tx.operations.length; i < len; i++ ) { - op = tx.operations[ i ]; - if ( op.type === 'retain' ) { - newPosition += op.length; - } else if ( op.type === 'replace' ) { - ve.sparseSplice( - this.items, - newPosition, - op.remove.length, - this.document.getMetadata( new ve.Range( - newPosition, - newPosition + op.insert.length - ) ) - ); - newPosition += op.insert.length; - } else if ( op.type !== 'annotate' && op.type !== 'attribute' ) { - throw new Error( 'Unknown operation type: ' + op.type ); +ve.dm.MetaList.prototype.onNodeAttached = function ( node ) { + var i, + offsetPath = node.getOffsetPath(); + if ( node instanceof ve.dm.MetaItem ) { + i = OO.binarySearch( this.items, function searchFunc( other ) { + return ve.compareTuples( + offsetPath, + other.getOffsetPath() + }, true ); + this.items.splice( i, 0, node ); + *** TODO: emit an event *** + } +}; + +/** + * If a ve.dm.MetaItem was detached, remove it from items + */ +ve.dm.MetaList.prototype.onNodeDetached = function ( node ) { + var i; + if ( node instanceof ve.dm.MetaItem ) { + i = this.items.indexOf( node ); + if ( i !== -1 ) { + this.items.splice( i, 1 ); + *** TODO: emit an event *** } } -}; - -/** - * Get the item at a given offset, if there is one. - * - * @param {number} offset Offset in the linear model - * @return {ve.dm.MetaItem|null} The item at offset, or null if not found - */ -ve.dm.MetaList.prototype.getItemAt = function ( offset ) { - return this.items[ offset ] || null; -}; - -/** - * Get all items in a group. - *
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Fix highly misleading comment
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/386974 ) Change subject: Fix highly misleading comment .. Fix highly misleading comment Change-Id: Ibb7a0a46a266253cdb096c1f5202fe16b11338f4 --- M src/ve.BranchNode.js 1 file changed, 1 insertion(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/74/386974/1 diff --git a/src/ve.BranchNode.js b/src/ve.BranchNode.js index 1e4f68a..da4e5a5 100644 --- a/src/ve.BranchNode.js +++ b/src/ve.BranchNode.js @@ -141,7 +141,7 @@ if ( doc ) { // We've set the new doc, so recurse into children, then notify the doc. // That way, at notify time, all this node's ancestors and descendants have - // the new root. + // the new doc. for ( i = 0, len = this.children.length; i < len; i++ ) { this.children[ i ].setDocument( doc ); } -- To view, visit https://gerrit.wikimedia.org/r/386974 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ibb7a0a46a266253cdb096c1f5202fe16b11338f4 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: WIP: Get a ve.ce.BranchNode position's corresponding DOM pos...
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/383404 ) Change subject: WIP: Get a ve.ce.BranchNode position's corresponding DOM position .. WIP: Get a ve.ce.BranchNode position's corresponding DOM position TODO: unit testing Change-Id: I8c9a24dc877a530c9fa421e63caf73f78d79d04c --- M src/ce/ve.ce.BranchNode.js 1 file changed, 48 insertions(+), 39 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/04/383404/1 diff --git a/src/ce/ve.ce.BranchNode.js b/src/ce/ve.ce.BranchNode.js index b1a3131..5b5b04e 100644 --- a/src/ce/ve.ce.BranchNode.js +++ b/src/ce/ve.ce.BranchNode.js @@ -174,16 +174,8 @@ * @param {...ve.dm.BranchNode} [nodes] Variadic list of nodes to insert */ ve.ce.BranchNode.prototype.onSplice = function ( index ) { - var i, j, - length, - args = [], - anchorCeNode, - prevCeNode, - anchorDomNode, - afterAnchor, - node, - parentNode, - removals; + var i, length, removals, position, j, + args = []; for ( i = 0, length = arguments.length; i < length; i++ ) { args.push( arguments[ i ] ); @@ -205,37 +197,14 @@ removals[ i ].$element.detach(); } if ( args.length >= 3 ) { - if ( index > 0 ) { - // Get the element before the insertion - anchorCeNode = this.children[ index - 1 ]; - // If the CE node is a text node, its $element will be empty - // Look at its previous sibling, which cannot be a text node - if ( anchorCeNode.getType() === 'text' ) { - prevCeNode = this.children[ index - 2 ]; - if ( prevCeNode ) { - anchorDomNode = prevCeNode.$element.last()[ 0 ].nextSibling; - } else { - anchorDomNode = this.$element[ 0 ].firstChild; - } - } else { - anchorDomNode = anchorCeNode.$element.last()[ 0 ]; - } - } + position = this.getDomPosition( index ); for ( i = args.length - 1; i >= 2; i-- ) { args[ i ].attach( this ); - if ( anchorDomNode ) { - // DOM equivalent of $( anchorDomNode ).after( args[i].$element ); - afterAnchor = anchorDomNode.nextSibling; - parentNode = anchorDomNode.parentNode; - for ( j = 0, length = args[ i ].$element.length; j < length; j++ ) { - parentNode.insertBefore( args[ i ].$element[ j ], afterAnchor ); - } - } else { - // DOM equivalent of this.$element.prepend( args[j].$element ); - node = this.$element[ 0 ]; - for ( j = args[ i ].$element.length - 1; j >= 0; j-- ) { - node.insertBefore( args[ i ].$element[ j ], node.firstChild ); - } + for ( j = 0, length = args[ i ].$element.length; j < length; j++ ) { + position.node.insertBefore( + args[ i ].$element[ j ], + position.node.children[ position.offset ] + ); } if ( this.live !== args[ i ].isLive() ) { args[ i ].setLive( this.live ); @@ -386,3 +355,43 @@ // Parent method ve.ce.BranchNode.super.prototype.destroy.call( this ); }; + +/** + * Get the DOM position (node and offset) corresponding to a position in this node + * + * @param {number} offset The offset inside this node of the required position + * @return {Object|null} position The DOM position, or null if unattached + * @return {Node} return.node DOM node; guaranteed to be this node's final DOM node + * @return {number} return.offset Offset + */ +ve.ce.BranchNode.prototype.getDomPosition = function ( offset ) { + var ceNode, domOffset, + domNode = this.$element.last()[ 0 ], + textNodeCount = 0; + while ( true ) { + offset--; + ceNode = this.children[ offset ]; + if ( !ceNode ) { + // No children with DOM nodes; return the first offset inside this + // node's DOM node. +
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Don't assume events have an originalEvent object
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/382971 ) Change subject: Don't assume events have an originalEvent object .. Don't assume events have an originalEvent object Because jQuery synthetic events do not Bug: T176104 Change-Id: I7a712480ec1afd5194a0fe8d93b14110084f2c95 --- M src/ce/ve.ce.Surface.js 1 file changed, 1 insertion(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/71/382971/1 diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js index b81f76c..66d3860 100644 --- a/src/ce/ve.ce.Surface.js +++ b/src/ce/ve.ce.Surface.js @@ -2453,7 +2453,7 @@ * @param {jQuery.Event} e The input event */ ve.ce.Surface.prototype.onDocumentInput = function ( e ) { - var inputType = e.originalEvent.inputType; + var inputType = ( e.originalEvent && e.originalEvent.inputType ); if ( inputType && inputType in this.constructor.static.inputTypeCommands ) { this.getSurface().executeCommand( this.constructor.static.inputTypeCommands[ inputType ] ); -- To view, visit https://gerrit.wikimedia.org/r/382971 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I7a712480ec1afd5194a0fe8d93b14110084f2c95 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Do not setup inline slugs when rendering is locked
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/380900 ) Change subject: Do not setup inline slugs when rendering is locked .. Do not setup inline slugs when rendering is locked Bug: T176762 Change-Id: I54ab0c936efd27657bf8ad8899c5490291b0e0bb --- M src/ce/ve.ce.ContentBranchNode.js 1 file changed, 17 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/00/380900/1 diff --git a/src/ce/ve.ce.ContentBranchNode.js b/src/ce/ve.ce.ContentBranchNode.js index 6e73bf5..cd3a292 100644 --- a/src/ce/ve.ce.ContentBranchNode.js +++ b/src/ce/ve.ce.ContentBranchNode.js @@ -161,6 +161,7 @@ */ ve.ce.ContentBranchNode.prototype.setupBlockSlugs = function () { // Respect render lock + // TODO: Can this check be moved into the parent method? if ( this.root instanceof ve.ce.DocumentNode && this.root.getSurface().isRenderingLocked() @@ -172,6 +173,22 @@ }; /** + * @inheritdoc + */ +ve.ce.ContentBranchNode.prototype.setupInlineSlugs = function () { + // Respect render lock + // TODO: Can this check be moved into the parent method? + if ( + this.root instanceof ve.ce.DocumentNode && + this.root.getSurface().isRenderingLocked() + ) { + return; + } + // Parent method + ve.ce.ContentBranchNode.super.prototype.setupInlineSlugs.apply( this, arguments ); +}; + +/** * Get an HTML rendering of the contents. * * If you are actually going to append the result to a DOM, you need to -- To view, visit https://gerrit.wikimedia.org/r/380900 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I54ab0c936efd27657bf8ad8899c5490291b0e0bb Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Make IME tests more consistent across test environments
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/380451 ) Change subject: Make IME tests more consistent across test environments .. Make IME tests more consistent across test environments Bug: T176453 Change-Id: Id6441ed82bd810de253db5c9696343da4657a7f6 --- M tests/ce/ve.ce.TestRunner.js 1 file changed, 16 insertions(+), 17 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/51/380451/1 diff --git a/tests/ce/ve.ce.TestRunner.js b/tests/ce/ve.ce.TestRunner.js index a48bacc..f1412ae 100644 --- a/tests/ce/ve.ce.TestRunner.js +++ b/tests/ce/ve.ce.TestRunner.js @@ -182,34 +182,33 @@ * @param {string} text The new text */ ve.ce.TestRunner.prototype.changeText = function ( text ) { - var focusNode, focusOffset; + var paragraph, range, textNode; // TODO: This method doesn't handle arbitrary text changes in a paragraph // with non-text nodes. It just works for the main cases that are important // in the existing IME tests. - // Store the focus before the selection gets clobbered - focusNode = this.nativeSelection.focusNode; - focusOffset = this.nativeSelection.focusOffset; - - // Empty all descendent text nodes + // Remove all descendent text nodes // This may clobber the selection, so the test had better call changeSel next. - $( this.getParagraph() ).find( '*' ).addBack().contents().each( function () { + paragraph = this.getParagraph(); + $( paragraph ).find( '*' ).addBack().contents().each( function () { if ( this.nodeType === Node.TEXT_NODE ) { - this.textContent = ''; + this.parentNode.removeChild( this ); } } ); - // Insert text at the focus - if ( focusNode === null ) { - throw new Error( 'No focus node' ); - } else if ( focusNode.nodeType === Node.TEXT_NODE ) { - focusNode.textContent = text; + range = document.createRange(); + if ( text === '' ) { + range.setStart( paragraph, 0 ); } else { - focusNode.insertBefore( - document.createTextNode( text ), - focusNode.childNodes[ focusOffset ] - ); + // Insert the text at the start of the paragraph, and put the cursor after + // the insertion, to ensure consistency across test environments. + // See T176453 + textNode = document.createTextNode( text ); + paragraph.insertBefore( textNode, paragraph.firstChild ); + range.setStart( textNode, text.length ); } + this.nativeSelection.removeAllRanges(); + this.nativeSelection.addRange( range ); this.lastText = text; }; -- To view, visit https://gerrit.wikimedia.org/r/380451 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Id6441ed82bd810de253db5c9696343da4657a7f6 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: WIP dontmerge: dummy patchset to check whether CI fails
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/379695 ) Change subject: WIP dontmerge: dummy patchset to check whether CI fails .. WIP dontmerge: dummy patchset to check whether CI fails Change-Id: I3f465d40f5be7bdfaaf438d54b9c2160a2447bd9 --- M tests/ce/imetests/backspace-chromium-ubuntu-none.js 1 file changed, 1 insertion(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/95/379695/1 diff --git a/tests/ce/imetests/backspace-chromium-ubuntu-none.js b/tests/ce/imetests/backspace-chromium-ubuntu-none.js index 46538df..ebb6f65 100644 --- a/tests/ce/imetests/backspace-chromium-ubuntu-none.js +++ b/tests/ce/imetests/backspace-chromium-ubuntu-none.js @@ -1,5 +1,5 @@ /*! - * VisualEditor IME backspace test for Chromium on Ubuntu. + * VisualEditor IME backspace test for Chromium on Ubuntu * * @copyright 2011-2017 VisualEditor Team and others; see http://ve.mit-license.org */ -- To view, visit https://gerrit.wikimedia.org/r/379695 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I3f465d40f5be7bdfaaf438d54b9c2160a2447bd9 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Setup slugs in TreeModifier
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/378378 ) Change subject: Setup slugs in TreeModifier .. Setup slugs in TreeModifier Bug: T175852 Change-Id: I9cea81cfe71d97a38e3fdf30015d8389eedde756 --- M src/ce/ve.ce.BranchNode.js M src/dm/ve.dm.BranchNode.js M src/dm/ve.dm.TreeModifier.js 3 files changed, 7 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/78/378378/1 diff --git a/src/ce/ve.ce.BranchNode.js b/src/ce/ve.ce.BranchNode.js index 9b73ac4..b1a3131 100644 --- a/src/ce/ve.ce.BranchNode.js +++ b/src/ce/ve.ce.BranchNode.js @@ -243,7 +243,9 @@ } } + // TODO: restructure to clarify the logic (exactly one of these is a no-op) this.setupBlockSlugs(); + this.setupInlineSlugs(); }; /** diff --git a/src/dm/ve.dm.BranchNode.js b/src/dm/ve.dm.BranchNode.js index a9550ad..0ea04a0 100644 --- a/src/dm/ve.dm.BranchNode.js +++ b/src/dm/ve.dm.BranchNode.js @@ -155,6 +155,8 @@ /** * Setup a sparse array of booleans indicating where to place slugs + * + * TODO: The function name is misleading: in ContentBranchNodes it sets up inline slugs */ ve.dm.BranchNode.prototype.setupBlockSlugs = function () { var i, len, diff --git a/src/dm/ve.dm.TreeModifier.js b/src/dm/ve.dm.TreeModifier.js index 2ba9b68..b0e2bce 100644 --- a/src/dm/ve.dm.TreeModifier.js +++ b/src/dm/ve.dm.TreeModifier.js @@ -649,6 +649,9 @@ */ ve.dm.TreeModifier.prototype.create = function ( data ) { var node = ve.dm.nodeFactory.createFromElement( data[ 0 ] ); + if ( node instanceof ve.dm.BranchNode ) { + node.setupBlockSlugs(); + } this.ensureNotTextNode(); this.insertNode( node, data ); }; -- To view, visit https://gerrit.wikimedia.org/r/378378 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I9cea81cfe71d97a38e3fdf30015d8389eedde756 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: ve.ce.BranchNode#splice: disconnect nodes fully
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/377510 ) Change subject: ve.ce.BranchNode#splice: disconnect nodes fully .. ve.ce.BranchNode#splice: disconnect nodes fully Change-Id: If2c549d4fefe3f5b18a5274b7b49d64eddc617b9 --- M src/ce/ve.ce.BranchNode.js 1 file changed, 1 insertion(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/10/377510/1 diff --git a/src/ce/ve.ce.BranchNode.js b/src/ce/ve.ce.BranchNode.js index 5b33564..6008b05 100644 --- a/src/ce/ve.ce.BranchNode.js +++ b/src/ce/ve.ce.BranchNode.js @@ -198,6 +198,7 @@ removals = this.children.splice.apply( this.children, args ); for ( i = 0, length = removals.length; i < length; i++ ) { removals[ i ].model.disconnect( this, { update: 'onModelUpdate' } ); + removals[ i ].model.disconnect( removals[ i ] ); removals[ i ].setLive( false ); removals[ i ].detach(); removals[ i ].$element.detach(); -- To view, visit https://gerrit.wikimedia.org/r/377510 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: If2c549d4fefe3f5b18a5274b7b49d64eddc617b9 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: WIP: Notification for DM node attached/detached
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/377237 ) Change subject: WIP: Notification for DM node attached/detached .. WIP: Notification for DM node attached/detached Change-Id: I2d42f0e3345c49417d2ec8c9d1b291f10175d938 --- M src/dm/ve.dm.Document.js M src/ve.BranchNode.js M src/ve.Document.js M src/ve.Node.js 4 files changed, 76 insertions(+), 6 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/37/377237/1 diff --git a/src/dm/ve.dm.Document.js b/src/dm/ve.dm.Document.js index 6087c9b..056e5c2 100644 --- a/src/dm/ve.dm.Document.js +++ b/src/dm/ve.dm.Document.js @@ -1697,3 +1697,17 @@ ve.dm.Document.prototype.getDir = function () { return this.dir; }; + +/** + * @inheritdoc + */ +ve.dm.Document.prototype.onNodeAttached = function ( node ) { + console.log( 'attached', node ); +}; + +/** + * @inheritdoc + */ +ve.dm.Document.prototype.onNodeDetached = function ( node ) { + console.log( 'detached', node ); +}; diff --git a/src/ve.BranchNode.js b/src/ve.BranchNode.js index 477bb4b..3ed2bd9 100644 --- a/src/ve.BranchNode.js +++ b/src/ve.BranchNode.js @@ -92,7 +92,7 @@ return; } if ( oldRoot ) { - // Null the root, then recurse into children, then emit root/unroot. + // Null the root, then recurse into children, then emit unroot. // That way, at emit time, all this node's ancestors and descendants have // null root. this.root = null; @@ -103,7 +103,7 @@ } this.root = root; if ( root ) { - // We've set the new root, so recurse into children, then emit root/unroot. + // We've set the new root, so recurse into children, then emit root. // That way, at emit time, all this node's ancestors and descendants have // the new root. for ( i = 0, len = this.children.length; i < len; i++ ) { @@ -121,14 +121,35 @@ * @param {ve.Document} doc Document this node is a part of */ ve.BranchNode.prototype.setDocument = function ( doc ) { - var i; + var i, len, + oldDoc = this.doc; if ( doc === this.doc ) { // Nothing to do, don't recurse into all descendants return; } + if ( oldDoc ) { + // Null the doc, then recurse into children, then notify the doc. + // That way, at notify time, all this node's ancestors and descendants have + // null doc. + this.doc = null; + for ( i = 0, len = this.children.length; i < len; i++ ) { + this.children[ i ].setDocument( null ); + } + if ( oldDoc.onNodeDetached ) { + oldDoc.onNodeDetached( this ); + } + } this.doc = doc; - for ( i = 0; i < this.children.length; i++ ) { - this.children[ i ].setDocument( doc ); + if ( doc ) { + // We've set the new doc, so recurse into children, then notify the doc. + // That way, at notify time, all this node's ancestors and descendants have + // the new root. + for ( i = 0, len = this.children.length; i < len; i++ ) { + this.children[ i ].setDocument( doc ); + } + if ( doc.onNodeAttached ) { + doc.onNodeAttached( this ); + } } }; diff --git a/src/ve.Document.js b/src/ve.Document.js index 5e909c4..1522813 100644 --- a/src/ve.Document.js +++ b/src/ve.Document.js @@ -563,3 +563,23 @@ var selected = this.selectNodes( range, 'leaves' ); return selected.length === 1 && selected[ 0 ].nodeRange.containsRange( range ) && selected[ 0 ].indexInNode === undefined; }; + +/** + * Callback when a node is attached with ve.Node#setDocument + * + * The node and all its children are guaranteed to be attached + * + * @method + * @param {ve.Node} node The node attached + */ +ve.Document.prototype.onNodeAttached = null; + +/** + * Callback when a node is attached with ve.Node#setDocument + * + * The node and all its children are guaranteed to be attached + * + * @method + * @param {ve.Node} node The node detached + */ +ve.Document.prototype.onNodeDetached = null; diff --git a/src/ve.Node.js b/src/ve.Node.js index 55a4031..119f3e2 100644 --- a/src/ve.Node.js +++ b/src/ve.Node.js @@ -351,10 +351,25 @@ * This method is overridden by nodes with children. * * @method - * @param {ve.Document} doc Document this node is a part of + * @param {ve.Document|null} doc Document this node is a part of */ ve.Node.prototype.setDocument = function ( doc ) { + var oldDoc = this.doc; + if ( doc === oldDoc ) { + return; + } + if (
[MediaWiki-commits] [Gerrit] mediawiki...ContentTranslation[master]: Fix crashes when placeholder replacement contains references
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/376077 ) Change subject: Fix crashes when placeholder replacement contains references .. Fix crashes when placeholder replacement contains references Bug: T175059 Change-Id: I5d368f5980bf03b9e06b295168ac3ea25ad8e972 --- M modules/ui/mw.cx.ui.TranslationView.js 1 file changed, 2 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/ContentTranslation refs/changes/77/376077/1 diff --git a/modules/ui/mw.cx.ui.TranslationView.js b/modules/ui/mw.cx.ui.TranslationView.js index 43b4edb..b346089 100644 --- a/modules/ui/mw.cx.ui.TranslationView.js +++ b/modules/ui/mw.cx.ui.TranslationView.js @@ -361,7 +361,8 @@ tx1 = ve.dm.TransactionBuilder.static.newFromRemoval( doc, pRange ); tx2 = ve.dm.TransactionBuilder.static.newFromDocumentInsertion( doc, - pRange.start, + // Position the start of tx2 at the end of tx1, to work around T175059 + pRange.end, pasteDoc, new ve.Range( 1, -- To view, visit https://gerrit.wikimedia.org/r/376077 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I5d368f5980bf03b9e06b295168ac3ea25ad8e972 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/ContentTranslation Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] mediawiki...cxserver[master]: Fix failing test
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/373864 ) Change subject: Fix failing test .. Fix failing test Change-Id: If62aa152af63fc17526cc6d836bf551cdb12e57f --- M test/adaptation/AdaptationTests.json 1 file changed, 1 insertion(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/services/cxserver refs/changes/64/373864/1 diff --git a/test/adaptation/AdaptationTests.json b/test/adaptation/AdaptationTests.json index c044c5c..d7c884c 100644 --- a/test/adaptation/AdaptationTests.json +++ b/test/adaptation/AdaptationTests.json @@ -39,7 +39,7 @@ "from": "en", "to": "es", "source": "", - "result": "" + "result": "" }, { "desc": "Category adaptation", -- To view, visit https://gerrit.wikimedia.org/r/373864 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: If62aa152af63fc17526cc6d836bf551cdb12e57f Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/services/cxserver Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Don't use eslint-config-wikimedia 0.4.0
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/371758 ) Change subject: Don't use eslint-config-wikimedia 0.4.0 .. Don't use eslint-config-wikimedia 0.4.0 It fails to let you mark code as ES6 because of a (closed) bug. Release 0.3.0 is fine and any future release will also be fine. See https://github.com/wikimedia/eslint-config-wikimedia/issues/56 Change-Id: I488cf4c83d15b0d7635265db378a4619d61a8da4 --- M package.json 1 file changed, 1 insertion(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/58/371758/1 diff --git a/package.json b/package.json index 93a5d26..582ad9b 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ } ], "devDependencies": { -"eslint-config-wikimedia": "0.4.0", +"eslint-config-wikimedia": "0.3.0", "grunt": "1.0.1", "grunt-banana-checker": "0.6.0", "grunt-contrib-clean": "1.1.0", -- To view, visit https://gerrit.wikimedia.org/r/371758 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I488cf4c83d15b0d7635265db378a4619d61a8da4 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] mediawiki...Cite[master]: Fix expected remove data to match actual remove data exactly
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/371718 ) Change subject: Fix expected remove data to match actual remove data exactly .. Fix expected remove data to match actual remove data exactly Change-Id: I0fb294265fc41015da842f7505bdedb39db7b91a --- M AUTHORS.txt M modules/ve-cite/tests/ve.dm.citeExample.js 2 files changed, 2 insertions(+), 3 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Cite refs/changes/18/371718/1 diff --git a/AUTHORS.txt b/AUTHORS.txt index 3222bac..73c7cf3 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -23,6 +23,7 @@ Chad Horohoe Daniel Cannon Danny B. +David Chan Derk-Jan Hartman Erick Guan Fomafix diff --git a/modules/ve-cite/tests/ve.dm.citeExample.js b/modules/ve-cite/tests/ve.dm.citeExample.js index a531cd4..95f7817 100644 --- a/modules/ve-cite/tests/ve.dm.citeExample.js +++ b/modules/ve-cite/tests/ve.dm.citeExample.js @@ -532,13 +532,11 @@ 'F', [ 'o', [ ve.dm.example.bold ] ], [ 'o', [ ve.dm.example.italic ] ], // 4 { type: 'mwReference', attributes: { - mw: {}, about: '#mwt1', listIndex: 0, listGroup: 'mwReference/', listKey: 'auto/0', - refGroup: '', - contentsUsed: true + refGroup: '' } }, // 5 { type: '/mwReference' }, -- To view, visit https://gerrit.wikimedia.org/r/371718 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I0fb294265fc41015da842f7505bdedb39db7b91a Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Cite Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] mediawiki...VisualEditor[master]: MWLinkAction: Don't annotate close tags
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/371717 ) Change subject: MWLinkAction: Don't annotate close tags .. MWLinkAction: Don't annotate close tags Change-Id: I273838eba4cb259cf053ce88378da10b0e241155 --- M modules/ve-mw/tests/ui/actions/ve.ui.MWLinkAction.test.js M modules/ve-mw/ui/actions/ve.ui.MWLinkAction.js M modules/ve-mw/ui/inspectors/ve.ui.MWLinkAnnotationInspector.js 3 files changed, 3 insertions(+), 8 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor refs/changes/17/371717/1 diff --git a/modules/ve-mw/tests/ui/actions/ve.ui.MWLinkAction.test.js b/modules/ve-mw/tests/ui/actions/ve.ui.MWLinkAction.test.js index 2843e8a..e074601 100644 --- a/modules/ve-mw/tests/ui/actions/ve.ui.MWLinkAction.test.js +++ b/modules/ve-mw/tests/ui/actions/ve.ui.MWLinkAction.test.js @@ -41,8 +41,7 @@ }, annotations: data[ 1 ][ 1 ] }, { - type: '/link/mwMagic', - annotations: data[ 1 ][ 1 ] + type: '/link/mwMagic' } ); }, undo: true @@ -72,8 +71,7 @@ }, annotations: data[ 1 ][ 1 ] }, { - type: '/link/mwMagic', - annotations: data[ 1 ][ 1 ] + type: '/link/mwMagic' } ); }, undo: true @@ -103,8 +101,7 @@ }, annotations: data[ 1 ][ 1 ] }, { - type: '/link/mwMagic', - annotations: data[ 1 ][ 1 ] + type: '/link/mwMagic' } ); }, undo: true diff --git a/modules/ve-mw/ui/actions/ve.ui.MWLinkAction.js b/modules/ve-mw/ui/actions/ve.ui.MWLinkAction.js index 42afe67..f71bc45 100644 --- a/modules/ve-mw/ui/actions/ve.ui.MWLinkAction.js +++ b/modules/ve-mw/ui/actions/ve.ui.MWLinkAction.js @@ -132,7 +132,6 @@ // Before we get here #autolink has guaranteed that the annotations // do not contain any link annotations. data.setAnnotationsAtOffset( 0, annotations ); - data.setAnnotationsAtOffset( 1, annotations ); return ve.dm.TransactionBuilder.static.newFromReplacement( doc, range, data.getData() ); diff --git a/modules/ve-mw/ui/inspectors/ve.ui.MWLinkAnnotationInspector.js b/modules/ve-mw/ui/inspectors/ve.ui.MWLinkAnnotationInspector.js index ba3c32b..1870e96 100644 --- a/modules/ve-mw/ui/inspectors/ve.ui.MWLinkAnnotationInspector.js +++ b/modules/ve-mw/ui/inspectors/ve.ui.MWLinkAnnotationInspector.js @@ -261,7 +261,6 @@ } ] ); data.setAnnotationsAtOffset( 0, annotations ); - data.setAnnotationsAtOffset( 1, annotations ); fragment.insertContent( data.getData(), true ); } -- To view, visit https://gerrit.wikimedia.org/r/371717 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I273838eba4cb259cf053ce88378da10b0e241155 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] mediawiki...ContentTranslation[master]: QUnit 2 compatibility fixes
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/371062 ) Change subject: QUnit 2 compatibility fixes .. QUnit 2 compatibility fixes Change-Id: I737fabe4412a20627ca7a8a60da741583c79eeba --- M tests/qunit/tools/ext.cx.tools.mtabuse.test.js M tests/qunit/translation/ext.cx.translation.loader.test.js M tests/qunit/translation/ext.cx.translation.test.js 3 files changed, 7 insertions(+), 4 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/ContentTranslation refs/changes/62/371062/1 diff --git a/tests/qunit/tools/ext.cx.tools.mtabuse.test.js b/tests/qunit/tools/ext.cx.tools.mtabuse.test.js index 0ac4ed5..c4c1c4f 100644 --- a/tests/qunit/tools/ext.cx.tools.mtabuse.test.js +++ b/tests/qunit/tools/ext.cx.tools.mtabuse.test.js @@ -10,9 +10,12 @@ QUnit.module( 'ext.cx.tools.mtabuse', QUnit.newMwEnvironment() ); - QUnit.test( 'MT Abuse - isAbuse method tests', 5, function ( assert ) { + QUnit.test( 'MT Abuse - isAbuse method tests', function ( assert ) { /* eslint new-cap:off */ var progress, mtAbuseCard = new mw.cx.tools.mtabuse(); + + assert.expect( 5 ); + progress = { any: 0, human: 0, diff --git a/tests/qunit/translation/ext.cx.translation.loader.test.js b/tests/qunit/translation/ext.cx.translation.loader.test.js index 9bfd6f6..38df40d 100644 --- a/tests/qunit/translation/ext.cx.translation.loader.test.js +++ b/tests/qunit/translation/ext.cx.translation.loader.test.js @@ -46,7 +46,7 @@ QUnit.test( 'Translation daft restore test', function ( assert ) { var i; - QUnit.expect( tests.length ); + assert.expect( tests.length ); // Without old revision flag set true, orphan sections wont get added. this.translatonLoader.originalRevision = true; for ( i = 0; i < tests.length; i++ ) { diff --git a/tests/qunit/translation/ext.cx.translation.test.js b/tests/qunit/translation/ext.cx.translation.test.js index 296ddcf..0fdeb40 100644 --- a/tests/qunit/translation/ext.cx.translation.test.js +++ b/tests/qunit/translation/ext.cx.translation.test.js @@ -10,7 +10,7 @@ QUnit.test( 'isHeading', function ( assert ) { var cxTranslation = new mw.cx.ContentTranslationEditor(); - QUnit.expect( 3 ); + assert.expect( 3 ); assert.strictEqual( cxTranslation.isHeading( 'H1' ), true ); assert.strictEqual( cxTranslation.isHeading( 'h6' ), true ); @@ -19,7 +19,7 @@ QUnit.test( 'isParentHeading', function ( assert ) { var cxTranslation = new mw.cx.ContentTranslationEditor(); - QUnit.expect( 6 ); + assert.expect( 6 ); assert.strictEqual( cxTranslation.isParentHeading( 'H1', 'DIV' ), true ); assert.strictEqual( cxTranslation.isParentHeading( 'H2', 'H3' ), true ); -- To view, visit https://gerrit.wikimedia.org/r/371062 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I737fabe4412a20627ca7a8a60da741583c79eeba Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/ContentTranslation Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] mediawiki...cxserver[master]: WIP: Avoid segmenting within certain types of tag
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/370869 ) Change subject: WIP: Avoid segmenting within certain types of tag .. WIP: Avoid segmenting within certain types of tag To avoid adding spans in places that violate the MediaWiki DOM spec https://www.mediawiki.org/wiki/Specs/HTML/1.4.0#Images Change-Id: I7d25b5996876951f675cdf4b797dbb1371a0d16e --- M config.dev.yaml M lib/lineardoc/Builder.js M lib/lineardoc/Doc.js M lib/lineardoc/Parser.js M lib/lineardoc/TextBlock.js M lib/routes/v1.js M lib/translationunits/MWImage.js 7 files changed, 60 insertions(+), 17 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/services/cxserver refs/changes/69/370869/1 diff --git a/config.dev.yaml b/config.dev.yaml index f171eef..0962b13 100644 --- a/config.dev.yaml +++ b/config.dev.yaml @@ -61,7 +61,7 @@ mt: # Apertium web API URL apertium: - api: http://apertium.wmflabs.org + api: http://localhost:2737 yandex: api: https://translate.yandex.net key: null diff --git a/lib/lineardoc/Builder.js b/lib/lineardoc/Builder.js index 57d69f8..7097d2d 100644 --- a/lib/lineardoc/Builder.js +++ b/lib/lineardoc/Builder.js @@ -22,6 +22,7 @@ this.doc = new Doc( wrapperTag || null ); this.textChunks = []; this.parent = parent || null; + this.noSegmentBlock = false; } Builder.prototype.createChildBuilder = function ( wrapperTag ) { @@ -109,9 +110,12 @@ return tag; }; -Builder.prototype.addTextChunk = function ( text ) { +Builder.prototype.addTextChunk = function ( text, noSegment ) { this.textChunks.push( new TextChunk( text, this.inlineAnnotationTags.slice() ) ); this.inlineAnnotationTagsUsed = this.inlineAnnotationTags.length; + if ( noSegment ) { + this.noSegmentBlock = true; + } }; /** @@ -119,10 +123,14 @@ * * @method * @param {Object} content Sub-document or empty SAX tag + * @param {boolean} noSegment */ -Builder.prototype.addInlineContent = function ( content ) { +Builder.prototype.addInlineContent = function ( content, noSegment ) { this.textChunks.push( new TextChunk( '', this.inlineAnnotationTags.slice(), content ) ); this.inlineAnnotationTagsUsed = this.inlineAnnotationTags.length; + if ( noSegment ) { + this.noSegmentBlock = true; + } }; Builder.prototype.finishTextBlock = function () { @@ -145,7 +153,7 @@ if ( whitespaceOnly ) { this.doc.addItem( 'blockspace', whitespace.join( '' ) ); } else { - this.doc.addItem( 'textblock', new TextBlock( this.textChunks ) ); + this.doc.addItem( 'textblock', new TextBlock( this.textChunks, this.noSegmentBlock ) ); } this.textChunks = []; }; diff --git a/lib/lineardoc/Doc.js b/lib/lineardoc/Doc.js index e9f4157..5240cd3 100644 --- a/lib/lineardoc/Doc.js +++ b/lib/lineardoc/Doc.js @@ -122,7 +122,7 @@ textBlock = item.item; newDoc.addItem( 'textblock', - textBlock.segment( getBoundaries, getNextId ) + textBlock.noSegment ? textBlock : textBlock.segment( getBoundaries, getNextId ) ); } } diff --git a/lib/lineardoc/Parser.js b/lib/lineardoc/Parser.js index beb4c80..96ad429 100644 --- a/lib/lineardoc/Parser.js +++ b/lib/lineardoc/Parser.js @@ -4,7 +4,9 @@ Builder = require( './Builder.js' ), Utils = require( './Utils.js' ), util = require( 'util' ), - blockTags; + blockTags, + relBlacklist, + relWhitelist; blockTags = [ 'html', 'head', 'body', 'script', @@ -33,6 +35,26 @@ 'img', 'br' ]; +relBlacklist = [ /^mw:/ ]; + +relWhitelist = [ 'mw:Entity', 'mw:ExtLink', 'mw:MediaLink', 'mw:WikiLink', 'mw:referencedBy' ]; + +function matches( patterns, text ) { + return patterns.filter( function ( pattern ) { + return typeof pattern === 'string' ? + text.indexOf( pattern ) > -1 : + pattern.exec( text ); + } ).length > 0; +}; + +function isBlacklisted( tag ) { + var attr = tag.attributes.typeof || tag.attributes.rel; + if ( !attr ) { + return false; + } + return matches( relBlacklist, attr ) && !matches( relWhitelist, attr ); +} + /** * Parser to read an HTML stream into a Doc * @@ -53,6 +75,9 @@ Parser.prototype.init = function () { this.rootBuilder = new Builder(); this.builder = this.rootBuilder; + // Number of currently open tags within which translation should not occur + this.allTags = []; + this.noSegmentTags = 0; }; Parser.prototype.onopentag = function ( tag ) { @@ -68,21
[MediaWiki-commits] [Gerrit] mediawiki...VisualEditor[master]: Expose ve.ui.MWInternalLinkContextItem generateBody logic
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/370823 ) Change subject: Expose ve.ui.MWInternalLinkContextItem generateBody logic .. Expose ve.ui.MWInternalLinkContextItem generateBody logic Change-Id: I94912ac2c471cc5d227fa8b9cb29c302ca29814d --- M modules/ve-mw/ui/contextitems/ve.ui.MWInternalLinkContextItem.js 1 file changed, 31 insertions(+), 18 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor refs/changes/23/370823/1 diff --git a/modules/ve-mw/ui/contextitems/ve.ui.MWInternalLinkContextItem.js b/modules/ve-mw/ui/contextitems/ve.ui.MWInternalLinkContextItem.js index 03072ef..7170feb 100644 --- a/modules/ve-mw/ui/contextitems/ve.ui.MWInternalLinkContextItem.js +++ b/modules/ve-mw/ui/contextitems/ve.ui.MWInternalLinkContextItem.js @@ -33,35 +33,26 @@ ve.ui.MWInternalLinkContextItem.static.modelClasses = [ ve.dm.MWInternalLinkAnnotation ]; -/* Methods */ +/* Static methods */ /** - * @inheritdoc + * Render */ -ve.ui.MWInternalLinkContextItem.prototype.getDescription = function () { - return this.model.getAttribute( 'normalizedTitle' ); -}; - -/** - * @inheritdoc - */ -ve.ui.MWInternalLinkContextItem.prototype.renderBody = function () { +ve.ui.MWInternalLinkContextItem.static.generateBody = function ( linkCache, title, htmlDoc, description, href, fragment ) { var icon, $description, usePageImages = mw.config.get( 'wgVisualEditor' ).usePageImages, usePageDescriptions = mw.config.get( 'wgVisualEditor' ).usePageDescriptions, - title = this.model.getAttribute( 'lookupTitle' ), - htmlDoc = this.context.getSurface().getModel().getDocument().getHtmlDocument(), $wrapper = $( '' ), $link = $( '' ) .addClass( 've-ui-mwInternalLinkContextItem-link' ) - .text( this.getDescription() ) + .text( description ) .attr( { - href: ve.resolveUrl( this.model.getHref(), htmlDoc ), + href: ve.resolveUrl( href, htmlDoc ), target: '_blank' } ); // Style based on link cache information - ve.init.platform.linkCache.styleElement( title, $link, this.model.getFragment() ); + ve.init.platform.linkCache.styleElement( title, $link, fragment ); // Don't style as a self-link in the context menu (but do elsewhere) $link.removeClass( 'mw-selflink' ); @@ -78,10 +69,8 @@ $wrapper.addClass( 've-ui-mwInternalLinkContextItem-withDescription' ); } - this.$body.empty().append( $wrapper ); - if ( usePageImages || usePageDescriptions ) { - ve.init.platform.linkCache.get( title ).then( function ( linkData ) { + linkCache.get( title ).then( function ( linkData ) { if ( usePageImages ) { if ( linkData.imageUrl ) { icon.$element @@ -99,6 +88,30 @@ } } ); } + return $wrapper; +}; + +/* Methods */ + +/** + * @inheritdoc + */ +ve.ui.MWInternalLinkContextItem.prototype.getDescription = function () { + return this.model.getAttribute( 'normalizedTitle' ); +}; + +/** + * @inheritdoc + */ +ve.ui.MWInternalLinkContextItem.prototype.renderBody = function () { + this.$body.empty().append( this.constructor.static.generateBody( + ve.init.platform.linkCache, + this.model.getAttribute( 'lookupTitle' ), + this.context.getSurface().getModel().getDocument().getHtmlDocument(), + this.getDescription(), + this.model.getHref(), + this.model.getFragment() + ) ); }; /* Registration */ -- To view, visit https://gerrit.wikimedia.org/r/370823 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I94912ac2c471cc5d227fa8b9cb29c302ca29814d Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] mediawiki...VisualEditor[master]: WIP: Miscellaneous support for ContentTranslation
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/363521 ) Change subject: WIP: Miscellaneous support for ContentTranslation .. WIP: Miscellaneous support for ContentTranslation Change-Id: Ib14ab6878cffeabafe513e8416451b36c63915d8 --- M extension.json M modules/ve-mw/dm/nodes/ve.dm.MWBlockImageNode.js M modules/ve-mw/ui/contextitems/ve.ui.MWInternalLinkContextItem.js 3 files changed, 64 insertions(+), 26 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor refs/changes/21/363521/1 diff --git a/extension.json b/extension.json index 8fa97dd..ae73e93 100644 --- a/extension.json +++ b/extension.json @@ -259,6 +259,26 @@ "mobile" ] }, + "ext.visualEditor.mwembed": { + "dependencies": [ + "ext.visualEditor.mwcore", + "ext.visualEditor.change", + "ext.visualEditor.mwlink", + "ext.visualEditor.mwformatting", + "ext.visualEditor.data", + "ext.visualEditor.mwtransclusion", + "ext.visualEditor.mwgallery", + "ext.visualEditor.mwalienextension", + "ext.visualEditor.language", + "ext.visualEditor.icons", + "ext.visualEditor.mwimage", + "ext.visualEditor.mwmeta", + "ext.visualEditor.base", + "ext.visualEditor.mediawiki", + "ext.visualEditor.core.desktop", + "ext.visualEditor.desktopArticleTarget" + ] + }, "ext.visualEditor.supportCheck": { "scripts": "lib/ve/src/init/ve.init.SupportCheck.js", "targets": [ @@ -679,6 +699,7 @@ "lib/ve/src/ce/keydownhandlers/ve.ce.TableEnterKeyDownHandler.js", "lib/ve/src/ce/keydownhandlers/ve.ce.LinearTabKeyDownHandler.js", "lib/ve/src/ce/nodes/ve.ce.GeneratedContentNode.js", + "lib/ve/src/ce/nodes/ve.ce.ContentEditableNode.js", "lib/ve/src/ce/nodes/ve.ce.ActiveNode.js", "lib/ve/src/ce/nodes/ve.ce.AlienNode.js", "lib/ve/src/ce/nodes/ve.ce.ArticleNode.js", @@ -1045,6 +1066,14 @@ "mobile" ] }, + "ext.visualEditor.change": { + "scripts": [ + "lib/ve/src/dm/ve.dm.Change.js" + ], + "dependencies": [ + "ext.visualEditor.core" + ] + }, "ext.visualEditor.core.desktop": { "scripts": [ "lib/ve/src/ui/contexts/ve.ui.DesktopContext.js", diff --git a/modules/ve-mw/dm/nodes/ve.dm.MWBlockImageNode.js b/modules/ve-mw/dm/nodes/ve.dm.MWBlockImageNode.js index a93cad7..1914029 100644 --- a/modules/ve-mw/dm/nodes/ve.dm.MWBlockImageNode.js +++ b/modules/ve-mw/dm/nodes/ve.dm.MWBlockImageNode.js @@ -93,7 +93,7 @@ figure = domElements[ 0 ]; imgWrapper = findChildren( figure, [ 'a', 'span' ] )[ 0 ] || null; - img = imgWrapper && findChildren( imgWrapper, [ 'img' ] )[ 0 ] || null; + img = imgWrapper && imgWrapper.getElementsByTagName( 'img' )[ 0 ] || null; caption = findChildren( figure, [ 'figcaption' ] )[ 0 ] || null; classAttr = figure.getAttribute( 'class' ); typeofAttrs = figure.getAttribute( 'typeof' ).split( ' ' ); diff --git a/modules/ve-mw/ui/contextitems/ve.ui.MWInternalLinkContextItem.js b/modules/ve-mw/ui/contextitems/ve.ui.MWInternalLinkContextItem.js index 2020158..7d64953 100644 --- a/modules/ve-mw/ui/contextitems/ve.ui.MWInternalLinkContextItem.js +++ b/modules/ve-mw/ui/contextitems/ve.ui.MWInternalLinkContextItem.js @@ -27,41 +27,26 @@ OO.inheritClass( ve.ui.MWInternalLinkContextItem, ve.ui.LinkContextItem ); -/* Static Properties */ +/* Static properties */ ve.ui.MWInternalLinkContextItem.static.name = 'link/internal'; ve.ui.MWInternalLinkContextItem.static.modelClasses = [ ve.dm.MWInternalLinkAnnotation ]; -/* Methods */ +/* Static methods */ -/** - * @inheritdoc - */ -ve.ui.MWInternalLinkContextItem.prototype.getDescription = function () { - return this.model.getAttribute( 'normalizedTitle' ); -}; - -/** - * @inheritdoc - */
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: TransactionProcessor: modify DM tree branches instead of reb...
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/357171 ) Change subject: TransactionProcessor: modify DM tree branches instead of rebuilding them .. TransactionProcessor: modify DM tree branches instead of rebuilding them This re-applies reverted commit 6c915f3055433fb62e0d413c115ea6036523b530. Bug: T165965 Change-Id: I6e98c8f1197dadbb037eeb3f9176bc47703f62c5 --- M .jsduck/categories.json M build/modules.json M demos/ve/desktop.html M demos/ve/mobile.html M src/dm/ve.dm.TransactionProcessor.js A src/dm/ve.dm.TreeCursor.js A src/dm/ve.dm.TreeModifier.js M tests/dm/ve.dm.RebaseServer.test.js M tests/dm/ve.dm.TransactionProcessor.test.js A tests/dm/ve.dm.TreeModifier.test.js M tests/index.html 11 files changed, 884 insertions(+), 129 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/71/357171/1 diff --git a/.jsduck/categories.json b/.jsduck/categories.json index f5f5ade..9d8e149 100644 --- a/.jsduck/categories.json +++ b/.jsduck/categories.json @@ -63,6 +63,8 @@ "ve.dm.*Selection", "ve.dm.Transaction", "ve.dm.TransactionBuilder", + "ve.dm.TreeCursor", + "ve.dm.TreeModifier", "ve.dm.TransactionProcessor", "ve.dm.TransactionProcessor.*" ] diff --git a/build/modules.json b/build/modules.json index dd14f92..6bde720 100644 --- a/build/modules.json +++ b/build/modules.json @@ -287,6 +287,8 @@ "src/dm/ve.dm.TransactionProcessor.js", "src/dm/ve.dm.Transaction.js", "src/dm/ve.dm.TransactionBuilder.js", + "src/dm/ve.dm.TreeCursor.js", + "src/dm/ve.dm.TreeModifier.js", "src/dm/ve.dm.Selection.js", "src/dm/ve.dm.Surface.js", "src/dm/ve.dm.SurfaceFragment.js", @@ -692,6 +694,7 @@ "tests/dm/ve.dm.TestRebaseClient.js", "tests/dm/ve.dm.TestRebaseServer.js", "tests/dm/ve.dm.RebaseServer.test.js", + "tests/dm/ve.dm.TreeModifier.test.js", "tests/dm/ve.dm.TransactionProcessor.test.js", "tests/dm/ve.dm.APIResultsQueue.test.js", "tests/dm/ve.dm.Surface.test.js", diff --git a/demos/ve/desktop.html b/demos/ve/desktop.html index 9da9ba0..5f95793 100644 --- a/demos/ve/desktop.html +++ b/demos/ve/desktop.html @@ -228,6 +228,8 @@ + + diff --git a/demos/ve/mobile.html b/demos/ve/mobile.html index dc4291f..2e140d3 100644 --- a/demos/ve/mobile.html +++ b/demos/ve/mobile.html @@ -228,6 +228,8 @@ + + diff --git a/src/dm/ve.dm.TransactionProcessor.js b/src/dm/ve.dm.TransactionProcessor.js index 4cdfb0f..6e6209e 100644 --- a/src/dm/ve.dm.TransactionProcessor.js +++ b/src/dm/ve.dm.TransactionProcessor.js @@ -47,6 +47,7 @@ this.replaceMinInsertLevel = 0; this.retainDepth = 0; this.replaceSpliceQueue = []; + this.treeModifier = null; }; /* Static members */ @@ -84,6 +85,9 @@ ve.dm.TransactionProcessor.prototype.process = function () { var i, completed; + // Ensure the pre-modification document tree has been generated + this.document.getDocumentNode(); + // First process each operation to gather modifications in the modification queue. // If an exception occurs during this stage, we don't need to do anything to recover, // because no modifications were made yet. @@ -98,6 +102,8 @@ try { completed = false; this.applyModifications(); + this.treeModifier = new ve.dm.TreeModifier( this.document, this.transaction ); + this.treeModifier.process(); this.queueAnnotateEvents(); completed = true; } finally { @@ -345,19 +351,14 @@ * {number} splices[].offset Offset to remove/insert at (unadjusted) * {number} splices[].removeLength Number of elements to remove * {Array} splices[].insert Data to insert; for efficiency, objects are inserted without cloning - * @param {number} splitAncestorLevel How many levels of ancestors were split (closed by inserted data) - * For example, if inserting `` splitAncestorLevel=1, and if inserting `` - * splitAncestorLevel=3 */
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: WIP: Fixes to TreeModifier
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/355605 ) Change subject: WIP: Fixes to TreeModifier .. WIP: Fixes to TreeModifier TODO: * Decide what to do about the metadata failures * Un-revert TreeModifier and rebase this on top Change-Id: Id5872ff94ac996e5d32c46b1841747a8c74505ba --- M src/dm/ve.dm.TransactionProcessor.js M src/dm/ve.dm.TreeCursor.js M src/dm/ve.dm.TreeModifier.js M tests/dm/ve.dm.TreeModifier.test.js 4 files changed, 244 insertions(+), 84 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/05/355605/1 diff --git a/src/dm/ve.dm.TransactionProcessor.js b/src/dm/ve.dm.TransactionProcessor.js index 6e6209e..a6ed924 100644 --- a/src/dm/ve.dm.TransactionProcessor.js +++ b/src/dm/ve.dm.TransactionProcessor.js @@ -101,6 +101,7 @@ // Apply the queued modifications try { completed = false; + this.treeModifier = null; this.applyModifications(); this.treeModifier = new ve.dm.TreeModifier( this.document, this.transaction ); this.treeModifier.process(); @@ -110,6 +111,9 @@ // Don't catch and re-throw errors so that they are reported properly if ( !completed ) { // Restore the linear model to its original state + if ( this.treeModifier ) { + this.treeModifier.undoLinearSplices(); + } this.rollbackModifications(); // The tree may have been left in some sort of half-baked state, so rebuild it // from scratch @@ -689,10 +693,10 @@ if ( this.replaceRemoveLevel === 0 && this.replaceInsertLevel === 0 && this.retainDepth === 0 ) { // Things are balanced again, flush the queue - this.queueModification( { - type: 'splice', - args: [ this.replaceSpliceQueue, -this.replaceMinInsertLevel ] - } ); + // this.queueModification( { + // type: 'splice', + // args: [ this.replaceSpliceQueue, -this.replaceMinInsertLevel ] + // } ); this.replaceSpliceQueue = []; this.replaceMinInsertLevel = 0; } diff --git a/src/dm/ve.dm.TreeCursor.js b/src/dm/ve.dm.TreeCursor.js index 20a38f1..90f78cb 100644 --- a/src/dm/ve.dm.TreeCursor.js +++ b/src/dm/ve.dm.TreeCursor.js @@ -15,8 +15,9 @@ * @constructor * @param {ve.dm.Node} root A document node or a branch root within which to walk * @param {ve.dm.Node[]} liveIgnoreNodes Live array of nodes to ignore (cross without counting) + * @param {number} [linearOffset] The first linear model offset inside root; default 0 */ -ve.dm.TreeCursor = function VeDmTreeCursor( root, liveIgnoreNodes ) { +ve.dm.TreeCursor = function VeDmTreeCursor( root, liveIgnoreNodes, linearOffset ) { this.root = root; this.liveIgnoreNodes = liveIgnoreNodes; this.path = []; @@ -24,6 +25,10 @@ this.nodes = [ root ]; this.node = root; this.lastStep = null; + if ( linearOffset === undefined ) { + linearOffset = 0; + } + this.linearOffset = linearOffset; }; /* Inheritance */ @@ -60,6 +65,7 @@ this.liveIgnoreNodes.indexOf( item ) !== -1 ) { this.offset++; + this.linearOffset += item.getOuterLength(); } // If at the start of long enough text node, step in if ( @@ -72,6 +78,27 @@ this.nodes.push( item ); this.path.push( this.offset ); this.offset = 0; + } +}; + +ve.dm.TreeCursor.prototype.checkLinearOffset = function () { + var expected = this.node.getOffset(); + if ( this.node instanceof ve.dm.TextNode ) { + expected += this.offset; + } else { + if ( this.node !== this.root ) { + // Add 1 for the open tag + expected += 1; + } + if ( this.node.hasChildren() ) { + // Add the outer length of each crossed child + this.node.children.slice( 0, this.offset ).forEach( function ( child ) { + expected += child.getOuterLength(); + } ); + } + } + if ( expected !== this.linearOffset ) { + throw new Error( 'Linear offset does not match tree position' ); } }; @@ -99,6 +126,7 @@ this.lastStep = undefined; return undefined; } + this.checkLinearOffset(); this.normalize( maxLength ); if ( this.node instanceof ve.dm.TextNode ) { // We
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Tree modifications: don't presume the tree is in sync with t...
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/354888 ) Change subject: Tree modifications: don't presume the tree is in sync with the linear model .. Tree modifications: don't presume the tree is in sync with the linear model Change-Id: Ia79e9a393309b1dec024869f15b19218f463fd7d --- M src/ce/ve.ce.ContentBranchNode.js M tests/ce/ve.ce.Surface.test.js 2 files changed, 19 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/88/354888/1 diff --git a/src/ce/ve.ce.ContentBranchNode.js b/src/ce/ve.ce.ContentBranchNode.js index 6e73bf5..8c19362 100644 --- a/src/ce/ve.ce.ContentBranchNode.js +++ b/src/ce/ve.ce.ContentBranchNode.js @@ -335,6 +335,9 @@ unicornInfo.unicorns = null; } } else { + if ( item.length === undefined ) { + throw new Error( 'Unexpected item type' ); + } if ( buffer !== '' ) { current.appendChild( doc.createTextNode( buffer ) ); buffer = ''; diff --git a/tests/ce/ve.ce.Surface.test.js b/tests/ce/ve.ce.Surface.test.js index cb53164..fd78f8a 100644 --- a/tests/ce/ve.ce.Surface.test.js +++ b/tests/ce/ve.ce.Surface.test.js @@ -179,6 +179,22 @@ this.preventDefault = this.stopPropagation = function () {}; }; +QUnit.test( 'Transaction with two removals in the same CBN', function ( assert ) { + var tx, + view = ve.test.utils.createSurfaceViewFromHtml( 'abcdefghijklmnopx' ), + doc = view.model.documentModel, + txBuilder = new ve.dm.TransactionBuilder(); + + txBuilder.pushRetain( 1 ); + txBuilder.pushReplace( doc, 1, 3, [] ); + txBuilder.pushRetain( 4 ); + txBuilder.pushReplace( doc, 8, 11, [] ); + txBuilder.pushRetain( 4 ); + tx = txBuilder.getTransaction(); + view.model.change( tx ); + assert.ok( true, 'No crash' ); +} ); + QUnit.test( 'special key down: backspace/delete', function ( assert ) { var i, emptyList = '', -- To view, visit https://gerrit.wikimedia.org/r/354888 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ia79e9a393309b1dec024869f15b19218f463fd7d Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: rebaseUncommittedChange: remove weird duplicated selection u...
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/354692 ) Change subject: rebaseUncommittedChange: remove weird duplicated selection update code .. rebaseUncommittedChange: remove weird duplicated selection update code Change-Id: I18699ae0e469a126a344789b3e704f529db594b7 --- M src/dm/ve.dm.Change.js 1 file changed, 0 insertions(+), 9 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/92/354692/1 diff --git a/src/dm/ve.dm.Change.js b/src/dm/ve.dm.Change.js index 63b1e8f..c867305 100644 --- a/src/dm/ve.dm.Change.js +++ b/src/dm/ve.dm.Change.js @@ -389,11 +389,6 @@ throw new Error( 'Different starts: ' + history.start + ' and ' + uncommitted.start ); } - for ( author in selectionsB ) { - author = parseInt( author ); - delete selectionsA[ author ]; - selectionsB[ author ] = selectionsB[ author ].translateByChange( history, author ); - } // For each element b_i of transactionsB, rebase the whole list transactionsA over b_i. // To rebase a1, a2, a3, ..., aN over b_i, first we rebase a1 onto b_i. Then we rebase // a2 onto some b', defined as @@ -445,10 +440,6 @@ } // Length calculations below assume no removal of empty rebased transactions - for ( author in selectionsB ) { - author = parseInt( author ); - selectionsB[ author ] = selectionsB[ author ].translateByChange( history, author ); - } rebased = new ve.dm.Change( uncommitted.start + transactionsA.length, transactionsB, -- To view, visit https://gerrit.wikimedia.org/r/354692 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I18699ae0e469a126a344789b3e704f529db594b7 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: ve.dm.SurfaceFragment#delete: Don't pre-build a sequence of ...
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/353994 ) Change subject: ve.dm.SurfaceFragment#delete: Don't pre-build a sequence of transactions .. ve.dm.SurfaceFragment#delete: Don't pre-build a sequence of transactions Change-Id: I1c79815d733b6fc5436325762410f5f301b5d382 --- M src/dm/ve.dm.SurfaceFragment.js M tests/ce/ve.ce.Surface.test.js 2 files changed, 7 insertions(+), 9 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/94/353994/1 diff --git a/src/dm/ve.dm.SurfaceFragment.js b/src/dm/ve.dm.SurfaceFragment.js index c9d4a71..7d2c97b 100644 --- a/src/dm/ve.dm.SurfaceFragment.js +++ b/src/dm/ve.dm.SurfaceFragment.js @@ -1005,14 +1005,12 @@ ); if ( !tx.isNoOp() ) { // Move contents of endNode into startNode, and delete nodeToDelete - this.change( [ - tx, - ve.dm.TransactionBuilder.static.newFromInsertion( - this.document, - rangeAfterRemove.start, - endNodeData - ) - ] ); + this.change( tx ); + this.change( ve.dm.TransactionBuilder.static.newFromInsertion( + this.document, + rangeAfterRemove.start, + endNodeData + ) ); } } } diff --git a/tests/ce/ve.ce.Surface.test.js b/tests/ce/ve.ce.Surface.test.js index bb94d34..a6051ba 100644 --- a/tests/ce/ve.ce.Surface.test.js +++ b/tests/ce/ve.ce.Surface.test.js @@ -378,7 +378,7 @@ expectedData: function ( data ) { var paragraph = data.splice( 14, 5 ); data.splice( 13, 2 ); // remove the empty listItem - data.splice.apply( data, [ 14, 0 ].concat( paragraph, { type: 'list', attributes: { style: 'bullet' } }, { type: '/list' } ) ); + data.splice.apply( data, [ 14, 0 ].concat( paragraph ) ); }, expectedRangeOrSelection: new ve.Range( 15 ), msg: 'Non-empty multi-item list at end of document unwrapped by delete' -- To view, visit https://gerrit.wikimedia.org/r/353994 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I1c79815d733b6fc5436325762410f5f301b5d382 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Process transaction before selecting nodes for annotation ev...
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/353830 ) Change subject: Process transaction before selecting nodes for annotation events .. Process transaction before selecting nodes for annotation events Change-Id: I459bceba9651540aa1e65a69e60ab26cb17784b5 --- M src/dm/ve.dm.TransactionProcessor.js 1 file changed, 19 insertions(+), 21 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/30/353830/1 diff --git a/src/dm/ve.dm.TransactionProcessor.js b/src/dm/ve.dm.TransactionProcessor.js index 8ec0744..4cdfb0f 100644 --- a/src/dm/ve.dm.TransactionProcessor.js +++ b/src/dm/ve.dm.TransactionProcessor.js @@ -40,6 +40,7 @@ // inserted or retained. this.set = new ve.dm.AnnotationSet( this.document.getStore() ); this.clear = new ve.dm.AnnotationSet( this.document.getStore() ); + this.annotatedRanges = []; // State tracking for unbalanced replace operations this.replaceRemoveLevel = 0; this.replaceInsertLevel = 0; @@ -97,6 +98,7 @@ try { completed = false; this.applyModifications(); + this.queueAnnotateEvents(); completed = true; } finally { // Don't catch and re-throw errors so that they are reported properly @@ -298,12 +300,24 @@ } ); } } - // Queue a "modification" that emits annotate events if ( this.cursor < to ) { - this.queueModification( { - type: 'emitAnnotate', - args: [ new ve.Range( this.cursor, to ) ] - } ); + this.annotatedRanges.push( new ve.Range( this.cursor, to ) ); + } +}; + +/** + * Queue annotate and update events on all leaf nodes whose annotations have changed + */ +ve.dm.TransactionProcessor.prototype.queueAnnotateEvents = function () { + var i, iLen, range, j, jLen, selection, node; + for ( i = 0, iLen = this.annotatedRanges.length; i < iLen; i++ ) { + range = this.transaction.translateRange( this.annotatedRanges[ i ] ); + selection = this.document.selectNodes( range, 'leaves' ); + for ( j = 0, jLen = selection.length; j < jLen; j++ ) { + node = selection[ j ].node; + this.queueEvent( node, 'annotation' ); + this.queueEvent( node, 'update', this.isStaging ); + } } }; @@ -553,22 +567,6 @@ this.queueUndoFunction( function () { metadata.setAnnotationsAtOffsetAndIndex( offset, index, oldAnnotations ); } ); -}; - -/** - * Emit annotate and update events on all leaf nodes in the given range. - * - * @param {ve.Range} range Range that was annotated (unadjusted) - */ -ve.dm.TransactionProcessor.modifiers.emitAnnotate = function ( range ) { - var i, selection; - range = range.translate( this.adjustment ); - - selection = this.document.selectNodes( range, 'leaves' ); - for ( i = 0; i < selection.length; i++ ) { - this.queueEvent( selection[ i ].node, 'annotation' ); - this.queueEvent( selection[ i ].node, 'update', this.isStaging ); - } }; /** -- To view, visit https://gerrit.wikimedia.org/r/353830 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I459bceba9651540aa1e65a69e60ab26cb17784b5 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: WIP: Restructure DM tree instead of rebuilding it afresh
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/348450 ) Change subject: WIP: Restructure DM tree instead of rebuilding it afresh .. WIP: Restructure DM tree instead of rebuilding it afresh TODO: Loads of stuff Bug: T162762 Change-Id: I22d32e7f3a3afb176367f2163acb4c123e8f0ee0 --- M build/modules.json M demos/ve/desktop.html M demos/ve/mobile.html A src/dm/ve.dm.TreeModifier.js A tests/dm/ve.dm.TreeModifier.test.js M tests/index.html 6 files changed, 520 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/50/348450/1 diff --git a/build/modules.json b/build/modules.json index 62a8dfe..64dd1d7 100644 --- a/build/modules.json +++ b/build/modules.json @@ -281,6 +281,7 @@ "src/dm/ve.dm.TransactionProcessor.js", "src/dm/ve.dm.Transaction.js", "src/dm/ve.dm.TransactionBuilder.js", + "src/dm/ve.dm.TreeModifier.js", "src/dm/ve.dm.Selection.js", "src/dm/ve.dm.Surface.js", "src/dm/ve.dm.SurfaceFragment.js", @@ -677,6 +678,7 @@ "tests/dm/ve.dm.TransactionBuilder.test.js", "tests/dm/ve.dm.Change.test.js", "tests/dm/ve.dm.RebaseServer.test.js", + "tests/dm/ve.dm.TreeModifier.test.js", "tests/dm/ve.dm.TransactionProcessor.test.js", "tests/dm/ve.dm.APIResultsQueue.test.js", "tests/dm/ve.dm.Surface.test.js", diff --git a/demos/ve/desktop.html b/demos/ve/desktop.html index 684a76f..f82dbdd 100644 --- a/demos/ve/desktop.html +++ b/demos/ve/desktop.html @@ -219,6 +219,7 @@ + diff --git a/demos/ve/mobile.html b/demos/ve/mobile.html index f5da8a3..f5955b9 100644 --- a/demos/ve/mobile.html +++ b/demos/ve/mobile.html @@ -219,6 +219,7 @@ + diff --git a/src/dm/ve.dm.TreeModifier.js b/src/dm/ve.dm.TreeModifier.js new file mode 100644 index 000..2fb6739 --- /dev/null +++ b/src/dm/ve.dm.TreeModifier.js @@ -0,0 +1,434 @@ +/*! + * VisualEditor DataModel TreeCursor class + * + * @copyright 2011-2017 VisualEditor Team and others; see http://ve.mit-license.org + */ + +/** + * DataModel TreeCursor - a tree walker that tracks the path to the current position. + * + * @class + * + * @constructor + * @param {ve.dm.Node} root A document node or a branch root within which to walk + */ +ve.dm.TreeCursor = function VeDmTreeCursor( root ) { + this.path = []; + this.offset = 0; + this.nodes = [ root ]; + this.node = root; + this.lastStep = null; +}; + +/* Inheritance */ + +OO.initClass( ve.dm.TreeCursor ); + +/* Static Methods */ + +ve.dm.TreeCursor.static.getChildLength = function ( node ) { + if ( node instanceof ve.dm.TextNode ) { + return node.length; + } + if ( !node.hasChildren() ) { + return 0; + } + return node.children.length; +}; + +/* Methods */ + +/** + * Take a single step in the walk, consuming no more than a given linear model length + * + * A "single step" means either stepping into a node, or stepping out of a node, or stepping + * over a node, or stepping across text content inside a text node. + * + * See https://phabricator.wikimedia.org/T162762 + * + * @param {number} maxLength Maximum linear model length to step over (integer >= 1) + * @return {Object|undefined} The type of step taken, or undefined if there are no more steps + * @return {string} return.type open|close|cross + * @return {number} length Linear length of the step (integer >= 1, or 0 for open/close text node) + * @return {number[]} path The offset path from the root to the node containing the stepped item + * @return {ve.dm.Node|null} node The node containing the stepped item + * @return {number} offset The offset of the stepped item within its parent + * @return {number} [offsetLength] Number of children 'cross' passed (1 unless inside a text node) + * @return {ve.dm.Node} [item] The node stepped into/out of/across (absent for text 'cross') + */ +ve.dm.TreeCursor.prototype.advanceAtMost = function ( maxLength ) { + var childLength, item, step, length; + if ( !this.node ) { + return this.lastStep = undefined; + } + childLength = this.constructor.static.getChildLength( this.node ); + // Step across and ignore any newly-created nodes immediately ahead. + // They must have been created by the other pointer, so we must be the trailing + // pointer, so we can clear the newly-created flag +
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: When setting ce=true/false on a ve.ce.DocumentNode, change d...
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/345955 ) Change subject: When setting ce=true/false on a ve.ce.DocumentNode, change descendants too .. When setting ce=true/false on a ve.ce.DocumentNode, change descendants too Bug: T161944 Change-Id: I81f16a3bbcd2412b210c28fb584f64a434a60802 --- M src/ce/nodes/ve.ce.DocumentNode.js 1 file changed, 16 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/55/345955/1 diff --git a/src/ce/nodes/ve.ce.DocumentNode.js b/src/ce/nodes/ve.ce.DocumentNode.js index 3664a1e..5774c49 100644 --- a/src/ce/nodes/ve.ce.DocumentNode.js +++ b/src/ce/nodes/ve.ce.DocumentNode.js @@ -67,6 +67,7 @@ * @method */ ve.ce.DocumentNode.prototype.disable = function () { + this.setDescendantsEditable( false ); this.$element.prop( 'contentEditable', 'false' ); }; @@ -77,6 +78,21 @@ */ ve.ce.DocumentNode.prototype.enable = function () { this.$element.prop( 'contentEditable', 'true' ); + this.setDescendantsEditable( true ); +}; + +/** + * Enable or disable editing on descendant ActiveNodes + * @private + * @param {boolean} isEditable + */ +ve.ce.DocumentNode.prototype.setDescendantsEditable = function ( isEditable ) { + var editable = isEditable ? 'true' : 'false'; + this.traverse( function ( node ) { + if ( node.activeNodeSurface !== undefined ) { + node.$element.prop( 'contentEditable', editable ); + } + } ); }; /* Registration */ -- To view, visit https://gerrit.wikimedia.org/r/345955 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I81f16a3bbcd2412b210c28fb584f64a434a60802 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Serialize/deserialize for Transaction and IndexValueStore
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/344812 ) Change subject: Serialize/deserialize for Transaction and IndexValueStore .. Serialize/deserialize for Transaction and IndexValueStore Change-Id: I565c9a4e3de5af2cb46501ab84e08a71b0636929 --- M src/dm/ve.dm.Change.js M src/dm/ve.dm.IndexValueStore.js M src/dm/ve.dm.Transaction.js 3 files changed, 103 insertions(+), 55 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/12/344812/1 diff --git a/src/dm/ve.dm.Change.js b/src/dm/ve.dm.Change.js index 48aff04..3eb521c 100644 --- a/src/dm/ve.dm.Change.js +++ b/src/dm/ve.dm.Change.js @@ -86,19 +86,18 @@ ve.dm.Change.static = {}; /** - * Deserialize a JSON-serialized change + * Deserialize a change from a JSONable object * * Store values can be deserialized, or kept verbatim; the latter is an optimization if the * Change object will be rebased and reserialized without ever being applied to a document. * - * @param {Object} data JSON-serialized change + * @param {Object} data Change serialized as a JSONable object * @param {ve.dm.Document} [doc] Document, used for creating proper selections if deserializing in the client * @param {boolean} [preserveStoreValues] Keep store values verbatim instead of deserializing - * @return {ve.dm.Change} Deserialized Change object + * @return {ve.dm.Change} Deserialized change */ ve.dm.Change.static.deserialize = function ( data, doc, preserveStoreValues ) { - var author, - staticChange = this, + var author, deserializeStore, selections = {}; for ( author in data.selections ) { @@ -107,27 +106,16 @@ data.selections[ author ] ); } + deserializeStore = ve.dm.IndexValueStore.static.deserialize.bind( + null, + preserveStoreValues ? function noop( x ) { + return x; + } : this.deserializeValue + ); return new ve.dm.Change( data.start, - data.transactions.map( function ( tx ) { - var newTx = new ve.dm.Transaction( tx.operations ); - newTx.author = tx.author; - return newTx; - } ), - data.stores.map( function ( serializedStore ) { - var hash, value, - store = new ve.dm.IndexValueStore(); - store.hashes = serializedStore.hashes; - store.hashStore = {}; - for ( hash in serializedStore.hashStore ) { - value = serializedStore.hashStore[ hash ]; - if ( !preserveStoreValues ) { - value = staticChange.deserializeValue( value ); - } - store.hashStore[ hash ] = value; - } - return store; - } ), + data.transactions.map( ve.dm.Transaction.static.deserialize ), + data.stores.map( deserializeStore ), selections ); }; @@ -733,39 +721,27 @@ * already, i.e. the Change object was created by #deserialize without deserializing store values). * * @param {boolean} [preserveStoreValues] If true, keep store values verbatim instead of serializing - * @return {ve.dm.Change} Deserialized Change object + * @return {ve.dm.Change} Deserialized change */ ve.dm.Change.prototype.serialize = function ( preserveStoreValues ) { - var author, - selections = {}, - change = this; + var author, serializeStoreValues, serializeStore, + selections = {}; for ( author in this.selections ) { selections[ author ] = this.selections[ author ].toJSON(); } + serializeStoreValues = preserveStoreValues ? function noop( x ) { + return x; + } : this.constructor.static.serializeValue; + serializeStore = function ( store ) { + return store.serialize( serializeStoreValues ); + }; return { start: this.start, - transactions: this.transactions.map( function ( transaction ) { - return { - operations: transaction.operations, - author: transaction.author - }; + transactions: this.transactions.map( function ( tx ) { + return tx.serialize(); } ), - stores: this.stores.map( function ( store ) { - var hash, value, - serialized = {}; - for ( hash in store.hashStore ) { -
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: When indexing originalDomElements for ve.dm.Annotations, dis...
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/343458 ) Change subject: When indexing originalDomElements for ve.dm.Annotations, disregard child nodes .. When indexing originalDomElements for ve.dm.Annotations, disregard child nodes Bug: T160839 Change-Id: I1aec6072452051990f1147e4617739620c7b251f --- M src/dm/ve.dm.Converter.js M tests/ce/ve.ce.Surface.test.js M tests/ce/ve.ce.TextState.test.js M tests/dm/lineardata/ve.dm.ElementLinearData.test.js M tests/dm/ve.dm.example.js 5 files changed, 80 insertions(+), 52 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/58/343458/1 diff --git a/src/dm/ve.dm.Converter.js b/src/dm/ve.dm.Converter.js index 3a5c68f..745f6bb 100644 --- a/src/dm/ve.dm.Converter.js +++ b/src/dm/ve.dm.Converter.js @@ -402,7 +402,8 @@ * @return {Object|Array|null} Data element or array of linear model data, or null to alienate */ ve.dm.Converter.prototype.createDataElements = function ( modelClass, domElements ) { - var dataElements = modelClass.static.toDataElement( domElements, this ); + var serializer, + dataElements = modelClass.static.toDataElement( domElements, this ); if ( !dataElements ) { return null; @@ -411,7 +412,18 @@ dataElements = [ dataElements ]; } if ( dataElements.length ) { - dataElements[ 0 ].originalDomElementsIndex = this.store.index( domElements, domElements.map( ve.getNodeHtml ).join( '' ) ); + if ( modelClass.prototype instanceof ve.dm.Annotation ) { + serializer = function ( node ) { + // Do not include childNodes; see T160839 + return node.cloneNode( false ).outerHTML; + }; + } else { + serializer = ve.getNodeHtml; + } + dataElements[ 0 ].originalDomElementsIndex = this.store.index( + domElements, + domElements.map( serializer ).join( '' ) + ); } return dataElements; }; diff --git a/tests/ce/ve.ce.Surface.test.js b/tests/ce/ve.ce.Surface.test.js index b782245..53aa686 100644 --- a/tests/ce/ve.ce.Surface.test.js +++ b/tests/ce/ve.ce.Surface.test.js @@ -1068,7 +1068,7 @@ QUnit.test( 'handleObservedChanges (content changes)', function ( assert ) { var i, - linkIndex = 'h4601de4ee174fedd', + linkIndex = 'h3f6906f71a963fc3', cases = [ { prevHtml: '', @@ -1140,7 +1140,7 @@ { type: 'retain', length: 2 }, { type: 'replace', - insert: [ [ 'Y', [ 'h3f03d2abae6ddc0d' ] ] ], + insert: [ [ 'Y', [ 'hd72ee073faddca4e' ] ] ], remove: [], insertedDataOffset: 0, insertedDataLength: 1 diff --git a/tests/ce/ve.ce.TextState.test.js b/tests/ce/ve.ce.TextState.test.js index 34e064d..f0b8563 100644 --- a/tests/ce/ve.ce.TextState.test.js +++ b/tests/ce/ve.ce.TextState.test.js @@ -24,7 +24,7 @@ { type: 'retain', length: 5 }, { type: 'replace', - remove: [ [ 'b', [ annIndex( 'b', 'bar' ) ] ], [ 'a', [ annIndex( 'b', 'bar' ) ] ], [ 'r', [ annIndex( 'b', 'bar' ) ] ] ], + remove: [ [ 'b', [ annIndex( 'b' ) ] ], [ 'a', [ annIndex( 'b' ) ] ], [ 'r', [ annIndex( 'b' ) ] ] ], insert: [ 'b', 'a', 'r' ], insertedDataOffset: 0, insertedDataLength: 3 @@ -42,7 +42,7 @@ { type: 'replace', remove: [], - insert: [ [ 'r', [ annIndex( 'b', 'ba' ) ] ] ], + insert: [ [ 'r', [ annIndex( 'b' ) ] ] ], insertedDataOffset: 0, insertedDataLength: 1 }, @@ -76,7 +76,7 @@ { type: 'replace', remove: [], - insert: [ [ 'z', [ annIndex( 'b',
[MediaWiki-commits] [Gerrit] mediawiki...cxserver[master]: Update bin/apertium-xhtml to work with config.yaml
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/336957 ) Change subject: Update bin/apertium-xhtml to work with config.yaml .. Update bin/apertium-xhtml to work with config.yaml Change-Id: Ie1a586917b7af5943d493bf42d89bf5a3867d1bc --- M bin/apertium-xhtml 1 file changed, 18 insertions(+), 3 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/services/cxserver refs/changes/57/336957/1 diff --git a/bin/apertium-xhtml b/bin/apertium-xhtml index 4d23f06..5f0e33d 100755 --- a/bin/apertium-xhtml +++ b/bin/apertium-xhtml @@ -1,6 +1,21 @@ #!/usr/bin/env node -var sourceLang, targetLang, sourceHtml, script, args, +var sourceLang, targetLang, sourceHtml, script, args, config, cxConfig, + fs = require( 'fs' ), + yaml = require( 'js-yaml' ), Apertium = require( __dirname + '/../mt/Apertium.js' ); + +config = yaml.load( fs.readFileSync( 'config.yaml' ) ); +if ( !config ) { + console.error( 'Failed to load config' ); + process.exit( 1 ); +} +cxConfig = config.services && Array.isArray( config.services ) && config.services.filter( function ( item ) { + return item && item.name === 'cxserver'; +} )[ 0 ]; +if ( !cxConfig ) { + console.error( 'Cannot find cxserver config' ); + process.exit( 1 ); +} script = process.argv[ 1 ]; args = process.argv.slice( 2 ); @@ -22,13 +37,13 @@ sourceHtml.push( data ); } ); process.stdin.on( 'end', function() { - new Apertium().translate( + new Apertium( cxConfig ).translate( sourceLang, targetLang, sourceHtml.join( '' ) ).then( function( targetHtml ) { process.stdout.write( targetHtml + '\n' ); - }, function( error ) { + }).catch( function( error ) { if ( error.stack ) { console.error( 'error', error.stack ); } else { -- To view, visit https://gerrit.wikimedia.org/r/336957 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ie1a586917b7af5943d493bf42d89bf5a3867d1bc Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/services/cxserver Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Destroy unicorns properly when cursoring to another branch node
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/335962 ) Change subject: Destroy unicorns properly when cursoring to another branch node .. Destroy unicorns properly when cursoring to another branch node Bug: T157019 Change-Id: Idd98c4529b24901ec685f80b870b5cd65480e591 --- M src/ce/ve.ce.Surface.js 1 file changed, 46 insertions(+), 24 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/62/335962/1 diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js index 020c0a8..6690fc0 100644 --- a/src/ce/ve.ce.Surface.js +++ b/src/ce/ve.ce.Surface.js @@ -1492,7 +1492,9 @@ * @return {boolean} Whether unicorns have been destroyed */ ve.ce.Surface.prototype.cleanupUnicorns = function ( fixupCursor ) { - var preUnicorn, range, node, fixup, veRange; + var preUnicorn, range, node, fixup, veRange, + contentBranchNodeBefore, contentBranchNodeAfter; + if ( !this.unicorningNode || !this.unicorningNode.unicorns ) { return false; } @@ -1536,11 +1538,13 @@ fixup = 1; } + contentBranchNodeBefore = this.getSelectedContentBranchNode(); + // Apply the DOM selection to the model - this.incRenderLock(); - try { - veRange = ve.ce.veRangeFromSelection( this.nativeSelection ); - if ( veRange ) { + veRange = ve.ce.veRangeFromSelection( this.nativeSelection ); + if ( veRange ) { + this.incRenderLock(); + try { // The most likely reason for this condition to not-pass is if we // try to cleanup unicorns while the native selection is outside // the model momentarily, as sometimes happens during paste. @@ -1548,14 +1552,22 @@ this.model.getDocument(), veRange ) ); + if ( fixupCursor ) { + this.moveModelCursor( fixup ); + } + } finally { + this.decRenderLock(); } - if ( fixupCursor ) { - this.moveModelCursor( fixup ); - } - } finally { - this.decRenderLock(); } - this.renderSelectedContentBranchNode(); + + contentBranchNodeAfter = this.getSelectedContentBranchNode(); + if ( contentBranchNodeAfter ) { + contentBranchNodeAfter.renderContents(); + } + if ( contentBranchNodeBefore && contentBranchNodeBefore !== contentBranchNodeAfter ) { + contentBranchNodeBefore.renderContents(); + } + this.showModelSelection(); return true; }; @@ -2645,25 +2657,35 @@ }; /** - * Re-render the ContentBranchNode the selection is currently in. + * Get the ContentBranchNode containing the selection focus, if any + * + * @return {ve.ce.ContentBranchNode|null} ContentBranchNode containing selection focus, or null + */ +ve.ce.Surface.prototype.getSelectedContentBranchNode = function () { + var node, + selection = this.model.getSelection(); + + if ( !( selection instanceof ve.dm.LinearSelection ) ) { + return null; + } + node = this.documentView.getBranchNodeFromOffset( selection.getRange().to ); + if ( !node || !( node instanceof ve.ce.ContentBranchNode ) ) { + return null; + } + return node; +}; + +/** + * Re-render the ContentBranchNode containing the selection focus, if any * * @return {boolean} Whether a re-render actually happened */ ve.ce.Surface.prototype.renderSelectedContentBranchNode = function () { - var selection, ceNode; - selection = this.model.getSelection(); - if ( !( selection instanceof ve.dm.LinearSelection ) ) { + var node = this.getSelectedContentBranchNode(); + if ( !node ) { return false; } - ceNode = this.documentView.getBranchNodeFromOffset( selection.getRange().start ); - if ( ceNode === null ) { - return false; - } - if ( !( ceNode instanceof ve.ce.ContentBranchNode ) ) { - // not a content branch node - return false; - } - return ceNode.renderContents(); + return node.renderContents(); }; /** -- To view, visit https://gerrit.wikimedia.org/r/335962 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Idd98c4529b24901ec685f80b870b5cd65480e591 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Check correctly whether the cursor crossed a preunicorn
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/335641 ) Change subject: Check correctly whether the cursor crossed a preunicorn .. Check correctly whether the cursor crossed a preunicorn Without this fix, cursoring isn't correctly broken when cursoring backwards at the beginning of a paragraph (this subtle bug masks the more obvious one in T157019) Bug: T157019 Change-Id: I43cf181231e21d8cef56d9ce70cfeeb6e35c8088 --- M src/ce/ve.ce.Surface.js 1 file changed, 3 insertions(+), 2 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/41/335641/1 diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js index fa77314..020c0a8 100644 --- a/src/ce/ve.ce.Surface.js +++ b/src/ce/ve.ce.Surface.js @@ -1527,8 +1527,9 @@ range.endOffset, preUnicorn.parentNode, ve.parentIndex( preUnicorn ) - ) < 0 ) { - // before the pre-unicorn + ) <= 0 ) { + // before the pre-unicorn (including in the equality case, because the selection + // endpoint is an offset between sibling positions) fixup = -1; } else { // at or after the pre-unicorn (actually must be after the post-unicorn) -- To view, visit https://gerrit.wikimedia.org/r/335641 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I43cf181231e21d8cef56d9ce70cfeeb6e35c8088 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: WIPissimo: RebaseServer persistent storage
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/334995 ) Change subject: WIPissimo: RebaseServer persistent storage .. WIPissimo: RebaseServer persistent storage Change-Id: I06cb8a1264ec74ae96b90d525c8328237001e99c --- A rebaser/MongoStateStore.js M rebaser/server.js A rebaser/test-MongoStateStore.js M src/dm/ve.dm.RebaseDocState.js 4 files changed, 140 insertions(+), 4 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/95/334995/1 diff --git a/rebaser/MongoStateStore.js b/rebaser/MongoStateStore.js new file mode 100644 index 000..249d895 --- /dev/null +++ b/rebaser/MongoStateStore.js @@ -0,0 +1,87 @@ +/*! + * VisualEditor DataModel mongo state store class. + * + * @copyright 2011-2017 VisualEditor Team and others; see http://ve.mit-license.org + */ + +/* eslint-env node, es6 */ +/* eslint-disable no-console */ + +var ve = require( '../dist/ve-rebaser.js' ), + MongoClient = require( 'mongodb' ).MongoClient; + +/** + * DataModel mongo state store + * + * @class + * + * @constructor + * @param {Object} db MongoClient db connection + */ +function MongoStateStore( db ) { + this.db = db; + this.collection = db.collection( 'foo' ); +} + +/* Initialization */ + +OO.inheritClass( MongoStateStore, ve.dm.RebaseServer ); + +/* Static methods */ + +MongoStateStore.static.connect = ve.async( function* connect( url ) { + var db = yield MongoClient.connect( url ); + // yield db.dropDatabase(); + return new MongoStateStore( db ); +} ); + +/* Methods */ + +MongoStateStore.prototype.getDocState = ve.async( function* getDocState( doc ) { + var result = ( yield Promise.resolve( this.collection.find( { name: doc } ).toArray() ) )[ 0 ]; + console.log( 'MongoStateStore#getDocState', result ); + if ( !result ) { + result = { + name: doc, + transactions: [], + stores: [], + selections: {}, + continueBases: {}, + rejections: {} + }; + yield this.collection.insert( result ); + } + return ve.dm.RebaseDocState.static.deserialize( { + history: { + start: 0, + transactions: result.transactions, + stores: result.stores, + selections: result.selections + }, + continueBases: result.continueBases, + rejections: result.rejections + } ); +} ); + +MongoStateStore.prototype.updateDocState = ve.async( function* updateDocState( doc, author, newHistory, continueBase, rejections ) { + var update; + newHistory = newHistory.serialize(); + continueBase = continueBase ? continueBase.serialize() : null; + update = { + $push: { + transactions: { $each: newHistory.transactions }, + stores: { $each: newHistory.stores } + }, + $set: { + selections: newHistory.selections + } + }; + update.$set[ 'rejections.' + author ] = rejections; + if ( continueBase ) { + update.$set[ 'continueBases.' + author ] = continueBase; + } + console.log( 'MongoStateStore#updateDocStore', update ); + yield this.collection.update( { name: doc }, update ); +} ); + +module.exports = { MongoStateStore: MongoStateStore }; diff --git a/rebaser/server.js b/rebaser/server.js index 66cb48d..bc070f6 100644 --- a/rebaser/server.js +++ b/rebaser/server.js @@ -14,7 +14,8 @@ url = require( 'url' ), http = require( 'http' ).Server( app ), io = require( 'socket.io' )( http ), - ve = require( '../dist/ve-rebaser.js' ); + ve = require( '../dist/ve-rebaser.js' ), + MongoStateStore = require( './MongoStateStore.js' ).MongoStateStore; function summarize( author, backtrack, change ) { var storeCount = 0, @@ -49,7 +50,7 @@ console.log( err.stack ); } -rebaseServer = new ve.dm.RebaseServer(); +rebaseServer = null; docNamespaces = new Map(); lastAuthorForDoc = new Map(); pendingForDoc = new Map(); @@ -131,5 +132,11 @@ } } ); -http.listen( port ); -console.log( 'Listening on ' + port + ' (artificial delay ' + artificialDelay + ' ms)' ); +MongoStateStore.static.connect( 'mongodb://localhost:27017/test' ).then( function ( store ) { + rebaseServer = store; + http.listen( port ); + console.log( 'Listening on ' + port + ' (artificial delay ' + artificialDelay + ' ms)' ); +} ).catch( function ( err ) { + console.error( err.stack ); + rebaseServer.db.close(); +} ); diff --git a/rebaser/test-MongoStateStore.js b/rebaser/test-MongoStateStore.js new file mode 100644 index
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Include oojs-ui-core.js in debugging pages
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/333561 ) Change subject: Include oojs-ui-core.js in debugging pages .. Include oojs-ui-core.js in debugging pages Change-Id: I816068f6e4b98ade0734354a61f47feff9cb0d66 --- M demos/ve/eventLogger.html M demos/ve/eventSequencer.html 2 files changed, 2 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/61/333561/1 diff --git a/demos/ve/eventLogger.html b/demos/ve/eventLogger.html index 80ac675..f6c7419 100644 --- a/demos/ve/eventLogger.html +++ b/demos/ve/eventLogger.html @@ -59,7 +59,7 @@ - + diff --git a/demos/ve/eventSequencer.html b/demos/ve/eventSequencer.html index d7b2c4a..26d5cb4 100644 --- a/demos/ve/eventSequencer.html +++ b/demos/ve/eventSequencer.html @@ -17,6 +17,7 @@ + -- To view, visit https://gerrit.wikimedia.org/r/333561 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I816068f6e4b98ade0734354a61f47feff9cb0d66 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Minor changes to RebaseServer
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/331822 ) Change subject: Minor changes to RebaseServer .. Minor changes to RebaseServer Change-Id: I59d1995fa6330c6ee6ffa9fc06079a2d39ebe67d --- M .jsduck/categories.json M build/modules.json M rebaser/server.js A src/dm/ve.dm.RebaseDocState.js M src/dm/ve.dm.RebaseServer.js M tests/dm/ve.dm.RebaseServer.test.js M tests/index.html 7 files changed, 77 insertions(+), 25 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/22/331822/1 diff --git a/.jsduck/categories.json b/.jsduck/categories.json index e768281..866f841 100644 --- a/.jsduck/categories.json +++ b/.jsduck/categories.json @@ -104,6 +104,7 @@ "name": "Rebasing", "classes": [ "ve.dm.Change", + "ve.dm.RebaseDocState", "ve.dm.RebaseServer", "ve.dm.RebaseClient", "ve.dm.SurfaceSynchronizer" diff --git a/build/modules.json b/build/modules.json index 40c33a2..81cc35b 100644 --- a/build/modules.json +++ b/build/modules.json @@ -622,6 +622,7 @@ "visualEditor.rebase": { "scripts": [ "src/dm/ve.dm.Change.js", + "src/dm/ve.dm.RebaseDocState.js", "src/dm/ve.dm.RebaseServer.js", "src/dm/ve.dm.RebaseClient.js", "src/dm/ve.dm.SurfaceSynchronizer.js" @@ -910,6 +911,7 @@ "src/dm/ve.dm.IndexValueStore.js", "src/dm/ve.dm.Transaction.js", "src/dm/ve.dm.Change.js", + "src/dm/ve.dm.RebaseDocState.js", "src/dm/ve.dm.RebaseServer.js", "src/ve.Range.js", "src/dm/ve.dm.Selection.js", diff --git a/rebaser/server.js b/rebaser/server.js index 9f24955..feea48a 100644 --- a/rebaser/server.js +++ b/rebaser/server.js @@ -39,7 +39,7 @@ function makeConnectionHandler( docName ) { return function handleConnection( socket ) { - var history = rebaseServer.getStateForDoc( docName ).history, + var history = rebaseServer.getDocState( docName ).history, author = 1 + ( lastAuthorForDoc.get( docName ) || 0 ); lastAuthorForDoc.set( docName, author ); console.log( 'new client ' + author + ' for ' + docName ); diff --git a/src/dm/ve.dm.RebaseDocState.js b/src/dm/ve.dm.RebaseDocState.js new file mode 100644 index 000..3a06686 --- /dev/null +++ b/src/dm/ve.dm.RebaseDocState.js @@ -0,0 +1,38 @@ +/*! + * VisualEditor DataModel rebase document state class. + * + * @copyright 2011-2017 VisualEditor Team and others; see http://ve.mit-license.org + */ + +/* eslint-env node, es6 */ + +/** + * DataModel rebase document state + * + * @class + * + * @constructor + * @param {ve.dm.Change} history History as one big change + * @param {Map} continueBases Per-author transposed history for rebasing + * @param {Map } rejections Per-author count of unacknowledged rejections + */ +ve.dm.RebaseDocState = function VeDmRebaseDocState( history, continueBases, rejections ) { + /** +* @property {ve.dm.Change} history History as one big change +*/ + this.history = history || new ve.dm.Change( 0, [], [], {} ); + + /** +* @property {Map. } continueBases Per-author transposed history for rebasing +*/ + this.continueBases = continueBases || new Map(); + + /** +* @property {Map. } Per-author count of unacknowledged rejections +*/ + this.rejections = rejections || new Map(); +}; + +/* Inheritance */ + +OO.initClass( ve.dm.RebaseDocState ); diff --git a/src/dm/ve.dm.RebaseServer.js b/src/dm/ve.dm.RebaseServer.js index ada232d..af9918b 100644 --- a/src/dm/ve.dm.RebaseServer.js +++ b/src/dm/ve.dm.RebaseServer.js @@ -21,21 +21,34 @@ /** * Get the state of a document by name. * - * @param {string} name Name of a document - * @return {Object} Document state (history and selections) - * @return {ve.dm.Change} return.history History as one big Change - * @return {Map. } return.continueBases Per-author transposed history for rebasing - * @return {Map. } return.rejections Per-author count of unacknowledged rejections + * @param {string} doc Name of a document + * @return {ve.dm.RebaseDocState} Document state */ -ve.dm.RebaseServer.prototype.getStateForDoc = function ( name ) { - if ( !this.stateForDoc.has( name ) ) { - this.stateForDoc.set( name, { -
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: WIP: Make RebaseServer asynchronous
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/331423 ) Change subject: WIP: Make RebaseServer asynchronous .. WIP: Make RebaseServer asynchronous Change-Id: I6f565ab1893a91eb4e4e241fc8ba7f1a27fd96c2 --- M build/modules.json M rebaser/server.js M src/dm/ve.dm.RebaseServer.js A src/ve.utils-es6.js M tests/dm/ve.dm.RebaseServer.test.js M tests/index.html 6 files changed, 126 insertions(+), 46 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/23/331423/1 diff --git a/build/modules.json b/build/modules.json index 40c33a2..1f695dc 100644 --- a/build/modules.json +++ b/build/modules.json @@ -621,6 +621,7 @@ }, "visualEditor.rebase": { "scripts": [ + "src/ve.utils-es6.js", "src/dm/ve.dm.Change.js", "src/dm/ve.dm.RebaseServer.js", "src/dm/ve.dm.RebaseClient.js", @@ -907,6 +908,7 @@ }, "rebaser.build": { "scripts": [ + "src/ve.utils-es6.js", "src/dm/ve.dm.IndexValueStore.js", "src/dm/ve.dm.Transaction.js", "src/dm/ve.dm.Change.js", diff --git a/rebaser/server.js b/rebaser/server.js index 9f24955..f5b956a 100644 --- a/rebaser/server.js +++ b/rebaser/server.js @@ -32,6 +32,12 @@ return summary.join( ', ' ); } +function wait( timeout ) { + return new Promise( function ( resolve ) { + setTimeout( resolve, timeout ); + } ); +} + rebaseServer = new ve.dm.RebaseServer(); docNamespaces = new Map(); lastAuthorForDoc = new Map(); @@ -39,7 +45,7 @@ function makeConnectionHandler( docName ) { return function handleConnection( socket ) { - var history = rebaseServer.getStateForDoc( docName ).history, + var gotHistory = rebaseServer.getHistoryForDoc( docName ), author = 1 + ( lastAuthorForDoc.get( docName ) || 0 ); lastAuthorForDoc.set( docName, author ); console.log( 'new client ' + author + ' for ' + docName ); @@ -49,14 +55,17 @@ // comments in the /raw handler. Keeping an updated linmod on the server could be // feasible if TransactionProcessor was modified to have a "don't sync, just apply" // mode and ve.dm.Document was faked with { data: ..., metadata: ..., store: ... } - console.log( 'Sending full history: ' + summarize( null, 0, history ) ); - socket.emit( 'newChange', history.serialize( true ) ); - socket.on( 'submitChange', setTimeout.bind( null, function ( data ) { + gotHistory.then( function ( history ) { + socket.emit( 'newChange', history.serialize( true ) ); + } ); + socket.on( 'submitChange', ve.async( function* onSubmitChange( data ) { var change, applied; + yield gotHistory; + yield wait( artificialDelay ); try { change = ve.dm.Change.static.deserialize( data.change, null, true ); console.log( 'receive ' + summarize( author, data.backtrack, change ) ); - applied = rebaseServer.applyChange( docName, author, data.backtrack, change ); + applied = yield rebaseServer.applyChange( docName, author, data.backtrack, change ); if ( !applied.isEmpty() ) { console.log( 'applied ' + summarize( author, 0, applied ) ); docNamespaces.get( docName ).emit( @@ -70,7 +79,7 @@ } catch ( error ) { console.error( error.stack ); } - }, artificialDelay ) ); + } ) ); }; } diff --git a/src/dm/ve.dm.RebaseServer.js b/src/dm/ve.dm.RebaseServer.js index ada232d..b6c5d0c 100644 --- a/src/dm/ve.dm.RebaseServer.js +++ b/src/dm/ve.dm.RebaseServer.js @@ -21,22 +21,43 @@ /** * Get the state of a document by name. * - * @param {string} name Name of a document + * @param {string} doc Name of a document * @return {Object} Document state (history and selections) * @return {ve.dm.Change} return.history History as one big Change * @return {Map.} return.continueBases Per-author transposed history for rebasing - * @return {Map. } return.rejections Per-author count of unacknowledged rejections + * @return {Promise >} return.rejections Per-author count of unacknowledged rejections */ -ve.dm.RebaseServer.prototype.getStateForDoc = function ( name ) { -
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Remove serialization test cheat; make tests actually pass
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/329657 ) Change subject: Remove serialization test cheat; make tests actually pass .. Remove serialization test cheat; make tests actually pass The author of I1eccd4ef99d764911994d11d747f13ae42919eff is clearly a very shady character Change-Id: I69038332adf57ce43edd85930028d337a4946356 --- M tests/dm/ve.dm.Change.test.js 1 file changed, 32 insertions(+), 24 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/57/329657/1 diff --git a/tests/dm/ve.dm.Change.test.js b/tests/dm/ve.dm.Change.test.js index ef67971..53e404e 100644 --- a/tests/dm/ve.dm.Change.test.js +++ b/tests/dm/ve.dm.Change.test.js @@ -269,28 +269,34 @@ serialized = { start: 0, transactions: [ - [ - { type: 'retain', length: 1 }, - { - type: 'replace', - remove: [], - insert: [ [ 'f', bIndex ] ], - insertedDataOffset: 0, - insertedDataLength: 1 - }, - { type: 'retain', length: 4 } - ], - [ - { type: 'retain', length: 2 }, - { - type: 'replace', - remove: [], - insert: [ [ 'u', bIndex ] ], - insertedDataOffset: 0, - insertedDataLength: 1 - }, - { type: 'retain', length: 4 } - ] + { + author: null, + operations: [ + { type: 'retain', length: 1 }, + { + type: 'replace', + remove: [], + insert: [ [ 'f', bIndex ] ], + insertedDataOffset: 0, + insertedDataLength: 1 + }, + { type: 'retain', length: 4 } + ] + }, + { + author: null, + operations: [ + { type: 'retain', length: 2 }, + { + type: 'replace', + remove: [], + insert: [ [ 'u', bIndex ] ], + insertedDataOffset: 0, + insertedDataLength: 1 + }, + { type: 'retain', length: 4 } + ] + } ], stores: [ { @@ -305,7 +311,10 @@ }, hashes: bIndex }, - {} + { + hashStore: {}, + hashes: [] + } ], selections: {} }; @@ -313,7 +322,6 @@ // Fixup second insert change.transactions[ 1 ].operations[ 2 ].length += 1; - serialized = change.serialize(); assert.deepEqual( change.serialize(), serialized, 'Serialize' ); assert.deepEqual( -- To view, visit https://gerrit.wikimedia.org/r/329657 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I69038332adf57ce43edd85930028d337a4946356 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Make BlockquoteNode fully non-ContentBranchNode
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/329448 ) Change subject: Make BlockquoteNode fully non-ContentBranchNode .. Make BlockquoteNode fully non-ContentBranchNode Before, BlockquoteNode was modelled in two conflicting ways; ve.ce.BlockquoteNode extended ve.ce.ContentBranchNode but ve.dm.BlockquoteNode extended ve.dm.BranchNode . Standardized on the latter model, because the HTML blockquote element can contain flow content such as paragraph elements. See: https://html.spec.whatwg.org/multipage/semantics.html#the-blockquote-element Bug: T154231 Change-Id: I3b13cbbb94802b3e08d795cffd3f6109460e3628 --- M src/ce/nodes/ve.ce.BlockquoteNode.js M src/dm/nodes/ve.dm.BlockquoteNode.js M tests/ce/ve.ce.Surface.test.js M tests/dm/ve.dm.example.js 4 files changed, 8 insertions(+), 6 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/48/329448/1 diff --git a/src/ce/nodes/ve.ce.BlockquoteNode.js b/src/ce/nodes/ve.ce.BlockquoteNode.js index 9367d70..704a516 100644 --- a/src/ce/nodes/ve.ce.BlockquoteNode.js +++ b/src/ce/nodes/ve.ce.BlockquoteNode.js @@ -9,7 +9,7 @@ * ContentEditable Blockquote node. * * @class - * @extends ve.ce.ContentBranchNode + * @extends ve.ce.BranchNode * @constructor * @param {ve.dm.BlockquoteNode} model Model to observe * @param {Object} [config] Configuration options @@ -21,7 +21,7 @@ /* Inheritance */ -OO.inheritClass( ve.ce.BlockquoteNode, ve.ce.ContentBranchNode ); +OO.inheritClass( ve.ce.BlockquoteNode, ve.ce.BranchNode ); /* Static Properties */ diff --git a/src/dm/nodes/ve.dm.BlockquoteNode.js b/src/dm/nodes/ve.dm.BlockquoteNode.js index bcf99ab..31f5859 100644 --- a/src/dm/nodes/ve.dm.BlockquoteNode.js +++ b/src/dm/nodes/ve.dm.BlockquoteNode.js @@ -27,8 +27,6 @@ ve.dm.BlockquoteNode.static.name = 'blockquote'; -ve.dm.BlockquoteNode.static.canContainContent = true; - ve.dm.BlockquoteNode.static.matchTagNames = [ 'blockquote' ]; /* Registration */ diff --git a/tests/ce/ve.ce.Surface.test.js b/tests/ce/ve.ce.Surface.test.js index 7b9fbbe..55051c0 100644 --- a/tests/ce/ve.ce.Surface.test.js +++ b/tests/ce/ve.ce.Surface.test.js @@ -1969,7 +1969,7 @@ { rangeOrSelection: new ve.Range( 1 ), documentHtml: '', - pasteHtml: 'Foo', + pasteHtml: 'Foo', expectedOps: [], expectedRangeOrSelection: new ve.Range( 1 ), msg: 'Pasting block content that is fully stripped does nothing' diff --git a/tests/dm/ve.dm.example.js b/tests/dm/ve.dm.example.js index a150f65..b56896e 100644 --- a/tests/dm/ve.dm.example.js +++ b/tests/dm/ve.dm.example.js @@ -3488,7 +3488,9 @@ { type: 'horizontalRule' }, { type: '/horizontalRule' }, { type: 'blockquote' }, + { type: 'paragraph', internal: { generated: 'wrapper' } }, 'B', 'a', 'r', + { type: '/paragraph' }, { type: '/blockquote' }, { type: 'internalList' }, { type: '/internalList' } @@ -3497,7 +3499,9 @@ 'Foo' + '' + '' + - 'Bar' + '' + + 'Bar' + + '' } }; -- To view, visit https://gerrit.wikimedia.org/r/329448 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I3b13cbbb94802b3e08d795cffd3f6109460e3628 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Refactor ve.dm.TransactionBuilder#newFromWrap
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/328583 ) Change subject: Refactor ve.dm.TransactionBuilder#newFromWrap .. Refactor ve.dm.TransactionBuilder#newFromWrap Change-Id: I81c4548cfd596eceba30fc84bc45f81adbd240c0 --- M src/dm/ve.dm.TransactionBuilder.js 1 file changed, 79 insertions(+), 63 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/83/328583/1 diff --git a/src/dm/ve.dm.TransactionBuilder.js b/src/dm/ve.dm.TransactionBuilder.js index 6c54999..6f63056 100644 --- a/src/dm/ve.dm.TransactionBuilder.js +++ b/src/dm/ve.dm.TransactionBuilder.js @@ -614,7 +614,7 @@ * @return {ve.dm.Transaction} */ ve.dm.TransactionBuilder.static.newFromWrap = function ( doc, range, unwrapOuter, wrapOuter, unwrapEach, wrapEach ) { - var i, j, unwrapOuterData, startOffset, unwrapEachData, closingWrapEach, + var i, startOffset, closingUnwrapEach, closingWrapEach, endOffset, ptr, txBuilder = new ve.dm.TransactionBuilder(), depth = 0; @@ -628,83 +628,99 @@ } return closings; } - /* closingUnwrapEach = */ closingArray( unwrapEach ); + closingUnwrapEach = closingArray( unwrapEach ); closingWrapEach = closingArray( wrapEach ); // TODO: check for and fix nesting validity like fixupInsertion does - if ( range.start > unwrapOuter.length ) { - // Retain up to the first thing we're unwrapping - // The outer unwrapping takes place *outside* - // the range, so compensate for that - txBuilder.pushRetain( range.start - unwrapOuter.length ); - } else if ( range.start < unwrapOuter.length ) { - throw new Error( 'unwrapOuter is longer than the data preceding the range' ); - } - // Replace the opening elements for the outer unwrap - if ( wrapOuter.length > 0 || unwrapOuter.length > 0 ) { - // Verify that wrapOuter matches the data at this position - unwrapOuterData = doc.data.slice( range.start - unwrapOuter.length, range.start ); - for ( i = 0; i < unwrapOuterData.length; i++ ) { - if ( unwrapOuterData[ i ].type !== unwrapOuter[ i ].type ) { - throw new Error( 'Element in unwrapOuter does not match: expected ' + - unwrapOuter[ i ].type + ' but found ' + unwrapOuterData[ i ].type ); + /** +* Match items before/after an offset, skipping over MetaItems +* +* @param {string} direction Direction of match, backwards|forwards +* @param {number} offset First boundary for the matching items +* @param {Object[]} matchList List of objects with .type properties to compare +* @param {string} matchName Description of the match, for error messages +* @return {number} Other slice boundary for the matching items +* @throws {Error} Unmatched item foo in matchName [(found bar)] +*/ + function match( direction, offset, matchList, matchName ) { + var start, stop, step, i, item; + if ( direction === 'forwards' ) { + start = 0; + stop = matchList.length; + step = 1; + // Inclusive 'from' slice boundary + offset--; + } else { + start = matchList.length - 1; + stop = -1; + step = -1; + } + for ( i = start; i !== stop; i += step ) { + offset += step; + item = doc.data.data[ offset ]; + if ( item.type !== matchList[ i ].type ) { + throw new Error( 'Unmatched item ' + matchList[ i ].type + ' in ' + + matchName + ' (found ' + item.type + ')' ); } } - // Instead of putting in unwrapOuter as given, put it in the - // way it appears in the model so we pick up any attributes - txBuilder.pushReplace( doc, range.start - unwrapOuter.length, unwrapOuter.length, ve.copy( wrapOuter ) ); + if ( direction === 'forwards' ) { + // Exclusive 'to' slice boundary + offset++; + } + return offset; } + // Verify the data before range.start matches unwrapOuter, and find where to retain up to + ptr = match( 'backwards', range.start, unwrapOuter, 'unwrapOuter' ); + txBuilder.pushRetain( ptr ); + // Replace wrapper + txBuilder.pushReplace( doc, ptr, range.start - ptr, ve.copy( wrapOuter ) ); - if (
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Remove ve.getHtmlAttributes and ve.getOpeningHtmlTag (both u...
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/327148 ) Change subject: Remove ve.getHtmlAttributes and ve.getOpeningHtmlTag (both unused) .. Remove ve.getHtmlAttributes and ve.getOpeningHtmlTag (both unused) They seem to have been unused since I31991488579b8cce6d98ed8b29b486ba5ec38cdc . Change-Id: I7185bb529827e0163ac4798ca60c3b61781e3c81 --- M src/ve.utils.js M tests/ve.test.js 2 files changed, 0 insertions(+), 107 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/48/327148/1 diff --git a/src/ve.utils.js b/src/ve.utils.js index 52b259d..6c75610 100644 --- a/src/ve.utils.js +++ b/src/ve.utils.js @@ -570,57 +570,6 @@ }() ); /** - * Generate HTML attributes. - * - * NOTE: While the values of attributes are escaped, the names of attributes (i.e. the keys in - * the attributes objects) are NOT ESCAPED. The caller is responsible for making sure these are - * sane tag/attribute names and do not contain unsanitized content from an external source - * (e.g. from the user or from the web). - * - * @param {Object} [attributes] Key-value map of attributes for the tag - * @return {string} HTML attributes - */ -ve.getHtmlAttributes = function ( attributes ) { - var attrName, attrValue, - parts = []; - - if ( !ve.isPlainObject( attributes ) || ve.isEmptyObject( attributes ) ) { - return ''; - } - - for ( attrName in attributes ) { - attrValue = attributes[ attrName ]; - if ( attrValue === true ) { - // Convert name=true to name=name - attrValue = attrName; - } else if ( attrValue === false ) { - // Skip name=false - continue; - } - parts.push( attrName + '="' + ve.escapeHtml( String( attrValue ) ) + '"' ); - } - - return parts.join( ' ' ); -}; - -/** - * Generate an opening HTML tag. - * - * NOTE: While the values of attributes are escaped, the tag name and the names of - * attributes (i.e. the keys in the attributes objects) are NOT ESCAPED. The caller is - * responsible for making sure these are sane tag/attribute names and do not contain - * unsanitized content from an external source (e.g. from the user or from the web). - * - * @param {string} tagName HTML tag name - * @param {Object} [attributes] Key-value map of attributes for the tag - * @return {string} Opening HTML tag - */ -ve.getOpeningHtmlTag = function ( tagName, attributes ) { - var attr = ve.getHtmlAttributes( attributes ); - return '<' + tagName + ( attr ? ' ' + attr : '' ) + '>'; -}; - -/** * Get the attributes of a DOM element as an object with key/value pairs. * * @param {HTMLElement} element diff --git a/tests/ve.test.js b/tests/ve.test.js index 3983ad3..5481fff 100644 --- a/tests/ve.test.js +++ b/tests/ve.test.js @@ -211,62 +211,6 @@ ); } ); -QUnit.test( 'getHtmlAttributes', 7, function ( assert ) { - assert.deepEqual( - ve.getHtmlAttributes(), - '', - 'no attributes argument' - ); - assert.deepEqual( - ve.getHtmlAttributes( NaN + 'px' ), - '', - 'invalid attributes argument' - ); - assert.deepEqual( - ve.getHtmlAttributes( {} ), - '', - 'empty attributes argument' - ); - assert.deepEqual( - ve.getHtmlAttributes( { src: 'foo' } ), - 'src="foo"', - 'one attribute' - ); - assert.deepEqual( - ve.getHtmlAttributes( { href: 'foo', rel: 'bar' } ), - 'href="foo" rel="bar"', - 'two attributes' - ); - assert.deepEqual( - ve.getHtmlAttributes( { selected: true, blah: false, value: 3 } ), - 'selected="selected" value="3"', - 'handling of booleans and numbers' - ); - assert.deepEqual( - ve.getHtmlAttributes( { placeholder: '&"bar"&\'baz\'' } ), - 'placeholder="foobarbaz"', - 'escaping of attribute values' - ); -} ); - -QUnit.test( 'getOpeningHtmlTag', 3, function ( assert ) { - assert.deepEqual( - ve.getOpeningHtmlTag( 'code', {} ), - '', - 'opening tag without attributes' - ); - assert.deepEqual( - ve.getOpeningHtmlTag( 'img', { src: 'foo' } ), - '', - 'opening tag with one attribute' - ); - assert.deepEqual( - ve.getOpeningHtmlTag( 'a', { href: 'foo', rel: 'bar' } ), - '', - 'tag with two attributes' - ); -} ); - QUnit.test( 'sparseSplice', function ( assert ) { var tests, i, len, test; // Convert
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Use try-finally instead of try-catch-rethrow
Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/327143 ) Change subject: Use try-finally instead of try-catch-rethrow .. Use try-finally instead of try-catch-rethrow This works better with debuggers that break on uncaught exceptions Change-Id: I28e4432ef83a6b7803d212575b43ad50344c78a2 --- M src/dm/ve.dm.TransactionProcessor.js 1 file changed, 18 insertions(+), 14 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/43/327143/1 diff --git a/src/dm/ve.dm.TransactionProcessor.js b/src/dm/ve.dm.TransactionProcessor.js index b0db940..891e0db 100644 --- a/src/dm/ve.dm.TransactionProcessor.js +++ b/src/dm/ve.dm.TransactionProcessor.js @@ -84,7 +84,7 @@ * @param {Function} [presynchronizeHandler] Callback to emit before synchronizing */ ve.dm.TransactionProcessor.prototype.process = function ( presynchronizeHandler ) { - var op; + var op, completed; // First process each operation to gather modifications in the modification queue. // If an exception occurs during this stage, we don't need to do anything to recover, @@ -98,30 +98,34 @@ // Apply the queued modifications try { + completed = false; this.applyModifications(); - } catch ( e ) { - // Restore the linear model to its original state - this.rollbackModifications(); - // Rethrow the exception - throw e; + completed = true; + } finally { + if ( !completed ) { + // Restore the linear model to its original state + this.rollbackModifications(); + } } // Mark the transaction as committed this.transaction.markAsApplied(); // Synchronize the node tree for the modifications we just made try { + completed = false; if ( presynchronizeHandler ) { presynchronizeHandler(); } this.synchronizer.synchronize( this.transaction ); - } catch ( e ) { - // Restore the linear model to its original state - this.rollbackModifications(); - // The synchronizer may have left the tree in some sort of weird half-baked state, - // so rebuild it from scratch - this.document.rebuildTree(); - // Rethrow the exception - throw e; + completed = true; + } finally { + if ( !completed ) { + // Restore the linear model to its original state + this.rollbackModifications(); + // The synchronizer may have left the tree in some sort of weird half-baked state, + // so rebuild it from scratch + this.document.rebuildTree(); + } } }; -- To view, visit https://gerrit.wikimedia.org/r/327143 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I28e4432ef83a6b7803d212575b43ad50344c78a2 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Fix socket.io-client path
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/325575 Change subject: Fix socket.io-client path .. Fix socket.io-client path Change-Id: If83a2ab094b7497b3c71e6915dd35912ebcbdaf9 --- M build/modules.json 1 file changed, 1 insertion(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/75/325575/1 diff --git a/build/modules.json b/build/modules.json index f07920f..d4fabbb 100644 --- a/build/modules.json +++ b/build/modules.json @@ -1,7 +1,7 @@ { "socket.io": { "scripts": [ - "rebaser/node_modules/socket.io/node_modules/socket.io-client/dist/socket.io.min.js" + "rebaser/node_modules/socket.io-client/dist/socket.io.min.js" ] }, "jquery": { -- To view, visit https://gerrit.wikimedia.org/r/325575 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: If83a2ab094b7497b3c71e6915dd35912ebcbdaf9 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Refactor ve.dm.Transaction
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/324415 Change subject: Refactor ve.dm.Transaction .. Refactor ve.dm.Transaction * Create ve.dm.TransactionBuilder; put ve.dm.Transaction-building code there * Put rebasing code into ve.dm.Change * Add simple non-validating methods that clearly show possible operations * Make ve.dm.Transaction into an OOjs class In a future commit, ve.dm.TransactionBuilder should be refactored further; it's currently structured to have a small diff against the old ve.dm.Transaction.js file. The same goes for various unit tests that create transactions. Change-Id: I61fcb3b1b77da37410f415466ffee7835aeb --- M .jsduck/categories.json M build/modules.json M demos/ve/desktop.html M demos/ve/mobile.html M src/ce/keydownhandlers/ve.ce.LinearEnterKeyDownHandler.js M src/ce/nodes/ve.ce.TableRowNode.js M src/ce/ve.ce.Surface.js M src/ce/ve.ce.TextState.js M src/ce/ve.ce.js M src/dm/ve.dm.Change.js M src/dm/ve.dm.InternalList.js M src/dm/ve.dm.MetaList.js M src/dm/ve.dm.Node.js M src/dm/ve.dm.SurfaceFragment.js M src/dm/ve.dm.Transaction.js A src/dm/ve.dm.TransactionBuilder.js M src/ui/actions/ve.ui.IndentationAction.js M src/ui/actions/ve.ui.TableAction.js M src/ui/elements/ve.ui.DiffElement.js M tests/dm/ve.dm.Change.test.js M tests/dm/ve.dm.Document.test.js M tests/dm/ve.dm.MetaList.test.js M tests/dm/ve.dm.Surface.test.js M tests/dm/ve.dm.Transaction.test.js A tests/dm/ve.dm.TransactionBuilder.test.js M tests/dm/ve.dm.TransactionProcessor.test.js M tests/index.html 27 files changed, 4,014 insertions(+), 3,921 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/15/324415/1 -- To view, visit https://gerrit.wikimedia.org/r/324415 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I61fcb3b1b77da37410f415466ffee7835aeb Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Focusable cursor tests: place cursor in cursorHolders
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/324029 Change subject: Focusable cursor tests: place cursor in cursorHolders .. Focusable cursor tests: place cursor in cursorHolders Change-Id: Ifff0206e3ab2adee718e54adca99553c70cb9175 --- M tests/ce/ve.ce.Surface.test.js 1 file changed, 40 insertions(+), 5 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/29/324029/1 diff --git a/tests/ce/ve.ce.Surface.test.js b/tests/ce/ve.ce.Surface.test.js index 0ce15e8..7b9fbbe 100644 --- a/tests/ce/ve.ce.Surface.test.js +++ b/tests/ce/ve.ce.Surface.test.js @@ -37,8 +37,15 @@ // would need the faked testing surface to be improved. view.eventSequencer.onEvent( 'keydown', $.Event( 'keydown', e ) ); view.eventSequencer.onEvent( 'keypress', $.Event( 'keypress', e ) ); - if ( forceSelection ) { + if ( forceSelection instanceof ve.Range ) { view.showSelectionState( view.getSelectionState( forceSelection ) ); + } else if ( forceSelection && forceSelection.focusNode ) { + view.showSelectionState( new ve.SelectionState( { + anchorNode: view.$element.find( forceSelection.anchorNode )[ 0 ], + anchorOffset: forceSelection.anchorOffset, + focusNode: view.$element.find( forceSelection.focusNode )[ 0 ], + focusOffset: forceSelection.focusOffset + } ) ); } view.eventSequencer.onEvent( 'keyup', $.Event( 'keyup', e ) ); view.eventSequencer.endLoop(); @@ -774,7 +781,14 @@ htmlOrDoc: blockImageDoc, rangeOrSelection: new ve.Range( 4 ), keys: [ 'RIGHT' ], - forceSelection: new ve.Range( 8 ), // cursor moves into the caption + // Force cursor into the cursor holder before the block image + forceSelection: { + anchorNode: '.ve-ce-cursorHolder-before', + // Emulating Chromium 50, right arrow lands at offset 0 + anchorOffset: 0, + focusNode: '.ve-ce-cursorHolder-before', + focusOffset: 0 + }, expectedRangeOrSelection: new ve.Range( 5, 18 ), msg: 'Cursor right onto a block node' }, @@ -782,7 +796,14 @@ htmlOrDoc: blockImageDoc, rangeOrSelection: new ve.Range( 19 ), keys: [ 'LEFT' ], - forceSelection: new ve.Range( 17 ), + // Force cursor into the cursor holder after the block image + forceSelection: { + anchorNode: '.ve-ce-cursorHolder-after', + // Emulating Chromium 50, left arrow lands at offset 1 + anchorOffset: 1, + focusNode: '.ve-ce-cursorHolder-after', + focusOffset: 1 + }, expectedRangeOrSelection: new ve.Range( 18, 5 ), msg: 'Cursor left onto a block node' }, @@ -790,7 +811,14 @@ htmlOrDoc: blockImageDoc, rangeOrSelection: new ve.Range( 4 ), keys: [ 'DOWN' ], - forceSelection: new ve.Range( 14 ), // cursor moves into the caption + // Force cursor into the cursor holder before the block image + forceSelection: { + anchorNode: '.ve-ce-cursorHolder-before', + // Emulating Chromium 50, down arrow lands at offset 0 + anchorOffset: 0, + focusNode: '.ve-ce-cursorHolder-before', + focusOffset: 0 + }, expectedRangeOrSelection: new ve.Range( 5, 18 ), msg: 'Cursor down onto a block node'
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Hijack EventSequencer timeouts in unit testing
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/324028 Change subject: Hijack EventSequencer timeouts in unit testing .. Hijack EventSequencer timeouts in unit testing Change-Id: I9839edf578ef7d9693500dbb36cf76810e1e1555 --- M tests/ce/ve.ce.Surface.test.js M tests/ce/ve.ce.TestRunner.js M tests/ve.test.utils.js 3 files changed, 45 insertions(+), 30 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/28/324028/1 diff --git a/tests/ce/ve.ce.Surface.test.js b/tests/ce/ve.ce.Surface.test.js index 0743891..0ce15e8 100644 --- a/tests/ce/ve.ce.Surface.test.js +++ b/tests/ce/ve.ce.Surface.test.js @@ -16,6 +16,8 @@ model = view.getModel(), data = ve.copy( model.getDocument().getFullData() ); + ve.test.utils.hijackEventSequencerTimeouts( view.eventSequencer ); + model.setSelection( ve.test.utils.selectionFromRangeOrSelection( model.getDocument(), rangeOrSelection ) ); @@ -34,14 +36,12 @@ // TODO: Could probably switch to using this for every test, but it // would need the faked testing surface to be improved. view.eventSequencer.onEvent( 'keydown', $.Event( 'keydown', e ) ); + view.eventSequencer.onEvent( 'keypress', $.Event( 'keypress', e ) ); if ( forceSelection ) { view.showSelectionState( view.getSelectionState( forceSelection ) ); } - view.eventSequencer.runPendingCalls( 'keydown' ); - view.eventSequencer.onEvent( 'keypress', $.Event( 'keypress', e ) ); - view.eventSequencer.runPendingCalls( 'keypress' ); view.eventSequencer.onEvent( 'keyup', $.Event( 'keyup', e ) ); - view.eventSequencer.runPendingCalls( 'keyup' ); + view.eventSequencer.endLoop(); } else { if ( forceSelection ) { view.showSelectionState( view.getSelectionState( forceSelection ) ); @@ -60,7 +60,6 @@ { type: 'linear', range: expectedRangeOrSelection } : expectedRangeOrSelection ); - assert.equalHash( model.getSelection(), expectedSelection, msg + ': selection' ); view.destroy(); }; diff --git a/tests/ce/ve.ce.TestRunner.js b/tests/ce/ve.ce.TestRunner.js index 6308d6f..534d3f6 100644 --- a/tests/ce/ve.ce.TestRunner.js +++ b/tests/ce/ve.ce.TestRunner.js @@ -118,13 +118,10 @@ * @param {ve.ce.Surface} surface The UI Surface */ ve.ce.TestRunner = function VeCeTestRunner( surface ) { - var testRunner, - callId = 0; this.view = surface; this.model = surface.getModel(); this.doc = surface.getElementDocument(); this.nativeSelection = surface.nativeSelection; - this.postponedCalls = {}; // TODO: The code assumes that the document consists of exactly one paragraph this.lastText = this.getParagraph().textContent; @@ -133,14 +130,7 @@ surface.surfaceObserver.pollInterval = null; // Take control of eventSequencer 'setTimeouts' - testRunner = this; - this.view.eventSequencer.postpone = function ( f ) { - testRunner.postponedCalls[ ++callId ] = f; - return callId; - }; - this.view.eventSequencer.cancelPostponed = function ( callId ) { - delete testRunner.postponedCalls[ callId ]; - }; + ve.test.utils.hijackEventSequencerTimeouts( this.view.eventSequencer ); }; /* Methods */ @@ -166,22 +156,10 @@ /** * Run any pending postponed calls * - * Exceptions thrown may leave this.postponedCalls in an inconsistent state + * Exceptions thrown will leave postponed calls in an inconsistent state */ ve.ce.TestRunner.prototype.endLoop = function () { - var callId, postponedCalls, - check = true; - - // postponed calls may add more postponed calls - while ( check ) { - postponedCalls = this.postponedCalls; - this.postponedCalls = {}; - check = false; - for ( callId in postponedCalls ) { - check = true; - postponedCalls[ callId ](); - } - } + this.view.eventSequencer.endLoop(); }; /** diff --git a/tests/ve.test.utils.js b/tests/ve.test.utils.js index 0a5006c..e53993f 100644 --- a/tests/ve.test.utils.js +++ b/tests/ve.test.utils.js @@ -459,4 +459,42 @@ add( rootNode ); return html.join( '' ); }; + + /** +* Take control of EventSequencer timeouts +* +* Modifies an EventSequencer object in-place to allow
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: OOjs: remove internal lib/ version and use npm instead
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/323353 Change subject: OOjs: remove internal lib/ version and use npm instead .. OOjs: remove internal lib/ version and use npm instead Change-Id: I23f1e0933023ed196b32af00d887674de21c5c4b --- M .jsduck/eg-iframe.html M build/modules.json M demos/ve/desktop-dist.html M demos/ve/desktop.html M demos/ve/minimal-rtl.html M demos/ve/minimal.html M demos/ve/mobile-dist.html M demos/ve/mobile.html D lib/oojs/AUTHORS.txt D lib/oojs/LICENSE-MIT.txt D lib/oojs/README.md D lib/oojs/oojs.jquery.js M package.json M tests/index.html 14 files changed, 10 insertions(+), 1,692 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/53/323353/1 diff --git a/.jsduck/eg-iframe.html b/.jsduck/eg-iframe.html index b7fb423..3eacb11 100644 --- a/.jsduck/eg-iframe.html +++ b/.jsduck/eg-iframe.html @@ -33,7 +33,7 @@ - + diff --git a/build/modules.json b/build/modules.json index d50d6ba..09e2b27 100644 --- a/build/modules.json +++ b/build/modules.json @@ -33,7 +33,7 @@ }, "oojs": { "scripts": [ - "lib/oojs/oojs.jquery.js" + "node_modules/oojs/dist/oojs.jquery.js" ] }, "oojs-ui": { diff --git a/demos/ve/desktop-dist.html b/demos/ve/desktop-dist.html index e51591e..adb08d5 100644 --- a/demos/ve/desktop-dist.html +++ b/demos/ve/desktop-dist.html @@ -47,7 +47,7 @@ - + diff --git a/demos/ve/desktop.html b/demos/ve/desktop.html index 7b88b5d..a2dfd8b 100644 --- a/demos/ve/desktop.html +++ b/demos/ve/desktop.html @@ -102,7 +102,7 @@ - + diff --git a/demos/ve/minimal-rtl.html b/demos/ve/minimal-rtl.html index f4d08ee..db74763 100644 --- a/demos/ve/minimal-rtl.html +++ b/demos/ve/minimal-rtl.html @@ -40,7 +40,7 @@ - + diff --git a/demos/ve/minimal.html b/demos/ve/minimal.html index 2f0c730..4388b0b 100644 --- a/demos/ve/minimal.html +++ b/demos/ve/minimal.html @@ -40,7 +40,7 @@ - + diff --git a/demos/ve/mobile-dist.html b/demos/ve/mobile-dist.html index db92755..50c719d 100644 --- a/demos/ve/mobile-dist.html +++ b/demos/ve/mobile-dist.html @@ -47,7 +47,7 @@ - + diff --git a/demos/ve/mobile.html b/demos/ve/mobile.html index 4168a23..8e0af33 100644 --- a/demos/ve/mobile.html +++ b/demos/ve/mobile.html @@ -100,7 +100,7 @@ - + diff --git a/lib/oojs/AUTHORS.txt b/lib/oojs/AUTHORS.txt deleted file mode 100644 index f5bce10..000 --- a/lib/oojs/AUTHORS.txt +++ /dev/null @@ -1,8 +0,0 @@ -Bartosz Dziewoński-David Chan -Ed Sanders -James D. Forrester -Ori Livneh -Roan Kattouw -Timo Tijhof -Trevor Parscal diff --git a/lib/oojs/LICENSE-MIT.txt b/lib/oojs/LICENSE-MIT.txt deleted file mode 100644 index 1eef012..000 --- a/lib/oojs/LICENSE-MIT.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright 2011-2015 OOjs Team and other contributors. - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/lib/oojs/README.md b/lib/oojs/README.md deleted file mode 100644 index df6b2f9..000 ---
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Rebase logic
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/322714 Change subject: Rebase logic .. Rebase logic Change-Id: I2876abff50eb37a80b8c2407db64a6e39393aed1 --- M build/modules.json A src/dm/ve.dm.RebaseClient.js A src/dm/ve.dm.RebaseServer.js A tests/dm/ve.dm.RebaseServer.test.js M tests/index.html 5 files changed, 584 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/14/322714/1 diff --git a/build/modules.json b/build/modules.json index 6da8b1c..010e68f 100644 --- a/build/modules.json +++ b/build/modules.json @@ -603,6 +603,15 @@ "diffMatchPatch" ] }, + "visualEditor.rebase": { + "scripts": [ + "src/dm/ve.dm.RebaseServer.js", + "src/dm/ve.dm.RebaseClient.js" + ], + "dependencies": [ + "visualEditor.core.build" + ] + }, "visualEditor.test": { "scripts": [ "tests/ve.qunit.js", @@ -631,6 +640,7 @@ "tests/dm/ve.dm.LinearData.test.js", "tests/dm/ve.dm.Transaction.test.js", "tests/dm/ve.dm.Change.test.js", + "tests/dm/ve.dm.RebaseServer.test.js", "tests/dm/ve.dm.TransactionProcessor.test.js", "tests/dm/ve.dm.APIResultsQueue.test.js", "tests/dm/ve.dm.Surface.test.js", @@ -712,7 +722,8 @@ "dependencies": [ "jsdifflib", "qunit", - "visualEditor.desktop.standalone" + "visualEditor.desktop.standalone", + "visualEditor.rebase" ] }, "visualEditor.theme.apex": { diff --git a/src/dm/ve.dm.RebaseClient.js b/src/dm/ve.dm.RebaseClient.js new file mode 100644 index 000..4b483d0 --- /dev/null +++ b/src/dm/ve.dm.RebaseClient.js @@ -0,0 +1,162 @@ +/*! + * VisualEditor DataModel rebase client class. + * + * @copyright 2011-2016 VisualEditor Team and others; see http://ve.mit-license.org + */ + +// FIXME: Remove before merging +/* global console */ +/* eslint-disable no-console */ + +/** + * DataModel rebase client + * + * @class + */ +ve.dm.RebaseClient = function VeDmRebaseClient() { + /** +* @property {number} Author ID +*/ + this.author = null; + + /** +* @property {number} Offset up to which we know we have no differences with the server +*/ + this.commitLength = 0; + + /** +* @property {number} Offset up to which we have no unsent changes +*/ + this.sentLength = 0; + + /** +* @property {number} Number of transactions backtracked (i.e. rejected) since the last send +*/ + this.backtrack = 0; +}; + +/* Inheritance */ + +OO.initClass( ve.dm.RebaseClient ); + +/** Abstract methods */ + +/** + * @param {number} start Start point for the change + * @param {boolean} toSubmit If true, mark current selection as sent + * @return {ve.dm.Change} The change since start in the client's local history + */ +ve.dm.RebaseClient.prototype.getChangeSince = null; + +/** + * @param {number} backtrack Number of rejected changes backtracked immediately before this change + * @param {ve.dm.Change} change The change to send + */ +ve.dm.RebaseClient.prototype.sendChange = null; + +/** + * Apply a change to the surface, and add it to the history + * + * @param {ve.dm.Change} change The change to apply + */ +ve.dm.RebaseClient.prototype.applyChange = null; + +/** + * Unapply a change from the surface, and remove it from the history + * + * @param {ve.dm.Change} change The change to unapply + */ +ve.dm.RebaseClient.prototype.unapplyChange = null; + +/** + * Add a change to history, without applying it to the surface + * + * @param {ve.dm.Change} change The change to add + */ +ve.dm.RebaseClient.prototype.addToHistory = null; + +/** + * Remove a change from history, without unapplying it to the surface + * + * @param {ve.dm.Change} change The change to remove + */ +ve.dm.RebaseClient.prototype.removeFromHistory = null; + +/* Methods */ + +/** + * @return {number} Author ID + */ +ve.dm.RebaseClient.prototype.getAuthor = function () { + return this.author; +}; + +/** + * @param {number} author Author ID + */ +ve.dm.RebaseClient.prototype.setAuthor = function ( author ) { + this.author = author; +}; + +/** + * Submit all outstanding changes + * + * This will submit all transactions that exist in local history but have not been broadcast + * by the server. + */ +ve.dm.RebaseClient.prototype.submitChange = function () { + var change = this.getChangeSince( this.sentLength, true ); + if ( change.isEmpty() ) {
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: WIP: Partial change rebasing in the case of conflicts
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/319522 Change subject: WIP: Partial change rebasing in the case of conflicts .. WIP: Partial change rebasing in the case of conflicts Change-Id: Ice73a863008c41078c2d931cd1f84a2a4661a9c2 --- M src/dm/ve.dm.Change.js M tests/dm/ve.dm.Change.test.js 2 files changed, 35 insertions(+), 19 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/22/319522/1 diff --git a/src/dm/ve.dm.Change.js b/src/dm/ve.dm.Change.js index 10dd578..f224d3c 100644 --- a/src/dm/ve.dm.Change.js +++ b/src/dm/ve.dm.Change.js @@ -193,8 +193,8 @@ * rebased onto a1 * ... * aN . Iteratively we can take the same approach to rebase over * b2,...,bM, giving both rebased lists as required. * - * If any of the transaction rebases conflict, then we immediately return a conflict for the - * whole change rebase. + * If any of the transaction rebases conflict, then we return all of a1,...,aN rebased onto + * the largest non-conflicting initial segment b1,...,bK (where clearly K < M). * * If ordering is ambiguous (two inserts at the same location), the insert for the transaction * with the highest author ID is put first (Javascript less-than is used, so comparisons with @@ -203,11 +203,14 @@ * * @param {ve.dm.Change} changeA A change * @param {ve.dm.Change} changeB Another change - * @return {ve.dm.Change[]} [ changeAOnChangeB, changeBOnChangeA ], or [ null, null ] if conflict - * @throws {Error} If changeA and changeB have different starts + * @return {Object} Rebased changeA and (the largest non-conflicting initial segment of) changeB + * @return {ve.dm.Change} return.a All of changeA rebased onto an initial segment of changeB + * @return {ve.dm.Change} return.b An initial segment of changeB rebased onto all of changeA + * @return {boolean} return.conflict Whether part of changeB was rejected due to conflict */ ve.dm.Change.static.rebaseChanges = function ( changeA, changeB ) { - var i, iLen, b, j, jLen, a, rebases, + var i, iLen, b, j, jLen, a, rebases, rebasedTransactionsA, + conflict = false, transactionsA = changeA.transactions.slice(), transactionsB = changeB.transactions.slice(); @@ -234,9 +237,11 @@ // // These identities hold if all the rebases work; if any of them fail, the entire // rebase fails and we return null values. + bLoop: for ( i = 0, iLen = transactionsB.length; i < iLen; i++ ) { b = transactionsB[ i ]; // Rebase transactions list onto otherTx + rebasedTransactionsA = []; for ( j = 0, jLen = transactionsA.length; j < jLen; j++ ) { a = transactionsA[ j ]; if ( a.author < b.author ) { @@ -244,30 +249,34 @@ } else { rebases = ve.dm.Transaction.rebaseTransactions( a, b ); } - transactionsA[ j ] = rebases[ 0 ]; - b = rebases[ 1 ]; - if ( b === null ) { - return [ null, null ]; + if ( rebases[ 0 ] === null ) { + conflict = true; + transactionsB.length = i; + break bLoop; } + rebasedTransactionsA[ j ] = rebases[ 0 ]; + b = rebases[ 1 ]; } + transactionsA = rebasedTransactionsA; transactionsB[ i ] = b; } - return [ + return { // These length calculations assume no removal of empty rebased transactions - new ve.dm.Change( - changeA.transactionStart + changeB.transactions.length, + a: new ve.dm.Change( + changeA.transactionStart + transactionsB.length, transactionsA, changeB.storeStart + changeB.store.getLength(), changeA.store.difference( changeB.store ) ), - new ve.dm.Change( - changeB.transactionStart + changeA.transactions.length, + b: new ve.dm.Change( + changeB.transactionStart + transactionsA.length, transactionsB, changeA.storeStart + changeA.store.getLength(), changeB.store.difference( changeA.store ) - ) - ]; + ), + conflict: conflict + }; }; /* Methods */ @@ -312,10 +321,13 @@ * @throws {Error} If this change and other have different starts */ ve.dm.Change.prototype.rebasedOnto = function ( other,
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: ve.dm.Transaction: add 'author' field
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/317373 Change subject: ve.dm.Transaction: add 'author' field .. ve.dm.Transaction: add 'author' field Also remove toJSON method, as it is no longer needed Change-Id: Icfbd542d0c66ecc656bd734d1d1fb44dd1869d90 --- M src/dm/ve.dm.Transaction.js M tests/dm/ve.dm.Transaction.test.js 2 files changed, 7 insertions(+), 13 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/73/317373/1 diff --git a/src/dm/ve.dm.Transaction.js b/src/dm/ve.dm.Transaction.js index 1b25e82..05f10af 100644 --- a/src/dm/ve.dm.Transaction.js +++ b/src/dm/ve.dm.Transaction.js @@ -25,6 +25,7 @@ ve.dm.Transaction = function VeDmTransaction( operations ) { this.operations = operations || []; this.applied = false; + this.author = null; }; /* Static Methods */ @@ -904,15 +905,6 @@ /* Methods */ /** - * Get a serializable object describing the transaction - * - * @return {Object} Serializable object - */ -ve.dm.Transaction.prototype.toJSON = function () { - return this.operations; -}; - -/** * Get a human-readable summary * * @return {string} Human-readable summary @@ -932,7 +924,7 @@ } } ).join( '' ) + '\''; } - return '(' + this.operations.map( function ( op ) { + return '(' + this.author + ' ' + this.operations.map( function ( op ) { if ( op.type === 'retain' ) { return ( annotations ? 'annotate ' : 'retain ' ) + op.length; } else if ( op.type === 'replace' ) { @@ -970,6 +962,7 @@ ve.dm.Transaction.prototype.clone = function () { var tx = new this.constructor(); tx.operations = ve.copy( this.operations ); + tx.author = this.author; return tx; }; @@ -997,6 +990,7 @@ } tx.operations.push( newOp ); } + tx.author = this.author; return tx; }; diff --git a/tests/dm/ve.dm.Transaction.test.js b/tests/dm/ve.dm.Transaction.test.js index 8d1b295..d16c7b1 100644 --- a/tests/dm/ve.dm.Transaction.test.js +++ b/tests/dm/ve.dm.Transaction.test.js @@ -2464,7 +2464,7 @@ } ); } ); -QUnit.test( 'toJSON/build with operations', function ( assert ) { +QUnit.test( 'operations/build from operations', function ( assert ) { var i, tx, ops, doc = ve.dm.example.createExampleDocument(), underline = ve.dm.example.createAnnotation( ve.dm.example.underline ), @@ -2545,8 +2545,8 @@ for ( i = 0; i < cases.length; i++ ) { tx = ve.dm.Transaction[ cases[ i ].method ].apply( ve.dm.Transaction, cases[ i ].args ); - ops = JSON.parse( JSON.stringify( tx.toJSON() ) ); - assert.deepEqual( ops, cases[ i ].expected, cases[ i ].msg + ': toJSON' ); + ops = ve.copy( tx.operations ); + assert.deepEqual( ops, cases[ i ].expected, cases[ i ].msg + ': operations' ); if ( cases[ i ].roundTripArgs ) { tx = ve.dm.Transaction[ cases[ i ].method ].apply( ve.dm.Transaction, cases[ i ].roundTripArgs ); } -- To view, visit https://gerrit.wikimedia.org/r/317373 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Icfbd542d0c66ecc656bd734d1d1fb44dd1869d90 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Fix translateRange bug that expands selections
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/317330 Change subject: Fix translateRange bug that expands selections .. Fix translateRange bug that expands selections Change-Id: Ib93e88afe8a4be61fa3306db87d6f51f6f495198 --- M src/dm/selections/ve.dm.LinearSelection.js M src/dm/selections/ve.dm.NullSelection.js M src/dm/selections/ve.dm.TableSelection.js M src/dm/ve.dm.Selection.js M src/dm/ve.dm.Surface.js M src/dm/ve.dm.Transaction.js M tests/dm/ve.dm.Surface.test.js 7 files changed, 63 insertions(+), 2 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/30/317330/1 diff --git a/src/dm/selections/ve.dm.LinearSelection.js b/src/dm/selections/ve.dm.LinearSelection.js index e97d81c..4dc4251 100644 --- a/src/dm/selections/ve.dm.LinearSelection.js +++ b/src/dm/selections/ve.dm.LinearSelection.js @@ -106,6 +106,13 @@ /** * @inheritdoc */ +ve.dm.Selection.prototype.translateByTransactionWithBias = function ( tx, bias ) { + return new this.constructor( this.getDocument(), tx.translateRangeWithBias( this.getRange(), bias ) ); +}; + +/** + * @inheritdoc + */ ve.dm.LinearSelection.prototype.getRanges = function () { return [ this.range ]; }; diff --git a/src/dm/selections/ve.dm.NullSelection.js b/src/dm/selections/ve.dm.NullSelection.js index 7f0a370..aa34916 100644 --- a/src/dm/selections/ve.dm.NullSelection.js +++ b/src/dm/selections/ve.dm.NullSelection.js @@ -73,6 +73,8 @@ ve.dm.NullSelection.prototype.translateByTransaction = ve.dm.NullSelection.prototype.clone; +ve.dm.NullSelection.prototype.translateByTransactionWithBias = ve.dm.NullSelection.prototype.clone; + /** * @inheritdoc */ diff --git a/src/dm/selections/ve.dm.TableSelection.js b/src/dm/selections/ve.dm.TableSelection.js index def74f1..ad13733 100644 --- a/src/dm/selections/ve.dm.TableSelection.js +++ b/src/dm/selections/ve.dm.TableSelection.js @@ -303,6 +303,21 @@ }; /** + * @inheritdoc + */ +ve.dm.TableSelection.prototype.translateByTransactionWithBias = function ( tx, bias ) { + var newRange = tx.translateRangeWithBias( this.tableRange, bias ); + + if ( newRange.isCollapsed() ) { + return new ve.dm.NullSelection( this.getDocument() ); + } + return new this.constructor( + this.getDocument(), newRange, + this.fromCol, this.fromRow, this.toCol, this.toRow + ); +}; + +/** * Check if the selection spans a single cell * * @return {boolean} The selection spans a single cell diff --git a/src/dm/ve.dm.Selection.js b/src/dm/ve.dm.Selection.js index dc80892..92b519e 100644 --- a/src/dm/ve.dm.Selection.js +++ b/src/dm/ve.dm.Selection.js @@ -140,6 +140,17 @@ ve.dm.Selection.prototype.translateByTransaction = null; /** + * Apply translations from a transaction + * + * @abstract + * @method + * @param {ve.dm.Transaction} tx Transaction + * @param {string} [bias] The bias, forward|backward + * @return {ve.dm.Selection} A new translated selection + */ +ve.dm.Selection.prototype.translateByTransactionWithBias = null; + +/** * Apply translations from a set of transactions * * @param {ve.dm.Transaction[]} txs Transactions diff --git a/src/dm/ve.dm.Surface.js b/src/dm/ve.dm.Surface.js index 7e6ac5f..716c5fe 100644 --- a/src/dm/ve.dm.Surface.js +++ b/src/dm/ve.dm.Surface.js @@ -931,7 +931,7 @@ * @fires documentUpdate */ ve.dm.Surface.prototype.onDocumentTransact = function ( tx ) { - this.setSelection( this.getSelection().translateByTransaction( tx ) ); + this.setSelection( this.getSelection().translateByTransactionWithBias( tx, 'backward' ) ); this.emit( 'documentUpdate', tx ); }; diff --git a/src/dm/ve.dm.Transaction.js b/src/dm/ve.dm.Transaction.js index 36c05a2..c811b2b 100644 --- a/src/dm/ve.dm.Transaction.js +++ b/src/dm/ve.dm.Transaction.js @@ -1114,7 +1114,7 @@ }; /** - * Translate a range based on a transaction. + * Translate a range based on the transaction, with grow/shrink preference at changes * * This is useful when you want to anticipate what a selection will be after a transaction is * processed. @@ -1133,6 +1133,20 @@ }; /** + * Translate a range based on the transaction, with forward/backward preference at changes + * + * @see #translateOffset + * @param {ve.Range} range Range in the linear model before the transaction has been processed + * @param {string} bias Preference for moving range boundaries at insertions: forward|backward + * @return {ve.Range} Translated range, as it will be after processing transaction + */ +ve.dm.Transaction.prototype.translateRangeWithBias = function ( range, bias ) { + var start = this.translateOffset( range.start, bias === 'backward' ), + end = this.translateOffset( range.end, bias === 'backward' ); + return range.isBackwards() ? new ve.Range( end, start ) : new
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Human-readable transaction summary
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/317094 Change subject: Human-readable transaction summary .. Human-readable transaction summary Change-Id: I6920514df81c304a02a672a2eabffb91a8f1e5e7 --- M src/dm/ve.dm.Transaction.js 1 file changed, 46 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/94/317094/1 diff --git a/src/dm/ve.dm.Transaction.js b/src/dm/ve.dm.Transaction.js index 36c05a2..1b25e82 100644 --- a/src/dm/ve.dm.Transaction.js +++ b/src/dm/ve.dm.Transaction.js @@ -913,6 +913,52 @@ }; /** + * Get a human-readable summary + * + * @return {string} Human-readable summary + */ +ve.dm.Transaction.prototype.summarize = function () { + var annotations = 0; + function summarizeItems( items ) { + return '\'' + items.map( function ( item ) { + if ( item.type ) { + return '<' + item.type + '>'; + } else if ( Array.isArray( item ) ) { + return item[ 0 ]; + } else if ( typeof item === 'string' ) { + return item; + } else { + throw new Error( 'Unknown item type: ' + item ); + } + } ).join( '' ) + '\''; + } + return '(' + this.operations.map( function ( op ) { + if ( op.type === 'retain' ) { + return ( annotations ? 'annotate ' : 'retain ' ) + op.length; + } else if ( op.type === 'replace' ) { + if ( op.remove.length === 0 ) { + return 'insert ' + summarizeItems( op.insert ); + } else if ( op.insert.length === 0 ) { + return 'remove ' + summarizeItems( op.remove ); + } else { + return 'replace ' + summarizeItems( op.remove ) + + ' -> ' + summarizeItems( op.insert ); + } + } else if ( op.type === 'attribute' ) { + return 'attribute'; + } else if ( op.type === 'annotate' ) { + annotations += op.bias === 'start' ? 1 : -1; + return 'annotate'; + } else if ( op.type.endsWith( 'Metadata' ) ) { + // We don't care much because we're deprecating this + return 'metadata'; + } else { + throw new Error( 'Unknown op type: ' + op.type ); + } + } ).join( ', ' ) + ')'; +}; + +/** * Create a clone of this transaction. * * The returned transaction will be exactly the same as this one, except that its 'applied' flag -- To view, visit https://gerrit.wikimedia.org/r/317094 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I6920514df81c304a02a672a2eabffb91a8f1e5e7 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Allow shallow clone of whole document
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/317088 Change subject: Allow shallow clone of whole document .. Allow shallow clone of whole document Change-Id: Ic35a724bceb9de69ffe81b5d61d4d9ec5b99189e --- M src/dm/ve.dm.Document.js 1 file changed, 3 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/88/317088/1 diff --git a/src/dm/ve.dm.Document.js b/src/dm/ve.dm.Document.js index 901f951..af01a77 100644 --- a/src/dm/ve.dm.Document.js +++ b/src/dm/ve.dm.Document.js @@ -448,7 +448,7 @@ * * The new document's elements, internal list and store will only contain references to data within the slice. * - * @param {ve.Range} range Range of data to slice + * @param {ve.Range} [range] Range of data to slice; defaults to whole document * @return {ve.dm.DocumentSlice} New document */ ve.dm.Document.prototype.shallowCloneFromRange = function ( range ) { @@ -463,6 +463,8 @@ contextOpenings = [], contextClosings = []; + range = range || new ve.Range( 0, this.data.getLength() ); + // Fix up selection to remove empty items in unwrapped nodes // TODO: fix this is selectNodes while ( selection[ 0 ] && selection[ 0 ].range && selection[ 0 ].range.isCollapsed() && !selection[ 0 ].node.isWrapped() ) { -- To view, visit https://gerrit.wikimedia.org/r/317088 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ic35a724bceb9de69ffe81b5d61d4d9ec5b99189e Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: ve.sparseSplice: Splice one array into another, replicating ...
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/315657 Change subject: ve.sparseSplice: Splice one array into another, replicating any holes .. ve.sparseSplice: Splice one array into another, replicating any holes Change-Id: I6a06cf90d7036c8bdadadd74c4a667b36e54d72b --- M src/ve.utils.js M tests/ve.test.js 2 files changed, 123 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/57/315657/1 diff --git a/src/ve.utils.js b/src/ve.utils.js index 013d85a..4f18c13 100644 --- a/src/ve.utils.js +++ b/src/ve.utils.js @@ -224,7 +224,7 @@ * Includes a replacement for broken implementations of Array.prototype.splice(). * * @param {Array|ve.dm.BranchNode} arr Target object (must have `splice` method, object will be modified) - * @param {number} offset Offset in arr to splice at. This may NOT be negative, unlike the + * @param {number} offset Offset in arr to splice at. This MUST NOT be negative, unlike the * 'index' parameter in Array#splice. * @param {number} remove Number of elements to remove at the offset. May be zero * @param {Array} data Array of items to insert at the offset. Must be non-empty if remove=0 @@ -287,6 +287,56 @@ }; /** + * Splice one array into another, replicating any holes + * + * Similar to arr.splice.apply( arr, [ offset, remove ].concat( data ) ), except + * holes in data are copied remain holes in arr. Optimized for length changes that are + * negative, zero, or fairly small positive. + * + * @param {Array} arr Array to modify + * @param {number} offset Offset in arr to splice at. This MUST NOT be negative, unlike the + * 'index' parameter in Array#splice. + * @param {number} remove Number of elements to remove at the offset. May be zero + * @param {Array} data Array of items to insert at the offset + * @return {Array} Array of items removed, with holes preserved + */ +ve.sparseSplice = function ( arr, offset, remove, data ) { + var i, + removed = [], + endOffset = offset + remove, + diff = data.length - remove; + if ( data === arr ) { + // Pathological case: arr and data are reference-identical + data = data.slice(); + } + // Remove content without adjusting length + arr.slice( offset, endOffset ).forEach( function ( item, i ) { + removed[ i ] = item; + delete arr[ offset + i ]; + } ); + // Adjust length + if ( diff > 0 ) { + // Grow with undefined values, then delete. (This is optimised for diff + // comparatively small: otherwise, it would sometimes be quicker to relocate + // each element of arr that lies above offset). + ve.batchSplice( arr, endOffset, 0, new Array( diff ) ); + for ( i = endOffset + diff - 1; i >= endOffset; i-- ) { + delete arr[ i ]; + } + } else if ( diff < 0 ) { + // Shrink + arr.splice( offset, -diff ); + } + // Insert new content + data.forEach( function ( item, i ) { + arr[ offset + i ] = item; + } ); + // Set removed.length in case there are holes at the end + removed.length = remove; + return removed; +}; + +/** * Insert one array into another. * * Shortcut for `ve.batchSplice( arr, offset, 0, src )`. diff --git a/tests/ve.test.js b/tests/ve.test.js index 8555a38..3997b5c 100644 --- a/tests/ve.test.js +++ b/tests/ve.test.js @@ -266,6 +266,78 @@ ); } ); +QUnit.test( 'sparseSplice', function ( assert ) { + var tests, i, len, test; + // Convert a sparse array of primitives to an array of strings, with '' for holes. + // This is needed because QUnit.equiv treats holes as equivalent to undefined. + function mapToString( flatArray ) { + var j, jLen, + strings = []; + for ( j = 0, jLen = flatArray.length; j < jLen; j++ ) { + strings.push( flatArray.hasOwnProperty( j ) ? String( flatArray[ j ] ) : '' ); + } + return strings; + } + function runTest( arr, offset, remove, data, expectedReturn, expectedArray, msg ) { + var observedReturn, + testArr = arr.slice(); + + observedReturn = ve.sparseSplice( testArr, offset, remove, data ); + assert.deepEqual( + mapToString( observedReturn ), + mapToString( expectedReturn ), + msg + ': return' + ); + assert.deepEqual( + mapToString( testArr ), + mapToString( expectedArray ), + msg + ': modification' + ); + } +
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: ve.Range: Don't fixup invalid arguments
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/315199 Change subject: ve.Range: Don't fixup invalid arguments .. ve.Range: Don't fixup invalid arguments Hitherto, calls such as "new ve.Range( NaN, undefined )" that indicate a programming error were having their invalid arguments whitewashed to 0. This impeded debugging, particularly as range calculation errors can often propagate quite far before surfacing. Change-Id: I05a99fb8f6760af875aca64400832e9ade236fac --- M src/ve.Range.js 1 file changed, 7 insertions(+), 3 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/99/315199/1 diff --git a/src/ve.Range.js b/src/ve.Range.js index c12dccf..4047200 100644 --- a/src/ve.Range.js +++ b/src/ve.Range.js @@ -8,12 +8,16 @@ * @class * * @constructor - * @param {number} from Anchor offset + * @param {number} [from=0] Anchor offset * @param {number} [to=from] Focus offset */ ve.Range = function VeRange( from, to ) { - this.from = from || 0; - this.to = to === undefined ? this.from : to; + // For ease of debugging, check arguments.length when applying defaults, to preserve + // invalid arguments such as undefined and NaN that indicate a programming error. + // Range calculation errors often seem to propagate quite far before surfacing, so the + // indication is important. + this.from = arguments.length >= 1 ? from : 0; + this.to = arguments.length >= 2 ? to : this.from; this.start = this.from < this.to ? this.from : this.to; this.end = this.from < this.to ? this.to : this.from; }; -- To view, visit https://gerrit.wikimedia.org/r/315199 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I05a99fb8f6760af875aca64400832e9ade236fac Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Apply inserted annotations above background annotation stack
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/315198 Change subject: Apply inserted annotations above background annotation stack .. Apply inserted annotations above background annotation stack Bug: T142245 Change-Id: I52b0b3de6cf835c16fdee441e48b85a7c920c54e --- M src/dm/ve.dm.SurfaceFragment.js M tests/ce/ve.ce.Surface.test.js 2 files changed, 34 insertions(+), 42 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/98/315198/1 diff --git a/src/dm/ve.dm.SurfaceFragment.js b/src/dm/ve.dm.SurfaceFragment.js index c7456b5..140b09e 100644 --- a/src/dm/ve.dm.SurfaceFragment.js +++ b/src/dm/ve.dm.SurfaceFragment.js @@ -851,7 +851,7 @@ * @chainable */ ve.dm.SurfaceFragment.prototype.insertDocument = function ( newDoc, newDocRange, annotate ) { - var tx, newRange, annotations, offset, + var tx, newRange, annotations, offset, i, item, range = this.getSelection().getCoveringRange(), doc = this.getDocument(); @@ -877,17 +877,35 @@ .getAnnotationsFromOffset( offset === 0 ? 0 : offset - 1 ); } - tx = ve.dm.Transaction.newFromDocumentInsertion( doc, offset, newDoc, newDocRange ); + if ( annotations && annotations.getLength() > 0 ) { + // Backup newDoc.data.data, to restore below + // TODO: clone newDoc instead? Or just let this method modify newDoc? + newDoc.data.origData = newDoc.data.slice(); + for ( i = newDocRange.start; i < newDocRange.end; i++ ) { + item = newDoc.data.data[ i ]; + if ( Array.isArray( item ) ) { + newDoc.data.data[ i ] = [ + item[ 0 ], + annotations.storeIndexes.concat( item[ 1 ] ) + ]; + } else { + newDoc.data.data[ i ] = [ item, annotations.storeIndexes.slice() ]; + } + } + } + try { + tx = ve.dm.Transaction.newFromDocumentInsertion( doc, offset, newDoc, newDocRange ); + } finally { + // Restore newDoc.data.data + newDoc.data.data = newDoc.data.origData; + delete newDoc.data.origData; + } if ( !tx.isNoOp() ) { // Set the range to cover the inserted content; the offset translation will be wrong // if newFromInsertion() decided to move the insertion point newRange = tx.getModifiedRange( doc ); this.change( tx, newRange ? new ve.dm.LinearSelection( doc, newRange ) : new ve.dm.NullSelection( doc ) ); - if ( annotations && annotations.getLength() > 0 ) { - this.annotateContent( 'set', annotations ); - } } - return this; }; diff --git a/tests/ce/ve.ce.Surface.test.js b/tests/ce/ve.ce.Surface.test.js index 7adbd27..456f7d9 100644 --- a/tests/ce/ve.ce.Surface.test.js +++ b/tests/ce/ve.ce.Surface.test.js @@ -1427,28 +1427,15 @@ { type: 'retain', length: 25 }, { type: 'replace', - insert: [ 'F', 'o', 'o' ], + insert: [ + [ 'F', [ bold ] ], + [ 'o', [ bold ] ], + [ 'o', [ bold ] ] + ], remove: [] }, { type: 'retain', length: docLen - 25 } ], - [ - { type: 'retain', length: 25 }, - { - type: 'annotate', - method: 'set', - bias: 'start', - index: ve.dm.example.annIndex( 'b', 'Quux' ) - }, - { type: 'retain', length: 3 }, - { - type: 'annotate', - method:
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Optimize batchPush on small lists
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/315196 Change subject: Optimize batchPush on small lists .. Optimize batchPush on small lists Doubles the speed of ve.batchPush( [], [ 1, 2, 3, 4, 5 ] ) on Chromium Change-Id: I187381a3c5dfaed536f15195630365721728bb76 --- M src/ve.utils.js 1 file changed, 4 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/96/315196/1 diff --git a/src/ve.utils.js b/src/ve.utils.js index d59da58..013d85a 100644 --- a/src/ve.utils.js +++ b/src/ve.utils.js @@ -316,6 +316,10 @@ var length, index = 0, batchSize = 1024; + if ( batchSize >= data.length ) { + // Avoid slicing for small lists + return arr.push.apply( arr, data ); + } while ( index < data.length ) { // Call arr.push( i0, i1, i2, ..., i1023 ); length = arr.push.apply( -- To view, visit https://gerrit.wikimedia.org/r/315196 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I187381a3c5dfaed536f15195630365721728bb76 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Check for null keyDownSelectionState in handlers
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/313997 Change subject: Check for null keyDownSelectionState in handlers .. Check for null keyDownSelectionState in handlers Bug: T147304 Change-Id: I0b910feb6a09159915d987bbaa9bd45c1877d1b2 --- M src/ce/ve.ce.Surface.js 1 file changed, 4 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/97/313997/1 diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js index 6e1167b..bb27c09 100644 --- a/src/ce/ve.ce.Surface.js +++ b/src/ce/ve.ce.Surface.js @@ -83,7 +83,7 @@ // Snapshot updated at keyDown. See storeKeyDownState. this.keyDownState = { event: null, - selection: null + selectionState: null }; this.cursorDirectionality = null; @@ -576,6 +576,7 @@ // Remove ranges so the user can't accidentally type into the document this.nativeSelection.removeAllRanges(); this.updateDeactivatedSelection(); + this.clearKeyDownState(); } }; @@ -1272,6 +1273,7 @@ function getDirection() { return ( isArrow && + keyDownSelectionState && ve.compareDocumentOrder( surface.nativeSelection.focusNode, surface.nativeSelection.focusOffset, @@ -1360,6 +1362,7 @@ !e.ctrlKey && !e.altKey && !e.metaKey && + keyDownSelectionState && keyDownSelectionState.isCollapsed && this.nativeSelection.isCollapsed && ( direction = getDirection() ) !== null -- To view, visit https://gerrit.wikimedia.org/r/313997 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I0b910feb6a09159915d987bbaa9bd45c1877d1b2 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: On CBN detach, mark contentBranchNodeChanged in the CE Surface
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/311371 Change subject: On CBN detach, mark contentBranchNodeChanged in the CE Surface .. On CBN detach, mark contentBranchNodeChanged in the CE Surface Bug: T122291 Change-Id: I0930ac8d227a8a1cff86bd5fdd38be42ec979b61 --- M src/ce/ve.ce.ContentBranchNode.js 1 file changed, 7 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/71/311371/1 diff --git a/src/ce/ve.ce.ContentBranchNode.js b/src/ce/ve.ce.ContentBranchNode.js index ee7ad80..94e6c0c 100644 --- a/src/ce/ve.ce.ContentBranchNode.js +++ b/src/ce/ve.ce.ContentBranchNode.js @@ -33,6 +33,7 @@ // Events this.connect( this, { childUpdate: 'onChildUpdate' } ); + this.model.connect( this, { detach: 'onModelDetach' } ); // Some browsers allow clicking links inside contenteditable, such as in iOS Safari when the // keyboard is closed this.$element.on( 'click', this.onClickHandler ); @@ -354,6 +355,12 @@ return wrapper; }; +ve.ce.ContentBranchNode.prototype.onModelDetach = function () { + if ( this.root instanceof ve.ce.DocumentNode ) { + this.root.getSurface().setContentBranchNodeChanged(); + } +}; + /** * Render contents. * -- To view, visit https://gerrit.wikimedia.org/r/311371 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I0930ac8d227a8a1cff86bd5fdd38be42ec979b61 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Test selections without relying on a ve.dm.Surface select ev...
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/311238 Change subject: Test selections without relying on a ve.dm.Surface select event listener .. Test selections without relying on a ve.dm.Surface select event listener Bug: T145938 Change-Id: I3cc3d3d0bf5eaef135160d762607cd799d48d910 --- M src/ui/ve.ui.DebugBar.js M tests/ce/ve.ce.Surface.test.js 2 files changed, 8 insertions(+), 13 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/38/311238/1 diff --git a/src/ui/ve.ui.DebugBar.js b/src/ui/ve.ui.DebugBar.js index 74c9187..3ba417f 100644 --- a/src/ui/ve.ui.DebugBar.js +++ b/src/ui/ve.ui.DebugBar.js @@ -113,6 +113,8 @@ * @param {ve.dm.Selection} selection */ ve.ui.DebugBar.prototype.onSurfaceSelect = function ( selection ) { + // Ignore the function argument, because nested emits can cause it to be outdated + selection = this.surface.model.getSelection(); this.selectionLabel.setLabel( selection.getDescription() ); this.logRangeButton.setDisabled( !( ( selection instanceof ve.dm.LinearSelection && !selection.isCollapsed() ) || diff --git a/tests/ce/ve.ce.Surface.test.js b/tests/ce/ve.ce.Surface.test.js index 5a2d5c6..7adbd27 100644 --- a/tests/ce/ve.ce.Surface.test.js +++ b/tests/ce/ve.ce.Surface.test.js @@ -9,23 +9,16 @@ /* Tests */ ve.test.utils.runSurfaceHandleSpecialKeyTest = function ( assert, htmlOrDoc, rangeOrSelection, keys, expectedData, expectedRangeOrSelection, msg, forceSelection, fullEvents ) { - var i, e, selection, expectedSelection, key, + var i, e, expectedSelection, key, view = typeof htmlOrDoc === 'string' ? ve.test.utils.createSurfaceViewFromHtml( htmlOrDoc ) : ( htmlOrDoc instanceof ve.ce.Surface ? htmlOrDoc : ve.test.utils.createSurfaceViewFromDocument( htmlOrDoc || ve.dm.example.createExampleDocument() ) ), model = view.getModel(), data = ve.copy( model.getDocument().getFullData() ); - // TODO: model.getSelection() should be consistent after it has been - // changed but appears to behave differently depending on the browser. - // The selection from the select event is still consistent. - selection = ve.test.utils.selectionFromRangeOrSelection( model.getDocument(), rangeOrSelection ); - - model.on( 'select', function ( s ) { - selection = s; - } ); - - model.setSelection( selection ); + model.setSelection( + ve.test.utils.selectionFromRangeOrSelection( model.getDocument(), rangeOrSelection ) + ); for ( i = 0; i < keys.length; i++ ) { key = keys[ i ].split( '+' ); e = { @@ -54,7 +47,7 @@ view.showSelectionState( view.getSelectionState( forceSelection ) ); } ve.ce.keyDownHandlerFactory.executeHandlersForKey( - e.keyCode, selection.getName(), view, e + e.keyCode, model.getSelection().getName(), view, e ); } } @@ -66,7 +59,7 @@ ); assert.equalLinearData( model.getDocument().getFullData(), data, msg + ': data' ); - assert.equalHash( selection, expectedSelection, msg + ': selection' ); + assert.equalHash( model.getSelection(), expectedSelection, msg + ': selection' ); view.destroy(); }; -- To view, visit https://gerrit.wikimedia.org/r/311238 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I3cc3d3d0bf5eaef135160d762607cd799d48d910 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Fix 'new ve.dm.Transaction.newFromInsertion' typos in tests
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/310544 Change subject: Fix 'new ve.dm.Transaction.newFromInsertion' typos in tests .. Fix 'new ve.dm.Transaction.newFromInsertion' typos in tests They were harmless because the function returned an object which supplants the spurious one 'new' creates. Change-Id: I46a6b8cf072f342c81eeb01e6659f2f0500445d6 --- M tests/dm/ve.dm.Surface.test.js 1 file changed, 11 insertions(+), 11 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/44/310544/1 diff --git a/tests/dm/ve.dm.Surface.test.js b/tests/dm/ve.dm.Surface.test.js index c82285e..48cd63f 100644 --- a/tests/dm/ve.dm.Surface.test.js +++ b/tests/dm/ve.dm.Surface.test.js @@ -60,7 +60,7 @@ fragment = surface.getFragment(), doc = surface.getDocument(), selection = new ve.dm.LinearSelection( doc, range ), - tx = new ve.dm.Transaction.newFromInsertion( doc, 1, [ 'x' ] ); + tx = ve.dm.Transaction.newFromInsertion( doc, 1, [ 'x' ] ); assert.strictEqual( surface.breakpoint(), false, 'Returns false if no transactions applied' ); @@ -106,14 +106,14 @@ assert.strictEqual( surface.doesStagingAllowUndo(), undefined, 'doesStagingAllowUndo undefined when not staging' ); assert.equalHash( surface.getSelection(), fragment.getSelection(), 'Surface range matches fragment range' ); - surface.change( new ve.dm.Transaction.newFromInsertion( doc, 1, [ 'a' ] ) ); + surface.change( ve.dm.Transaction.newFromInsertion( doc, 1, [ 'a' ] ) ); surface.pushStaging(); assert.strictEqual( surface.isStaging(), true, 'isStaging true after pushStaging' ); assert.deepEqual( surface.getStagingTransactions(), [], 'getStagingTransactions empty array after pushStaging' ); assert.strictEqual( surface.doesStagingAllowUndo(), false, 'doesStagingAllowUndo false when staging without undo' ); - tx1 = new ve.dm.Transaction.newFromInsertion( doc, 2, [ 'b' ] ); + tx1 = ve.dm.Transaction.newFromInsertion( doc, 2, [ 'b' ] ); surface.change( tx1 ); assert.strictEqual( fragment.getText(), 'abhi', 'document contents match after first transaction' ); @@ -126,7 +126,7 @@ assert.strictEqual( surface.doesStagingAllowUndo(), true, 'doesStagingAllowUndo true when staging with undo' ); assert.equalHash( surface.getSelection(), fragment.getSelection(), 'Surface selection matches fragment range' ); - tx2 = new ve.dm.Transaction.newFromInsertion( doc, 3, [ 'c' ] ); + tx2 = ve.dm.Transaction.newFromInsertion( doc, 3, [ 'c' ] ); surface.change( tx2 ); assert.strictEqual( fragment.getText(), 'abchi', 'document contents match after second transaction' ); @@ -143,11 +143,11 @@ assert.equalHash( surface.getSelection(), fragment.getSelection(), 'Surface selection matches fragment range' ); surface.pushStaging(); - tx1 = new ve.dm.Transaction.newFromInsertion( doc, 2, [ 'b' ] ); + tx1 = ve.dm.Transaction.newFromInsertion( doc, 2, [ 'b' ] ); surface.change( tx1 ); surface.pushStaging(); - tx2 = new ve.dm.Transaction.newFromInsertion( doc, 3, [ 'c' ] ); + tx2 = ve.dm.Transaction.newFromInsertion( doc, 3, [ 'c' ] ); surface.change( tx2 ); assert.deepEqual( surface.popAllStaging(), [ tx1, tx2 ], 'popAllStaging returns full transaction list' ); @@ -155,11 +155,11 @@ assert.equalHash( surface.getSelection(), fragment.getSelection(), 'Surface selection matches fragment range' ); surface.pushStaging(); - tx1 = new ve.dm.Transaction.newFromInsertion( doc, 2, [ 'b' ] ); + tx1 = ve.dm.Transaction.newFromInsertion( doc, 2, [ 'b' ] ); surface.change( tx1 ); surface.pushStaging(); - tx2 = new ve.dm.Transaction.newFromInsertion( doc, 3, [ 'c' ] ); + tx2 = ve.dm.Transaction.newFromInsertion( doc, 3, [ 'c' ] ); surface.change( tx2 ); surface.applyStaging(); @@ -171,11 +171,11 @@ assert.equalHash( surface.getSelection(), fragment.getSelection(), 'Surface selection matches fragment range' ); surface.pushStaging(); - tx1 = new ve.dm.Transaction.newFromInsertion( doc, 4, [ 'd' ] ); + tx1 = ve.dm.Transaction.newFromInsertion( doc, 4, [ 'd' ] ); surface.change( tx1 ); surface.pushStaging(); - tx2 = new ve.dm.Transaction.newFromInsertion( doc, 5, [ 'e' ] ); + tx2 = ve.dm.Transaction.newFromInsertion( doc, 5, [ 'e' ] ); surface.change( tx2 ); surface.applyAllStaging(); @@ -190,7 +190,7 @@ surface.pushStaging(); surface.pushStaging(); // Apply transaction at second level, first level is empty and has no selctionBefore - tx1 = new
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Make ve.dm.Transaction plain data by removing the .doc property
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/308925 Change subject: Make ve.dm.Transaction plain data by removing the .doc property .. Make ve.dm.Transaction plain data by removing the .doc property Also clarify the required state for ve.dm.Document parameters Change-Id: Idf7c69ffe5cc54506fee3730a6290c1ae61cedc2 --- M src/dm/ve.dm.Surface.js M src/dm/ve.dm.SurfaceFragment.js M src/dm/ve.dm.Transaction.js M tests/dm/ve.dm.Document.test.js M tests/dm/ve.dm.MetaList.test.js M tests/dm/ve.dm.Transaction.test.js M tests/dm/ve.dm.TransactionProcessor.test.js 7 files changed, 51 insertions(+), 64 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/25/308925/1 diff --git a/src/dm/ve.dm.Surface.js b/src/dm/ve.dm.Surface.js index cefc7ac..7e6ac5f 100644 --- a/src/dm/ve.dm.Surface.js +++ b/src/dm/ve.dm.Surface.js @@ -1004,7 +1004,7 @@ this.getHistory().forEach( function ( stackItem ) { stackItem.transactions.forEach( function ( tx ) { - var newRange = tx.getModifiedRange(); + var newRange = tx.getModifiedRange( this.documentModel ); // newRange will by null for no-ops if ( newRange ) { // Translate previous ranges by the current transaction diff --git a/src/dm/ve.dm.SurfaceFragment.js b/src/dm/ve.dm.SurfaceFragment.js index 837ddd1..5326aea 100644 --- a/src/dm/ve.dm.SurfaceFragment.js +++ b/src/dm/ve.dm.SurfaceFragment.js @@ -777,7 +777,7 @@ tx = ve.dm.Transaction.newFromInsertion( doc, offset, content ); // Set the range to cover the inserted content; the offset translation will be wrong // if newFromInsertion() decided to move the insertion point - newRange = tx.getModifiedRange(); + newRange = tx.getModifiedRange( doc ); this.change( tx, newRange ? new ve.dm.LinearSelection( doc, newRange ) : new ve.dm.NullSelection( doc ) ); } @@ -845,7 +845,7 @@ if ( !tx.isNoOp() ) { // Set the range to cover the inserted content; the offset translation will be wrong // if newFromInsertion() decided to move the insertion point - newRange = tx.getModifiedRange(); + newRange = tx.getModifiedRange( doc ); this.change( tx, newRange ? new ve.dm.LinearSelection( doc, newRange ) : new ve.dm.NullSelection( doc ) ); if ( annotations && annotations.getLength() > 0 ) { this.annotateContent( 'set', annotations ); diff --git a/src/dm/ve.dm.Transaction.js b/src/dm/ve.dm.Transaction.js index 2d37988..22ae957 100644 --- a/src/dm/ve.dm.Transaction.js +++ b/src/dm/ve.dm.Transaction.js @@ -9,13 +9,11 @@ * * @class * @constructor - * @param {ve.dm.Document} doc The document to which this transaction applies * @param {Object[]} [operations] The operations comprising this transaction; default [] */ -ve.dm.Transaction = function VeDmTransaction( doc, operations ) { +ve.dm.Transaction = function VeDmTransaction( operations ) { this.operations = operations || []; this.applied = false; - this.doc = doc; }; /* Static Methods */ @@ -24,7 +22,7 @@ * Generate a transaction that replaces data in a range. * * @method - * @param {ve.dm.Document} doc Document to create transaction for + * @param {ve.dm.Document} doc Document in pre-transaction state * @param {ve.Range} range Range of data to remove * @param {Array} data Data to insert * @param {boolean} [removeMetadata=false] Remove metadata instead of collapsing it @@ -33,7 +31,7 @@ */ ve.dm.Transaction.newFromReplacement = function ( doc, range, data, removeMetadata ) { var endOffset, - tx = new ve.dm.Transaction( doc ); + tx = new ve.dm.Transaction(); endOffset = tx.pushRemoval( doc, 0, range, removeMetadata ); endOffset = tx.pushInsertion( doc, endOffset, endOffset, data ); tx.pushFinalRetain( doc, endOffset ); @@ -45,13 +43,13 @@ * * @static * @method - * @param {ve.dm.Document} doc Document to create transaction for + * @param {ve.dm.Document} doc Document in pre-transaction state * @param {number} offset Offset to insert at * @param {Array} data Data to insert * @return {ve.dm.Transaction} Transaction that inserts data */ ve.dm.Transaction.newFromInsertion = function ( doc, offset, data ) { - var tx = new ve.dm.Transaction( doc ), + var tx = new ve.dm.Transaction(), endOffset = tx.pushInsertion( doc, 0, offset, data ); // Retain to end of document, if needed (for completeness) tx.pushFinalRetain( doc, endOffset ); @@ -77,14 +75,14 @@ * 3. Merges take place at the highest common ancestor * * @method - *
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Fix 'new ve.dm.Transaction.newFromDocumentInsertion' typo
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/308919 Change subject: Fix 'new ve.dm.Transaction.newFromDocumentInsertion' typo .. Fix 'new ve.dm.Transaction.newFromDocumentInsertion' typo Seems to originate in Iaddc4a7e7cc42a468a62ae550637f3eaacb64e07 . It was harmless because the function returned an object which supplants the spurious one 'new' creates. Change-Id: I40b39815f0b39e1a57a2d32f58f8a1a0b454cbcb --- M src/dm/ve.dm.SurfaceFragment.js 1 file changed, 1 insertion(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/19/308919/1 diff --git a/src/dm/ve.dm.SurfaceFragment.js b/src/dm/ve.dm.SurfaceFragment.js index 837ddd1..f56087f 100644 --- a/src/dm/ve.dm.SurfaceFragment.js +++ b/src/dm/ve.dm.SurfaceFragment.js @@ -841,7 +841,7 @@ .getAnnotationsFromOffset( offset === 0 ? 0 : offset - 1 ); } - tx = new ve.dm.Transaction.newFromDocumentInsertion( doc, offset, newDoc, newDocRange ); + tx = ve.dm.Transaction.newFromDocumentInsertion( doc, offset, newDoc, newDocRange ); if ( !tx.isNoOp() ) { // Set the range to cover the inserted content; the offset translation will be wrong // if newFromInsertion() decided to move the insertion point -- To view, visit https://gerrit.wikimedia.org/r/308919 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I40b39815f0b39e1a57a2d32f58f8a1a0b454cbcb Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Make ve.dm.IndexValueStore ordered, append-only and slicable
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/306480 Change subject: Make ve.dm.IndexValueStore ordered, append-only and slicable .. Make ve.dm.IndexValueStore ordered, append-only and slicable Change-Id: I3428175d0c09c1d930b7bb03730bda2bf3d7fc03 --- M src/dm/ve.dm.IndexValueStore.js M tests/dm/ve.dm.IndexValueStore.test.js 2 files changed, 69 insertions(+), 11 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/80/306480/1 diff --git a/src/dm/ve.dm.IndexValueStore.js b/src/dm/ve.dm.IndexValueStore.js index f2ac182..45ff2e1 100644 --- a/src/dm/ve.dm.IndexValueStore.js +++ b/src/dm/ve.dm.IndexValueStore.js @@ -7,10 +7,13 @@ /* global SparkMD5 */ /** - * Hash-keyed value store + * Ordered append-only hash store, whose values once inserted are immutable * * Values are objects, strings or Arrays, and are hashed using an algorithm with low collision * probability: values with the same hash can be assumed equal. + * + * Values are stored in insertion order, and the store can be sliced to get a subset of values + * inserted consecutively. * * Two stores can be merged even if they have differently computed hashes, so long as two values * will (with high probability) have the same hash only if equal. In this case, equivalent @@ -22,11 +25,41 @@ * @constructor */ ve.dm.IndexValueStore = function VeDmIndexValueStore() { - // maps values to hashes + // Maps hashes to values this.hashStore = {}; + // hashes in order of insertion (used for slicing) + this.hashes = []; }; /* Methods */ + +/** + * Get the number of values in the store + * + * @return {number} Number of values in the store + */ +ve.dm.IndexValueStore.prototype.getLength = function () { + return this.hashes.length; +}; + +/** + * Return a new store containing a slice of the values in insertion order + * + * @param {number} [start] Include values from position start onwards (default: 0) + * @param {number} [end] Include values to position end exclusive (default: slice to end) + * @return {ve.dm.IndexValueStore} Slice of the current store (with non-cloned value references) + */ +ve.dm.IndexValueStore.prototype.slice = function ( start, end ) { + var i, len, hash, + sliced = new this.constructor(); + + sliced.hashes = this.hashes.slice( start, end ); + for ( i = 0, len = sliced.hashes.length; i < len; i++ ) { + hash = sliced.hashes[ i ]; + sliced.hashStore[ hash ] = this.hashStore[ hash ]; + } + return sliced; +}; /** * Insert a value into the store @@ -34,12 +67,14 @@ * @method * @param {Object|string|Array} value Value to store * @param {string} [stringified] Stringified version of value; default OO.getHash( value ) - * @param {boolean} [overwrite=false] Overwrite the value in the store if the hash is found * @return {string} Hash value with low collision probability */ -ve.dm.IndexValueStore.prototype.index = function ( value, stringified, overwrite ) { +ve.dm.IndexValueStore.prototype.index = function ( value, stringified ) { var hash = this.indexOfValue( value, stringified ); - if ( !this.hashStore[ hash ] || overwrite ) { + if ( arguments[ 2 ] ) { + throw new Error( 'Overwrite is no longer supported' ); + } + if ( !this.hashStore[ hash ] ) { if ( Array.isArray( value ) ) { this.hashStore[ hash ] = ve.copy( value ); } else if ( typeof value === 'object' ) { @@ -47,6 +82,7 @@ } else { this.hashStore[ hash ] = value; } + this.hashes.push( hash ); } return hash; @@ -131,7 +167,10 @@ * @return {ve.dm.IndexValueStore} New store with the same contents as this one */ ve.dm.IndexValueStore.prototype.clone = function () { - var hash, clone = new this.constructor(); + var hash, + clone = new this.constructor(); + + clone.hashes = this.hashes.slice(); for ( hash in this.hashStore ) { clone.hashStore[ hash ] = this.hashStore[ hash ]; } @@ -145,16 +184,19 @@ * will (with high probability) have the same hash only if equal. In this case, equivalent * values can have two different hashes. * - * Objects added to the store are added by reference, not cloned like in .index() + * Values are added in the order they appear in the other store. Objects added to the store are + * added by reference, not cloned, unlike in .index() * * @param {ve.dm.IndexValueStore} other Store to merge into this one */ ve.dm.IndexValueStore.prototype.merge = function ( other ) { - var hash; + var i, len, hash; - for ( hash in other.hashStore ) { + for ( i = 0, len = other.hashes.length; i < len;
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: WIP: collab-service
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/305564 Change subject: WIP: collab-service .. WIP: collab-service Change-Id: I068447d8155b0732c08d642357dab07cfca5aa2a --- A collab/Collab.js A collab/package.json A collab/server.js M src/dm/ve.dm.Change.js 4 files changed, 81 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/64/305564/1 diff --git a/collab/Collab.js b/collab/Collab.js new file mode 100644 index 000..75e071b --- /dev/null +++ b/collab/Collab.js @@ -0,0 +1,33 @@ +var ve = { dm: {} }; +require( '../src/dm/ve.dm.Change' )( ve ); + +Collab = function () { + this.transactionsForDoc = new Map(); +}; + +Collab.prototype.applyChange = function ( doc, author, remote ) { + var txs, local, resolved; + + if ( remote.clear ) { + this.transactionsForDoc = new Map(); + } + remote = new ve.dm.Change( remote.start, remote.transactions ); + + if ( !this.transactionsForDoc.has( doc ) ) { + this.transactionsForDoc.set( doc, [] ); + } + transactions = this.transactionsForDoc.get( doc ); + + if ( remote.start > transactions.length ) { + throw new Error( 'Remote start ' + remote.start + ' is beyond committed history' ); + } + local = new ve.dm.Change( remote.start, transactions.slice( remote.start ) ); + resolved = remote.rebaseOnto( local ); + if ( resolved ) { + Array.prototype.push.apply( transactions, resolved.transactions ); + console.log( JSON.stringify( transactions ) ); + } + return { reverted: !resolved, parallel: local }; +}; + +module.exports = Collab; diff --git a/collab/package.json b/collab/package.json new file mode 100644 index 000..b71ffcd --- /dev/null +++ b/collab/package.json @@ -0,0 +1,15 @@ +{ + "name": "ve-collab", + "description": "Collab server for VisualEditor", + "version": "0.0.1", + "dependencies": { + "express": "4.x" + }, + "devDependencies": {}, + "scripts": { + "start": "node server.js" + }, + "repository": { + "type": "git" + } +} diff --git a/collab/server.js b/collab/server.js new file mode 100644 index 000..e8f6c05 --- /dev/null +++ b/collab/server.js @@ -0,0 +1,21 @@ +var port = 8081, + express = require( 'express' ), + bodyParser = require( 'body-parser' ), + app = express(), + Collab = require( './Collab' ); + +collab = new Collab(); +app.use( express.static( __dirname + '/..' ) ); +app.use( bodyParser.json() ); +app.post( '/applyChange', function ( req, res ) { + var response; + try { + response = collab.applyChange( req.body.doc, req.body.author, req.body.change ); + } catch ( error ) { + response = { error: error.toString() }; + } + res.setHeader( 'Content-Type', 'application/json' ); + res.end( JSON.stringify( response ) ); +} ); +app.listen( port ); +console.log( 'Listening on ' + port ); diff --git a/src/dm/ve.dm.Change.js b/src/dm/ve.dm.Change.js index 3339e74..448bc19 100644 --- a/src/dm/ve.dm.Change.js +++ b/src/dm/ve.dm.Change.js @@ -1,3 +1,13 @@ +( function ( createClass ) { + if ( typeof window !== 'undefined' ) { + // Browser. new ve.dm.Change(...) + createClass( window.ve ); + } else { + // Node. ve={dm:{}}; require( 've.dm.Change' )( ve ); new ve.dm.Change(...) + module.exports = createClass; + } +} ( function ( ve ) { + /*! * VisualEditor DataModel Change class. * @@ -134,3 +144,5 @@ ve.dm.Change.prototype.serialize = function () { return { start: this.start, transactions: this.transactions }; }; + +} ) ); -- To view, visit https://gerrit.wikimedia.org/r/305564 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I068447d8155b0732c08d642357dab07cfca5aa2a Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: WIP: ve.dm.Change class with rebase operations
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/305563 Change subject: WIP: ve.dm.Change class with rebase operations .. WIP: ve.dm.Change class with rebase operations Change-Id: I1eccd4ef99d764911994d11d747f13ae42919eff --- M build/modules.json M demos/ve/desktop.html M demos/ve/mobile.html A src/dm/ve.dm.Change.js M tests/index.html 5 files changed, 140 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/63/305563/1 diff --git a/build/modules.json b/build/modules.json index 02a714a..a9294d8 100644 --- a/build/modules.json +++ b/build/modules.json @@ -254,6 +254,7 @@ "src/dm/ve.dm.TableMatrix.js", "src/dm/ve.dm.TransactionProcessor.js", "src/dm/ve.dm.Transaction.js", + "src/dm/ve.dm.Change.js", "src/dm/ve.dm.Selection.js", "src/dm/ve.dm.Surface.js", "src/dm/ve.dm.SurfaceFragment.js", diff --git a/demos/ve/desktop.html b/demos/ve/desktop.html index 5eb7bcb..b5c0cbc 100644 --- a/demos/ve/desktop.html +++ b/demos/ve/desktop.html @@ -210,6 +210,7 @@ + diff --git a/demos/ve/mobile.html b/demos/ve/mobile.html index e52ff99..b800234 100644 --- a/demos/ve/mobile.html +++ b/demos/ve/mobile.html @@ -211,6 +211,7 @@ + diff --git a/src/dm/ve.dm.Change.js b/src/dm/ve.dm.Change.js new file mode 100644 index 000..3339e74 --- /dev/null +++ b/src/dm/ve.dm.Change.js @@ -0,0 +1,136 @@ +/*! + * VisualEditor DataModel Change class. + * + * @copyright 2011-2016 VisualEditor Team and others; see http://ve.mit-license.org + */ + +/** + * DataModel change. + * + * @class + * @constructor + * @param {number} start Position in the history stack where change starts + * @param {ve.dm.Transaction[]} transactions Transactions to apply + */ +ve.dm.Change = function VeDmChange( start, transactions ) { + this.start = start; + this.transactions = transactions; +}; + +/* Static methods */ + +ve.dm.Change.static = {}; + +ve.dm.Change.static.deserialize = function ( doc, data ) { + return new ve.dm.Change( data.start, data.transactions.map( function ( txHash ) { + return ve.dm.Transaction.newFromHash( doc, txHash ); + } ) ); +}; + +/* Methods */ + +/** + * @return {ve.dm.Change} The change that backs out this change + */ +ve.dm.Change.prototype.reversed = function () { + return new ve.dm.Change( + this.start + this.transactions.length, + this.transactions.map( function ( tx ) { + return tx.reversed(); + } ).reverse() + ); +}; + +/** + * Rebase this change onto other (ready to apply on top of other) + * + * @param {ve.dm.Change} other Other change + * @return {ve.dm.Change|null} Rebased change applicable on top of other, or null if rebasing fails + * @throws {Error} If this change and other have different starts + */ +ve.dm.Change.prototype.rebaseOnto = function ( other ) { + if ( this.start !== other.start ) { + throw new Error( 'Different starts: ' + this.start + ' and ' + other.start ); + } + // Trivial rebase: fail if both this or other are non-empty + // TODO: make a little less trivial + if ( this.transactions.length && other.transactions.length ) { + return null; + } + return new ve.dm.Change( other.start + other.transactions.length, this.transactions ); +}; + +/** + * Rebase this change below other (ready to replace other) + * + * @param {ve.dm.Change} other Other change + * @return {ve.dm.Change|null} Rebased change applicable instead of other, or null if rebasing fails + * @throws {Error} If this change does not start where other ends + */ +ve.dm.Change.prototype.rebaseBelow = function ( other ) { + if ( this.start !== other.start + other.length ) { + throw new Error( 'This starts at ' + this.start + + ' but other ends at ' + ( other.start + other.length ) ); + } + // Trivial rebase: fail if both this or other are non-empty + // TODO: make a little less trivial + if ( this.transactions.length && other.transactions.length ) { + return null; + } + return new ve.dm.Change( other.start, this.transactions ); +}; + +/** + * Build a composite change from two consecutive changes + * + * @param {ve.dm.Change} other Change that starts immediately after this + * @returns {ve.dm.Change} Composite change + * @throws {Error} If other does not start immediately after this + */ +ve.dm.Change.prototype.concat =
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: WIP: Function to rebase a transaction onto another
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
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Forcibly reapply selection on insertion annotation change, t...
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/304325 Change subject: Forcibly reapply selection on insertion annotation change, to move between unicorns .. Forcibly reapply selection on insertion annotation change, to move between unicorns Change-Id: Id740f2a40a825f1aa3113fe79507546682862b93 --- M src/ce/ve.ce.Surface.js 1 file changed, 15 insertions(+), 4 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/25/304325/1 diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js index f22fc36..3b960ca 100644 --- a/src/ce/ve.ce.Surface.js +++ b/src/ce/ve.ce.Surface.js @@ -2563,7 +2563,7 @@ return; } // Must re-apply the selection after re-rendering - this.showModelSelection(); + this.forceShowModelSelection(); this.surfaceObserver.pollOnceNoCallback(); }; @@ -3261,12 +3261,23 @@ }; /** - * Apply a DM selection to the DOM + * Apply a DM selection to the DOM, even if the old DOM selection is different but DM-equivalent * * @method * @return {boolean} Whether the selection actually changed */ -ve.ce.Surface.prototype.showModelSelection = function () { +ve.ce.Surface.prototype.forceShowModelSelection = function () { + return this.showModelSelection( true ); +}; + +/** + * Apply a DM selection to the DOM + * + * @method + * @param {boolean} [force] Replace the DOM selection if it is different but DM-equivalent + * @return {boolean} Whether the selection actually changed + */ +ve.ce.Surface.prototype.showModelSelection = function ( force ) { var selection, changed, modelRange, impliedModelRange; if ( this.deactivated ) { @@ -3283,7 +3294,7 @@ return false; } modelRange = selection.getModel().getRange(); - if ( this.documentView.documentNode.$element.get( 0 ).contains( + if ( !force && this.documentView.documentNode.$element.get( 0 ).contains( this.nativeSelection.focusNode ) ) { // See whether the model range implied by the DOM selection is already equal to -- To view, visit https://gerrit.wikimedia.org/r/304325 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Id740f2a40a825f1aa3113fe79507546682862b93 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Fix TextState#getChangeTransaction bug
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/304135 Change subject: Fix TextState#getChangeTransaction bug .. Fix TextState#getChangeTransaction bug Also document the algorithm more clearly Change-Id: I3cfca36c289a6936810665233547d37ef504905f --- M src/ce/ve.ce.TextState.js M tests/ce/ve.ce.TextState.test.js 2 files changed, 52 insertions(+), 11 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/35/304135/1 diff --git a/src/ce/ve.ce.TextState.js b/src/ce/ve.ce.TextState.js index 1663f74..5aa464b 100644 --- a/src/ce/ve.ce.TextState.js +++ b/src/ce/ve.ce.TextState.js @@ -213,7 +213,11 @@ // During typical typing, there is a single changed chunk with matching start/end chars. textStart = 0; textEnd = 0; - if ( change.start < Math.min( oldChunks.length, newChunks.length ) ) { + if ( change.start + change.end < Math.min( oldChunks.length, newChunks.length ) ) { + // Both oldChunks and newChunks include a changed chunk. Therefore the first changed + // chunk of oldChunks and newChunks is respectively oldChunks[ change.start ] and + // newChunks[ change.start ] . If they have matching annotations, then matching + // characters at their start are also part of the unchanged start region. if ( oldChunks[ change.start ].hasEqualElements( newChunks[ change.start ] ) ) { oldChunk = oldChunks[ change.start ]; newChunk = newChunks[ change.start ]; @@ -226,19 +230,22 @@ textStart = i; } - if ( - change.end < Math.min( oldChunks.length, newChunks.length ) && - oldChunks[ oldChunks.length - 1 - change.end ].hasEqualElements( + // Likewise, the last changed chunk of oldChunks and newChunks is respectively + // oldChunks[ oldChunks.length - 1 - change.end ] and + // newChunks[ newChunks.length - 1 - change.end ] , and if they have matching + // annotations, then matching characters at their end potentially form part of + // the unchanged end region. + if ( oldChunks[ oldChunks.length - 1 - change.end ].hasEqualElements( newChunks[ newChunks.length - 1 - change.end ] - ) - ) { + ) ) { oldChunk = oldChunks[ oldChunks.length - 1 - change.end ]; newChunk = newChunks[ newChunks.length - 1 - change.end ]; - // For oldChunks/newChunks/both, it's possible that only one chunk - // changed, in which case textStart has already eaten into that chunk; - // so take care not to overlap it. (For example, for 'ana'->'anna', - // textStart will be 2 so we want to limit textEnd to 1, else the 'n' - // of 'ana' will be counted twice). + // However, if only one chunk has changed in oldChunks/newChunks, then + // oldChunk/newChunk is also the *first* changed chunk, in which case + // textStart has already eaten into that chunk; so take care not to + // overlap it. (For example, for 'ana'->'anna', textStart will be 2 so + // we want to limit textEnd to 1, else the 'n' of 'ana' will be counted + // twice). iLen = Math.min( oldChunk.text.length - ( change.start + change.end === oldChunks.length - 1 ? textStart : 0 ), diff --git a/tests/ce/ve.ce.TextState.test.js b/tests/ce/ve.ce.TextState.test.js index 593c987..57e3342 100644 --- a/tests/ce/ve.ce.TextState.test.js +++ b/tests/ce/ve.ce.TextState.test.js @@ -317,6 +317,40 @@ }, { type: 'retain', length: 3 } ] + }, + { + msg: 'Insert new chunk whose annotations match end chunk\'s', + oldRawHtml: 'xyz', + oldInnerHtml: 'xyz', + newInnerHtml: 'xywyz', + operations: [ + { type: 'retain', length: 2 }, + { + type: 'replace', + remove: [], + insert: [ 'y', [ 'w', [ 0 ] ] ], + insertedDataOffset: 0, + insertedDataLength: 2 + }, +
[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: Always call back if SurfaceObserver sees a branch node change
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/303335 Change subject: Always call back if SurfaceObserver sees a branch node change .. Always call back if SurfaceObserver sees a branch node change Bug: T122291 Change-Id: I1e1094b1d94a21ed742ef52d612bef52997f2ba4 --- M src/ce/ve.ce.SurfaceObserver.js 1 file changed, 12 insertions(+), 7 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/35/303335/1 diff --git a/src/ce/ve.ce.SurfaceObserver.js b/src/ce/ve.ce.SurfaceObserver.js index 4c9d9f1..1f601b6 100644 --- a/src/ce/ve.ce.SurfaceObserver.js +++ b/src/ce/ve.ce.SurfaceObserver.js @@ -123,6 +123,9 @@ /** * Poll to update SurfaceObserver, but don't signal any changes back to the Surface + * (except branch node changes) + * + * TODO: The method name is misleading because branch node changes are signalled * * @method */ @@ -146,7 +149,8 @@ * * @method * @private - * @param {boolean} signalChanges If there changes are observed, call Surface#handleObservedChange + * @param {boolean} signalChanges Call Surface#handleObservedChange if content/selection changes + * are observed (branch node changes are always signalled). * @param {boolean} selectionOnly Check for selection changes only */ ve.ce.SurfaceObserver.prototype.pollOnceInternal = function ( signalChanges, selectionOnly ) { @@ -164,13 +168,14 @@ ); this.rangeState = newState; - if ( signalChanges && ( - newState.contentChanged || - // TODO: The prior code signalled branchNode changes even if !signalChanges . - // Was this needed? + if ( + // Signal branch node changes even if !signalChanges: see T122291. newState.branchNodeChanged || - newState.selectionChanged - ) ) { + ( + signalChanges && + ( newState.contentChanged || newState.selectionChanged ) + ) + ) { this.surface.handleObservedChanges( oldState, newState ); } }; -- To view, visit https://gerrit.wikimedia.org/r/303335 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I1e1094b1d94a21ed742ef52d612bef52997f2ba4 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] mediawiki...Cite[master]: WIP: Hide text without confusing Chromium's cursoring
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/303008 Change subject: WIP: Hide text without confusing Chromium's cursoring .. WIP: Hide text without confusing Chromium's cursoring Change-Id: I8c16277d87780fd0f1cd39175fc85e3e0579 TODO: Check what impact this has on bidi --- M modules/ext.cite.style.css 1 file changed, 4 insertions(+), 3 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Cite refs/changes/08/303008/1 diff --git a/modules/ext.cite.style.css b/modules/ext.cite.style.css index a728298..ad68080 100644 --- a/modules/ext.cite.style.css +++ b/modules/ext.cite.style.css @@ -42,11 +42,12 @@ content: '[' counter( mw-Ref, decimal ) ']'; } -/* Hide the default rendering in browsers that support content - * generation by selecting for :after pseudo-element.*/ +/* Hide the default rendering in browsers that support content generation by + * selecting for :after pseudo-element. Use zero font size rather than display:none + * to work around T123608 (cursoring bug in Chromium).*/ x-thereisnoelementwiththisname:after, span.mw-reflink-text { - display: none; + font-size: 0; } /* Style for linkbacks from to s */ -- To view, visit https://gerrit.wikimedia.org/r/303008 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I8c16277d87780fd0f1cd39175fc85e3e0579 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Cite Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] TransactionProcessor: Apply annotations to ranges at the hig... - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/299570 Change subject: TransactionProcessor: Apply annotations to ranges at the highest uniform offset .. TransactionProcessor: Apply annotations to ranges at the highest uniform offset Bug: T140538 Change-Id: I731ca0fd6da624bd81a4b715c187be3d6c0406d0 --- M src/dm/ve.dm.AnnotationSet.js M src/dm/ve.dm.TransactionProcessor.js M src/ve.utils.js M tests/ve.test.js 4 files changed, 102 insertions(+), 9 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/70/299570/1 diff --git a/src/dm/ve.dm.AnnotationSet.js b/src/dm/ve.dm.AnnotationSet.js index 551401a..b685781 100644 --- a/src/dm/ve.dm.AnnotationSet.js +++ b/src/dm/ve.dm.AnnotationSet.js @@ -411,15 +411,25 @@ }; /** - * Add all annotations in the given set to the end of the set. + * Add all annotations in the given set, removing any duplicates (including existing ones). * - * Annotations from the other set that are already in the set will not be added again. + * The offset calculation happens before duplicates are removed. * * @method * @param {ve.dm.AnnotationSet} set Set to add to the set + * @param {number} [offset] Offset at which to insert; defaults to the end of the set + */ -ve.dm.AnnotationSet.prototype.addSet = function ( set ) { - this.storeIndexes = OO.simpleArrayUnion( this.getIndexes(), set.getIndexes() ); +ve.dm.AnnotationSet.prototype.addSet = function ( set, offset ) { + var indexes = this.getIndexes(); + if ( offset === undefined ) { + offset = indexes.length; + } + this.storeIndexes = OO.simpleArrayUnion( + indexes.slice( 0, offset ), + set.getIndexes(), + indexes.slice( offset ) + ); }; /** diff --git a/src/dm/ve.dm.TransactionProcessor.js b/src/dm/ve.dm.TransactionProcessor.js index 33c964d..15f9f46 100644 --- a/src/dm/ve.dm.TransactionProcessor.js +++ b/src/dm/ve.dm.TransactionProcessor.js @@ -184,7 +184,8 @@ * Apply the current annotation stacks. * * This will set all annotations in this.set and clear all annotations in `this.clear` on the data - * between the offsets `this.cursor` and `this.cursor + to`. + * between the offsets `this.cursor` and `this.cursor + to`. Annotations are set at the highest + * annotation set offset below which annotations are uniform across the whole range. * * @method * @param {number} to Offset to stop annotating at, annotating starts at this.cursor @@ -193,13 +194,13 @@ * @throws {Error} Annotation to be cleared is not set */ ve.dm.TransactionProcessor.prototype.applyAnnotations = function ( to ) { - var isElement, annotations, i, j, jlen; + var annotationsForOffset, setIndex, isElement, annotations, i, j, jlen; - function setAndClear( anns, set, clear ) { + function setAndClear( anns, set, clear, index ) { if ( anns.containsAnyOf( set ) ) { throw new Error( 'Invalid transaction, annotation to be set is already set' ); } else { - anns.addSet( set ); + anns.addSet( set, index ); } if ( !anns.containsAllOf( clear ) ) { throw new Error( 'Invalid transaction, annotation to be cleared is not set' ); @@ -212,6 +213,17 @@ return; } // Set/clear annotations on data + annotationsForOffset = []; + for ( i = this.cursor; i < to; i++ ) { + annotationsForOffset[ i - this.cursor ] = this.document.data.getAnnotationsFromOffset( i ); + } + // Calculate highest offset below which annotations are uniform across the whole range + setIndex = ve.getCommonStartSequenceLength( + annotationsForOffset.map( function ( annotations ) { + return annotations.storeIndexes; + } ) + ); + for ( i = this.cursor; i < to; i++ ) { isElement = this.document.data.isElementData( i ); if ( isElement ) { @@ -224,7 +236,7 @@ } } annotations = this.document.data.getAnnotationsFromOffset( i ); - setAndClear( annotations, this.set, this.clear ); + setAndClear( annotations, this.set, this.clear, setIndex ); // Store annotation indexes in linear model this.queueModification( { type: 'annotateData', diff --git a/src/ve.utils.js b/src/ve.utils.js index 12eeec2..4ff5f2f 100644 --- a/src/ve.utils.js +++ b/src/ve.utils.js @@ -1307,6 +1307,37 @@ }; /** + * Find the length of the common start sequence of one or more sequences + * + * + * @param {Array[]} sequences Array of sequences (arrays, strings etc) + * @return {number} Common start
[MediaWiki-commits] [Gerrit] New decodeURIComponentIntoArticleTitle method - change (mediawiki...VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/294393 Change subject: New decodeURIComponentIntoArticleTitle method .. New decodeURIComponentIntoArticleTitle method This replaces ve.safeDecodeURIComponent(...).replace( /_/g, ' ' ) . This action is really specific to the quirks of mediawiki title processing. Change-Id: Ia9e525c9340e6de9e48535586c97867ccb48 --- M extension.json M modules/ve-mw/ce/nodes/ve.ce.MWTransclusionNode.js M modules/ve-mw/dm/annotations/ve.dm.MWInternalLinkAnnotation.js M modules/ve-mw/dm/metaitems/ve.dm.MWCategoryMetaItem.js M modules/ve-mw/dm/nodes/ve.dm.MWImageNode.js M modules/ve-mw/dm/nodes/ve.dm.MWMagicLinkNode.js A modules/ve-mw/ve.MWutils.js 7 files changed, 41 insertions(+), 9 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor refs/changes/93/294393/1 diff --git a/extension.json b/extension.json index 810cb8c..7de529d 100644 --- a/extension.json +++ b/extension.json @@ -1109,6 +1109,7 @@ }, "ext.visualEditor.mwcore": { "scripts": [ + "modules/ve-mw/ve.MWutils.js", "modules/ve-mw/dm/nodes/ve.dm.MWEntityNode.js", "modules/ve-mw/dm/nodes/ve.dm.MWExtensionNode.js", "modules/ve-mw/dm/nodes/ve.dm.MWTableNode.js", diff --git a/modules/ve-mw/ce/nodes/ve.ce.MWTransclusionNode.js b/modules/ve-mw/ce/nodes/ve.ce.MWTransclusionNode.js index 64eb73e0..9fe764e 100644 --- a/modules/ve-mw/ce/nodes/ve.ce.MWTransclusionNode.js +++ b/modules/ve-mw/ce/nodes/ve.ce.MWTransclusionNode.js @@ -180,7 +180,7 @@ var targetData = ve.dm.MWInternalLinkAnnotation.static.getTargetDataFromHref( this.href, transclusionNode.getModelHtmlDocument() ), - normalisedHref = ve.safeDecodeURIComponent( targetData.title ); + normalisedHref = ve.decodeURIComponentIntoArticleTitle( targetData.title, false ); if ( mw.Title.newFromText( normalisedHref ) ) { normalisedHref = mw.Title.newFromText( normalisedHref ).getPrefixedText(); } diff --git a/modules/ve-mw/dm/annotations/ve.dm.MWInternalLinkAnnotation.js b/modules/ve-mw/dm/annotations/ve.dm.MWInternalLinkAnnotation.js index fafa709..4807da9 100644 --- a/modules/ve-mw/dm/annotations/ve.dm.MWInternalLinkAnnotation.js +++ b/modules/ve-mw/dm/annotations/ve.dm.MWInternalLinkAnnotation.js @@ -42,7 +42,7 @@ type: this.name, attributes: { hrefPrefix: targetData.hrefPrefix, - title: ve.safeDecodeURIComponent( targetData.title ).replace( /_/g, ' ' ), + title: ve.decodeURIComponentIntoArticleTitle( targetData.title ), normalizedTitle: this.normalizeTitle( targetData.title ), lookupTitle: this.getLookupTitle( targetData.title ), origTitle: targetData.title @@ -130,7 +130,7 @@ var href, title = dataElement.attributes.title, origTitle = dataElement.attributes.origTitle; - if ( origTitle !== undefined && ve.safeDecodeURIComponent( origTitle ).replace( /_/g, ' ' ) === title ) { + if ( origTitle !== undefined && ve.decodeURIComponentIntoArticleTitle( origTitle ) === title ) { // Restore href from origTitle href = origTitle; // Only use hrefPrefix if restoring from origTitle diff --git a/modules/ve-mw/dm/metaitems/ve.dm.MWCategoryMetaItem.js b/modules/ve-mw/dm/metaitems/ve.dm.MWCategoryMetaItem.js index c978373..d04c55d 100644 --- a/modules/ve-mw/dm/metaitems/ve.dm.MWCategoryMetaItem.js +++ b/modules/ve-mw/dm/metaitems/ve.dm.MWCategoryMetaItem.js @@ -41,9 +41,9 @@ type: this.name, attributes: { hrefPrefix: matches[ 1 ], - category: ve.safeDecodeURIComponent( matches[ 2 ] ).replace( /_/g, ' ' ), + category: ve.decodeURIComponentIntoArticleTitle( matches[ 2 ] ), origCategory: matches[ 2 ], - sortkey: ve.safeDecodeURIComponent( rawSortkey ).replace( /_/g, ' ' ), + sortkey: ve.decodeURIComponentIntoArticleTitle( rawSortkey ), origSortkey: rawSortkey } }; @@ -57,8 +57,8 @@ sortkey = dataElement.attributes.sortkey || '', origCategory = dataElement.attributes.origCategory || '', origSortkey = dataElement.attributes.origSortkey ||
[MediaWiki-commits] [Gerrit] Rename keyDownState.selection to keyDownState.selectionState - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/293093 Change subject: Rename keyDownState.selection to keyDownState.selectionState .. Rename keyDownState.selection to keyDownState.selectionState Because it's a ve.SelectionState, not a ve.ce.Selection Change-Id: I9e8068021c8a32269f75de9a8a1f7332454b67a8 --- M src/ce/ve.ce.Surface.js 1 file changed, 10 insertions(+), 10 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/93/293093/1 diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js index 1fdbf16..d6ae3dd 100644 --- a/src/ce/ve.ce.Surface.js +++ b/src/ce/ve.ce.Surface.js @@ -1206,7 +1206,7 @@ * @param {jQuery.Event} e keydown event */ ve.ce.Surface.prototype.afterDocumentKeyDown = function ( e ) { - var keyDownSelection, direction, focusableNode, startOffset, endOffset, + var keyDownSelectionState, direction, focusableNode, startOffset, endOffset, offsetDiff, dmFocus, dmSelection, inNonSlug, ceSelection, ceNode, range, fixupCursorForUnicorn, matrix, col, row, $focusNode, removedUnicorns, surface = this, @@ -1273,8 +1273,8 @@ ve.compareDocumentOrder( surface.nativeSelection.focusNode, surface.nativeSelection.focusOffset, - keyDownSelection.focusNode, - keyDownSelection.focusOffset + keyDownSelectionState.focusNode, + keyDownSelectionState.focusOffset ) ) || null; } @@ -1282,7 +1282,7 @@ if ( e !== this.keyDownState.event ) { return; } - keyDownSelection = this.keyDownState.selection; + keyDownSelectionState = this.keyDownState.selectionState; this.clearKeyDownState(); if ( @@ -1358,7 +1358,7 @@ !e.ctrlKey && !e.altKey && !e.metaKey && - keyDownSelection.isCollapsed && + keyDownSelectionState.isCollapsed && this.nativeSelection.isCollapsed && ( direction = getDirection() ) !== null ) { @@ -1372,8 +1372,8 @@ // Calculate the DM offsets of our motion try { startOffset = ve.ce.getOffset( - keyDownSelection.focusNode, - keyDownSelection.focusOffset + keyDownSelectionState.focusNode, + keyDownSelectionState.focusOffset ); endOffset = ve.ce.getOffset( this.nativeSelection.focusNode, @@ -2965,7 +2965,7 @@ */ ve.ce.Surface.prototype.storeKeyDownState = function ( e ) { this.keyDownState.event = e; - this.keyDownState.selection = null; + this.keyDownState.selectionState = null; if ( this.nativeSelection.rangeCount > 0 && e && ( e.keyCode === OO.ui.Keys.UP || @@ -2973,7 +2973,7 @@ e.keyCode === OO.ui.Keys.LEFT || e.keyCode === OO.ui.Keys.RIGHT ) ) { - this.keyDownState.selection = new ve.SelectionState( this.nativeSelection ); + this.keyDownState.selectionState = new ve.SelectionState( this.nativeSelection ); } }; @@ -2982,7 +2982,7 @@ */ ve.ce.Surface.prototype.clearKeyDownState = function () { this.keyDownState.event = null; - this.keyDownState.selection = null; + this.keyDownState.selectionState = null; }; /** -- To view, visit https://gerrit.wikimedia.org/r/293093 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I9e8068021c8a32269f75de9a8a1f7332454b67a8 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] Clarify EventSequencer listener slice/splice behaviour - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/293088 Change subject: Clarify EventSequencer listener slice/splice behaviour .. Clarify EventSequencer listener slice/splice behaviour Change-Id: I8a2696e2d5b1b647a7a27e2f99900c8c6f76c636 --- M src/ve.EventSequencer.js 1 file changed, 8 insertions(+), 10 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/88/293088/1 diff --git a/src/ve.EventSequencer.js b/src/ve.EventSequencer.js index 56f35c3..8a2194c 100644 --- a/src/ve.EventSequencer.js +++ b/src/ve.EventSequencer.js @@ -259,9 +259,9 @@ this.doOnLoop(); } - onListeners = this.onListenersForEvent[ eventName ] || []; + // Listener list: take snapshot (for immutability if a listener adds another listener) + onListeners = ( this.onListenersForEvent[ eventName ] || [] ).slice(); - // Length cache 'len' is required, as an onListener could add another onListener for ( i = 0, len = onListeners.length; i < len; i++ ) { onListener = onListeners[ i ]; this.callListener( 'on', eventName, i, onListener, ev ); @@ -297,11 +297,10 @@ ve.EventSequencer.prototype.afterEvent = function ( eventName, ev ) { var i, len, afterListeners, afterOneListeners; - // Snapshot the listener lists, and blank *OneListener list. - // This ensures reasonable behaviour if a function called adds another listener. + // Listener list: take snapshot (for immutability if a listener adds another listener) afterListeners = ( this.afterListenersForEvent[ eventName ] || [] ).slice(); - afterOneListeners = ( this.afterOneListenersForEvent[ eventName ] || [] ).slice(); - ( this.afterOneListenersForEvent[ eventName ] || [] ).length = 0; + // One-time listener list: take snapshot (for immutability) and blank the list + afterOneListeners = ( this.afterOneListenersForEvent[ eventName ] || [] ).splice(); for ( i = 0, len = afterListeners.length; i < len; i++ ) { this.callListener( 'after', eventName, i, afterListeners[ i ], ev ); @@ -342,11 +341,10 @@ } this.afterLoopTimeoutId = null; - // Snapshot the listener lists, and blank *OneListener list. - // This ensures reasonable behaviour if a function called adds another listener. + // Loop listener list: take snapshot (for immutability if a listener adds another listener) afterLoopListeners = this.afterLoopListeners.slice(); - afterLoopOneListeners = this.afterLoopOneListeners.slice(); - this.afterLoopOneListeners.length = 0; + // One-time loop listener list: take snapshot (for immutability) and blank the list + afterLoopOneListeners = this.afterLoopOneListeners.splice(); for ( i = 0, len = afterLoopListeners.length; i < len; i++ ) { this.callListener( 'afterLoop', null, i, this.afterLoopListeners[ i ], null ); -- To view, visit https://gerrit.wikimedia.org/r/293088 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I8a2696e2d5b1b647a7a27e2f99900c8c6f76c636 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] Document the purpose of setTimeout calls in ve.ce.Surface - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/292895 Change subject: Document the purpose of setTimeout calls in ve.ce.Surface .. Document the purpose of setTimeout calls in ve.ce.Surface Change-Id: I16baa986b9611ebf317d8d96f67172685344d8ff --- M src/ce/ve.ce.Surface.js 1 file changed, 15 insertions(+), 6 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/95/292895/1 diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js index 1fdbf16..dc3a09a 100644 --- a/src/ce/ve.ce.Surface.js +++ b/src/ce/ve.ce.Surface.js @@ -480,6 +480,7 @@ // If we are calling focus after replacing a node the selection may be gone // but onDocumentFocus won't fire so restore the selection here too. this.onModelSelect(); + // setTimeout: postpone until onDocumentFocus has been called setTimeout( function () { // Support: Chrome // In some browsers (e.g. Chrome) giving the document node focus doesn't @@ -700,8 +701,9 @@ this.$document.on( 'mouseup', this.onDocumentMouseUpHandler ); this.surfaceObserver.stopTimerLoop(); - // In some browsers the selection doesn't change until after the event - // so poll in the 'after' function + // setTimeout: In some browsers the selection doesn't change until after the event + // so poll in the 'after' function. + // TODO: rewrite to use EventSequencer setTimeout( this.afterDocumentMouseDown.bind( this, e, this.getSelection() ) ); // Support: IE @@ -754,8 +756,9 @@ ve.ce.Surface.prototype.onDocumentMouseUp = function ( e ) { this.$document.off( 'mouseup', this.onDocumentMouseUpHandler ); this.surfaceObserver.startTimerLoop(); - // In some browsers the selection doesn't change until after the event + // setTimeout: In some browsers the selection doesn't change until after the event // so poll in the 'after' function + // TODO: rewrite to use EventSequencer setTimeout( this.afterDocumentMouseUp.bind( this, e, this.getSelection() ) ); }; @@ -1557,6 +1560,7 @@ } this.onCopy( e ); + // setTimeout: postpone until after the setTimeout in onCopy setTimeout( function () { // Trigger a fake backspace to remove the content: this behaves differently based on the selection, // e.g. in a TableSelection. @@ -1675,6 +1679,7 @@ // Restore scroll position after changing focus this.$window.scrollTop( scrollTop ); + // setTimeout: postpone until after the default copy action setTimeout( function () { // If the range was in $highlights (right-click copy), don't restore it if ( !OO.ui.contains( view.$highlights[ 0 ], originalSelection.focusNode, true ) ) { @@ -1716,6 +1721,7 @@ this.surfaceObserver.disable(); this.pasting = true; this.fakePasting = !!fakePaste; + // setTimeout: postpone until after the default paste action setTimeout( function () { try { if ( !e.isDefaultPrevented() ) { @@ -2211,7 +2217,7 @@ // Restore focus and scroll position this.$documentNode[ 0 ].focus(); this.$window.scrollTop( beforePasteData.scrollTop ); - // Firefox sometimes doesn't change scrollTop immediately when pasting + // setTimeout: Firefox sometimes doesn't change scrollTop immediately when pasting // line breaks at the end of a line so do it again later. setTimeout( function () { view.$window.scrollTop( beforePasteData.scrollTop ); @@ -2563,7 +2569,7 @@ } // Update the state of the SurfaceObserver this.surfaceObserver.pollOnceNoCallback(); - // Wait for other documentUpdate listeners to run before emitting + // setTimeout: Wait for other documentUpdate listeners to run before emitting setTimeout( function () { surface.emit( 'position' ); } ); @@ -2690,6 +2696,7 @@ newSelection = oldState && oldState.veRange ? new ve.dm.LinearSelection( dmDoc, oldState.veRange ) : new ve.dm.NullSelection( dmDoc ); + // TODO: setTimeout: document purpose setTimeout( function () { surface.changeModel( null, newSelection ); surface .showModelSelection(); @@ -2754,6 +2761,7 @@ // Animate the slug open $slug =
[MediaWiki-commits] [Gerrit] WIP: Preserve prior valid DOM selections in showModelSelection - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/292835 Change subject: WIP: Preserve prior valid DOM selections in showModelSelection .. WIP: Preserve prior valid DOM selections in showModelSelection This matters because different DOM selections may correspond to the same model selection. We shouldn't generally replace one such valid DOM selection with an arbitrary other one. TODO: This makes it easier to jump chimeras etc. It may well have other similar consequences. Change-Id: I2a75c847482bca940de2ee8605727ac6c52db8f0 --- M src/ce/ve.ce.Surface.js 1 file changed, 20 insertions(+), 4 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/35/292835/1 diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js index 1fdbf16..ce90a01 100644 --- a/src/ce/ve.ce.Surface.js +++ b/src/ce/ve.ce.Surface.js @@ -3295,7 +3295,7 @@ * @return {boolean} Whether the selection actually changed */ ve.ce.Surface.prototype.showModelSelection = function () { - var selection, changed; + var selection, changed, modelRange; if ( this.deactivated ) { // Defer until view has updated @@ -3306,9 +3306,25 @@ selection = this.getSelection(); if ( selection.isNativeCursor() && !this.focusedBlockSlug ) { - changed = this.showSelectionState( - this.getSelectionState( selection.getModel().getRange() ) - ); + modelRange = selection.getModel().getRange(); + + if ( this.documentView.documentNode.$element.get( 0 ).contains( + this.nativeSelection.focusNode + ) && modelRange.equals( new ve.Range( + ve.ce.getOffset( + this.nativeSelection.anchorNode, + this.nativeSelection.anchorOffset + ), + ve.ce.getOffset( + this.nativeSelection.focusNode, + this.nativeSelection.focusOffset + ) + ) ) ) { + // Current surface selection fits model range; don't change + return; + } + + changed = this.showSelectionState( this.getSelectionState( modelRange ) ); // Support: Chrome // Fixes T131674, which is only triggered with Chromium-style ce=false cursoring // restrictions (but other cases of non-updated cursor holders can probably occur -- To view, visit https://gerrit.wikimedia.org/r/292835 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I2a75c847482bca940de2ee8605727ac6c52db8f0 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] WIP: Calculate model ranges on demand, not RangeState creation - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/290425 Change subject: WIP: Calculate model ranges on demand, not RangeState creation .. WIP: Calculate model ranges on demand, not RangeState creation Change-Id: I244dfad38348b279a51b7233014566d4dd33f4b3 --- M src/ce/keydownhandlers/ve.ce.LinearArrowKeyDownHandler.js M src/ce/ve.ce.RangeState.js M src/ce/ve.ce.Surface.js M src/ce/ve.ce.SurfaceObserver.js M src/ce/ve.ce.js M src/ve.SelectionState.js 6 files changed, 76 insertions(+), 200 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/25/290425/1 diff --git a/src/ce/keydownhandlers/ve.ce.LinearArrowKeyDownHandler.js b/src/ce/keydownhandlers/ve.ce.LinearArrowKeyDownHandler.js index f57abf6..24faf2b 100644 --- a/src/ce/keydownhandlers/ve.ce.LinearArrowKeyDownHandler.js +++ b/src/ce/keydownhandlers/ve.ce.LinearArrowKeyDownHandler.js @@ -186,7 +186,10 @@ } else { // Check where the range has moved to surface.surfaceObserver.pollOnceNoCallback(); - newRange = new ve.Range( surface.surfaceObserver.getRange().to ); + newRange = new ve.Range( ve.ce.getOffset( + surface.nativeSelection.focusNode, + surface.nativeSelection.focusOffset + ) ); } // Adjust range to use old anchor, if necessary diff --git a/src/ce/ve.ce.RangeState.js b/src/ce/ve.ce.RangeState.js index 27a7ef6..0569120 100644 --- a/src/ce/ve.ce.RangeState.js +++ b/src/ce/ve.ce.RangeState.js @@ -34,11 +34,6 @@ this.contentChanged = false; /** -* @property {ve.Range|null} veRange The current selection range -*/ - this.veRange = null; - - /** * @property {ve.ce.BranchNode|null} node The current branch node */ this.node = null; @@ -100,10 +95,8 @@ if ( selection.equalsSelection( oldSelection ) ) { // No change; use old values for speed this.selectionChanged = false; - this.veRange = old && old.veRange; } else { this.selectionChanged = true; - this.veRange = ve.ce.veRangeFromSelection( selection ); } anchorNodeChanged = oldSelection.anchorNode !== selection.anchorNode; @@ -119,7 +112,6 @@ // Check this node belongs to our document if ( this.node && this.node.root !== documentNode ) { this.node = null; - this.veRange = null; } } } @@ -167,3 +159,12 @@ // misleadingly different from when the selection was saved). this.misleadingSelection = selection; }; + +/** + * Whether the selection is null + * + * @return {boolean} Whether the selection is null + */ +ve.ce.RangeState.prototype.isNullSelection = function () { + return this.misleadingSelection.isNull(); +}; diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js index e1dcc5e..1f74770 100644 --- a/src/ce/ve.ce.Surface.js +++ b/src/ce/ve.ce.Surface.js @@ -2618,7 +2618,7 @@ */ ve.ce.Surface.prototype.handleObservedChanges = function ( oldState, newState ) { - var newSelection, transaction, removedUnicorns, + var newSelection, transaction, oldRange, removedUnicorns, activeNode, coveringRange, nodeRange, containsStart, containsEnd, surface = this, dmDoc = this.getModel().getDocument(), @@ -2632,6 +2632,7 @@ newState.node.unicornAnnotations ); if ( transaction ) { + oldRange = ve.ce.veRangeFromSelection( oldState.misleadingSelection ); this.incRenderLock(); try { this.changeModel( transaction ); @@ -2651,21 +2652,22 @@ oldState.node.root && oldState.node instanceof ve.ce.ContentBranchNode ) { + oldRange = ve.ce.veRangeFromSelection( oldState.misleadingSelection ); oldState.node.renderContents(); } - - if ( newState.selectionChanged && !( - // Ignore when the newRange is just a flipped oldRange - oldState && - oldState.veRange && - newState.veRange && - !newState.veRange.isCollapsed() && - oldState.veRange.equalsSelection( newState.veRange ) - ) ) { - if ( newState.veRange ) { - newSelection = new ve.dm.LinearSelection( dmDoc, newState.veRange ); - } else { + if ( + newState.selectionChanged && + // Ignore
[MediaWiki-commits] [Gerrit] Handle about groups correctly in getNodeAndOffset - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/287048 Change subject: Handle about groups correctly in getNodeAndOffset .. Handle about groups correctly in getNodeAndOffset Bug: T133608 Change-Id: I15897b0da1ee0abbab48e2f7302ba507a3ca876c --- M src/ce/ve.ce.Document.js 1 file changed, 17 insertions(+), 4 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/48/287048/1 diff --git a/src/ce/ve.ce.Document.js b/src/ce/ve.ce.Document.js index d4803df..fc7c772 100644 --- a/src/ce/ve.ce.Document.js +++ b/src/ce/ve.ce.Document.js @@ -58,9 +58,8 @@ * @throws {Error} Offset could not be translated to a DOM element and offset */ ve.ce.Document.prototype.getNodeAndOffset = function ( offset ) { - var branchNode, position, count, step, node, model, steps, - countedNodes = [], - found = {}; + var branchNode, position, count, step, node, model, steps, found, prevNode, $aboutGroup, + countedNodes = []; // 1. Step with ve.adjacentDomPosition( ..., { stop: function () { return true; } } ) // until we hit a position at the correct offset (which is guaranteed to be the first @@ -168,7 +167,21 @@ } } // Now "position" is the first DOM position (in document order) at the correct - // model offset. Find all DOM positions at the same model offset + // model offset. + + // Jump past any about grouped nodes + prevNode = position.node.childNodes[ position.offset - 1 ]; + if ( prevNode && prevNode.nodeType === Node.ELEMENT_NODE && ( + prevNode.classList.contains( 've-ce-branchNode' ) || + prevNode.classList.contains( 've-ce-leafNode' ) + ) ) { + $aboutGroup = $.data( prevNode, 'view' ).$element; + if ( $aboutGroup.length > 1 ) { + position.offset = 1 + ve.parentIndex( $aboutGroup.get( -1 ) ); + } + } + + // Find all subsequent DOM positions at the same model offset found = {}; function stop( step ) { var model; -- To view, visit https://gerrit.wikimedia.org/r/287048 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I15897b0da1ee0abbab48e2f7302ba507a3ca876c Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] Reinstate Firefox img hack for versions >= 38 - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/285579 Change subject: Reinstate Firefox img hack for versions >= 38 .. Reinstate Firefox img hack for versions >= 38 Partially reverts I0ee0daaab6b27198f3239a64648d82c5c19444af Bug: T133610 Change-Id: I4e5a000652a83059c254d56763fa7367b6554928 --- M src/ce/ve.ce.BranchNode.js 1 file changed, 4 insertions(+), 3 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/79/285579/1 diff --git a/src/ce/ve.ce.BranchNode.js b/src/ce/ve.ce.BranchNode.js index 10e3107..bbecc6e 100644 --- a/src/ce/ve.ce.BranchNode.js +++ b/src/ce/ve.ce.BranchNode.js @@ -68,10 +68,11 @@ .addClass( 've-ce-branchNode-slug ve-ce-branchNode-inlineSlug' ) .append( $img ); - // Support: Firefox<=37 - // Firefox misbehaves if we don't set an src: https://bugzilla.mozilla.org/show_bug.cgi?id=989012 + // Support: Firefox + // Firefox <=37 misbehaves if we don't set an src: https://bugzilla.mozilla.org/show_bug.cgi?id=989012 + // Firefox misbehaves if we don't set an src and there is no sizing at node creation time: https://bugzilla.mozilla.org/show_bug.cgi?id=1267906 // Setting an src in Chrome is slow, so only set it in affected versions of Firefox - if ( profile.layout === 'gecko' && profile.versionNumber < 38 ) { + if ( profile.layout === 'gecko' ) { $img.prop( 'src', ve.ce.minImgDataUri ); } return $span.get( 0 ); -- To view, visit https://gerrit.wikimedia.org/r/285579 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I4e5a000652a83059c254d56763fa7367b6554928 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] Update cursor holders in showModelSelection - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/285335 Change subject: Update cursor holders in showModelSelection .. Update cursor holders in showModelSelection Bug: T131674 Change-Id: I388056285a9b19fb3356b153da7c717fa691cdb8 --- M src/ce/ve.ce.Surface.js 1 file changed, 8 insertions(+), 2 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/35/285335/1 diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js index 128028b..655fdcd 100644 --- a/src/ce/ve.ce.Surface.js +++ b/src/ce/ve.ce.Surface.js @@ -3177,7 +3177,7 @@ * @return {boolean} Whether the selection actually changed */ ve.ce.Surface.prototype.showModelSelection = function () { - var selection; + var selection, changed; if ( this.deactivated ) { // Defer until view has updated @@ -3188,7 +3188,13 @@ selection = this.getSelection(); if ( selection.isNativeCursor() && !this.focusedBlockSlug ) { - return this.showSelectionState( this.getSelectionState( selection.getModel().getRange() ) ); + changed = this.showSelectionState( + this.getSelectionState( selection.getModel().getRange() ) + ); + if ( changed ) { + this.updateCursorHolders(); + return true; + } } return false; -- To view, visit https://gerrit.wikimedia.org/r/285335 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I388056285a9b19fb3356b153da7c717fa691cdb8 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] Fix ve.ce.KeyDownHandlerFactory.name - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/285331 Change subject: Fix ve.ce.KeyDownHandlerFactory.name .. Fix ve.ce.KeyDownHandlerFactory.name Change-Id: Ia0df321f439a53f7a93807336b51bdcf38c3c797 --- M src/ce/ve.ce.KeyDownHandlerFactory.js 1 file changed, 1 insertion(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/31/285331/1 diff --git a/src/ce/ve.ce.KeyDownHandlerFactory.js b/src/ce/ve.ce.KeyDownHandlerFactory.js index ec6bfe4..8047d5d 100644 --- a/src/ce/ve.ce.KeyDownHandlerFactory.js +++ b/src/ce/ve.ce.KeyDownHandlerFactory.js @@ -11,7 +11,7 @@ * @extends OO.Factory * @constructor */ -ve.ce.KeyDownHandlerFactory = function VeUiKeyDownHandlerFactory() { +ve.ce.KeyDownHandlerFactory = function VeCeKeyDownHandlerFactory() { // Parent constructor ve.ce.KeyDownHandlerFactory.super.apply( this, arguments ); -- To view, visit https://gerrit.wikimedia.org/r/285331 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Ia0df321f439a53f7a93807336b51bdcf38c3c797 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] WIP DONTMERGE: IME UI integration - change (mediawiki...UniversalLanguageSelector)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/283197 Change subject: WIP DONTMERGE: IME UI integration .. WIP DONTMERGE: IME UI integration Change-Id: I796fa6b5425e108f9b6b17f1b0f1579616619b6e --- M extension.json A lib/ve-mw/ext.ve-mw-jquery.ime.init.js A lib/ve-mw/ve.ui.MWCommandRegistry.js A lib/ve-mw/ve.ui.MWImeDialog.css A lib/ve-mw/ve.ui.MWImeDialog.js A lib/ve-mw/ve.ui.MWImeDialogTool.js A lib/ve-mw/ve.ui.MWInputMethodDialog.css A lib/ve-mw/ve.ui.MWInputMethodDialog.js 8 files changed, 405 insertions(+), 2 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/UniversalLanguageSelector refs/changes/97/283197/1 diff --git a/extension.json b/extension.json index e46c4c4..59c234f 100644 --- a/extension.json +++ b/extension.json @@ -282,8 +282,20 @@ "remoteExtPath": "UniversalLanguageSelector/resources" }, "jquery.ime": { - "scripts": "jquery.ime/jquery.ime.js", - "styles": "jquery.ime/css/jquery.ime.css", + "scripts": [ + "jquery.ime/jquery.ime.js", + "ve-mw/ve.ui.MWCommandRegistry.js", + "ve-mw/ve.ui.MWImeDialog.js", + "ve-mw/ve.ui.MWImeDialogTool.js", + "ve-mw/ve.ui.MWInputMethodDialog.js", + "ve-mw/ext.ve-mw-jquery.ime.init.js" + ], + "styles": [ + "jquery.ime/css/jquery.ime.css", + "ve-mw/ve.ui.MWImeDialog.css", + "ve-mw/ve.ui.MWInputMethodDialog.css" + ], + "dependencies": "ext.visualEditor.core", "localBasePath": "lib", "remoteExtPath": "UniversalLanguageSelector/lib" }, diff --git a/lib/ve-mw/ext.ve-mw-jquery.ime.init.js b/lib/ve-mw/ext.ve-mw-jquery.ime.init.js new file mode 100644 index 000..26bcdad --- /dev/null +++ b/lib/ve-mw/ext.ve-mw-jquery.ime.init.js @@ -0,0 +1,52 @@ +/*! + * ULS startup script - MediaWiki specific customization for jquery.uls + * + * Copyright (C) 2012-2013 Alolita Sharma, Amir Aharoni, Arun Ganesh, Brandon Harris, + * Niklas Laxström, Pau Giner, Santhosh Thottingal, Siebrand Mazeland and other + * contributors. See CREDITS for a list. + * + * UniversalLanguageSelector is dual licensed GPLv2 or later and MIT. You don't + * have to do anything special to choose one license or the other and you don't + * have to notify anyone which license you are using. You are free to use + * UniversalLanguageSelector in commercial projects as long as the copyright + * header is left intact. See files GPL-LICENSE and MIT-LICENSE for details. + * + * @file + * @ingroup Extensions + * @licence GNU General Public Licence 2.0 or later + * @licence MIT License + */ + +( function ( $, mw ) { + 'use strict'; + function veInit() { + // Patch IME toolbar + //ve.init.target.constructor.static.toolbarGroups.splice( 6, 1 ); + ve.init.target.constructor.static.toolbarGroups.push( { + type: 'list', + classes: [ 've-test-toolbar-ime' ], + indicator: 'down', + title: OO.ui.deferMsg( 'visualeditor-toolbar-ime-tooltip' ), + include: [ 'specialCharacter', 'mwIme' ], + icon: 'keyboard' + } ); + ve.init.target.setupToolbar( ve.init.target.surface ); + } + + if ( window.ve ) { + // Wait until ve.init.target is available + // TODO: get rid of this ungainly hack + ( function () { + var f = function () { + if ( ve.init && ve.init.target ) { + veInit(); + // ve.init.target.setupToolbar( ve.init.target.surface ); + // ve.init.target.constructor.static.toolbarGroups + } else { + setTimeout( f ); + } + }; + setTimeout( f ); + } () ); + } +}( jQuery, mediaWiki ) ); diff --git a/lib/ve-mw/ve.ui.MWCommandRegistry.js b/lib/ve-mw/ve.ui.MWCommandRegistry.js new file mode 100644 index 000..3ad26cc --- /dev/null +++ b/lib/ve-mw/ve.ui.MWCommandRegistry.js @@ -0,0 +1,14 @@ +/*! + * VisualEditor MediaWiki CommandRegistry registrations. + * + * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt + * @license The MIT License (MIT); see LICENSE.txt +
[MediaWiki-commits] [Gerrit] WIP DONTMERGE: integrate jquery.ime UI - change (mediawiki...VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/279747 Change subject: WIP DONTMERGE: integrate jquery.ime UI .. WIP DONTMERGE: integrate jquery.ime UI TODO: - Fix the UI - Improve jquery.ime dependency situation Bug: T126125 Change-Id: I92e5142d5b0a56c346a7d010ad3d8c4206a4e2ce --- M extension.json M modules/ve-mw/init/ve.init.mw.Target.js A modules/ve-mw/ui/dialogs/ve.ui.MWImeDialog.js A modules/ve-mw/ui/dialogs/ve.ui.MWInputMethodDialog.js A modules/ve-mw/ui/styles/dialogs/ve.ui.MWImeDialog.css A modules/ve-mw/ui/styles/dialogs/ve.ui.MWInputMethodDialog.css A modules/ve-mw/ui/tools/ve.ui.MWImeDialogTool.js M modules/ve-mw/ui/ve.ui.MWCommandRegistry.js 8 files changed, 349 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor refs/changes/47/279747/1 diff --git a/extension.json b/extension.json index 459d15e..58153a4 100644 --- a/extension.json +++ b/extension.json @@ -1083,6 +1083,8 @@ "modules/ve-mw/ui/widgets/ve.ui.MWTocWidget.js", "modules/ve-mw/ui/dialogs/ve.ui.MWExtensionDialog.js", "modules/ve-mw/ui/dialogs/ve.ui.MWExtensionPreviewDialog.js", + "modules/ve-mw/ui/dialogs/ve.ui.MWImeDialog.js", + "modules/ve-mw/ui/dialogs/ve.ui.MWInputMethodDialog.js", "modules/ve-mw/ui/dialogs/ve.ui.MWSaveDialog.js", "modules/ve-mw/ui/dialogs/ve.ui.MWWelcomeDialog.js", "modules/ve-mw/ui/dialogs/ve.ui.MWCommandHelpDialog.js", @@ -1092,6 +1094,7 @@ "modules/ve-mw/ui/elements/ve.ui.MWExpandableErrorElement.js", "modules/ve-mw/ui/elements/ve.ui.MWPreviewElement.js", "modules/ve-mw/ui/tools/ve.ui.MWEditModeTool.js", + "modules/ve-mw/ui/tools/ve.ui.MWImeDialogTool.js", "modules/ve-mw/ui/tools/ve.ui.MWPopupTool.js", "modules/ve-mw/ui/inspectors/ve.ui.MWExtensionInspector.js", "modules/ve-mw/ui/inspectors/ve.ui.MWLiveExtensionInspector.js", @@ -1101,6 +1104,8 @@ "styles": [ "modules/ve-mw/ui/styles/inspectors/ve.ui.MWExtensionInspector.css", "modules/ve-mw/ui/styles/inspectors/ve.ui.MWLiveExtensionInspector.css", + "modules/ve-mw/ui/styles/dialogs/ve.ui.MWImeDialog.css", + "modules/ve-mw/ui/styles/dialogs/ve.ui.MWInputMethodDialog.css", "modules/ve-mw/ui/styles/dialogs/ve.ui.MWWelcomeDialog.css", "modules/ve-mw/ui/styles/dialogs/ve.ui.MWSaveDialog.css", "modules/ve-mw/ui/styles/elements/ve.ui.MWExpandableErrorElement.css", @@ -1126,6 +1131,7 @@ "mediawiki.jqueryMsg", "jquery.cookie", "jquery.byteLimit", + "jquery.ime", "mediawiki.skinning.content.parsoid", "mediawiki.widgets", "ext.visualEditor.switching" diff --git a/modules/ve-mw/init/ve.init.mw.Target.js b/modules/ve-mw/init/ve.init.mw.Target.js index 491357b..7d3a2f3 100644 --- a/modules/ve-mw/init/ve.init.mw.Target.js +++ b/modules/ve-mw/init/ve.init.mw.Target.js @@ -80,7 +80,15 @@ promote: [ 'media', 'transclusion', 'insertTable' ] }, // SpecialCharacter - { include: [ 'specialCharacter' ] } + { include: [ 'specialCharacter' ] }, + // IME toolbar + { + classes: [ 've-test-toolbar-ime' ], + indicator: 'down', + title: OO.ui.deferMsg( 'visualeditor-toolbar-ime-tooltip' ), + include: [ 'mwIme' ], + icon: 'listBullet' + } ]; ve.init.mw.Target.static.importRules = { diff --git a/modules/ve-mw/ui/dialogs/ve.ui.MWImeDialog.js b/modules/ve-mw/ui/dialogs/ve.ui.MWImeDialog.js new file mode 100644 index 000..8739594 --- /dev/null +++ b/modules/ve-mw/ui/dialogs/ve.ui.MWImeDialog.js @@ -0,0 +1,185 @@ +/*! + * VisualEditor UserInterface MWImeDialog class. + * + * @copyright 2011-2016 VisualEditor Team and others; see http://ve.mit-license.org + */ + +/** + * IME dialog + * + * @class + * @extends ve.ui.ToolbarDialog + * + * @constructor + * @param {Object} [config] Configuration options + */ +ve.ui.MWImeDialog = function VeUiMWImeDialog( config ) { + // Parent constructor + ve.ui.MWImeDialog.super.call( this, config ); + + //
[MediaWiki-commits] [Gerrit] WIP DONTMERGE: integrate jquery.ime UI - change (mediawiki...VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/279748 Change subject: WIP DONTMERGE: integrate jquery.ime UI .. WIP DONTMERGE: integrate jquery.ime UI TODO: - Fix the UI - Improve jquery.ime dependency situation Bug: T126125 Change-Id: If1e8e9a6e340ddfed4ef0fb8ffbe61161f32582d --- M extension.json M modules/ve-mw/init/ve.init.mw.Target.js A modules/ve-mw/ui/dialogs/ve.ui.MWImeDialog.js A modules/ve-mw/ui/dialogs/ve.ui.MWInputMethodDialog.js A modules/ve-mw/ui/styles/dialogs/ve.ui.MWImeDialog.css A modules/ve-mw/ui/styles/dialogs/ve.ui.MWInputMethodDialog.css A modules/ve-mw/ui/tools/ve.ui.MWImeDialogTool.js M modules/ve-mw/ui/ve.ui.MWCommandRegistry.js 8 files changed, 349 insertions(+), 1 deletion(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor refs/changes/48/279748/1 diff --git a/extension.json b/extension.json index 459d15e..58153a4 100644 --- a/extension.json +++ b/extension.json @@ -1083,6 +1083,8 @@ "modules/ve-mw/ui/widgets/ve.ui.MWTocWidget.js", "modules/ve-mw/ui/dialogs/ve.ui.MWExtensionDialog.js", "modules/ve-mw/ui/dialogs/ve.ui.MWExtensionPreviewDialog.js", + "modules/ve-mw/ui/dialogs/ve.ui.MWImeDialog.js", + "modules/ve-mw/ui/dialogs/ve.ui.MWInputMethodDialog.js", "modules/ve-mw/ui/dialogs/ve.ui.MWSaveDialog.js", "modules/ve-mw/ui/dialogs/ve.ui.MWWelcomeDialog.js", "modules/ve-mw/ui/dialogs/ve.ui.MWCommandHelpDialog.js", @@ -1092,6 +1094,7 @@ "modules/ve-mw/ui/elements/ve.ui.MWExpandableErrorElement.js", "modules/ve-mw/ui/elements/ve.ui.MWPreviewElement.js", "modules/ve-mw/ui/tools/ve.ui.MWEditModeTool.js", + "modules/ve-mw/ui/tools/ve.ui.MWImeDialogTool.js", "modules/ve-mw/ui/tools/ve.ui.MWPopupTool.js", "modules/ve-mw/ui/inspectors/ve.ui.MWExtensionInspector.js", "modules/ve-mw/ui/inspectors/ve.ui.MWLiveExtensionInspector.js", @@ -1101,6 +1104,8 @@ "styles": [ "modules/ve-mw/ui/styles/inspectors/ve.ui.MWExtensionInspector.css", "modules/ve-mw/ui/styles/inspectors/ve.ui.MWLiveExtensionInspector.css", + "modules/ve-mw/ui/styles/dialogs/ve.ui.MWImeDialog.css", + "modules/ve-mw/ui/styles/dialogs/ve.ui.MWInputMethodDialog.css", "modules/ve-mw/ui/styles/dialogs/ve.ui.MWWelcomeDialog.css", "modules/ve-mw/ui/styles/dialogs/ve.ui.MWSaveDialog.css", "modules/ve-mw/ui/styles/elements/ve.ui.MWExpandableErrorElement.css", @@ -1126,6 +1131,7 @@ "mediawiki.jqueryMsg", "jquery.cookie", "jquery.byteLimit", + "jquery.ime", "mediawiki.skinning.content.parsoid", "mediawiki.widgets", "ext.visualEditor.switching" diff --git a/modules/ve-mw/init/ve.init.mw.Target.js b/modules/ve-mw/init/ve.init.mw.Target.js index 491357b..7d3a2f3 100644 --- a/modules/ve-mw/init/ve.init.mw.Target.js +++ b/modules/ve-mw/init/ve.init.mw.Target.js @@ -80,7 +80,15 @@ promote: [ 'media', 'transclusion', 'insertTable' ] }, // SpecialCharacter - { include: [ 'specialCharacter' ] } + { include: [ 'specialCharacter' ] }, + // IME toolbar + { + classes: [ 've-test-toolbar-ime' ], + indicator: 'down', + title: OO.ui.deferMsg( 'visualeditor-toolbar-ime-tooltip' ), + include: [ 'mwIme' ], + icon: 'listBullet' + } ]; ve.init.mw.Target.static.importRules = { diff --git a/modules/ve-mw/ui/dialogs/ve.ui.MWImeDialog.js b/modules/ve-mw/ui/dialogs/ve.ui.MWImeDialog.js new file mode 100644 index 000..8739594 --- /dev/null +++ b/modules/ve-mw/ui/dialogs/ve.ui.MWImeDialog.js @@ -0,0 +1,185 @@ +/*! + * VisualEditor UserInterface MWImeDialog class. + * + * @copyright 2011-2016 VisualEditor Team and others; see http://ve.mit-license.org + */ + +/** + * IME dialog + * + * @class + * @extends ve.ui.ToolbarDialog + * + * @constructor + * @param {Object} [config] Configuration options + */ +ve.ui.MWImeDialog = function VeUiMWImeDialog( config ) { + // Parent constructor + ve.ui.MWImeDialog.super.call( this, config ); + + //
[MediaWiki-commits] [Gerrit] Emulated setTimeout for unit testing - change (oojs/ui)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/277594 Change subject: Emulated setTimeout for unit testing .. Emulated setTimeout for unit testing Bug: T130064 Change-Id: I25f524836a182797d799e67321eda1f1f78bed12 --- M Gruntfile.js A tests/TestTimer.js M tests/core.test.js 3 files changed, 158 insertions(+), 52 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/oojs/ui refs/changes/94/277594/1 diff --git a/Gruntfile.js b/Gruntfile.js index 5490b85..0632f79 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -404,6 +404,7 @@ 'dist/oojs-ui-apex.js', 'dist/oojs-ui-mediawiki.js', 'tests/QUnit.assert.equalDomElement.js', + 'tests/TestTimer.js', 'tests/**/*.test.js' ], reporters: [ 'dots' ], diff --git a/tests/TestTimer.js b/tests/TestTimer.js new file mode 100644 index 000..7c07670 --- /dev/null +++ b/tests/TestTimer.js @@ -0,0 +1,76 @@ +/*! + * OO UI TestTimer class. + * + * @copyright 2011-2016 OOjs UI Team and others; see http://ve.mit-license.org + */ + +/** + * @class + * + * @constructor + */ +OO.ui.TestTimer = function TestTimer() { + this.pendingCalls = []; + this.nextId = 1; +}; + +/* Inheritance */ + +OO.initClass( OO.ui.TestTimer ); + +/* Methods */ + +/** + * Emulated setTimeout; just pushes the call into a queue + * + * @param {Function} f The function to call + * @param {number} [timeout] Minimum wait time in ms + * @return {number} Timeout id for cancellation + */ +OO.ui.TestTimer.prototype.setTimeout = function ( f, timeout ) { + this.pendingCalls.push( { + id: this.nextId, + f: f, + timeout: timeout || 0 + } ); + return this.nextId++; +}; + +/** + * Emulated clearTimeout; just blanks the queued call function + * + * @param {number} id Timeout id for cancellation + */ +OO.ui.TestTimer.prototype.clearTimeout = function ( id ) { + this.pendingCalls.forEach( function ( call ) { + if ( call.id === id ) { + call.f = null; + } + } ); +}; + +/** + * Run queued calls + * + * @param {number} [interval] Apparent passed time since last call (defaults to infinite) + */ +OO.ui.TestTimer.prototype.runPending = function ( interval ) { + var calls, i, len, call; + calls = this.pendingCalls.splice( 0, this.pendingCalls.length ).sort( function ( a, b ) { + return a.timeout - b.timeout; + } ); + for ( i = 0, len = calls.length; i < len; i++ ) { + call = calls[ i ]; + if ( interval === undefined || call.timeout <= interval ) { + if ( call.f ) { + call.f(); + } + } else { + this.pendingCalls.push( { + id: call.id, + f: call.f, + timeout: call.timeout - interval + } ); + } + } +}; diff --git a/tests/core.test.js b/tests/core.test.js index c26f207..a3f517c 100644 --- a/tests/core.test.js +++ b/tests/core.test.js @@ -94,57 +94,86 @@ } } ); -QUnit.asyncTest( 'debounce', 4, function ( assert ) { - var - realSetTimeout = window.setTimeout, - ourSetTimeout = function () { - setTimeoutCalled++; - return realSetTimeout.apply( window, arguments ); - }, - funCalled, - setTimeoutCalled, - fun = function () { - funCalled++; - }, - cases = [ - function () { - var fun50 = OO.ui.debounce( fun, 50 ); - funCalled = 0; - setTimeoutCalled = 0; - window.setTimeout = ourSetTimeout; - fun50(); - fun50(); - window.setTimeout = realSetTimeout; - setTimeout( function () { - assert.strictEqual( setTimeoutCalled, 2, 'wait=50: setTimeout was called twice' ); - assert.strictEqual( funCalled, 1, 'wait=50: debounced function was executed once' ); - maybeFinishTest(); - }, 100 ); - }, - function () { - var fun0 = OO.ui.debounce( fun ); - funCalled = 0;
[MediaWiki-commits] [Gerrit] WIP DONTMERGE: integrate jquery.ime UI - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/276145 Change subject: WIP DONTMERGE: integrate jquery.ime UI .. WIP DONTMERGE: integrate jquery.ime UI Needs tidying up Change-Id: I92e5142d5b0a56c346a7d010ad3d8c4206a4e2ce --- M .jsduck/eg-iframe.html M build/modules.json M demos/ve/desktop-dist.html M demos/ve/desktop.html M demos/ve/minimal-rtl.html M demos/ve/minimal.html M demos/ve/mobile-dist.html M demos/ve/mobile.html M demos/ve/pages/h1.html M demos/ve/ve.demo.init.js M i18n/en.json M i18n/qqq.json M lib/oojs-ui/oojs-ui-apex-icons-editing-advanced.css A lib/oojs-ui/themes/apex/images/icons/ime.svg M src/init/ve.init.Target.js A src/ui/dialogs/ve.ui.ImeDialog.js A src/ui/dialogs/ve.ui.InputMethodDialog.js A src/ui/styles/dialogs/ve.ui.ImeDialog.css A src/ui/styles/dialogs/ve.ui.InputMethodDialog.css M src/ui/tools/ve.ui.ToolbarDialogTool.js M src/ui/ve.ui.CommandRegistry.js M tests/index.html 22 files changed, 472 insertions(+), 4 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/45/276145/1 diff --git a/.jsduck/eg-iframe.html b/.jsduck/eg-iframe.html index a610010..44b5284 100644 --- a/.jsduck/eg-iframe.html +++ b/.jsduck/eg-iframe.html @@ -44,6 +44,15 @@ + + + + + + + + + diff --git a/build/modules.json b/build/modules.json index 45c4701..5497cf5 100644 --- a/build/modules.json +++ b/build/modules.json @@ -107,6 +107,22 @@ "CLDRPluralRuleParser" ] }, + "rangy": { + "scripts": [ + "lib/jquery.ime/libs/rangy/rangy-core.js" + ] + }, + "jquery.ime": { + "scripts": [ + "lib/jquery.ime/src/jquery.ime.js", + "lib/jquery.ime/src/jquery.ime.selector.js", + "lib/jquery.ime/src/jquery.ime.preferences.js", + "lib/jquery.ime/src/jquery.ime.inputmethods.js" + ], + "dependencies": [ + "rangy" + ] + }, "CLDRPluralRuleParser" : { "scripts": [ "lib/jquery.i18n/libs/CLDRPluralRuleParser/src/CLDRPluralRuleParser.js" @@ -159,6 +175,8 @@ "oojs", "oojs-ui", "jquery.i18n", + "rangy", + "jquery.ime", "jquery.uls.data", "jquery.client", "papaparse" @@ -170,6 +188,8 @@ "oojs", "oojs-ui", "jquery.i18n.dist", + "rangy", + "jquery.ime", "jquery.uls.data.dist", "jquery.client", "papaparse" @@ -476,6 +496,8 @@ "src/ui/widgets/ve.ui.LanguageResultWidget.js", "src/ui/dialogs/ve.ui.LanguageSearchDialog.js", "src/ui/widgets/ve.ui.LanguageInputWidget.js", + "src/ui/dialogs/ve.ui.InputMethodDialog.js", + "src/ui/dialogs/ve.ui.ImeDialog.js", "src/ui/widgets/ve.ui.TargetWidget.js", "src/ui/widgets/ve.ui.LinkAnnotationWidget.js", "src/ui/widgets/ve.ui.ContextSelectWidget.js", @@ -522,10 +544,11 @@ "src/ui/styles/dialogs/ve.ui.CommandHelpDialog.css", "src/ui/styles/dialogs/ve.ui.FindAndReplaceDialog.css", "src/ui/styles/dialogs/ve.ui.ProgressDialog.css", - "src/ui/styles/dialogs/ve.ui.SpecialCharacterDialog.css", "src/ui/styles/tools/ve.ui.FormatTool.css", "src/ui/styles/widgets/ve.ui.LanguageInputWidget.css", "src/ui/styles/widgets/ve.ui.LanguageSearchWidget.css", + "src/ui/styles/dialogs/ve.ui.InputMethodDialog.css", + "src/ui/styles/dialogs/ve.ui.ImeDialog.css", "src/ui/styles/widgets/ve.ui.ContextOptionWidget.css", "src/ui/styles/widgets/ve.ui.ContextSelectWidget.css", "src/ui/styles/widgets/ve.ui.DimensionsWidget.css", diff --git a/demos/ve/desktop-dist.html b/demos/ve/desktop-dist.html index 81d4f74..54c726f 100644 --- a/demos/ve/desktop-dist.html +++ b/demos/ve/desktop-dist.html @@ -58,6 +58,15 @@ + + + + + + + +
[MediaWiki-commits] [Gerrit] Use offset paths in selection state tests - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/273762 Change subject: Use offset paths in selection state tests .. Use offset paths in selection state tests This will facilitate expected positions that are not in text nodes Change-Id: Ib2b38e65b78b6dfed1194d6646c320cf12a74ea1 --- M tests/ce/ve.ce.Surface.test.js M tests/dm/ve.dm.example.js 2 files changed, 102 insertions(+), 92 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/62/273762/1 diff --git a/tests/ce/ve.ce.Surface.test.js b/tests/ce/ve.ce.Surface.test.js index c446d2e..7525a73 100644 --- a/tests/ce/ve.ce.Surface.test.js +++ b/tests/ce/ve.ce.Surface.test.js @@ -1926,104 +1926,36 @@ '' + '2nd' + '', + // The offset path of the result of getNodeAndOffset for + // each offset expected: [ - { anchorNode: 'Foo', anchorOffset: 0 }, - { anchorNode: 'Foo', anchorOffset: 0 }, - { anchorNode: 'Foo', anchorOffset: 1 }, - { anchorNode: 'Foo', anchorOffset: 2 }, - { anchorNode: 'Foo', anchorOffset: 3 }, - null, // Focusable - { anchorNode: 'Whee', anchorOffset: 0 }, - { anchorNode: 'Whee', anchorOffset: 1 }, - { anchorNode: 'Whee', anchorOffset: 2 }, - { anchorNode: 'Whee', anchorOffset: 3 }, - { anchorNode: 'Whee', anchorOffset: 4 }, - { anchorNode: 'Whee', anchorOffset: 4, focusNode: '2', focusOffset: 0 }, - { anchorNode: '2', anchorOffset: 0 }, - { anchorNode: '2', anchorOffset: 1 }, - { anchorNode: 'n', anchorOffset: 1 }, - { anchorNode: 'd', anchorOffset: 1 } + [ 0, 0, 0 ], + [ 0, 0, 0 ], + [ 0, 0, 1 ], + [ 0, 0, 2 ], + [ 0, 0, 3 ], + null, + [ 0, 4, 0 ], + [ 0, 4, 1 ], + [ 0, 4, 2 ], + [ 0, 4, 3 ], + [ 0, 4, 4 ], + [ 0, 4, 4 ], + [ 1, 0, 0 ], + [ 1, 0, 1 ], + [ 1, 1, 0, 1 ], + [ 1, 2, 1 ] ] }, { msg: 'Simple example doc', html: ve.dm.example.html, - expected: [ - { anchorNode: 'a', anchorOffset: 0 }, - { anchorNode: 'a', anchorOffset: 0 }, - { anchorNode: 'a', anchorOffset: 1 }, - { anchorNode: 'b', anchorOffset: 1 }, - { anchorNode: 'c', anchorOffset: 1 }, - { anchorNode: 'c', anchorOffset: 1, focusNode: 'd', focusOffset: 0 }, - { anchorNode: 'c', anchorOffset: 1, focusNode: 'd', focusOffset: 0 }, - { anchorNode: 'c', anchorOffset: 1, focusNode: 'd', focusOffset: 0 }, - { anchorNode: 'c', anchorOffset: 1, focusNode: 'd', focusOffset: 0 }, - { anchorNode: 'c', anchorOffset: 1, focusNode: 'd', focusOffset: 0 }, - // 10 - { anchorNode: 'd', anchorOffset: 0 }, - { anchorNode: 'd', anchorOffset: 1 }, - { anchorNode: 'd', anchorOffset: 1, focusNode: 'e', focusOffset: 0 }, - { anchorNode: 'd', anchorOffset: 1, focusNode: 'e', focusOffset: 0 }, - { anchorNode: 'd', anchorOffset: 1, focusNode: 'e', focusOffset: 0 }, -
[MediaWiki-commits] [Gerrit] Make getSelectionState preserve collapsedness - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/273435 Change subject: Make getSelectionState preserve collapsedness .. Make getSelectionState preserve collapsedness Bug: T128176 Change-Id: I006c5e56e7b5e077f7fef842d505a65b428b870f --- M src/ce/ve.ce.Surface.js M tests/ce/ve.ce.Surface.test.js 2 files changed, 17 insertions(+), 17 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/35/273435/1 diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js index da58f7b..aad32cc 100644 --- a/src/ce/ve.ce.Surface.js +++ b/src/ce/ve.ce.Surface.js @@ -3269,6 +3269,11 @@ /** * Get a SelectionState corresponding to a ve.Range. * + * If either endpoint of the ve.Range is not a cursor offset, adjust the SelectionState + * endpoints to be at cursor offsets. For a collapsed selection, the adjustment preserves + * collapsedness; for a non-collapsed selection, the adjustment is in the direction that + * grows the selection (thereby avoiding collapsing or reversing the selection). + * * @method * @param {ve.Range} range Range to get selection for * @return {Object} The selection @@ -3290,10 +3295,14 @@ dmDoc.getNearestCursorOffset( range.from, range.isBackwards() ? 1 : -1 ), !this.focused ); - focus = this.documentView.getNodeAndOffset( - dmDoc.getNearestCursorOffset( range.to, range.isBackwards() ? -1 : 1 ), - !this.focused - ); + if ( range.isCollapsed() ) { + focus = anchor; + } else { + focus = this.documentView.getNodeAndOffset( + dmDoc.getNearestCursorOffset( range.to, range.isBackwards() ? -1 : 1 ), + !this.focused + ); + } return new ve.SelectionState( { anchorNode: anchor.node, anchorOffset: anchor.offset, diff --git a/tests/ce/ve.ce.Surface.test.js b/tests/ce/ve.ce.Surface.test.js index 407560c..c446d2e 100644 --- a/tests/ce/ve.ce.Surface.test.js +++ b/tests/ce/ve.ce.Surface.test.js @@ -2022,7 +2022,7 @@ for ( i = 0; i < cases.length; i++ ) { for ( j = 0; j < cases[ i ].expected.length; j++ ) { - expect += cases[ i ].expected[ j ] ? ( cases[ i ].expected[ j ].focusNode === undefined ? 2 : 4 ) : 1; + expect += cases[ i ].expected[ j ] ? 2 : 1; } } @@ -2038,18 +2038,9 @@ assert.strictEqual( null, cases[ i ].expected[ j ], 'Focusable node at ' + j ); } else { selection = view.getSelectionState( new ve.Range( j ) ); - if ( selection.isCollapsed ) { - expectedNode = $( '' ).html( cases[ i ].expected[ j ].anchorNode )[ 0 ].childNodes[ 0 ]; - assert.equalDomElement( selection.anchorNode, expectedNode, 'Node ' + msg ); - assert.strictEqual( selection.anchorOffset, cases[ i ].expected[ j ].anchorOffset, 'Offset ' + msg ); - } else { - expectedNode = $( '' ).html( cases[ i ].expected[ j ].anchorNode )[ 0 ].childNodes[ 0 ]; - assert.equalDomElement( selection.anchorNode, expectedNode, 'Anchor node ' + msg ); - assert.strictEqual( selection.anchorOffset, cases[ i ].expected[ j ].anchorOffset, 'Anchor offset ' + msg ); - expectedNode = $( '' ).html( cases[ i ].expected[ j ].focusNode )[ 0 ].childNodes[ 0 ]; - assert.equalDomElement( selection.focusNode, expectedNode, 'End node ' + msg ); - assert.strictEqual( selection.focusOffset, cases[ i ].expected[ j ].focusOffset, 'Focus offset ' + msg ); - } + expectedNode = $( '' ).html( cases[ i ].expected[ j ].anchorNode )[ 0 ].childNodes[ 0 ]; + assert.equalDomElement( selection.anchorNode, expectedNode, 'Node ' + msg ); + assert.strictEqual( selection.anchorOffset, cases[ i ].expected[ j ].anchorOffset, 'Offset ' + msg ); } } view.destroy(); -- To view, visit https://gerrit.wikimedia.org/r/273435 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I006c5e56e7b5e077f7fef842d505a65b428b870f Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___
[MediaWiki-commits] [Gerrit] Clarify documentation of directionality methods - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/271064 Change subject: Clarify documentation of directionality methods .. Clarify documentation of directionality methods Change-Id: I56056629c4e5bf46d0cc03abd84e468fe56f3388 --- M src/ce/ve.ce.Document.js M src/ce/ve.ce.Selection.js 2 files changed, 6 insertions(+), 4 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/64/271064/1 diff --git a/src/ce/ve.ce.Document.js b/src/ce/ve.ce.Document.js index a139254..cd21ba3 100644 --- a/src/ce/ve.ce.Document.js +++ b/src/ce/ve.ce.Document.js @@ -290,9 +290,9 @@ }; /** - * Get the directionality of some range. + * Get the block directionality of some range * - * Uses the computed CSS direction value of the current node. + * Uses the computed CSS direction value of the current node * * @method * @param {ve.Range} range Range diff --git a/src/ce/ve.ce.Selection.js b/src/ce/ve.ce.Selection.js index 25a3f97..687379b 100644 --- a/src/ce/ve.ce.Selection.js +++ b/src/ce/ve.ce.Selection.js @@ -111,9 +111,11 @@ }; /** - * Get the text directionality of the selection + * Get the block directionality of the selection * - * Note: This is the text's directionality, not the direction of the selection (e.g. ve.Range#isBackwards) + * Note: This is not the direction of the selection (e.g. ve.Range#isBackwards); it is the + * computed block-level CSS directionality. The actual directionality at any point within the + * selection depends on both this and the browser's implementation of BIDI algorithm. * * @abstract * @return {string} 'rtl', 'ltr' -- To view, visit https://gerrit.wikimedia.org/r/271064 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I56056629c4e5bf46d0cc03abd84e468fe56f3388 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] WIP: Refactor getNodeAndOffset - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/270315 Change subject: WIP: Refactor getNodeAndOffset .. WIP: Refactor getNodeAndOffset Change-Id: I8b833feee813b10004fc9f1cf862a6fdbf7e1634 --- M src/ce/ve.ce.Document.js 1 file changed, 71 insertions(+), 85 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/15/270315/1 diff --git a/src/ce/ve.ce.Document.js b/src/ce/ve.ce.Document.js index d9f5f27..c013f99 100644 --- a/src/ce/ve.ce.Document.js +++ b/src/ce/ve.ce.Document.js @@ -167,9 +167,16 @@ * @return {number} return.offset location offset within the node */ ve.ce.Document.prototype.getNodeAndOffsetUnadjustedForUnicorn = function ( offset ) { - var node, startOffset, current, stack, item, $item, length, model, + var branchNode, position, count, step, node, textLength, matchingPositions, model, countedNodes = [], slug = this.getSlugAtOffset( offset ); + + // Cleaner method: + // 1. Step with ve.adjacentDomPosition until we hit a position at the correct offset + // (which is guaranteed to be the first such position in document order). + // 2. Use ve.adjacentDomPosition( ..., { skipSoft: false } ) once to return all + // subsequent positions at the same offset. + // 3. Look at the possible positions and pick accordingly. // If we're a block slug, or an empty inline slug, return its location // Start at the current branch node; get its start offset @@ -197,94 +204,73 @@ ) ) { return { node: slug, offset: 0 }; } - node = this.getBranchNodeFromOffset( offset ); - startOffset = node.getOffset() + ( ( node.isWrapped() ) ? 1 : 0 ); - current = { $contents: node.$element.contents(), offset: 0 }; - stack = [ current ]; - while ( stack.length > 0 ) { - if ( current.offset >= current.$contents.length ) { - stack.pop(); - current = stack[ stack.length - 1 ]; - if ( current && startOffset === offset ) { - // The current node has no DOM children and no DM length (e.g. - // it is a browser-generated that doesn't have class - // ve-ce-leafNode), but the node itself is at the required DM - // offset. Return the first offset inside this node (even if - // it's a node type that cannot contain content, like br). - return { node: current.$contents[ current.offset - 1 ], offset: 0 }; + branchNode = this.getBranchNodeFromOffset( offset ); + position = { node: branchNode.$element, offset: 0 }; + count = branchNode.getOffset() + ( ( branchNode.isWrapped() ) ? 1 : 0 ); + + function noDescend() { + return this.classList.contains( 've-ce-branchNode-blockSlug' ) || + ve.rejectsCursor( this ); + } + + while ( true ) { + if ( count === offset ) { + break; + } + position = ve.adjacentDomPosition( position, 1, { noDescend: noDescend } ); + step = position.steps[ 0 ]; + node = step.node; + if ( node.nodeType === Node.TEXT_NODE ) { + // this branch always breaks or skips over the text node; therefore it + // is guaranteed that this is the first time we encounter the text node, + // so step.type === 'enter' (we just stepped in) + // TODO: what about zero-length text nodes? + textLength = node.data.length; + if ( offset <= count + textLength ) { + // match the appropriate offset in the text node + matchingPositions.push( { node: node, offset: offset - count } ); + break; + } else { + // skip over the text node + count += textLength; + position = { node: node, offset: textLength }; + continue; } + } // else is an element node (TODO: handle comment etc) + + if ( !( + node.classList.contains( 've-ce-branchNode' ) || + node.classList.contains( 've-ce-leafNode' ) + ) ) { + // Nodes like b, inline slug, browser-generated br that doesn't have + // class ve-ce-leafNode: continue walk without incrementing continue; } - item =
[MediaWiki-commits] [Gerrit] Document annotation content container usage - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/269988 Change subject: Document annotation content container usage .. Document annotation content container usage Explicitly state the usage restrictions on the ve.ce.Annotation content container with respect to .appendContents and .appendTo calls. Bug: T121351 Change-Id: Iecad249d6dcb33283b80cb7c3fdd79504c050e27 --- M src/ce/annotations/ve.ce.LinkAnnotation.js M src/ce/annotations/ve.ce.TextStyleAnnotation.js M src/ce/ve.ce.Annotation.js 3 files changed, 21 insertions(+), 4 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/88/269988/1 diff --git a/src/ce/annotations/ve.ce.LinkAnnotation.js b/src/ce/annotations/ve.ce.LinkAnnotation.js index 850dc48..ac0c29b 100644 --- a/src/ce/annotations/ve.ce.LinkAnnotation.js +++ b/src/ce/annotations/ve.ce.LinkAnnotation.js @@ -77,19 +77,21 @@ }; /** - * Attach contents to the annotation as descendent nodes, if not already attached + * @inheritdoc */ ve.ce.LinkAnnotation.prototype.attachContents = function () { var anchor = this.$anchor[ 0 ]; + // Insert post-open nail, annotation contents, and pre-close nail into the anchor anchor.appendChild( this.constructor.static.makeNail( 'post-open' ) ); anchor.appendChild( this.contentFragment ); anchor.appendChild( this.constructor.static.makeNail( 'pre-close' ) ); }; /** - * @param {Node} node Parent node + * @inheritdoc */ ve.ce.LinkAnnotation.prototype.appendTo = function ( node ) { + // Insert pre-open nail, anchor, and post-close nail into a parent node node.appendChild( this.constructor.static.makeNail( 'pre-open' ) ); node.appendChild( this.$anchor[ 0 ] ); node.appendChild( this.constructor.static.makeNail( 'post-close' ) ); diff --git a/src/ce/annotations/ve.ce.TextStyleAnnotation.js b/src/ce/annotations/ve.ce.TextStyleAnnotation.js index 2cd573f..b75b5cd 100644 --- a/src/ce/annotations/ve.ce.TextStyleAnnotation.js +++ b/src/ce/annotations/ve.ce.TextStyleAnnotation.js @@ -33,6 +33,9 @@ /* Methods */ +/** + * @inheritdoc + */ ve.ce.TextStyleAnnotation.prototype.getTagName = function () { return this.getModel().getAttribute( 'nodeName' ) || this.constructor.static.tagName; }; diff --git a/src/ce/ve.ce.Annotation.js b/src/ce/ve.ce.Annotation.js index c5382a4..f92d4e3 100644 --- a/src/ce/ve.ce.Annotation.js +++ b/src/ce/ve.ce.Annotation.js @@ -79,7 +79,7 @@ }; /** - * Get the content container + * Get the container into which annotation contents should be appended * * @return {HTMLElement} Content container */ @@ -87,16 +87,28 @@ return this.$element[ 0 ]; }; +/** + * Attach completed contents to the annotation as descendent nodes, if not already attached + * + * No further contents should be appended into the content container after calling this + */ ve.ce.Annotation.prototype.attachContents = function () { // Do nothing; already attached }; +/** + * Append the completed annotation to a parent node + * + * #attachContents should have been called first + * + * @param {Node} node Parent node + */ ve.ce.Annotation.prototype.appendTo = function ( node ) { node.appendChild( this.$element[ 0 ] ); }; /** - * Release all memory. + * Release all memory */ ve.ce.Annotation.prototype.destroy = function () { this.parentNode = null; -- To view, visit https://gerrit.wikimedia.org/r/269988 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Iecad249d6dcb33283b80cb7c3fdd79504c050e27 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] Handle Enter keyPress without matching keyDown - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/269362 Change subject: Handle Enter keyPress without matching keyDown .. Handle Enter keyPress without matching keyDown This can happen with OS X "New Romanising" Korean IME on Firefox. Change-Id: I51e3275c8371c3b5ca28dd95838499a87fb04328 --- M src/ce/ve.ce.Surface.js 1 file changed, 32 insertions(+), 9 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/62/269362/1 diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js index 4efa1b8..6312a9d 100644 --- a/src/ce/ve.ce.Surface.js +++ b/src/ce/ve.ce.Surface.js @@ -,6 +,25 @@ * @param {jQuery.Event} e Key press event */ ve.ce.Surface.prototype.onDocumentKeyPress = function ( e ) { + var selection; + + // Handle the case where keyPress Enter is fired without a matching keyDown. + // This can happen with OS X "New Romansing" OS Korean IME on Firefox; see + // https://phabricator.wikimedia.org/T120156 . Behave as though keyDown Enter + // has been fired. + if ( + e.keyCode === OO.ui.Keys.ENTER && + !this.keyDownState.event && + !( ( selection = this.getModel().getSelection() ) instanceof ve.dm.NullSelection ) + ) { + this.surfaceObserver.stopTimerLoop(); + if ( ve.ce.keyDownHandlerFactory.executeHandlersForKey( e.keyCode, selection.getName(), this, e ) ) { + this.surfaceObserver.pollOnce(); + } + this.surfaceObserver.startTimerLoop(); + return; + } + // Filter out non-character keys. Doing this prevents: // * Unexpected content deletion when selection is not collapsed and the user presses, for // example, the Home key (Firefox fires 'keypress' for it) @@ -1135,8 +1154,9 @@ * @param {jQuery.Event} e keydown event */ ve.ce.Surface.prototype.afterDocumentKeyDown = function ( e ) { - var direction, focusableNode, startOffset, endOffset, offsetDiff, dmFocus, dmSelection, - inNonSlug, ceSelection, ceNode, range, fixupCursorForUnicorn, matrix, col, row, $focusNode, + var keyDownEvent, keyDownSelection, direction, focusableNode, startOffset, endOffset, + offsetDiff, dmFocus, dmSelection, inNonSlug, ceSelection, ceNode, range, + fixupCursorForUnicorn, matrix, col, row, $focusNode, surface = this, isArrow = ( e.keyCode === OO.ui.Keys.UP || @@ -1207,6 +1227,13 @@ ) || null; } + keyDownEvent = this.keyDownState.event; + keyDownSelection = this.keyDownState.selection; + if ( e !== keyDownEvent ) { + return; + } + this.clearKeyDownState(); + if ( ( e.keyCode === OO.ui.Keys.BACKSPACE || e.keyCode === OO.ui.Keys.DELETE ) && this.nativeSelection.focusNode @@ -1249,10 +1276,6 @@ } } - if ( e !== this.keyDownState.event ) { - return; - } - // Only fixup cursoring on linear selections. if ( isArrow && !( surface.model.getSelection() instanceof ve.dm.LinearSelection ) ) { return; @@ -1284,7 +1307,7 @@ !e.ctrlKey && !e.altKey && !e.metaKey && - this.keyDownState.selection.isCollapsed && + keyDownSelection.isCollapsed && this.nativeSelection.isCollapsed && ( direction = getDirection() ) !== null ) { @@ -1298,8 +1321,8 @@ // Calculate the DM offsets of our motion try { startOffset = ve.ce.getOffset( - this.keyDownState.selection.focusNode, - this.keyDownState.selection.focusOffset + keyDownSelection.focusNode, + keyDownSelection.focusOffset ); endOffset = ve.ce.getOffset( this.nativeSelection.focusNode, -- To view, visit https://gerrit.wikimedia.org/r/269362 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I51e3275c8371c3b5ca28dd95838499a87fb04328 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec___ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
[MediaWiki-commits] [Gerrit] Utility function for "index of node in its parentNode's chil... - change (VisualEditor/VisualEditor)
Divec has uploaded a new change for review. https://gerrit.wikimedia.org/r/268061 Change subject: Utility function for "index of node in its parentNode's childNode list" .. Utility function for "index of node in its parentNode's childNode list" Change-Id: I44c4f1257551e9f3bfec3ee1010b6ba8be09f717 --- M src/ce/keydownhandlers/ve.ce.LinearDeleteKeyDownHandler.js M src/ce/ve.ce.Surface.js M src/ce/ve.ce.js M src/ve.utils.js 4 files changed, 20 insertions(+), 19 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/61/268061/1 diff --git a/src/ce/keydownhandlers/ve.ce.LinearDeleteKeyDownHandler.js b/src/ce/keydownhandlers/ve.ce.LinearDeleteKeyDownHandler.js index 77e0c1f..8a15d1d 100644 --- a/src/ce/keydownhandlers/ve.ce.LinearDeleteKeyDownHandler.js +++ b/src/ce/keydownhandlers/ve.ce.LinearDeleteKeyDownHandler.js @@ -116,16 +116,10 @@ ) { linkNode = skipNode.parentNode; range = document.createRange(); - range.setStart( - linkNode.parentNode, - // Link's offset, minus 1 to allow for outer nail deletion - // (browsers actually tend to adjust range offsets automatically - // for previous sibling deletion, but just in case ...) - Array.prototype.indexOf.call( - linkNode.parentNode.childNodes, - linkNode - ) - 1 - ); + // Set start to link's offset, minus 1 to allow for outer nail deletion + // (browsers actually tend to adjust range offsets automatically + // for previous sibling deletion, but just in case ...) + range.setStart( linkNode.parentNode, ve.parentIndex( linkNode ) - 1 ); // Remove the outer nails, then the link itself linkNode.parentNode.removeChild( linkNode.previousSibling ); linkNode.parentNode.removeChild( linkNode.nextSibling ); diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js index e288175..a951eb0 100644 --- a/src/ce/ve.ce.Surface.js +++ b/src/ce/ve.ce.Surface.js @@ -1414,7 +1414,7 @@ range.endContainer, range.endOffset, preUnicorn.parentNode, - Array.prototype.indexOf.call( preUnicorn.parentNode.childNodes, preUnicorn ) + ve.parentIndex( preUnicorn ) ) < 0 ) { // before the pre-unicorn fixup = -1; diff --git a/src/ce/ve.ce.js b/src/ce/ve.ce.js index 8d1ae42..73997fd 100644 --- a/src/ce/ve.ce.js +++ b/src/ce/ve.ce.js @@ -139,7 +139,7 @@ offset = 0; } else { nextNode = node.parentNode; - offset = 1 + Array.prototype.indexOf.call( node.parentNode.childNodes, node ); + offset = 1 + ve.parentIndex( node ); } return { node: nextNode, offset: offset }; }; @@ -159,7 +159,7 @@ offset = previousNode.data.length; } else { previousNode = node.parentNode; - offset = Array.prototype.indexOf.call( node.parentNode.childNodes, node ); + offset = ve.parentIndex( node ); } return { node: previousNode, offset: offset }; }; @@ -396,7 +396,7 @@ if ( offset > 0 ) { return false; } - offset = Array.prototype.indexOf.call( node.parentNode.childNodes, node ); + offset = ve.parentIndex( node ); node = node.parentNode; } if ( offset === 0 ) { diff --git a/src/ve.utils.js b/src/ve.utils.js index 7a15804..e7fb565 100644 --- a/src/ve.utils.js +++ b/src/ve.utils.js @@ -1324,6 +1324,16 @@ }; /** + * Get the index of a node in its parentNode's childNode list + * + * @param {Node} node The node + * @return {number} Index in parentNode's childNode list + */ +ve.parentIndex = function ( node ) { + return Array.prototype.indexOf.call( node.parentNode.childNodes, node ); +}; + +/** * Get the offset path from ancestor to offset in descendant * * @param {Node} ancestor The ancestor node @@ -1338,9 +1348,7 @@ ve.log( node, 'is not a descendant of', ancestor ); throw new Error( 'Not a descendant' ); } - path.unshift( - Array.prototype.indexOf.call( node.parentNode.childNodes, node ) - ); + path.unshift( ve.parentIndex( node ) ); node = node.parentNode; } return path; @@ -1513,8 +1521,7 @@