[MediaWiki-commits] [Gerrit] VisualEditor/VisualEditor[master]: rebaser: Only apply artificial delay to submitChange events

2018-01-23 Thread Divec (Code Review)
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...

2018-01-23 Thread Divec (Code Review)
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

2018-01-22 Thread Divec (Code Review)
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...

2018-01-22 Thread Divec (Code Review)
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...

2018-01-21 Thread Divec (Code Review)
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

2017-12-06 Thread Divec (Code Review)
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

2017-11-25 Thread Divec (Code Review)
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

2017-10-30 Thread Divec (Code Review)
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

2017-10-27 Thread Divec (Code Review)
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...

2017-10-10 Thread Divec (Code Review)
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

2017-10-07 Thread Divec (Code Review)
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

2017-09-26 Thread Divec (Code Review)
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

2017-09-25 Thread Divec (Code Review)
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

2017-09-21 Thread Divec (Code Review)
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

2017-09-16 Thread Divec (Code Review)
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

2017-09-12 Thread Divec (Code Review)
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

2017-09-11 Thread Divec (Code Review)
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

2017-09-05 Thread Divec (Code Review)
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

2017-08-25 Thread Divec (Code Review)
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

2017-08-13 Thread Divec (Code Review)
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

2017-08-13 Thread Divec (Code Review)
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

2017-08-13 Thread Divec (Code Review)
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

2017-08-10 Thread Divec (Code Review)
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

2017-08-09 Thread Divec (Code Review)
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

2017-08-09 Thread Divec (Code Review)
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

2017-07-05 Thread Divec (Code Review)
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...

2017-06-04 Thread Divec (Code Review)
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

2017-05-25 Thread Divec (Code Review)
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...

2017-05-20 Thread Divec (Code Review)
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...

2017-05-20 Thread Divec (Code Review)
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 ...

2017-05-16 Thread Divec (Code Review)
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...

2017-05-14 Thread Divec (Code Review)
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

2017-04-17 Thread Divec (Code Review)
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...

2017-04-01 Thread Divec (Code Review)
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

2017-03-25 Thread Divec (Code Review)
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...

2017-03-18 Thread Divec (Code Review)
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

2017-02-09 Thread Divec (Code Review)
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

2017-02-03 Thread Divec (Code Review)
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

2017-02-02 Thread Divec (Code Review)
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

2017-01-30 Thread Divec (Code Review)
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

2017-01-22 Thread Divec (Code Review)
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

2017-01-11 Thread Divec (Code Review)
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

2017-01-09 Thread Divec (Code Review)
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

2016-12-29 Thread Divec (Code Review)
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

2016-12-28 Thread Divec (Code Review)
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

2016-12-21 Thread Divec (Code Review)
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...

2016-12-13 Thread Divec (Code Review)
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

2016-12-13 Thread Divec (Code Review)
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

2016-12-06 Thread Divec (Code Review)
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

2016-11-30 Thread Divec (Code Review)
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

2016-11-28 Thread Divec (Code Review)
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

2016-11-28 Thread Divec (Code Review)
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

2016-11-23 Thread Divec (Code Review)
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

2016-11-21 Thread Divec (Code Review)
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

2016-11-03 Thread Divec (Code Review)
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

2016-10-22 Thread Divec (Code Review)
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

2016-10-22 Thread Divec (Code Review)
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

2016-10-20 Thread Divec (Code Review)
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

2016-10-20 Thread Divec (Code Review)
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 ...

2016-10-13 Thread Divec (Code Review)
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

2016-10-10 Thread Divec (Code Review)
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

2016-10-10 Thread Divec (Code Review)
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

2016-10-10 Thread Divec (Code Review)
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

2016-10-04 Thread Divec (Code Review)
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

2016-09-18 Thread Divec (Code Review)
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...

2016-09-17 Thread Divec (Code Review)
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

2016-09-14 Thread Divec (Code Review)
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

2016-09-06 Thread Divec (Code Review)
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

2016-09-06 Thread Divec (Code Review)
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

2016-08-24 Thread Divec (Code Review)
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

2016-08-18 Thread Divec (Code Review)
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

2016-08-18 Thread Divec (Code Review)
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

2016-08-17 Thread Divec (Code Review)
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...

2016-08-11 Thread Divec (Code Review)
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

2016-08-10 Thread Divec (Code Review)
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

2016-08-05 Thread Divec (Code Review)
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

2016-08-04 Thread Divec (Code Review)
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)

2016-07-18 Thread Divec (Code Review)
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)

2016-06-14 Thread Divec (Code Review)
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)

2016-06-07 Thread Divec (Code Review)
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)

2016-06-07 Thread Divec (Code Review)
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)

2016-06-06 Thread Divec (Code Review)
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)

2016-06-05 Thread Divec (Code Review)
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)

2016-05-24 Thread Divec (Code Review)
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)

2016-05-04 Thread Divec (Code Review)
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)

2016-04-26 Thread Divec (Code Review)
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)

2016-04-25 Thread Divec (Code Review)
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)

2016-04-25 Thread Divec (Code Review)
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)

2016-04-13 Thread Divec (Code Review)
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)

2016-03-27 Thread Divec (Code Review)
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)

2016-03-27 Thread Divec (Code Review)
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)

2016-03-15 Thread Divec (Code Review)
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)

2016-03-09 Thread Divec (Code Review)
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)

2016-02-28 Thread Divec (Code Review)
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)

2016-02-26 Thread Divec (Code Review)
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)

2016-02-16 Thread Divec (Code Review)
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)

2016-02-12 Thread Divec (Code Review)
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)

2016-02-11 Thread Divec (Code Review)
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)

2016-02-08 Thread Divec (Code Review)
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)

2016-02-03 Thread Divec (Code Review)
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 @@
 

  1   2   3   >