JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.1
[ckeditor.git] / _source / core / htmlparser / fragment.js
index 66bb3be..6c7686c 100644 (file)
@@ -1,5 +1,5 @@
 /*\r
-Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.\r
+Copyright (c) 2003-2010, CKSource - Frederico Knabben. All rights reserved.\r
 For licensing, see LICENSE.html or http://ckeditor.com/license\r
 */\r
 \r
@@ -114,7 +114,9 @@ CKEDITOR.htmlParser.fragment = function()
                                        elementName = realElementName;\r
                                else\r
                                        elementName =  element.name;\r
-                               if ( !( elementName in CKEDITOR.dtd.$body ) )\r
+                               if ( elementName\r
+                                               && !( elementName in CKEDITOR.dtd.$body )\r
+                                               && !( elementName in CKEDITOR.dtd.$nonBodyContent )  )\r
                                {\r
                                        var savedCurrent = currentNode;\r
 \r
@@ -179,32 +181,32 @@ CKEDITOR.htmlParser.fragment = function()
                                return;\r
                        }\r
 \r
-                       var currentName = currentNode.name,\r
-                               currentDtd = ( currentName && CKEDITOR.dtd[ currentName ] ) || ( currentNode._.isBlockLike ? CKEDITOR.dtd.div : CKEDITOR.dtd.span );\r
+                       var currentName = currentNode.name;\r
+\r
+                       var currentDtd = currentName\r
+                               && ( CKEDITOR.dtd[ currentName ]\r
+                                       || ( currentNode._.isBlockLike ? CKEDITOR.dtd.div : CKEDITOR.dtd.span ) );\r
 \r
                        // If the element cannot be child of the current element.\r
-                       if ( !element.isUnknown && !currentNode.isUnknown && !currentDtd[ tagName ] )\r
+                       if ( currentDtd   // Fragment could receive any elements.\r
+                                && !element.isUnknown && !currentNode.isUnknown && !currentDtd[ tagName ] )\r
                        {\r
-                               // If this is the fragment node, just ignore this tag and add\r
-                               // its children.\r
-                               if ( !currentName )\r
-                                       return;\r
 \r
                                var reApply = false,\r
                                        addPoint;   // New position to start adding nodes.\r
 \r
-                               // Fixing malformed nested lists(#3828).\r
+                               // Fixing malformed nested lists by moving it into a previous list item. (#3828)\r
                                if( tagName in listBlocks\r
                                        && currentName in listBlocks )\r
                                {\r
                                        var children = currentNode.children,\r
                                                lastChild = children[ children.length - 1 ];\r
-                                       // Move inner list into to previous list item if any.\r
-                                       if( lastChild && lastChild.name in listItems )\r
-                                               returnPoint = currentNode, addPoint = lastChild;\r
-                                       // Move inner list outside in the worst case.\r
-                                       else\r
-                                               addElement( currentNode, currentNode.parent );\r
+\r
+                                       // Establish the list item if it's not existed.\r
+                                       if ( !( lastChild && lastChild.name in listItems ) )\r
+                                               addElement( ( lastChild = new CKEDITOR.htmlParser.element( 'li' ) ), currentNode );\r
+\r
+                                       returnPoint = currentNode, addPoint = lastChild;\r
                                }\r
                                // If the element name is the same as the current element name,\r
                                // then just close the current one and append the new one to the\r
@@ -276,14 +278,16 @@ CKEDITOR.htmlParser.fragment = function()
                        }\r
 \r
                        var pendingAdd = [],\r
+                               newPendingInline = [],\r
                                candidate = currentNode;\r
 \r
                        while ( candidate.type && candidate.name != tagName )\r
                        {\r
-                               // If this is an inline element, add it to the pending list, so\r
-                               // it will continue after the closing tag.\r
+                               // If this is an inline element, add it to the pending list, if we're\r
+                               // really closing one of the parents element later, they will continue\r
+                               // after it.\r
                                if ( !candidate._.isBlockLike )\r
-                                       pendingInline.unshift( candidate );\r
+                                       newPendingInline.unshift( candidate );\r
 \r
                                // This node should be added to it's parent at this point. But,\r
                                // it should happen only if the closing tag is really closing\r
@@ -313,7 +317,12 @@ CKEDITOR.htmlParser.fragment = function()
                                // addElement changed the currentNode.\r
                                if ( candidate == currentNode )\r
                                        currentNode = currentNode.parent;\r
+\r
+                               pendingInline = pendingInline.concat( newPendingInline );\r
                        }\r
+\r
+                       if( tagName == 'body' )\r
+                               fixForBody = false;\r
                };\r
 \r
                parser.onText = function( text )\r
@@ -329,8 +338,12 @@ CKEDITOR.htmlParser.fragment = function()
 \r
                        checkPending();\r
 \r
-                       if ( fixForBody && !currentNode.type )\r
+                       if ( fixForBody\r
+                                && ( !currentNode.type || currentNode.name == 'body' )\r
+                                && CKEDITOR.tools.trim( text ) )\r
+                       {\r
                                this.onTagOpen( fixForBody, {} );\r
+                       }\r
 \r
                        // Shrinking consequential spaces into one single for all elements\r
                        // text contents.\r
@@ -359,7 +372,9 @@ CKEDITOR.htmlParser.fragment = function()
                        var parent = currentNode.parent,\r
                                node = currentNode;\r
 \r
-                       if ( fixForBody && !parent.type && !CKEDITOR.dtd.$body[ node.name ] )\r
+                       if ( fixForBody\r
+                                && ( !parent.type || parent.name == 'body' )\r
+                                && !CKEDITOR.dtd.$body[ node.name ] )\r
                        {\r
                                currentNode = parent;\r
                                parser.onTagOpen( fixForBody, {} );\r
@@ -428,7 +443,25 @@ CKEDITOR.htmlParser.fragment = function()
                 */\r
                writeHtml : function( writer, filter )\r
                {\r
-                       for ( var i = 0, len = this.children.length ; i < len ; i++ )\r
+                       var isChildrenFiltered;\r
+                       this.filterChildren = function()\r
+                       {\r
+                               var writer = new CKEDITOR.htmlParser.basicWriter();\r
+                               this.writeChildrenHtml.call( this, writer, filter, true );\r
+                               var html = writer.getHtml();\r
+                               this.children = new CKEDITOR.htmlParser.fragment.fromHtml( html ).children;\r
+                               isChildrenFiltered = 1;\r
+                       };\r
+\r
+                       // Filtering the root fragment before anything else.\r
+                       !this.name && filter && filter.onFragment( this );\r
+\r
+                       this.writeChildrenHtml( writer, isChildrenFiltered ? null : filter );\r
+               },\r
+\r
+               writeChildrenHtml : function( writer, filter )\r
+               {\r
+                       for ( var i = 0 ; i < this.children.length ; i++ )\r
                                this.children[i].writeHtml( writer, filter );\r
                }\r
        };\r