mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-09-27 12:16:51 +00:00
Merge branch 'dmrewrite' of ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor into dmrewrite
This commit is contained in:
commit
6e7c02a126
|
@ -21,8 +21,10 @@ ve.ce.BranchNode = function( type, model, $element ) {
|
|||
// Events
|
||||
this.model.addListenerMethod( this, 'splice', 'onSplice' );
|
||||
|
||||
this.$.addClass("ve-ce-branch");
|
||||
// DOM Changes
|
||||
this.$.addClass( 've-ce-branchNode' );
|
||||
|
||||
// Initialization
|
||||
if ( model.getChildren().length ) {
|
||||
this.onSplice.apply( this, [0, 0].concat( model.getChildren() ) );
|
||||
}
|
||||
|
|
|
@ -15,7 +15,10 @@ ve.ce.LeafNode = function( type, model, $element ) {
|
|||
ve.LeafNode.call( this );
|
||||
ve.ce.Node.call( this, type, model, $element );
|
||||
|
||||
this.$.addClass("ve-ce-leaf");
|
||||
// DOM Changes
|
||||
if ( model.isWrapped() ) {
|
||||
this.$.addClass( 've-ce-leafNode' );
|
||||
}
|
||||
};
|
||||
|
||||
/* Inheritance */
|
||||
|
|
|
@ -34,6 +34,8 @@ ve.Document.prototype.getDocumentNode = function() {
|
|||
* @returns {Array} List of objects describing nodes in the selection and the ranges therein
|
||||
* 'node': Reference to a ve.dm.Node
|
||||
* 'range': ve.Range, missing if the entire node is covered
|
||||
* 'index': Index of the node in its parent
|
||||
* 'nodeRange': Range covering the inside of the entire node
|
||||
* @throws 'Invalid start offset' if range.start is out of range
|
||||
* @throws 'Invalid end offset' if range.end is out of range
|
||||
*/
|
||||
|
@ -42,13 +44,18 @@ ve.Document.prototype.selectNodes = function( range, mode ) {
|
|||
retval = [],
|
||||
start = range.start,
|
||||
end = range.end,
|
||||
stack = [ { 'node': doc, 'index': 0 } ],
|
||||
stack = [ {
|
||||
'node': doc,
|
||||
'index': 0,
|
||||
'startOffset': 0
|
||||
} ],
|
||||
node,
|
||||
prevNode,
|
||||
nextNode,
|
||||
left,
|
||||
right,
|
||||
currentFrame = stack[0],
|
||||
parentFrame,
|
||||
startInside,
|
||||
endInside,
|
||||
startBetween,
|
||||
|
@ -68,9 +75,15 @@ ve.Document.prototype.selectNodes = function( range, mode ) {
|
|||
}
|
||||
|
||||
if ( !doc.children || doc.children.length === 0 ) {
|
||||
return [];
|
||||
// Document has no children. This is weird
|
||||
return [ {
|
||||
'node': doc,
|
||||
'range': new ve.Range( start, end ),
|
||||
'index': 0,
|
||||
'parentRange': new ve.Range( 0, doc.getLength() )
|
||||
} ];
|
||||
}
|
||||
// TODO we could find the start more efficiently using the offset map
|
||||
// TODO maybe we could find the start more efficiently using the offset map
|
||||
left = doc.children[0].isWrapped() ? 1 : 0;
|
||||
|
||||
while ( end >= left ) {
|
||||
|
@ -89,9 +102,14 @@ ve.Document.prototype.selectNodes = function( range, mode ) {
|
|||
|
||||
if ( start == end && ( startBetween || endBetween ) ) {
|
||||
// Empty range in the parent, outside of any child
|
||||
parentFrame = stack[stack.length - 2];
|
||||
return [ {
|
||||
'node': currentFrame.node,
|
||||
'range': new ve.Range( start, end )
|
||||
'range': new ve.Range( start, end ),
|
||||
'index': parentFrame.index,
|
||||
'nodeRange': new ve.Range( parentFrame.startOffset,
|
||||
parentFrame.startOffset + currentFrame.node.getLength()
|
||||
)
|
||||
} ];
|
||||
} else if ( startBetween ) {
|
||||
// start is between the previous sibling and node
|
||||
|
@ -99,7 +117,11 @@ ve.Document.prototype.selectNodes = function( range, mode ) {
|
|||
|
||||
if ( mode == 'leaves' && node.children && node.children.length ) {
|
||||
// Descend into node
|
||||
currentFrame = { 'node': node, 'index': 0 };
|
||||
currentFrame = {
|
||||
'node': node,
|
||||
'index': 0,
|
||||
'startOffset': left
|
||||
};
|
||||
stack.push( currentFrame );
|
||||
if ( node.children[0].isWrapped() ) {
|
||||
left++;
|
||||
|
@ -108,14 +130,22 @@ ve.Document.prototype.selectNodes = function( range, mode ) {
|
|||
continue;
|
||||
} else {
|
||||
// All of node is covered
|
||||
// TODO should this have a range or not?
|
||||
retval.push( { 'node': node } );
|
||||
retval.push( {
|
||||
'node': node,
|
||||
// no 'range' because the entire node is covered
|
||||
'index': currentFrame.index,
|
||||
'nodeRange': new ve.Range( left, right )
|
||||
} );
|
||||
startFound = true;
|
||||
}
|
||||
} else if ( startInside && endInside ) {
|
||||
if ( node.children && node.children.length ) {
|
||||
// Descend into node
|
||||
currentFrame = { 'node': node, 'index': 0 };
|
||||
currentFrame = {
|
||||
'node': node,
|
||||
'index': 0,
|
||||
'startOffset': left
|
||||
};
|
||||
stack.push( currentFrame );
|
||||
// If the first child of node has an opening, skip over it
|
||||
if ( node.children[0].isWrapped() ) {
|
||||
|
@ -126,14 +156,20 @@ ve.Document.prototype.selectNodes = function( range, mode ) {
|
|||
// node is a leaf node and the range is entirely inside it
|
||||
return [ {
|
||||
'node': node,
|
||||
'range': new ve.Range( left, right )
|
||||
'range': new ve.Range( left, right ),
|
||||
'index': currentFrame.index,
|
||||
'nodeRange': new ve.Range( left, right )
|
||||
} ];
|
||||
}
|
||||
} else if ( startInside ) {
|
||||
if ( mode == 'leaves' && node.children && node.children.length ) {
|
||||
// node is a branch node and the start is inside it
|
||||
// Descend into it
|
||||
currentFrame = { 'node': node, 'index': 0 };
|
||||
currentFrame = {
|
||||
'node': node,
|
||||
'index': 0,
|
||||
'startOffset': left
|
||||
};
|
||||
stack.push( currentFrame );
|
||||
if ( node.children[0].isWrapped() ) {
|
||||
left++;
|
||||
|
@ -144,7 +180,9 @@ ve.Document.prototype.selectNodes = function( range, mode ) {
|
|||
// Add to retval and keep going
|
||||
retval.push( {
|
||||
'node': node,
|
||||
'range': new ve.Range( start, right )
|
||||
'range': new ve.Range( start, right ),
|
||||
'index': currentFrame.index,
|
||||
'nodeRange': new ve.Range( left, right )
|
||||
} );
|
||||
startFound = true;
|
||||
}
|
||||
|
@ -156,7 +194,11 @@ ve.Document.prototype.selectNodes = function( range, mode ) {
|
|||
|
||||
if ( mode == 'leaves' && node.children && node.children.length ) {
|
||||
// Descend into node
|
||||
currentFrame = { 'node': node, 'index': 0 };
|
||||
currentFrame = {
|
||||
'node': node,
|
||||
'index': 0,
|
||||
'startOffset': left
|
||||
};
|
||||
stack.push( currentFrame );
|
||||
if ( node.children[0].isWrapped() ) {
|
||||
left++;
|
||||
|
@ -164,15 +206,23 @@ ve.Document.prototype.selectNodes = function( range, mode ) {
|
|||
continue;
|
||||
} else {
|
||||
// All of node is covered
|
||||
// TODO should this have a range or not?
|
||||
retval.push( { 'node': node } );
|
||||
retval.push( {
|
||||
'node': node,
|
||||
// no 'range' because the entire node is covered
|
||||
'index': currentFrame.index,
|
||||
'nodeRange': new ve.Range( left, right )
|
||||
} );
|
||||
return retval;
|
||||
}
|
||||
} else if ( endInside ) {
|
||||
if ( mode == 'leaves' && node.children && node.children.length ) {
|
||||
// node is a branch node and the end is inside it
|
||||
// Descend into it
|
||||
currentFrame = { 'node': node, 'index': 0 };
|
||||
currentFrame = {
|
||||
'node': node,
|
||||
'index': 0,
|
||||
'startOffset': left
|
||||
};
|
||||
stack.push( currentFrame );
|
||||
if ( node.children[0].isWrapped() ) {
|
||||
left++;
|
||||
|
@ -183,7 +233,9 @@ ve.Document.prototype.selectNodes = function( range, mode ) {
|
|||
// Add to retval and return
|
||||
retval.push( {
|
||||
'node': node,
|
||||
'range': new ve.Range( left, end )
|
||||
'range': new ve.Range( left, end ),
|
||||
'index': currentFrame.index,
|
||||
'nodeRange': new ve.Range( left, right )
|
||||
} );
|
||||
return retval;
|
||||
}
|
||||
|
@ -195,7 +247,11 @@ ve.Document.prototype.selectNodes = function( range, mode ) {
|
|||
|
||||
if ( mode == 'leaves' && node.children && node.children.length ) {
|
||||
// Descend into node
|
||||
currentFrame = { 'node': node, 'index': 0 };
|
||||
currentFrame = {
|
||||
'node': node,
|
||||
'index': 0,
|
||||
'startOffset': left
|
||||
};
|
||||
stack.push( currentFrame );
|
||||
if ( node.children[0].isWrapped() ) {
|
||||
left++;
|
||||
|
@ -203,8 +259,12 @@ ve.Document.prototype.selectNodes = function( range, mode ) {
|
|||
continue;
|
||||
} else {
|
||||
// All of node is covered
|
||||
// TODO should this have a range or not?
|
||||
retval.push( { 'node': node } );
|
||||
retval.push( {
|
||||
'node': node,
|
||||
// no 'range' because the entire node is covered
|
||||
'index': currentFrame.index,
|
||||
'nodeRange': new ve.Range( left, right )
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ test( 'canHaveGrandchildren', 1, function() {
|
|||
test( 'updateDomWrapper', 3, function() {
|
||||
var node = new ve.ce.BranchNodeStub( new ve.dm.BranchNodeStub( [], { 'type': 'a' } ) );
|
||||
// Add classes and content to the node
|
||||
node.$.addClass( 'test' ).text( 'hello' );
|
||||
node.$.attr( 'class', 'test' ).text( 'hello' );
|
||||
// Modify attribute
|
||||
node.getModel().attributes.type = 'b';
|
||||
node.updateDomWrapper( 'type' );
|
||||
|
|
|
@ -7,12 +7,6 @@ ve.ce.LeafNodeStub = function( model ) {
|
|||
ve.ce.LeafNode.call( this, 'leaf-stub', model );
|
||||
};
|
||||
|
||||
ve.ce.LeafNodeStub.rules = {
|
||||
'canHaveChildren': false,
|
||||
'canHaveGrandchildren': false,
|
||||
'isWrapped': true
|
||||
};
|
||||
|
||||
ve.extendClass( ve.ce.LeafNodeStub, ve.ce.LeafNode );
|
||||
|
||||
ve.ce.factory.register( 'leaf-stub', ve.ce.LeafNodeStub );
|
||||
|
|
|
@ -12,58 +12,115 @@ ve.example.getSelectNodesCases = function( doc ) {
|
|||
'actual': doc.selectNodes( new ve.Range( 0, 3 ), 'leaves' ),
|
||||
'expected': [
|
||||
// heading/text - partial leaf results have ranges with global offsets
|
||||
{ 'node': lookup( documentNode, 0, 0 ), 'range': new ve.Range( 1, 3 ) }
|
||||
{
|
||||
'node': lookup( documentNode, 0, 0 ),
|
||||
'range': new ve.Range( 1, 3 ),
|
||||
'index': 0,
|
||||
'nodeRange': new ve.Range( 1, 4 )
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'actual': doc.selectNodes( new ve.Range( 0, 10 ), 'leaves' ),
|
||||
'expected': [
|
||||
// heading/text - full coverage leaf nodes do not have ranges
|
||||
{ 'node': lookup( documentNode, 0, 0 ) },
|
||||
{
|
||||
'node': lookup( documentNode, 0, 0 ),
|
||||
'index': 0,
|
||||
'nodeRange': new ve.Range( 1, 4 )
|
||||
},
|
||||
// table/tableRow/tableCell/paragraph/text - leaf nodes from different levels
|
||||
{ 'node': lookup( documentNode, 1, 0, 0, 0, 0 ) }
|
||||
{
|
||||
'node': lookup( documentNode, 1, 0, 0, 0, 0 ),
|
||||
'index': 0,
|
||||
'nodeRange': new ve.Range( 9, 10 )
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'actual': doc.selectNodes( new ve.Range( 28, 41 ), 'leaves' ),
|
||||
'expected': [
|
||||
// table/tableRow/tableCell/list/listItem/paragraph/text
|
||||
{ 'node': lookup( documentNode, 1, 0, 0, 2, 0, 0, 0 ) },
|
||||
{
|
||||
'node': lookup( documentNode, 1, 0, 0, 2, 0, 0, 0 ),
|
||||
'index': 0,
|
||||
'nodeRange': new ve.Range( 28, 29 )
|
||||
},
|
||||
// preformatted/text
|
||||
{ 'node': lookup( documentNode, 2, 0 ) },
|
||||
{
|
||||
'node': lookup( documentNode, 2, 0 ),
|
||||
'index': 0,
|
||||
'nodeRange': new ve.Range( 36, 37 )
|
||||
},
|
||||
// preformatted/image - leaf nodes that are not text nodes
|
||||
{ 'node': lookup( documentNode, 2, 1 ) },
|
||||
{
|
||||
'node': lookup( documentNode, 2, 1 ),
|
||||
'index': 1,
|
||||
'nodeRange': new ve.Range( 38, 38 )
|
||||
},
|
||||
// preformatted/text
|
||||
{ 'node': lookup( documentNode, 2, 2 ) }
|
||||
{
|
||||
'node': lookup( documentNode, 2, 2 ),
|
||||
'index': 2,
|
||||
'nodeRange': new ve.Range( 39, 40 )
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'actual': doc.selectNodes( new ve.Range( 2, 15 ), 'siblings' ),
|
||||
'expected': [
|
||||
// heading
|
||||
{ 'node': lookup( documentNode, 0 ), 'range': new ve.Range( 2, 4 ) },
|
||||
{
|
||||
'node': lookup( documentNode, 0 ),
|
||||
'range': new ve.Range( 2, 4 ),
|
||||
'index': 0,
|
||||
'nodeRange': new ve.Range( 1, 4 )
|
||||
},
|
||||
// table
|
||||
{ 'node': lookup( documentNode, 1 ), 'range': new ve.Range( 6, 15 ) }
|
||||
{
|
||||
'node': lookup( documentNode, 1 ),
|
||||
'range': new ve.Range( 6, 15 ),
|
||||
'index': 1,
|
||||
'nodeRange': new ve.Range( 6, 34 )
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
'actual': doc.selectNodes( new ve.Range( 2, 49 ), 'siblings' ),
|
||||
'expected': [
|
||||
// heading
|
||||
{ 'node': lookup( documentNode, 0 ), 'range': new ve.Range( 2, 4 ) },
|
||||
{
|
||||
'node': lookup( documentNode, 0 ),
|
||||
'range': new ve.Range( 2, 4 ),
|
||||
'index': 0,
|
||||
'nodeRange': new ve.Range( 1, 4 )
|
||||
},
|
||||
// table
|
||||
{ 'node': lookup( documentNode, 1 ) },
|
||||
{
|
||||
'node': lookup( documentNode, 1 ),
|
||||
'index': 1,
|
||||
'nodeRange': new ve.Range( 6, 34 )
|
||||
},
|
||||
// preformatted
|
||||
{ 'node': lookup( documentNode, 2 ) },
|
||||
{
|
||||
'node': lookup( documentNode, 2 ),
|
||||
'index': 2,
|
||||
'nodeRange': new ve.Range( 36, 40 )
|
||||
},
|
||||
// definitionList
|
||||
{ 'node': lookup( documentNode, 3 ), 'range': new ve.Range( 42, 49 ) }
|
||||
{
|
||||
'node': lookup( documentNode, 3 ),
|
||||
'range': new ve.Range( 42, 49 ),
|
||||
'index': 3,
|
||||
'nodeRange': new ve.Range( 42, 52 )
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Asserts that two node trees are equavilant.
|
||||
* Asserts that two node trees are equivalent.
|
||||
*
|
||||
* This will perform 4 assertions on each branch node and 3 assertions on each leaf node.
|
||||
*
|
||||
|
@ -82,7 +139,7 @@ ve.example.nodeTreeEqual = function( a, b ) {
|
|||
};
|
||||
|
||||
/**
|
||||
* Asserts that two node selections are equavilant.
|
||||
* Asserts that two node selections are equivalent.
|
||||
*
|
||||
* This will perform 1 assertion to check the number of results in the selection and then 2
|
||||
* assertions on each result
|
||||
|
@ -98,6 +155,8 @@ ve.example.nodeSelectionEqual = function( a, b ) {
|
|||
} else {
|
||||
strictEqual( 'range' in a[i], 'range' in b[i], 'range existence match' );
|
||||
}
|
||||
deepEqual( a[i].index, b[i].index, 'index match' );
|
||||
deepEqual( a[i].nodeRange, b[i].nodeRange, 'nodeRange match' );
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue