X-Git-Url: https://jasonwoof.com/gitweb/?a=blobdiff_plain;ds=sidebyside;f=_source%2Fcore%2Fhtmlparser%2Ffragment.js;h=ad1c93edb2211aafad75bb83bb5f0d51a3b403cd;hb=c6e377a02b54abc07129d72b632763c727476a15;hp=66bb3be0e9f8d848f29e8744e630a5aca630a400;hpb=7cd80714081a8ffdf4a1a8d2c72f120ed5ef3d6d;p=ckeditor.git diff --git a/_source/core/htmlparser/fragment.js b/_source/core/htmlparser/fragment.js index 66bb3be..ad1c93e 100644 --- a/_source/core/htmlparser/fragment.js +++ b/_source/core/htmlparser/fragment.js @@ -1,5 +1,5 @@ /* -Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. +Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved. For licensing, see LICENSE.html or http://ckeditor.com/license */ @@ -64,6 +64,7 @@ CKEDITOR.htmlParser.fragment = function() html = [], fragment = new CKEDITOR.htmlParser.fragment(), pendingInline = [], + pendingBRs = [], currentNode = fragment, // Indicate we're inside a
element, spaces should be touched differently. inPre = false, @@ -71,6 +72,8 @@ CKEDITOR.htmlParser.fragment = function() function checkPending( newTagName ) { + var pendingBRsSent; + if ( pendingInline.length > 0 ) { for ( var i = 0 ; i < pendingInline.length ; i++ ) @@ -82,6 +85,12 @@ CKEDITOR.htmlParser.fragment = function() if ( ( !currentDtd || currentDtd[ pendingName ] ) && ( !newTagName || !pendingDtd || pendingDtd[ newTagName ] || !CKEDITOR.dtd[ newTagName ] ) ) { + if ( !pendingBRsSent ) + { + sendPendingBRs(); + pendingBRsSent = 1; + } + // Get a clone for the pending element. pendingElement = pendingElement.clone(); @@ -99,6 +108,12 @@ CKEDITOR.htmlParser.fragment = function() } } + function sendPendingBRs() + { + while ( pendingBRs.length ) + currentNode.add( pendingBRs.shift() ); + } + function addElement( element, target, enforceCurrent ) { target = target || currentNode || fragment; @@ -114,7 +129,9 @@ CKEDITOR.htmlParser.fragment = function() elementName = realElementName; else elementName = element.name; - if ( !( elementName in CKEDITOR.dtd.$body ) ) + if ( elementName + && !( elementName in CKEDITOR.dtd.$body ) + && !( elementName in CKEDITOR.dtd.$nonBodyContent ) ) { var savedCurrent = currentNode; @@ -179,32 +196,38 @@ CKEDITOR.htmlParser.fragment = function() return; } - var currentName = currentNode.name, - currentDtd = ( currentName && CKEDITOR.dtd[ currentName ] ) || ( currentNode._.isBlockLike ? CKEDITOR.dtd.div : CKEDITOR.dtd.span ); + if ( tagName == 'br' ) + { + pendingBRs.push( element ); + return; + } + + var currentName = currentNode.name; + + var currentDtd = currentName + && ( CKEDITOR.dtd[ currentName ] + || ( currentNode._.isBlockLike ? CKEDITOR.dtd.div : CKEDITOR.dtd.span ) ); // If the element cannot be child of the current element. - if ( !element.isUnknown && !currentNode.isUnknown && !currentDtd[ tagName ] ) + if ( currentDtd // Fragment could receive any elements. + && !element.isUnknown && !currentNode.isUnknown && !currentDtd[ tagName ] ) { - // If this is the fragment node, just ignore this tag and add - // its children. - if ( !currentName ) - return; var reApply = false, addPoint; // New position to start adding nodes. - // Fixing malformed nested lists(#3828). - if( tagName in listBlocks + // Fixing malformed nested lists by moving it into a previous list item. (#3828) + if ( tagName in listBlocks && currentName in listBlocks ) { var children = currentNode.children, lastChild = children[ children.length - 1 ]; - // Move inner list into to previous list item if any. - if( lastChild && lastChild.name in listItems ) - returnPoint = currentNode, addPoint = lastChild; - // Move inner list outside in the worst case. - else - addElement( currentNode, currentNode.parent ); + + // Establish the list item if it's not existed. + if ( !( lastChild && lastChild.name in listItems ) ) + addElement( ( lastChild = new CKEDITOR.htmlParser.element( 'li' ) ), currentNode ); + + returnPoint = currentNode, addPoint = lastChild; } // If the element name is the same as the current element name, // then just close the current one and append the new one to the @@ -237,7 +260,7 @@ CKEDITOR.htmlParser.fragment = function() reApply = true; } - if( addPoint ) + if ( addPoint ) currentNode = addPoint; // Try adding it to the return point, or the parent element. else @@ -276,14 +299,16 @@ CKEDITOR.htmlParser.fragment = function() } var pendingAdd = [], + newPendingInline = [], candidate = currentNode; while ( candidate.type && candidate.name != tagName ) { - // If this is an inline element, add it to the pending list, so - // it will continue after the closing tag. + // If this is an inline element, add it to the pending list, if we're + // really closing one of the parents element later, they will continue + // after it. if ( !candidate._.isBlockLike ) - pendingInline.unshift( candidate ); + newPendingInline.unshift( candidate ); // This node should be added to it's parent at this point. But, // it should happen only if the closing tag is really closing @@ -304,16 +329,24 @@ CKEDITOR.htmlParser.fragment = function() currentNode = candidate; - if( currentNode.name == 'pre' ) + if ( currentNode.name == 'pre' ) inPre = false; + if ( candidate._.isBlockLike ) + sendPendingBRs(); + addElement( candidate, candidate.parent ); // The parent should start receiving new nodes now, except if // addElement changed the currentNode. if ( candidate == currentNode ) currentNode = currentNode.parent; + + pendingInline = pendingInline.concat( newPendingInline ); } + + if ( tagName == 'body' ) + fixForBody = false; }; parser.onText = function( text ) @@ -327,10 +360,15 @@ CKEDITOR.htmlParser.fragment = function() return; } + sendPendingBRs(); checkPending(); - if ( fixForBody && !currentNode.type ) + if ( fixForBody + && ( !currentNode.type || currentNode.name == 'body' ) + && CKEDITOR.tools.trim( text ) ) + { this.onTagOpen( fixForBody, {} ); + } // Shrinking consequential spaces into one single for all elements // text contents. @@ -353,13 +391,17 @@ CKEDITOR.htmlParser.fragment = function() // Parse it. parser.parse( fragmentHtml ); + sendPendingBRs(); + // Close all pending nodes. while ( currentNode.type ) { var parent = currentNode.parent, node = currentNode; - if ( fixForBody && !parent.type && !CKEDITOR.dtd.$body[ node.name ] ) + if ( fixForBody + && ( !parent.type || parent.name == 'body' ) + && !CKEDITOR.dtd.$body[ node.name ] ) { currentNode = parent; parser.onTagOpen( fixForBody, {} ); @@ -428,7 +470,25 @@ CKEDITOR.htmlParser.fragment = function() */ writeHtml : function( writer, filter ) { - for ( var i = 0, len = this.children.length ; i < len ; i++ ) + var isChildrenFiltered; + this.filterChildren = function() + { + var writer = new CKEDITOR.htmlParser.basicWriter(); + this.writeChildrenHtml.call( this, writer, filter, true ); + var html = writer.getHtml(); + this.children = new CKEDITOR.htmlParser.fragment.fromHtml( html ).children; + isChildrenFiltered = 1; + }; + + // Filtering the root fragment before anything else. + !this.name && filter && filter.onFragment( this ); + + this.writeChildrenHtml( writer, isChildrenFiltered ? null : filter ); + }, + + writeChildrenHtml : function( writer, filter ) + { + for ( var i = 0 ; i < this.children.length ; i++ ) this.children[i].writeHtml( writer, filter ); } };