// parser fixing.\r
var nonBreakingBlocks = CKEDITOR.tools.extend(\r
{table:1,ul:1,ol:1,dl:1},\r
- CKEDITOR.dtd.table, CKEDITOR.dtd.ul, CKEDITOR.dtd.ol, CKEDITOR.dtd.dl );\r
+ CKEDITOR.dtd.table, CKEDITOR.dtd.ul, CKEDITOR.dtd.ol, CKEDITOR.dtd.dl ),\r
+ listBlocks = CKEDITOR.dtd.$list, listItems = CKEDITOR.dtd.$listItem;\r
\r
/**\r
* Creates a {@link CKEDITOR.htmlParser.fragment} from an HTML string.\r
if ( !currentName )\r
return;\r
\r
- var reApply = false;\r
+ var reApply = false,\r
+ addPoint; // New position to start adding nodes.\r
\r
+ // Fixing malformed nested lists(#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
// 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
// parent. This situation usually happens with <p>, <li>, <dt> and\r
// <dd>, specially in IE. Do not enter in this if block in this case.\r
- if ( tagName == currentName )\r
+ else if ( tagName == currentName )\r
{\r
addElement( currentNode, currentNode.parent );\r
}\r
reApply = true;\r
}\r
\r
- // In any of the above cases, we'll be adding, or trying to\r
- // add it to the parent.\r
- currentNode = currentNode.returnPoint || currentNode.parent;\r
+ if( addPoint )\r
+ currentNode = addPoint;\r
+ // Try adding it to the return point, or the parent element.\r
+ else\r
+ currentNode = currentNode.returnPoint || currentNode.parent;\r
\r
if ( reApply )\r
{\r
\r
parser.onTagClose = function( tagName )\r
{\r
- var index = 0,\r
- pendingAdd = [],\r
+ // Check if there is any pending tag to be closed.\r
+ for ( var i = pendingInline.length - 1 ; i >= 0 ; i-- )\r
+ {\r
+ // If found, just remove it from the list.\r
+ if ( tagName == pendingInline[ i ].name )\r
+ {\r
+ pendingInline.splice( i, 1 );\r
+ return;\r
+ }\r
+ }\r
+\r
+ var pendingAdd = [],\r
candidate = currentNode;\r
\r
while ( candidate.type && candidate.name != tagName )\r
// If this is an inline element, add it to the pending list, so\r
// it will continue after the closing tag.\r
if ( !candidate._.isBlockLike )\r
- {\r
pendingInline.unshift( candidate );\r
\r
- // Increase the index, so it will not get checked again in\r
- // the pending list check that follows.\r
- index++;\r
- }\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
// one of the nodes. So, for now, we just cache it.\r
if ( candidate.type )\r
{\r
// Add all elements that have been found in the above loop.\r
- for ( var i = 0 ; i < pendingAdd.length ; i++ )\r
+ for ( i = 0 ; i < pendingAdd.length ; i++ )\r
{\r
var node = pendingAdd[ i ];\r
addElement( node, node.parent );\r
if ( candidate == currentNode )\r
currentNode = currentNode.parent;\r
}\r
- // The tag is not actually closing anything, thus we need invalidate\r
- // the pending elements.(#3862)\r
- else\r
- {\r
- pendingInline.splice( 0, index );\r
- index = 0;\r
- }\r
-\r
- // Check if there is any pending tag to be closed.\r
- for ( ; index < pendingInline.length ; index++ )\r
- {\r
- // If found, just remove it from the list.\r
- if ( tagName == pendingInline[ index ].name )\r
- {\r
- pendingInline.splice( index, 1 );\r
-\r
- // Decrease the index so we continue from the next one.\r
- index--;\r
- }\r
- }\r
};\r
\r
parser.onText = function( text )\r