JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
vanilla ckeditor-3.6.2
[ckeditor.git] / _source / core / htmlparser / fragment.js
index bfa5cc5..f69f7cd 100644 (file)
@@ -49,6 +49,13 @@ CKEDITOR.htmlParser.fragment = function()
        // Dtd of the fragment element, basically it accept anything except for intermediate structure, e.g. orphan <li>.\r
        var rootDtd = CKEDITOR.tools.extend( {}, { html: 1 }, CKEDITOR.dtd.html, CKEDITOR.dtd.body, CKEDITOR.dtd.head, { style:1,script:1 } );\r
 \r
+       function isRemoveEmpty( node )\r
+       {\r
+               // Empty link is to be removed when empty but not anchor. (#7894)\r
+               return node.name == 'a' && node.attributes.href\r
+                       || CKEDITOR.dtd.$removeEmpty[ node.name ];\r
+       }\r
+\r
        /**\r
         * Creates a {@link CKEDITOR.htmlParser.fragment} from an HTML string.\r
         * @param {String} fragmentHtml The HTML to be parsed, filling the fragment.\r
@@ -67,6 +74,8 @@ CKEDITOR.htmlParser.fragment = function()
                        pendingInline = [],\r
                        pendingBRs = [],\r
                        currentNode = fragment,\r
+                   // Indicate we're inside a <textarea> element, spaces should be touched differently.\r
+                       inTextarea = false,\r
                    // Indicate we're inside a <pre> element, spaces should be touched differently.\r
                        inPre = false;\r
 \r
@@ -104,6 +113,13 @@ CKEDITOR.htmlParser.fragment = function()
                                                pendingInline.splice( i, 1 );\r
                                                i--;\r
                                        }\r
+                                       else\r
+                                       {\r
+                                               // Some element of the same type cannot be nested, flat them,\r
+                                               // e.g. <a href="#">foo<a href="#">bar</a></a>. (#7894)\r
+                                               if ( pendingName == currentNode.name )\r
+                                                       addElement( currentNode, currentNode.parent, 1 ), i--;\r
+                                       }\r
                                }\r
                        }\r
                }\r
@@ -161,7 +177,7 @@ CKEDITOR.htmlParser.fragment = function()
 \r
                        // Rtrim empty spaces on block end boundary. (#3585)\r
                        if ( element._.isBlockLike\r
-                                && element.name != 'pre' )\r
+                                && element.name != 'pre' && element.name != 'textarea' )\r
                        {\r
 \r
                                var length = element.children.length,\r
@@ -200,7 +216,7 @@ CKEDITOR.htmlParser.fragment = function()
                        element.isOptionalClose = tagName in optionalCloseTags || optionalClose;\r
 \r
                        // This is a tag to be removed if empty, so do not add it immediately.\r
-                       if ( CKEDITOR.dtd.$removeEmpty[ tagName ] )\r
+                       if ( isRemoveEmpty( element ) )\r
                        {\r
                                pendingInline.push( element );\r
                                return;\r
@@ -212,6 +228,8 @@ CKEDITOR.htmlParser.fragment = function()
                                currentNode.add( new CKEDITOR.htmlParser.text( '\n' ) );\r
                                return;\r
                        }\r
+                       else if ( tagName == 'textarea' )\r
+                               inTextarea = true;\r
 \r
                        if ( tagName == 'br' )\r
                        {\r
@@ -345,6 +363,9 @@ CKEDITOR.htmlParser.fragment = function()
                                if ( currentNode.name == 'pre' )\r
                                        inPre = false;\r
 \r
+                               if ( currentNode.name == 'textarea' )\r
+                                       inTextarea = false;\r
+\r
                                if ( candidate._.isBlockLike )\r
                                        sendPendingBRs();\r
 \r
@@ -364,8 +385,8 @@ CKEDITOR.htmlParser.fragment = function()
 \r
                parser.onText = function( text )\r
                {\r
-                       // Trim empty spaces at beginning of text contents except <pre>.\r
-                       if ( ( !currentNode._.hasInlineStarted || pendingBRs.length ) && !inPre )\r
+                       // Trim empty spaces at beginning of text contents except <pre> and <textarea>.\r
+                       if ( ( !currentNode._.hasInlineStarted || pendingBRs.length ) && !inPre && !inTextarea )\r
                        {\r
                                text = CKEDITOR.tools.ltrim( text );\r
 \r
@@ -385,7 +406,7 @@ CKEDITOR.htmlParser.fragment = function()
 \r
                        // Shrinking consequential spaces into one single for all elements\r
                        // text contents.\r
-                       if ( !inPre )\r
+                       if ( !inPre && !inTextarea )\r
                                text = text.replace( /[\t\r\n ]{2,}|[\t\r\n]/g, ' ' );\r
 \r
                        currentNode.add( new CKEDITOR.htmlParser.text( text ) );\r