Index: _source/core/dtd.js =================================================================== --- _source/core/dtd.js (revision 3491) +++ _source/core/dtd.js (working copy) @@ -68,6 +68,8 @@ $body : X({script:1}, block), + $cdata : { script:1,style:1}, + /** * List of empty (self-closing) elements, like "br" or "img". * @type Object Index: _source/core/htmlparser.js =================================================================== --- _source/core/htmlparser.js (revision 3491) +++ _source/core/htmlparser.js (working copy) @@ -73,6 +73,20 @@ onText : function() {}, /** + * Function to be fired when CDATA section is found. This function + * should be overriden when using this class. + * @param {String} cdata The CDATA been found. + * @example + * var parser = new CKEDITOR.htmlParser(); + * parser.onCDATA = function( cdata ) + * { + * alert( cdata ); // e.g. "var hello;" + * }); + * parser.parse( "<script>var hello;</script>" ); + */ + onCDATA : function() {}, + + /** * Function to be fired when a commend is found. This function * should be overriden when using this class. * @param {String} comment The comment text. @@ -101,19 +115,27 @@ { var parts, tagName, - nextIndex = 0; + nextIndex = 0, + cdata; // The collected data inside a CDATA section. while ( ( parts = this._.htmlPartsRegex.exec( html ) ) ) { var tagIndex = parts.index; if ( tagIndex > nextIndex ) - this.onText( html.substring( nextIndex, tagIndex ) ); + { + var text = html.substring( nextIndex, tagIndex ); + if ( cdata ) + cdata.push( text ); + else + this.onText( text ); + } + nextIndex = this._.htmlPartsRegex.lastIndex; /* "parts" is an array with the following items: - 0 : The entire match (not used) + 0 : The entire match for opening/closing tags and comments. 1 : Group filled with the tag name for closing tags. 2 : Group filled with the comment text. 3 : Group filled with the tag name for opening tags. @@ -123,7 +145,26 @@ // Closing tag if ( ( tagName = parts[ 1 ] ) ) { - this.onTagClose( tagName.toLowerCase() ); + tagName = tagName.toLowerCase(); + + if ( cdata && CKEDITOR.dtd.$cdata[ tagName ] ) + { + // Send the CDATA data. + this.onCDATA( cdata.join('') ); + cdata = null; + } + + if ( !cdata ) + { + this.onTagClose( tagName ); + continue; + } + } + + // If CDATA is enabled, just save the raw match. + if ( cdata ) + { + cdata.push( parts[ 0 ] ); continue; } @@ -150,6 +191,11 @@ } this.onTagOpen( tagName.toLowerCase(), attribs, selfClosing ); + + // Open CDATA mode when finding the appropriate tags. + if ( !cdata && CKEDITOR.dtd.$cdata[ tagName ] ) + cdata = []; + continue; } Index: _source/core/htmlparser/cdata.js =================================================================== --- _source/core/htmlparser/cdata.js (revision 0) +++ _source/core/htmlparser/cdata.js (revision 0) @@ -0,0 +1,44 @@ +/* +Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. +For licensing, see LICENSE.html or http://ckeditor.com/license +*/ + +(function() +{ + + /** + * A lightweight representation of HTML text. + * @constructor + * @example + */ + CKEDITOR.htmlParser.cdata = function( value ) + { + /** + * The CDATA value. + * @type String + * @example + */ + this.value = value; + + }; + + CKEDITOR.htmlParser.cdata.prototype = + { + /** + * CDATA has the same type as {@link CKEDITOR.htmlParser.text} This is + * a constant value set to {@link CKEDITOR.NODE_TEXT}. + * @type Number + * @example + */ + type : CKEDITOR.NODE_TEXT, + + /** + * Writes write the CDATA with no special manipulations. + * @param {CKEDITOR.htmlWriter} writer The writer to which write the HTML. + */ + writeHtml : function( writer ) + { + writer.write( this.value ); + } + }; +})(); Index: _source/core/htmlparser/fragment.js =================================================================== --- _source/core/htmlparser/fragment.js (revision 3491) +++ _source/core/htmlparser/fragment.js (working copy) @@ -289,6 +289,11 @@ currentNode.add( new CKEDITOR.htmlParser.text( text ) ); }; + parser.onCDATA = function( cdata ) + { + currentNode.add( new CKEDITOR.htmlParser.cdata( cdata ) ); + }; + parser.onComment = function( comment ) { currentNode.add( new CKEDITOR.htmlParser.comment( comment ) ); Index: _source/core/loader.js =================================================================== --- _source/core/loader.js (revision 3491) +++ _source/core/loader.js (working copy) @@ -53,8 +53,9 @@ 'core/htmlparser' : [], 'core/htmlparser/comment' : [ 'core/htmlparser' ], 'core/htmlparser/element' : [ 'core/htmlparser', 'core/htmlparser/fragment' ], - 'core/htmlparser/fragment' : [ 'core/htmlparser', 'core/htmlparser/comment', 'core/htmlparser/text' ], + 'core/htmlparser/fragment' : [ 'core/htmlparser', 'core/htmlparser/comment', 'core/htmlparser/text', 'core/htmlparser/cdata' ], 'core/htmlparser/text' : [ 'core/htmlparser' ], + 'core/htmlparser/cdata' : [ 'core/htmlparser' ], 'core/htmlparser/filter' : [ 'core/htmlparser' ], 'core/htmlparser/basicwriter': [ 'core/htmlparser' ], 'core/imagecacher' : [ 'core/dom/element' ], Index: _source/tests/core/htmlparser/fragment.html =================================================================== --- _source/tests/core/htmlparser/fragment.html (revision 3491) +++ _source/tests/core/htmlparser/fragment.html (working copy) @@ -145,6 +145,12 @@ '
1
3
' ); }, + test_ticket_3441 : function() + { + testParser( 'Test