Merge branch 'dmrewrite' of ssh://review/mediawiki/extensions/VisualEditor into dmrewrite

This commit is contained in:
Inez Korczynski 2012-05-23 17:22:23 -07:00
commit 5b52e5320a
2 changed files with 91 additions and 42 deletions

View file

@ -207,19 +207,35 @@ ve.dm.Document.isContentOffset = function( data, offset ) {
/**
* Checks if structure can be inserted at an offset in document data.
*
* If the {unrestricted} param is true than only offsets where any kind of element can be inserted
* will return true. This can be used to detect the difference between a location that a paragraph
* can be inserted, such as between two tables but not direclty inside a table.
*
* This method assumes that any value that has a type property that's a string is an element object.
*
* @example Structural offsets:
* @example Structural offsets (unrestricted = false):
* <heading> a </heading> <paragraph> b c <img> </img> </paragraph>
* ^ . . ^ . . . . . ^
*
* @example Structural offsets (unrestricted = true):
* <heading> a </heading> <paragraph> b c <img> </img> </paragraph>
* ^ . . ^ . . . . . ^
*
* @example Structural offsets (unrestricted = false):
* <list> <listItem> </listItem> <list>
* ^ ^ ^ ^ ^
*
* @example Content branch offsets (unrestricted = true):
* <list> <listItem> </listItem> <list>
* ^ . ^ . ^
*
* @static
* @method
* @param {Array} data Document data
* @param {Integer} offset Document offset
* @returns {Boolean} Structure can be inserted at offset
*/
ve.dm.Document.isStructuralOffset = function( data, offset ) {
ve.dm.Document.isStructuralOffset = function( data, offset, unrestricted ) {
// Edges are always structural
if ( offset === 0 || offset === data.length ) {
return true;
@ -242,15 +258,31 @@ ve.dm.Document.isStructuralOffset = function( data, offset ) {
// Is a closing
left.type.charAt( 0 ) === '/' &&
// Is a branch
factory.canNodeHaveChildren( left.type.substr( 1 ) )
factory.canNodeHaveChildren( left.type.substr( 1 ) ) &&
(
// Only apply this rule in unrestricted mode
!unrestricted ||
// Right of an unrestricted branch
// <list><listItem><paragraph>a</paragraph>|</listItem></list>|
// Both are non-content branches that can have any kind of child
factory.getParentNodeTypes( left.type.substr( 1 ) ) === null
)
) ||
// Left of branch
// Left of a branch
// |<list>|<listItem>|<paragraph>a</paragraph></listItem></list>
(
// Is not a closing
right.type.charAt( 0 ) !== '/' &&
// Is a branch
factory.canNodeHaveChildren( right.type )
factory.canNodeHaveChildren( right.type ) &&
(
// Only apply this rule in unrestricted mode
!unrestricted ||
// Left of an unrestricted branch
// |<list><listItem>|<paragraph>a</paragraph></listItem></list>
// Both are non-content branches that can have any kind of child
factory.getParentNodeTypes( right.type ) === null
)
) ||
// Inside empty non-content branch
// <list>|</list> or <list><listItem>|</listItem></list>
@ -258,7 +290,13 @@ ve.dm.Document.isStructuralOffset = function( data, offset ) {
// Inside empty element
'/' + left.type === right.type &&
// Both are non-content branches (right is the same type)
factory.canNodeHaveGrandchildren( left.type )
factory.canNodeHaveGrandchildren( left.type ) &&
(
// Only apply this rule in unrestricted mode
!unrestricted ||
// Both are non-content branches that can have any kind of child
factory.getChildNodeTypes( left.type ) === null
)
)
)
);

View file

@ -554,14 +554,14 @@ test( 'isContentOffset', function() {
{ 'msg': 'between content branches', 'expected': false },
{ 'msg': 'inside emtpy content branch', 'expected': true },
{ 'msg': 'between content branches', 'expected': false },
{ 'msg': 'begining of content branch and left of inline leaf', 'expected': true },
{ 'msg': 'inside content branch with only non-text inline leaf', 'expected': false },
{ 'msg': 'end of content branch and right of block leaf', 'expected': true },
{ 'msg': 'between content and non-content branches', 'expected': false },
{ 'msg': 'between parent and child branches, descending', 'expected': false },
{ 'msg': 'begining of content branch, left of inline leaf', 'expected': true },
{ 'msg': 'inside content branch with non-text inline leaf', 'expected': false },
{ 'msg': 'end of content branch, right of block leaf', 'expected': true },
{ 'msg': 'between content, non-content branches', 'expected': false },
{ 'msg': 'between parent, child branches, descending', 'expected': false },
{ 'msg': 'inside empty non-content branch', 'expected': false },
{ 'msg': 'between parent and child branches, ascending', 'expected': false },
{ 'msg': 'between non-content branch and block leaf', 'expected': false },
{ 'msg': 'between parent, child branches, ascending', 'expected': false },
{ 'msg': 'between non-content branch, block leaf', 'expected': false },
{ 'msg': 'inside block leaf', 'expected': false },
{ 'msg': 'right of document', 'expected': false }
];
@ -594,30 +594,41 @@ test( 'isStructuralOffset', function() {
{ 'type': '/alienBlock' }
],
cases = [
{ 'msg': 'left of document', 'expected': true },
{ 'msg': 'begining of content branch', 'expected': false },
{ 'msg': 'left of non-text inline leaf', 'expected': false },
{ 'msg': 'inside non-text inline leaf', 'expected': false },
{ 'msg': 'right of non-text inline leaf', 'expected': false },
{ 'msg': 'between characters', 'expected': false },
{ 'msg': 'end of content branch', 'expected': false },
{ 'msg': 'between content branches', 'expected': true },
{ 'msg': 'inside emtpy content branch', 'expected': false },
{ 'msg': 'between content branches', 'expected': true },
{ 'msg': 'begining of content branch and left of inline leaf', 'expected': false },
{ 'msg': 'inside content branch with only non-text inline leaf', 'expected': false },
{ 'msg': 'end of content branch and right of inline leaf', 'expected': false },
{ 'msg': 'between content and non-content branches', 'expected': true },
{ 'msg': 'between parent and child branches, descending', 'expected': true },
{ 'msg': 'inside empty non-content branch', 'expected': true },
{ 'msg': 'between parent and child branches, ascending', 'expected': true },
{ 'msg': 'between non-content branch and block leaf', 'expected': true },
{ 'msg': 'inside block leaf', 'expected': false },
{ 'msg': 'right of document', 'expected': true }
{ 'msg': 'left of document', 'expected': [true, true] },
{ 'msg': 'begining of content branch', 'expected': [false, false] },
{ 'msg': 'left of non-text inline leaf', 'expected': [false, false] },
{ 'msg': 'inside non-text inline leaf', 'expected': [false, false] },
{ 'msg': 'right of non-text inline leaf', 'expected': [false, false] },
{ 'msg': 'between characters', 'expected': [false, false] },
{ 'msg': 'end of content branch', 'expected': [false, false] },
{ 'msg': 'between content branches', 'expected': [true, true] },
{ 'msg': 'inside emtpy content branch', 'expected': [false, false] },
{ 'msg': 'between content branches', 'expected': [true, true] },
{ 'msg': 'begining of content branch, left of inline leaf', 'expected': [false, false] },
{ 'msg': 'inside content branch with non-text inline leaf', 'expected': [false, false] },
{ 'msg': 'end of content branch, right of inline leaf', 'expected': [false, false] },
{ 'msg': 'between content, non-content branches', 'expected': [true, true] },
{ 'msg': 'between parent, child branches, descending', 'expected': [true, false] },
{ 'msg': 'inside empty non-content branch', 'expected': [true, true] },
{ 'msg': 'between parent, child branches, ascending', 'expected': [true, false] },
{ 'msg': 'between non-content branch, block leaf', 'expected': [true, true] },
{ 'msg': 'inside block leaf', 'expected': [false, false] },
{ 'msg': 'right of document', 'expected': [true, true] }
];
expect( data.length + 1 );
expect( ( data.length + 1 ) * 2 );
for ( var i = 0; i < cases.length; i++ ) {
strictEqual( ve.dm.Document.isStructuralOffset( data, i ), cases[i].expected, cases[i].msg );
var left = data[i - 1] ? ( data[i - 1].type || data[i - 1][0] ) : '[start]',
right = data[i] ? ( data[i].type || data[i][0] ) : '[end]';
strictEqual(
ve.dm.Document.isStructuralOffset( data, i ),
cases[i].expected[0],
cases[i].msg + ' (' + left + '|' + right + ' @ ' + i + ')'
);
strictEqual(
ve.dm.Document.isStructuralOffset( data, i, true ),
cases[i].expected[1],
cases[i].msg + ', unrestricted (' + left + '|' + right + ' @ ' + i + ')'
);
}
} );
@ -654,14 +665,14 @@ test( 'isElementData', 1, function() {
{ 'msg': 'between content branches', 'expected': true },
{ 'msg': 'inside emtpy content branch', 'expected': true },
{ 'msg': 'between content branches', 'expected': true },
{ 'msg': 'begining of content branch and left of inline leaf', 'expected': true },
{ 'msg': 'inside content branch with only non-text leaf', 'expected': true },
{ 'msg': 'end of content branch and right of inline leaf', 'expected': true },
{ 'msg': 'between content and non-content branches', 'expected': true },
{ 'msg': 'between parent and child branches, descending', 'expected': true },
{ 'msg': 'begining of content branch, left of inline leaf', 'expected': true },
{ 'msg': 'inside content branch with non-text leaf', 'expected': true },
{ 'msg': 'end of content branch, right of inline leaf', 'expected': true },
{ 'msg': 'between content, non-content branches', 'expected': true },
{ 'msg': 'between parent, child branches, descending', 'expected': true },
{ 'msg': 'inside empty non-content branch', 'expected': true },
{ 'msg': 'between parent and child branches, ascending', 'expected': true },
{ 'msg': 'between non-content branch and block leaf', 'expected': true },
{ 'msg': 'between parent, child branches, ascending', 'expected': true },
{ 'msg': 'between non-content branch, block leaf', 'expected': true },
{ 'msg': 'inside block leaf', 'expected': true },
{ 'msg': 'right of document', 'expected': false }
];