jenkins-bot has submitted this change and it was merged.

Change subject: Use a chimera instead of  in inline slugs
......................................................................


Use a chimera instead of  in inline slugs

Chimeras are single, unicorn-like <img>s. Using them instead of
&#xFEFF; (zero-width non-breaking space) seems to have the same effect
for cursor behavior, and does not involve text that we need the observer
 to ignore. With this change, typing in an inline slug works without pawning.
The typed text ends up in the inline slug's <span> before/after the image.
It gets SurfaceObserved correctly despite that, because the <span> isn't
treated specially any more.

Also, don't rebuild entire paragraph when inserting text in slug location.
We already didn't rebuild the paragraph when text was inserted
into an existing text node: instead we resized the text node.
But for cases where the text insertion creates a new text node
(when typing into a slug), we would still rebuild the entire paragraph.

Instead, add an operation to DocumentSynchronizer to insert a new
text node, and use this operation in TransactionProcessor when
a text node insertion is detected.

Now that TextNodes can be spliced into existing ContentBranchNodes
without rebuilds, set ce.TextNode's $element to an empty collection,
so onSplice doesn't try to insert a span that will then be removed
again by renderContents. This allows us to avoid rerendering
when SurfaceObserver generates transactions like these
(onSplice will no longer modify the DOM and renderContents
will notice that the rendering is already up-to-date).

Changes:
* Replace FEFF with img in inlineSlugTemplate
* Make most slug-specific logic apply only to block slugs
* Account for inline slugs in getNodeAndOffset's unicorn adjustments
* Stop pawning inline slugs; and kill pawning code completely now that it's 
unused
* Respect render lock in CBN setupSlugs; maybe this should be in onSplice 
instead?
* Update tests for new inlineSlug structure

Change-Id: Id360d90d6cf6adad29b1f5f14bc27b7dc8109851
---
M src/ce/nodes/ve.ce.TextNode.js
M src/ce/ve.ce.BranchNode.js
M src/ce/ve.ce.ContentBranchNode.js
M src/ce/ve.ce.Document.js
M src/ce/ve.ce.Surface.js
M src/ce/ve.ce.SurfaceObserver.js
M src/ce/ve.ce.js
M src/dm/ve.dm.DocumentSynchronizer.js
M src/dm/ve.dm.TransactionProcessor.js
M tests/ce/ve.ce.imetests.test.js
M tests/ce/ve.ce.test.js
11 files changed, 141 insertions(+), 127 deletions(-)

Approvals:
  Divec: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/src/ce/nodes/ve.ce.TextNode.js b/src/ce/nodes/ve.ce.TextNode.js
index d8efe69..252fa3c 100644
--- a/src/ce/nodes/ve.ce.TextNode.js
+++ b/src/ce/nodes/ve.ce.TextNode.js
@@ -16,6 +16,8 @@
 ve.ce.TextNode = function VeCeTextNode() {
        // Parent constructor
        ve.ce.TextNode.super.apply( this, arguments );
+
+       this.$element = $( [] );
 };
 
 /* Inheritance */
diff --git a/src/ce/ve.ce.BranchNode.js b/src/ce/ve.ce.BranchNode.js
index 6fdeb49..0ac0e7a 100644
--- a/src/ce/ve.ce.BranchNode.js
+++ b/src/ce/ve.ce.BranchNode.js
@@ -26,7 +26,7 @@
 
        // Properties
        this.tagName = this.$element.get( 0 ).nodeName.toLowerCase();
-       this.slugNodes = {};
+       this.slugNodes = [];
 
        // Events
        this.model.connect( this, { splice: 'onSplice' } );
@@ -61,7 +61,28 @@
  */
 ve.ce.BranchNode.inlineSlugTemplate = $( '<span>' )
        .addClass( 've-ce-branchNode-slug ve-ce-branchNode-inlineSlug' )
-       .html( '&#xFEFF;' )
+       .append(
+               $( '<img>' )
+                       .attr( 'src', ve.minImgDataUri )
+                       .addClass( 've-ce-chimera' )
+       )
+       .get( 0 );
+
+/**
+ * Inline slug template for input debugging.
+ *
+ * TODO: Make iframe safe
+ *
+ * @static
+ * @property {HTMLElement}
+ */
+ve.ce.BranchNode.inputDebugInlineSlugTemplate = $( '<span>' )
+       .addClass( 've-ce-branchNode-slug ve-ce-branchNode-inlineSlug' )
+       .append(
+               $( '<img>' )
+                       .attr( 'src', ve.ce.chimeraImgDataUri )
+                       .addClass( 've-ce-chimera' )
+       )
        .get( 0 );
 
 /**
@@ -222,13 +243,19 @@
 
        // Remove all slugs in this branch
        for ( i in this.slugNodes ) {
-               if ( this.slugNodes[i].parentNode ) {
+               if ( this.slugNodes[i] !== undefined && 
this.slugNodes[i].parentNode ) {
                        this.slugNodes[i].parentNode.removeChild( 
this.slugNodes[i] );
                }
                delete this.slugNodes[i];
        }
 
-       slugTemplate = isBlock ? ve.ce.BranchNode.blockSlugTemplate : 
ve.ce.BranchNode.inlineSlugTemplate;
+       if ( isBlock ) {
+               slugTemplate = ve.ce.BranchNode.blockSlugTemplate;
+       } else if ( ve.inputDebug ) {
+               slugTemplate = ve.ce.BranchNode.inputDebugInlineSlugTemplate;
+       } else {
+               slugTemplate = ve.ce.BranchNode.inlineSlugTemplate;
+       }
 
        for ( i in this.getModel().slugPositions ) {
                slugNode = doc.importNode( slugTemplate, true );
diff --git a/src/ce/ve.ce.ContentBranchNode.js 
b/src/ce/ve.ce.ContentBranchNode.js
index e956d3d..25454cc 100644
--- a/src/ce/ve.ce.ContentBranchNode.js
+++ b/src/ce/ve.ce.ContentBranchNode.js
@@ -104,14 +104,37 @@
  *
  * @method
  */
-ve.ce.ContentBranchNode.prototype.onSplice = function () {
+ve.ce.ContentBranchNode.prototype.onSplice = function ( index, howmany ) {
        // Parent method
        ve.ce.BranchNode.prototype.onSplice.apply( this, arguments );
 
+       // HACK: adjust slugNodes indexes if isRenderingLocked. This should be 
sufficient to
+       // keep this.slugNodes valid - only text changes can occur, which 
cannot create a
+       // requirement for a new slug (it can make an existing slug redundant, 
but it is
+       // harmless to leave it there).
+       if (
+               this.root instanceof ve.ce.DocumentNode &&
+               this.root.getSurface().isRenderingLocked
+       ) {
+               this.slugNodes.splice.apply( this.slugNodes, [ index, howmany 
].concat( new Array( arguments.length - 2 ) ) );
+       }
+
        // Rerender to make sure annotations are applied correctly
        this.renderContents();
 };
 
+/** @inheritdoc */
+ve.ce.ContentBranchNode.prototype.setupSlugs = function () {
+       // Respect render lock
+       if (
+               this.root instanceof ve.ce.DocumentNode &&
+               this.root.getSurface().isRenderingLocked()
+       ) {
+               return;
+       }
+       ve.ce.BranchNode.prototype.setupSlugs.apply( this, arguments );
+};
+
 /**
  * Get an HTML rendering of the contents.
  *
diff --git a/src/ce/ve.ce.Document.js b/src/ce/ve.ce.Document.js
index 166f9c2..1ead7ac 100644
--- a/src/ce/ve.ce.Document.js
+++ b/src/ce/ve.ce.Document.js
@@ -91,13 +91,19 @@
        previousNode = getPrevious( currentNode );
 
        // Adjust for unicorn if necessary, then return
-       if ( currentNode.nodeType === Node.TEXT_NODE &&
-               nao.offset === currentNode.data.length &&
+       if (
+               ( (
+                       currentNode.nodeType === Node.TEXT_NODE &&
+                       nao.offset === currentNode.data.length
+               ) || (
+                       currentNode.nodeType === Node.ELEMENT_NODE &&
+                       currentNode.classList.contains( 
've-ce-branchNode-inlineSlug' )
+               ) ) &&
                nextNode &&
                nextNode.nodeType === Node.ELEMENT_NODE &&
                nextNode.classList.contains( 've-ce-pre-unicorn' )
        ) {
-               // At text offset just before the pre unicorn; return the point 
just after it
+               // At text offset or slug just before the pre unicorn; return 
the point just after it
                return ve.ce.nextCursorOffset( nextNode );
        } else if ( currentNode.nodeType === Node.ELEMENT_NODE &&
                currentNode.children.length > nao.offset &&
@@ -106,13 +112,19 @@
        ) {
                // At element offset just before the pre unicorn; return the 
point just after it
                return { node: nao.node, offset: nao.offset + 1 };
-       } else if ( currentNode.nodeType === Node.TEXT_NODE &&
-               // At text offset just after the post unicorn; return the point 
just before it
-               nao.offset === 0 &&
+       } else if (
+               ( (
+                       currentNode.nodeType === Node.TEXT_NODE &&
+                       nao.offset === 0
+               ) || (
+                       currentNode.nodeType === Node.ELEMENT_NODE &&
+                       currentNode.classList.contains( 
've-ce-branchNode-inlineSlug' )
+               ) ) &&
                previousNode &&
                previousNode.nodeType === Node.ELEMENT_NODE &&
                previousNode.classList.contains( 've-ce-post-unicorn' )
        ) {
+               // At text offset or slug just after the post unicorn; return 
the point just before it
                return ve.ce.previousCursorOffset( previousNode );
        } else if ( currentNode.nodeType === Node.ELEMENT_NODE &&
                nao.offset > 0 &&
@@ -133,7 +145,8 @@
        var node, startOffset, current, stack, item, $item, length, model,
                countedNodes = [],
                slug = this.getSlugAtOffset( offset );
-       if ( slug ) {
+       // Check for a slug that is empty (apart from a chimera)
+       if ( slug && ( !slug.firstChild || $( slug.firstChild ).hasClass( 
've-ce-chimera' ) ) ) {
                return { node: slug, offset: 0 };
        }
        node = this.getBranchNodeFromOffset( offset );
@@ -159,14 +172,7 @@
                        }
                } else if ( item.nodeType === Node.ELEMENT_NODE ) {
                        $item = current[0].eq( current[1] );
-                       if ( $item.hasClass( 've-ce-branchNode-slug' ) ) {
-                               if ( offset === startOffset ) {
-                                       return {
-                                               node: $item[0],
-                                               offset: 1
-                                       };
-                               }
-                       } else if ( $item.hasClass( 've-ce-unicorn' ) ) {
+                       if ( $item.hasClass( 've-ce-unicorn' ) ) {
                                if ( offset === startOffset ) {
                                        return {
                                                node: $item[0].parentNode,
@@ -190,6 +196,7 @@
                                        }
                                }
                        } else {
+                               // Maybe ve-ce-branchNode-slug
                                stack.push( [$item.contents(), 0] );
                                current[1]++;
                                current = stack[stack.length - 1];
diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js
index 41ca24b..1c3cf01 100644
--- a/src/ce/ve.ce.Surface.js
+++ b/src/ce/ve.ce.Surface.js
@@ -1133,8 +1133,6 @@
        // 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)
-       // * Incorrect pawning when selection is collapsed and the user presses 
a key that is not handled
-       //   elsewhere and doesn't produce any text, for example Escape
        // TODO: Should be covered with Selenium tests.
        if (
                // Catches most keys that don't produce output (charCode === 0, 
thus no character)
@@ -2694,7 +2692,7 @@
                return;
        }
 
-       var hasSlug, data, range, newRange, annotations, insertionAnnotations, 
placeholder,
+       var range, annotations,
                cellSelection,
                hasChanged = false,
                selection = this.model.getSelection(),
@@ -2735,35 +2733,6 @@
                        range = this.model.getSelection().getRange();
                }
                this.model.setInsertionAnnotations( annotations );
-       }
-
-       insertionAnnotations = this.model.getInsertionAnnotations() ||
-               new ve.dm.AnnotationSet( documentModel.getStore() );
-
-       if ( range.isCollapsed() ) {
-               hasSlug = documentModel.hasSlugAtOffset( range.start );
-               // Always pawn in a slug
-               if ( hasSlug ) {
-                       placeholder = '♙';
-                       if ( !insertionAnnotations.isEmpty() ) {
-                               placeholder = [placeholder, 
insertionAnnotations.getIndexes()];
-                       }
-                       // Is this a slug and if so, is this a block slug?
-                       if ( hasSlug && documentModel.data.isStructuralOffset( 
range.start ) ) {
-                               newRange = new ve.Range( range.start + 1, 
range.start + 2 );
-                               data = [{ type: 'paragraph' }, placeholder, { 
type: '/paragraph' }];
-                       } else {
-                               newRange = new ve.Range( range.start, 
range.start + 1 );
-                               data = [placeholder];
-                       }
-                       this.model.change(
-                               ve.dm.Transaction.newFromInsertion(
-                                       this.documentView.model, range.start, 
data
-                               ),
-                               new ve.dm.LinearSelection( documentModel, 
newRange )
-                       );
-                       hasChanged = true;
-               }
        }
 
        if ( hasChanged ) {
@@ -3237,58 +3206,6 @@
                        return Math.max( contentOffset, structuralOffset );
                }
        }
-};
-
-/**
- * Checks if we need to pawn for insertionAnnotations based on the related 
annotationSet.
- *
- * "Related" is typically to the left, unless at the beginning of a node.
- *
- * We choose to pawn if the related annotationSet doesn't match 
insertionAnnotations, or if
- * we are at the edge of an annotation that requires pawning (i.e. an 
annotation requiring pawning
- * is present on the left but not on the right, or vice versa).
- *
- * @method
- * @param {ve.Range} range
- * @param {ve.dm.AnnotationSet} insertionAnnotations
- * @returns {boolean} Whether we need to pawn
- */
-ve.ce.Surface.prototype.needsPawn = function ( range, insertionAnnotations ) {
-       var leftAnnotations, rightAnnotations, documentModel = 
this.model.documentModel;
-
-       function isForced( annotation ) {
-               return ve.ce.annotationFactory.isAnnotationContinuationForced( 
annotation.constructor.static.name );
-       }
-
-       if ( range.start > 0 ) {
-               leftAnnotations = documentModel.data.getAnnotationsFromOffset( 
range.start - 1 );
-       }
-       if ( range.start < documentModel.data.getLength() ) {
-               rightAnnotations = documentModel.data.getAnnotationsFromOffset( 
range.start + 1 );
-       }
-
-       // Take annotations from the left
-       // TODO reorganize the logic in this function
-       if ( leftAnnotations && !leftAnnotations.compareTo( 
insertionAnnotations ) ) {
-               return true;
-       }
-       // At the beginning of a node, take from the right
-       if (
-               this.nativeSelection.anchorOffset === 0 &&
-               rightAnnotations &&
-               !rightAnnotations.compareTo( insertionAnnotations )
-       ) {
-               return true;
-       }
-
-       if (
-               leftAnnotations && rightAnnotations &&
-               !leftAnnotations.filter( isForced ).compareTo( 
rightAnnotations.filter( isForced ) )
-       ) {
-               return true;
-       }
-
-       return false;
 };
 
 /*! Getters */
diff --git a/src/ce/ve.ce.SurfaceObserver.js b/src/ce/ve.ce.SurfaceObserver.js
index 368e593..89e70a2 100644
--- a/src/ce/ve.ce.SurfaceObserver.js
+++ b/src/ce/ve.ce.SurfaceObserver.js
@@ -70,7 +70,7 @@
  */
 
 /**
- * When #poll observes that the cursor was moved into a slug
+ * When #poll observes that the cursor was moved into a block slug
  *
  * @event slugEnter
  */
@@ -162,7 +162,7 @@
  *
  * TODO: fixing selection in certain cases, handling selection across multiple 
nodes in Firefox
  *
- * FIXME: Does not work well (rangeChange is not emitted) when cursor is 
placed inside a slug
+ * FIXME: Does not work well (rangeChange is not emitted) when cursor is 
placed inside a block slug
  * with a mouse.
  *
  * @method
@@ -198,7 +198,7 @@
  *
  * TODO: fixing selection in certain cases, handling selection across multiple 
nodes in Firefox
  *
- * FIXME: Does not work well (rangeChange is not emitted) when cursor is 
placed inside a slug
+ * FIXME: Does not work well (rangeChange is not emitted) when cursor is 
placed inside a block slug
  * with a mouse.
  *
  * @method
diff --git a/src/ce/ve.ce.js b/src/ce/ve.ce.js
index d3c062f..cd3d30f 100644
--- a/src/ce/ve.ce.js
+++ b/src/ce/ve.ce.js
@@ -30,6 +30,7 @@
  */
 ve.ce.minImgDataUri = 'data:image/gif;base64,R0lGODdhAQABAADcACwAAAAAAQABAAA';
 ve.ce.unicornImgDataUri = 
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAATCAQAAADly58hAAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfeChIMMi319aEqAAAAzUlEQVQoz4XSMUoDURAG4K8NIljaeQZrCwsRb5FWL5Daa1iIjQewTycphAQloBEUAoogFmqMsiBmHSzcdfOWlcyU3/+YGXgsqJZMbvv/wLqZDCw1B9rCBSaOmgOHQsfQvVYT7wszIbPSxO9CCF8ebNXx1J2TIvDoxlrKU3mBIYz1U87mMISB3QqXk7e/A4bp1WV/CiE3sFHymZ4X4cO57yLWdVDyjoknr47/MPRcput1k+ljt/O4V1vu2bXViq9qPNW3WfGoxrk37UVfxQ999n1bP+Vh5gAAAABJRU5ErkJggg==';
+ve.ce.chimeraImgDataUri = 
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAABGdBTUEAALGPC/xhBQAAAThJREFUOMvF088rRFEYxvGpKdnwJ8iStVnMytZ2ipJmI6xmZKEUe5aUULMzCxtlSkzNjCh2lClFSUpDmYj8KBZq6vreetLbrXs5Rjn1aWbuuee575z7nljsH8YkepoNaccsHrGFgWbCWpHCLZb+oroFzKOEbpeFHVp8gitsYltzSRyiqrkKhsKCevGMfWQwor/2ghns4BQTGMMcnlBA3Aa14U5VLeMDnqrq1/cDpHGv35eqrI5pG+Y/qYYp3WiN6zOHs8DcA7IK/BqLWMOuY5inQjwbNqheGnYMO9d+XtiwFu1BQU/y96ooKRO2Yq6vqog3jAbfZgKvuDELfGWFXQeu76GB9bD26MQRNnSMotTVJvGoxs2rx2oR/B47Rtd3pyBv3lCYnEtYWo0Yps8l7F3HKErjJ2G/Hp/F9YtlR3MQiAAAAABJRU5ErkJggg==';
 
 /* Static Methods */
 
@@ -57,8 +58,8 @@
                        nodeType === Node.DOCUMENT_NODE ||
                        nodeType === Node.DOCUMENT_FRAGMENT_NODE
                ) {
-                       if ( $element.hasClass( 've-ce-branchNode-slug' ) ) {
-                               // Slugs are not represented in the model at 
all, but they do
+                       if ( $element.hasClass( 've-ce-branchNode-blockSlug' ) 
) {
+                               // Block slugs are not represented in the model 
at all, but they do
                                // contain a single nbsp/FEFF character in the 
DOM, so make sure
                                // that character isn't counted
                                return '';
@@ -279,8 +280,8 @@
                        node = traverse( startNode );
                }
        } else {
-               // Text inside of a slug doesn't count
-               if ( !$( domNode.parentNode ).hasClass( 've-ce-branchNode-slug' 
) ) {
+               // Text inside of a block slug doesn't count
+               if ( !$( domNode.parentNode ).hasClass( 
've-ce-branchNode-blockSlug' ) ) {
                        lengthSum += domOffset;
                }
                startNode = domNode;
@@ -300,8 +301,8 @@
                        break;
                }
 
-               // Text inside of a slug doesn't count
-               if ( node.nodeType === Node.TEXT_NODE && !$( node.parentNode 
).hasClass( 've-ce-branchNode-slug' ) ) {
+               // Text inside of a block slug doesn't count
+               if ( node.nodeType === Node.TEXT_NODE && !$( node.parentNode 
).hasClass( 've-ce-branchNode-blockSlug' ) ) {
                        lengthSum += node.data.length;
                }
                // else: non-text nodes that don't have a .data( 'view' ) don't 
exist in the DM
diff --git a/src/dm/ve.dm.DocumentSynchronizer.js 
b/src/dm/ve.dm.DocumentSynchronizer.js
index 880ccbe..3356c32 100644
--- a/src/dm/ve.dm.DocumentSynchronizer.js
+++ b/src/dm/ve.dm.DocumentSynchronizer.js
@@ -111,6 +111,22 @@
 };
 
 /**
+ * Synchronize a text node insertion.
+ *
+ * This method is called within the context of a document synchronizer 
instance.
+ *
+ * @static
+ * @method
+ * @param {Object} action
+ */
+ve.dm.DocumentSynchronizer.synchronizers.insertTextNode = function ( action ) {
+       var textNode = new ve.dm.TextNode();
+       textNode.setLength( action.length );
+       action.parentNode.splice( action.index, 0, textNode );
+       this.adjustment += action.length;
+};
+
+/**
  * Synchronize a rebuild action.
  *
  * This method is called within the context of a document synchronizer 
instance.
@@ -214,6 +230,24 @@
 };
 
 /**
+ * Add a text node insertion action to the queue.
+ *
+ * This inserts a new text node.
+ *
+ * @param {ve.dm.Node} parentNode Node to insert text node into
+ * @param {number} index Index in parentNode to insert text node at
+ * @param {number} length Length of new text node
+ */
+ve.dm.DocumentSynchronizer.prototype.pushInsertTextNode = function ( 
parentNode, index, length ) {
+       this.actionQueue.push( {
+               type: 'insertTextNode',
+               parentNode: parentNode,
+               index: index,
+               length: length
+       } );
+};
+
+/**
  * Add a rebuild action to the queue.
  *
  * When a range of data has been changed arbitrarily this can be used to drop 
the nodes that
diff --git a/src/dm/ve.dm.TransactionProcessor.js 
b/src/dm/ve.dm.TransactionProcessor.js
index f4d55a1..c8d4c69 100644
--- a/src/dm/ve.dm.TransactionProcessor.js
+++ b/src/dm/ve.dm.TransactionProcessor.js
@@ -386,6 +386,13 @@
                        // Text-only replacement
                        // Queue a resize for the text node
                        this.synchronizer.pushResize( node, insert.length - 
remove.length );
+               } else if (
+                       !removeHasStructure && !insertHasStructure && 
remove.length === 0 && insert.length > 0 &&
+                       selection.length === 1 && node && 
node.canContainContent() &&
+                       ( selection[0].indexInNode !== undefined || 
node.getLength() === 0 )
+               ) {
+                       // Text-only addition where a text node didn't exist 
before. Create one
+                       this.synchronizer.pushInsertTextNode( node, 
selection[0].indexInNode || 0, insert.length - remove.length );
                } else {
                        // Replacement is not exclusively text
                        // Rebuild all covered nodes
diff --git a/tests/ce/ve.ce.imetests.test.js b/tests/ce/ve.ce.imetests.test.js
index 54985ea..7cc6e9d 100644
--- a/tests/ce/ve.ce.imetests.test.js
+++ b/tests/ce/ve.ce.imetests.test.js
@@ -11,7 +11,6 @@
 ve.ce.imetests = [];
 
 ve.ce.imetestsFailAt = {
-       'backspace-firefox-ubuntu-none': 17,
        'input-ie-win-chinese-traditional-handwriting': 4,
        'input-ie-win-korean': 4
 };
@@ -23,9 +22,6 @@
        'input-firefox-ubuntu-ibus-japanese-anthy--hiraganaonly': 8,
        'input-firefox-ubuntu-ibus-korean-korean': 7,
        'input-firefox-ubuntu-ibus-malayalam-swanalekha': 8,
-       'backspace-chromium-ubuntu-none': 3,
-       'backspace-firefox-ubuntu-none': 17,
        'input-ie-win-chinese-traditional-handwriting': 4,
-       'input-ie-win-korean': 4,
-       'leftarrow-chromium-ubuntu-none': 3
+       'input-ie-win-korean': 4
 };
diff --git a/tests/ce/ve.ce.test.js b/tests/ce/ve.ce.test.js
index 643ed43..b75a3f8 100644
--- a/tests/ce/ve.ce.test.js
+++ b/tests/ce/ve.ce.test.js
@@ -65,12 +65,12 @@
                                msg: 'Empty paragraph',
                                html: '<p></p>',
                                // CE HTML summary:
-                               // <p><span [inlineSlug]>&#xFEFF;</span></p>
+                               // <p><span [inlineSlug]><img /></span></p>
                                // Linmod:
                                // [<p>, </p>]
                                expected: [
                                        0,
-                                       1, 1, 1, 1, 1, 1,
+                                       1, 1, 1, 1, 1,
                                        2
                                ]
                        },
@@ -181,18 +181,18 @@
                                msg: 'Paragraph with inline slugs',
                                html: '<p><span rel="ve:Alien">Foo</span><span 
rel="ve:Alien">Bar</span><br></p>',
                                // CE HTML summary:
-                               // <p><span [inlineSlug]>&#xFEFF;</span><span 
[alien]>Foo</span>
-                               // <span [inlineSlug]>&#xFEFF;</span><span 
[alien]>Bar</span>
-                               // <span 
[inlineSlug]>&#xFEFF;</span><br></br><span [inlineSlug]>&#xFEFF;</span></p>
+                               // <p><span [inlineSlug]><img /></span><span 
[alien]>Foo</span>
+                               // <span [inlineSlug]><img /></span><span 
[alien]>Bar</span>
+                               // <span [inlineSlug]><img 
/></span><br></br><span [inlineSlug]><img /></span></p>
                                // Linmod:
                                // [<p>, <alineinline>, </alineinline>, 
<alineinline>, </alineinline>, <break>, </break>, </p>]
                                expected: [
                                        0,
-                                       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-                                       3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
-                                       5, 5, 5, 5, 5, 5,
+                                       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+                                       3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+                                       5, 5, 5, 5, 5,
                                        6,
-                                       7, 7, 7, 7, 7, 7,
+                                       7, 7, 7, 7, 7,
                                        8
                                ]
                        }

-- 
To view, visit https://gerrit.wikimedia.org/r/151046
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: Id360d90d6cf6adad29b1f5f14bc27b7dc8109851
Gerrit-PatchSet: 35
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Catrope <[email protected]>
Gerrit-Reviewer: Catrope <[email protected]>
Gerrit-Reviewer: Divec <[email protected]>
Gerrit-Reviewer: Inez <[email protected]>
Gerrit-Reviewer: Jforrester <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to