Revert "Revert "For empty / whitespace-only headings, output <p> instead of <h#>""

It's seemingly still needed.

This reverts commit 924c58a893.

Change-Id: Ib9428865fbab2669153bd23cf239717080eb8291
This commit is contained in:
Jforrester 2015-08-03 22:48:42 +00:00
parent 871a0a288f
commit dbe11c3b14
2 changed files with 169 additions and 0 deletions

View file

@ -30,6 +30,77 @@ ve.dm.MWHeadingNode.static.name = 'mwHeading';
ve.dm.MWHeadingNode.static.suggestedParentNodeTypes = [ 'document', 'tableCell' ];
ve.dm.MWHeadingNode.static.handlesOwnChildren = true;
ve.dm.MWHeadingNode.static.toDataElement = function ( domElements, converter ) {
var shouldConvert = this.shouldConvertToParagraph( domElements[0] ),
parentResult = ve.dm.MWHeadingNode.super.static.toDataElement.apply( this, arguments );
parentResult.type = this.name;
if ( shouldConvert ) {
ve.setProp( parentResult, 'attributes', 'noconvert', true );
}
return converter.getDataFromDomSubtree(
domElements[0],
parentResult,
new ve.dm.AnnotationSet( converter.getStore() )
);
};
ve.dm.MWHeadingNode.static.toDomElements = function ( dataElements, doc, converter ) {
var paragraph,
parentResult = ve.dm.MWHeadingNode.super.static.toDomElements.call( this, dataElements[0], doc, converter );
converter.getDomSubtreeFromData( dataElements.slice( 1, -1 ), parentResult[0] );
if (
( !dataElements[0].attributes || !dataElements[0].attributes.noconvert ) &&
this.shouldConvertToParagraph( parentResult[0] )
) {
// Change parentResult[0] to a paragraph
paragraph = doc.createElement( 'p' );
while ( parentResult[0].firstChild ) {
paragraph.appendChild( parentResult[0].firstChild );
}
parentResult[0] = paragraph;
}
return parentResult;
};
/**
* Determine whether a heading should be converted to a paragraph.
*
* This function is called by toDomElements to determine whether the heading should be
* converted to a paragraph, and also by toDataElement to determine whether the heading
* already met the conversion criteria coming in (in which case it won't be converted).
*
* This implementation returns true if the heading does not contain a non-whitespace character,
* but subclasses may override this to add their own logic.
*
* @param {HTMLElement} headingElement Heading DOM element
* @return {boolean} Whether the heading should be converted to a paragraph
*/
ve.dm.MWHeadingNode.static.shouldConvertToParagraph = function ( headingElement ) {
function containsNonWhitespace( el ) {
var i, len, childNode;
for ( i = 0, len = el.childNodes.length; i < len; i++ ) {
childNode = el.childNodes[i];
if (
childNode.nodeType === Node.TEXT_NODE &&
childNode.data.match( /\S/ )
) {
// Text node with a non-whitespace character
return true;
}
if ( childNode.nodeType === Node.ELEMENT_NODE && containsNonWhitespace( childNode ) ) {
return true;
}
}
return false;
}
return !containsNonWhitespace( headingElement );
};
/* Registration */
ve.dm.modelRegistry.register( ve.dm.MWHeadingNode );

View file

@ -1954,5 +1954,103 @@ ve.dm.mwExample.domToDataCases = {
model.data.data[7][1].push( model.getStore().index( ve.dm.example.createAnnotation( ve.dm.example.bold ) ) );
},
normalizedBody: '<p>Foo[[B<b>a</b>r]]Baz</p>'
},
'mwHeading with no content': {
data: [
{ type: 'mwHeading', attributes: { level: 1 } },
{ type: '/mwHeading' },
{ type: 'internalList' },
{ type: '/internalList' }
],
normalizedBody: '<p></p>'
},
'mwHeading with whitespace content': {
data: [
{ type: 'mwHeading', attributes: { level: 2 } },
' ', ' ', '\t', ' ',
{ type: '/mwHeading' },
{ type: 'internalList' },
{ type: '/internalList' }
],
normalizedBody: '<p> \t </p>'
},
'mwHeading containing metadata': {
data: [
{ type: 'mwHeading', attributes: { level: 3 } },
{ type: 'alienMeta', originalDomElements: $( '<meta />' ).toArray() },
{ type: '/alienMeta' },
{ type: '/mwHeading' },
{ type: 'internalList' },
{ type: '/internalList' }
],
normalizedBody: '<p><meta /></p>'
},
'mwHeading containing alienated text': {
data: [
{
type: 'mwHeading',
attributes: { level: 4 }
},
{ type: 'alienInline', originalDomElements: $( '<span rel="ve:Alien">Alien</span>' ).toArray() },
{ type: '/alienInline' },
{ type: '/mwHeading' },
{ type: 'internalList' },
{ type: '/internalList' }
],
body: '<h4><span rel="ve:Alien">Alien</span></h4>'
},
'existing empty mwHeading is not converted to paragraph': {
data: [
{
type: 'mwHeading',
attributes: {
level: 5,
noconvert: true
}
},
{ type: '/mwHeading' },
{ type: 'internalList' },
{ type: '/internalList' }
],
body: '<h5></h5>'
},
'adding whitespace to existing empty mwHeading does not convert to paragraph': {
data: [
{
type: 'mwHeading',
attributes: {
level: 6,
noconvert: true
}
},
{ type: '/mwHeading' },
{ type: 'internalList' },
{ type: '/internalList' }
],
modify: function ( doc ) {
doc.data.data.splice( 1, 0, ' ' );
},
body: '<h6></h6>',
normalizedBody: '<h6> </h6>'
},
'emptying existing meta-only mwHeading does not convert to paragraph': {
data: [
{
type: 'mwHeading',
attributes: {
level: 1,
noconvert: true
}
},
{ type: 'alienMeta', originalDomElements: $( '<meta />' ).toArray() },
{ type: '/alienMeta' },
{ type: '/mwHeading' },
{ type: 'internalList' },
{ type: '/internalList' }
],
modify: function ( doc ) {
doc.metadata.data[1].splice( 0, 1 );
},
normalizedBody: '<h1></h1>'
}
};