Merge "Fix whitespace preservation around meta items"

This commit is contained in:
jenkins-bot 2013-04-18 23:18:12 +00:00 committed by Gerrit Code Review
commit ed89820614
2 changed files with 110 additions and 9 deletions

View file

@ -342,6 +342,26 @@ ve.dm.Converter.prototype.getDataFromDomRecursion = function ( domElement, wrapp
nextWhitespace = '';
}
}
function outputWrappedMetaItems( whitespaceTreatment ) {
var i, len, prev = wrappingParagraph;
for ( i = 0, len = wrappedMetaItems.length; i < len; i++ ) {
if ( wrappedMetaItems[i].type && wrappedMetaItems[i].type.charAt( 0 ) !== '/' ) {
if ( wrappedMetaItems[i].internal && wrappedMetaItems[i].internal.whitespace ) {
if ( whitespaceTreatment === 'restore' ) {
data = data.concat( ve.dm.Converter.getDataContentFromText(
wrappedMetaItems[i].internal.whitespace[0], context.annotations
) );
delete wrappedMetaItems[i].internal;
} else if ( whitespaceTreatment === 'fixup' ) {
addWhitespace( prev, 3, wrappedMetaItems[i].internal.whitespace[0] );
}
}
prev = wrappedMetaItems[i];
}
data.push( wrappedMetaItems[i] );
}
wrappedMetaItems = [];
}
function startWrapping() {
// Mark this paragraph as having been generated by
// us, so we can strip it on the way out
@ -363,6 +383,7 @@ ve.dm.Converter.prototype.getDataFromDomRecursion = function ( domElement, wrapp
nextWhitespace = wrappedWhitespace;
}
data.push( { 'type': '/paragraph' } );
outputWrappedMetaItems( 'fixup' );
wrappingParagraph = undefined;
context.inWrapper = false;
context.canCloseWrapper = false;
@ -400,6 +421,7 @@ ve.dm.Converter.prototype.getDataFromDomRecursion = function ( domElement, wrapp
nextWhitespace = '',
wrappedWhitespace = '',
wrappedWhitespaceIndex,
wrappedMetaItems = [],
context = {},
prevContext = this.contextStack.length ? this.contextStack[this.contextStack.length - 1] : null;
@ -472,9 +494,19 @@ ve.dm.Converter.prototype.getDataFromDomRecursion = function ( domElement, wrapp
if ( childDataElements.length === 1 ) {
childDataElements.push( { 'type': '/' + childDataElements[0].type } );
}
data = data.concat( childDataElements );
processNextWhitespace( childDataElements[0] );
prevElement = childDataElements[0];
if ( context.inWrapper ) {
wrappedMetaItems = wrappedMetaItems.concat( childDataElements );
if ( wrappedWhitespace !== '' ) {
data.splice( wrappedWhitespaceIndex, wrappedWhitespace.length );
addWhitespace( childDataElements[0], 0, wrappedWhitespace );
nextWhitespace = wrappedWhitespace;
wrappedWhitespace = '';
}
} else {
data = data.concat( childDataElements );
processNextWhitespace( childDataElements[0] );
prevElement = childDataElements[0];
}
break;
}
@ -565,6 +597,7 @@ ve.dm.Converter.prototype.getDataFromDomRecursion = function ( domElement, wrapp
}
nextWhitespace = text;
wrappedWhitespace = '';
outputWrappedMetaItems( 'restore' );
}
// We're done, no actual text left to process
break;
@ -596,6 +629,7 @@ ve.dm.Converter.prototype.getDataFromDomRecursion = function ( domElement, wrapp
addWhitespace( wrappingParagraph, 0, matches[1] );
}
} else {
outputWrappedMetaItems( 'restore' );
// We were already wrapping in a paragraph,
// so the leading whitespace must be output
data = data.concat(
@ -659,7 +693,7 @@ ve.dm.Converter.prototype.getDataFromDomRecursion = function ( domElement, wrapp
);
break;
case Node.COMMENT_NODE:
// TODO treat this as a node with nodeName #comment
// TODO treat this as a node with nodeName #comment, removes code duplication
childDataElements = [
{
'type': 'alienMeta',
@ -670,9 +704,19 @@ ve.dm.Converter.prototype.getDataFromDomRecursion = function ( domElement, wrapp
},
{ 'type': '/alienMeta' }
];
data = data.concat( childDataElements );
processNextWhitespace( childDataElements[0] );
prevElement = childDataElements[0];
if ( context.inWrapper ) {
wrappedMetaItems = wrappedMetaItems.concat( childDataElements );
if ( wrappedWhitespace !== '' ) {
data.splice( wrappedWhitespaceIndex, wrappedWhitespace.length );
addWhitespace( childDataElements[0], 0, wrappedWhitespace );
nextWhitespace = wrappedWhitespace;
wrappedWhitespace = '';
}
} else {
data = data.concat( childDataElements );
processNextWhitespace( childDataElements[0] );
prevElement = childDataElements[0];
}
break;
}
}
@ -879,7 +923,7 @@ ve.dm.Converter.prototype.getDomSubtreeFromData = function ( store, data, contai
// Element
if ( dataElement.type.charAt( 0 ) === '/' ) {
parentDomElement = domElement.parentNode;
isContentNode = this.metaItemFactory.lookup( data[i].type.substr( 1 ) ) ||
isContentNode = !this.metaItemFactory.lookup( data[i].type.substr( 1 ) ) &&
this.nodeFactory.isNodeContent( data[i].type.substr( 1 ) );
// Process whitespace
// whitespace = [ outerPre, innerPre, innerPost, outerPost ]

View file

@ -1673,6 +1673,62 @@ ve.dm.example.domToDataCases = {
{ 'type': '/table' }
]
},
'whitespace preservation with wrapped text, comments and language links': {
'html': '<body><!-- Foo --> <!-- Bar -->\nFoo\n' +
'<link rel="mw:WikiLink/Language" href="http://de.wikipedia.org/wiki/Foo">\n' +
'<link rel="mw:WikiLink/Language" href="http://fr.wikipedia.org/wiki/Foo"></body>',
'data': [
{
'type': 'alienMeta',
'internal': { 'whitespace': [ undefined, undefined, undefined, ' ' ] },
'attributes': {
'style': 'comment',
'text': ' Foo '
}
},
{ 'type': '/alienMeta' },
{
'type': 'alienMeta',
'internal': { 'whitespace': [ ' ', undefined, undefined, '\n' ] },
'attributes': {
'style': 'comment',
'text': ' Bar '
}
},
{ 'type': '/alienMeta' },
{
'type': 'paragraph',
'internal': {
'generated': 'wrapper',
'whitespace': [ '\n', undefined, undefined, '\n' ]
}
},
'F',
'o',
'o',
{ 'type': '/paragraph' },
{
'type': 'MWlanguage',
'attributes': {
'href': 'http://de.wikipedia.org/wiki/Foo',
'html/0/href': 'http://de.wikipedia.org/wiki/Foo',
'html/0/rel': 'mw:WikiLink/Language'
},
'internal': { 'whitespace': [ '\n', undefined, undefined, '\n' ] }
},
{ 'type': '/MWlanguage' },
{
'type': 'MWlanguage',
'attributes': {
'href': 'http://fr.wikipedia.org/wiki/Foo',
'html/0/href': 'http://fr.wikipedia.org/wiki/Foo',
'html/0/rel': 'mw:WikiLink/Language'
},
'internal': { 'whitespace': [ '\n' ] }
},
{ 'type': '/MWlanguage' }
]
},
'mismatching whitespace data is ignored': {
'html': null,
'data': [
@ -2134,8 +2190,10 @@ ve.dm.example.domToDataCases = {
'F',
'o',
'o',
{ 'type': '/paragraph' },
{
'type': 'alienMeta',
'internal': { 'whitespace': [ '\n' ] },
'attributes': {
'style': 'meta',
'key': 'mw:foo',
@ -2145,7 +2203,6 @@ ve.dm.example.domToDataCases = {
}
},
{ 'type': '/alienMeta' },
{ 'type': '/paragraph' },
{ 'type': '/tableCell' },
{ 'type': '/tableRow' },
{ 'type': '/tableSection' },