Ticket #4067: 4067_4.patch

File 4067_4.patch, 26.9 KB (added by Garry Yao, 10 years ago)
  • _source/plugins/htmlwriter/plugin.js

     
    6767
    6868                var dtd = CKEDITOR.dtd;
    6969
    70                 for ( var e in CKEDITOR.tools.extend( {}, dtd.$block, dtd.$listItem, dtd.$tableContent ) )
     70                for ( var e in CKEDITOR.tools.extend( {}, dtd.$nonBodyContent, dtd.$block, dtd.$listItem, dtd.$tableContent ) )
    7171                {
    7272                        this.setRules( e,
    7373                                {
  • _source/core/tools.js

     
    6363                {
    6464                        var clone;
    6565
    66                         // Array.
    67                         if ( obj && ( obj instanceof Array ) )
    68                         {
    69                                 clone = [];
    70 
    71                                 for ( var i = 0 ; i < obj.length ; i++ )
    72                                         clone[ i ] = this.clone( obj[ i ] );
    73 
    74                                 return clone;
    75                         }
    76 
    7766                        // "Static" types.
    7867                        if ( obj === null
    7968                                || ( typeof( obj ) != 'object' )
    8069                                || ( obj instanceof String )
    8170                                || ( obj instanceof Number )
    8271                                || ( obj instanceof Boolean )
    83                                 || ( obj instanceof Date ) )
     72                                || ( obj instanceof Date )
     73                                || ( obj instanceof RegExp ) )
    8474                        {
    8575                                return obj;
    8676                        }
  • _source/core/htmlparser/element.js

     
    3535        this.children = [];
    3636
    3737        var dtd                 = CKEDITOR.dtd,
    38                 isBlockLike     = !!( dtd.$block[ name ] || dtd.$listItem[ name ] || dtd.$tableContent[ name ] || dtd.$nonEditable[ name ] || name == 'br' ),
     38                isBlockLike     = !!( dtd.$nonBodyContent[ name ] || dtd.$block[ name ] || dtd.$listItem[ name ] || dtd.$tableContent[ name ] || dtd.$nonEditable[ name ] || name == 'br' ),
    3939                isEmpty         = !!dtd.$empty[ name ];
    4040
    4141        this.isEmpty    = isEmpty;
  • _source/plugins/wysiwygarea/plugin.js

     
    1515         */
    1616        var nonExitableElementNames = { table:1,pre:1 };
    1717        // Matching an empty paragraph at the end of document.
    18         var emptyParagraphRegexp = /\s*<(p|div|address|h\d|center)[^>]*>\s*(?:<br[^>]*>|&nbsp;|\u00A0|&#160;)\s*(:?<\/\1>)?\s*$/gi;
     18        var emptyParagraphRegexp = /\s*<(p|div|address|h\d|center)[^>]*>\s*(?:<br[^>]*>|&nbsp;|\u00A0|&#160;)\s*(:?<\/\1>)?\s*(?=$|<\/body>)/gi;
    1919
    2020        function onInsertHtml( evt )
    2121        {
     
    555555
    556556                                                                // Get the HTML version of the data.
    557557                                                                if ( editor.dataProcessor )
    558                                                                 {
    559                                                                         data = editor.dataProcessor.toHtml( data, fixForBody );
    560                                                                 }
     558                                                                        data = editor.dataProcessor.toFullPageHtml( data, fixForBody );
    561559
    562                                                                 data =
    563                                                                         editor.config.docType +
    564                                                                         '<html dir="' + editor.config.contentsLangDirection + '">' +
    565                                                                         '<head>' +
    566                                                                                 '<link type="text/css" rel="stylesheet" href="' +
    567                                                                                 [].concat( editor.config.contentsCss ).join( '"><link type="text/css" rel="stylesheet" href="' ) +
    568                                                                                 '">' +
    569                                                                                 '<style type="text/css" _fcktemp="true">' +
    570                                                                                         editor._.styles.join( '\n' ) +
    571                                                                                 '</style>'+
    572                                                                         '</head>' +
    573                                                                         '<body>' +
    574                                                                                 data +
    575                                                                         '</body>' +
    576                                                                         '</html>' +
    577                                                                         activationScript;
     560                                                                if( !editor.config.fullPage )
     561                                                                {
     562                                                                        data =
     563                                                                                editor.config.docType +
     564                                                                                '<html dir="' + editor.config.contentsLangDirection + '">' +
     565                                                                                '<head>' +
     566                                                                                        '<link type="text/css" rel="stylesheet" href="' +
     567                                                                                        [].concat( editor.config.contentsCss ).join( '"><link type="text/css" rel="stylesheet" href="' ) +
     568                                                                                        '">' +
     569                                                                                        '<style type="text/css" _fcktemp="true">' +
     570                                                                                                editor._.styles.join( '\n' ) +
     571                                                                                        '</style>'+
     572                                                                                '</head>' +
     573                                                                                '<body>' +
     574                                                                                        data +
     575                                                                                '</body>' +
     576                                                                                '</html>';
     577                                                                }
    578578
     579                                                                data += activationScript;
     580
    579581                                                                window[ '_cke_htmlToLoad_' + editor.name ] = data;
    580582                                                                CKEDITOR._[ 'contentDomReady' + editor.name ] = contentDomReady;
    581583                                                                createIFrame();
     
    592594
    593595                                                        getData : function()
    594596                                                        {
    595                                                                 var data = iframe.getFrameDocument().getBody().getHtml();
     597                                                                var frameDoc = iframe.getFrameDocument(),
     598                                                                        documentElement = frameDoc.getDocumentElement(),
     599                                                                        data = editor.config.fullPage ? documentElement.getOuterHtml() : frameDoc.getBody().getHtml();
    596600
    597601                                                                if ( editor.dataProcessor )
    598                                                                         data = editor.dataProcessor.toDataFormat( data, fixForBody );
     602                                                                        data = editor.dataProcessor.toFullPageData( data, fixForBody );
    599603
    600604                                                                // Strip the last blank paragraph within document.
    601605                                                                if ( editor.config.ignoreEmptyParagraph )
     
    673677                                                        }
    674678                                                } ) + ')' );
    675679                        }
    676                 } )();
     680})();
    677681
    678682        }
    679683})();
  • _source/core/dom/element.js

     
    328328                 */
    329329                getHtml : function()
    330330                {
    331                         return this.$.innerHTML;
     331                        var retval = this.$.innerHTML;
     332                        // Strip <?xml:namespace> tag in the output HTML of
     333                        // namespaced element in IE(#3341).
     334                        return CKEDITOR.env.ie ? retval.replace( /<\?[^>]*>/g, '' ) : retval;
    332335                },
    333336
    334337                getOuterHtml : function()
  • _source/core/htmlparser/filter.js

     
    4545
    4646                                // Add the comment.
    4747                                this._.comment = transformNamedItem( this._.comment, rules.comment, priority ) || this._.comment;
     48
     49                                // Add root fragment.
     50                                this._.root = transformNamedItem( this._.root, rules.root, priority ) || this._.root;
    4851                        },
    4952
    5053                        onElementName : function( name )
     
    6972                                return textFilter ? textFilter.filter( commentText ) : commentText;
    7073                        },
    7174
     75                        onFragment : function( element )
     76                        {
     77                                var rootFilter = this._.root;
     78                                return rootFilter ? rootFilter.filter( element ) : element;
     79                        },
     80
    7281                        onElement : function( element )
    7382                        {
    7483                                // We must apply filters set to the specific element name as
     
    111120                                }
    112121
    113122                                return value;
     123                        },
     124
     125                        clone : function()
     126                        {
     127                                var clone = new CKEDITOR.htmlParser.filter();
     128                                // Shallow copy all the rules.
     129                                clone._ = CKEDITOR.tools.clone( this._ );
     130                                return clone;
    114131                        }
    115132                }
    116133        });
  • _source/plugins/fullpage/plugin.js

     
     1/*
     2Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved.
     3For licensing, see LICENSE.html or http://ckeditor.com/license
     4*/
     5
     6/**
     7 * @fileOverview The "wysiwygarea" plugin. It registers the "wysiwyg" editing
     8 *              mode, which handles the main editing area space.
     9 */
     10
     11( function()
     12{
     13        var docTypeRegex = /<!DOCTYPE[^>]*>\s*/i;
     14       
     15        var dtd = CKEDITOR.dtd;
     16        CKEDITOR.plugins.add( 'fullpage',
     17        {
     18                requires : [ 'htmldataprocessor' ],
     19                afterInit : function( editor )
     20                {
     21                        if( editor.config.fullPage )
     22                        {
     23                                var fullPageDataFilterRules =
     24                                {
     25                                        root : function( element )
     26                                        {
     27                                                // Adding missing parts of full page.
     28                                                var firstChild = element.children[ 0 ];
     29                                                // Full document.
     30                                                if ( firstChild && firstChild.name == 'html' )
     31                                                        return;
     32                                                // Missing <html>.
     33                                                if ( !firstChild || firstChild.name in dtd.html )
     34                                                        wrapContent( element, 'html' );
     35                                                // Missing <html> and <body>/<head>.
     36                                                else
     37                                                {
     38                                                        wrapContent( wrapContent( element, 'html' ),
     39                                                                        firstChild.name in dtd.head ? 'head' : 'body' );
     40                                                }
     41                                        },
     42
     43                                        // Full page support. ( #4067 )
     44                                        elements :
     45                                        {
     46                                                html : function ( element )
     47                                                {
     48                                                        // Both <head> and <body> are mandatory.
     49                                                        if ( !childByTagName( element, 'head' ) )
     50                                                                element.children.splice( 0, 0, new CKEDITOR.htmlParser.element( 'head', {} ) );
     51                                                        if ( !childByTagName( element, 'body' ) )
     52                                                                element.children.splice( element.children.length, 0, new CKEDITOR.htmlParser.element( 'body', {} ) );
     53
     54                                                        // 1. Save doc-type as a custom attribute;
     55                                                        // 2. Adding missing xml namespace attribute;
     56                                                        // 3. Adding missing language direction attribute.
     57                                                        var attrs = element.attributes,
     58                                                                        configDir = editor.config.contentsLangDirection;
     59                                                        if( docType )
     60                                                        {
     61                                                                attrs.cke_doctype = encodeURIComponent( docType );
     62                                                                docType.match( /xhtml/i )
     63                                                                                && !attrs.xmlns
     64                                                                                && ( attrs.xmlns = 'http://www.w3.org/1999/xhtml' );
     65                                                                !attrs.dir && configDir && ( attrs.dir = configDir );
     66                                                        }
     67                                                },
     68
     69                                                head : function ( element )
     70                                                {
     71                                                        // <title> is mandatory.
     72                                                        if ( !childByTagName( element, 'title' ) )
     73                                                                element.children.splice( 0, 0, new CKEDITOR.htmlParser.element( 'title', {} ) );
     74
     75                                                        // Adding default styles.
     76                                                        var styleLinks = [].concat( editor.config.contentsCss ),
     77                                                                        styleText = editor._.styles.join( '\n' );
     78
     79                                                        if ( styleLinks )
     80                                                        {
     81                                                                for ( var i = 0; i < styleLinks.length; i++ )
     82                                                                {
     83                                                                        var link = new CKEDITOR.htmlParser.element( 'link',
     84                                                                        {
     85                                                                                type: 'text/css' ,
     86                                                                                rel : 'stylesheet',
     87                                                                                href : styleLinks[ i ],
     88                                                                                cke_temp : 1
     89                                                                        } );
     90                                                                        element.add( link );
     91                                                                }
     92                                                        }
     93                                                        if ( styleText )
     94                                                        {
     95                                                                var style = new CKEDITOR.htmlParser.element( 'style',
     96                                                                {
     97                                                                        type: 'text/css',
     98                                                                        cke_temp : 1
     99                                                                } );
     100                                                                style.add( new CKEDITOR.htmlParser.text( styleText ) );
     101                                                                element.add( style );
     102                                                        }
     103                                                }
     104                                        }
     105                                };
     106
     107                                var fullPageHtmlFilterRules =
     108                                {
     109                                        elements :
     110                                        {
     111                                                html : function ( element )
     112                                                {
     113                                                        var attrs = element.attributes,
     114                                                                docTypeAttr = attrs.cke_doctype;
     115
     116                                                        if( docTypeAttr )
     117                                                        {
     118                                                                docType = decodeURIComponent( docTypeAttr );
     119                                                                delete attrs.cke_doctype;
     120                                                        }
     121                                                },
     122
     123                                                body : function( element )
     124                                                {
     125                                                        delete element.attributes.spellcheck;
     126                                                        delete element.attributes.contenteditable;
     127                                                },
     128                                                // Elements used interally in 'wysiwyg' mode shouldn't appear in output.
     129                                                style : removeInternal,
     130                                                link : removeInternal
     131                                        },
     132                                        attributeNames :
     133                                        [
     134                                                [ 'hidefocus', '' ]
     135                                        ]
     136                                };
     137
     138                                var dataProcessor = editor.dataProcessor;
     139                                dataProcessor.fullPageDataFilter.addRules( fullPageDataFilterRules );
     140                                dataProcessor.fullPageHtmlFilter.addRules( fullPageHtmlFilterRules );
     141
     142                                var docType = editor.config.docType;
     143
     144                                function removeDocType( evt )
     145                                {
     146                                        var data = evt.data;
     147                                        // Record and sweep the doc-type declaration.
     148                                        evt.data = data.replace( docTypeRegex, function( match )
     149                                        {
     150                                                docType = match;
     151                                                return '';
     152                                        } );
     153                                }
     154
     155                                function prependDocType( evt )
     156                                {
     157                                        // Prepend doc type to final data format.
     158                                        if( docType )
     159                                                evt.data = docType + '\n' + evt.data;
     160                                }
     161
     162                                // Properly apply doc-type on html or vice versa.
     163                                dataProcessor.on( 'fullPageHtmlPreProcess', removeDocType );
     164                                dataProcessor.on( 'fullPageHtmlPostProcess', prependDocType );
     165                                dataProcessor.on( 'fullPageDataPostProcess', prependDocType );
     166                        }
     167                }
     168        } );
     169
     170        function removeInternal( element )
     171        {
     172                if( element.attributes.cke_temp )
     173                        return false;
     174        }
     175
     176        function childByTagName( element, tagName )
     177        {
     178                var children = element.children,
     179                        child;
     180                for ( var i = 0; i < children.length; i++ )
     181                {
     182                        child = children[ i ];
     183                        if( child.name && child.name == tagName )
     184                                return child;
     185                }
     186        }
     187        function wrapContent( element, tagName )
     188        {
     189                var childrens = element.children,
     190                        root = new CKEDITOR.htmlParser.element( tagName, {} );
     191                element.children = [];
     192                element.add( root );
     193                for ( var i = 0; i < childrens.length; i++ )
     194                {
     195                        root.add( childrens[ i ] );
     196                }
     197                return root;
     198        }
     199
     200} )();
  • _source/core/config.js

     
    198198         * @type String
    199199         * @example
    200200         */
    201         plugins : 'about,basicstyles,blockquote,button,clipboard,colorbutton,colordialog,contextmenu,elementspath,enterkey,entities,filebrowser,find,flash,font,format,forms,horizontalrule,htmldataprocessor,image,indent,justify,keystrokes,link,list,maximize,newpage,pagebreak,pastefromword,pastetext,popup,preview,print,removeformat,resize,save,scayt,smiley,showblocks,sourcearea,stylescombo,table,tabletools,specialchar,tab,templates,toolbar,undo,wysiwygarea,wsc',
     201        plugins : 'about,basicstyles,blockquote,button,clipboard,colorbutton,colordialog,contextmenu,elementspath,enterkey,entities,filebrowser,find,flash,font,format,forms,fullpage,horizontalrule,htmldataprocessor,image,indent,justify,keystrokes,link,list,maximize,newpage,pagebreak,pastefromword,pastetext,popup,preview,print,removeformat,resize,save,scayt,smiley,showblocks,sourcearea,stylescombo,table,tabletools,specialchar,tab,templates,toolbar,undo,wysiwygarea,wsc',
    202202
    203203        /**
    204204         * List of additional plugins to be loaded. This is a tool setting which
  • _source/core/dtd.js

     
    5151                N = {'#':1},
    5252                O = X({param:1},K),
    5353                P = X({form:1},A,D,E,I),
    54                 Q = {li:1};
     54                Q = {li:1},
     55        R = {style:1,script:1},
     56        S = {base:1,link:1,meta:1,title:1},
     57                T = X(S,R),
     58                U = {head:1,body:1},
     59                V = {html:1};
    5560
    56         var block = {address:1,blockquote:1,center:1,dir:1,div:1,dl:1,fieldset:1,form:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,hr:1,isindex:1,menu:1,noframes:1,ol:1,p:1,pre:1,table:1,ul:1};
     61        var block = {address:1,blockquote:1,center:1,dir:1,div:1,dl:1,fieldset:1,form:1,h1:1,h2:1,h3:1,h4:1,h5:1,h6:1,hr:1,isindex:1,menu:1,noframes:1,ol:1,p:1,pre:1,table:1,ul:1},
     62                inline = {a:1,abbr:1,acronym:1,b:1,basefont:1,bdo:1,big:1,br:1,cite:1,code:1,dfn:1,em:1,font:1,i:1,img:1,input:1,kbd:1,label:1,q:1,s:1,samp:1,select:1,small:1,span:1,strike:1,strong:1,sub:1,sup:1,textarea:1,tt:1,u:1,'var':1,applet:1,button:1,del:1,iframe:1,ins:1,map:1,object:1,script:1};
    5763
    5864    return /** @lends CKEDITOR.dtd */ {
    5965
    6066                // The "$" items have been added manually.
    6167
    62                 /**
     68            $ : V,
     69
     70            // List of elements living outside body.
     71            $nonBodyContent: X(V,U,S),
     72
     73            /**
    6374                 * List of block elements, like "p" or "div".
    6475                 * @type Object
    6576                 * @example
    6677                 */
    6778                $block : block,
    6879
    69                 $body : X({script:1}, block),
     80                $body : X({script:1,style:1}, block),
    7081
    7182                $cdata : {script:1,style:1},
    7283
     
    120131                 */
    121132                $tableContent : {caption:1,col:1,colgroup:1,tbody:1,td:1,tfoot:1,th:1,thead:1,tr:1},
    122133
    123         col : {},
     134        html: U,
     135            head: T,
     136            style: N,
     137            script: N,
     138            body: X(inline, block),
     139            col : {},
    124140        tr : {td:1,th:1},
    125141        img : {},
    126142        colgroup : {col:1},
     
    200216        pre : X(G,C),
    201217        p : L,
    202218        em : L,
    203         dfn : L
     219        dfn : L,
     220            base: {},
     221                link: {},
     222            meta: {},
     223            title: N
    204224    };
    205225})();
    206226
  • _source/core/htmlparser/basicwriter.js

     
    117117                reset : function()
    118118                {
    119119                        this._.output = [];
     120                        this._.indent = false;
    120121                },
    121122
    122123                /**
  • _source/core/htmlparser/fragment.js

     
    114114                                        elementName = realElementName;
    115115                                else
    116116                                        elementName =  element.name;
    117                                 if ( !( elementName in CKEDITOR.dtd.$body ) )
     117                                if ( elementName
     118                                                && !( elementName in CKEDITOR.dtd.$body )
     119                                                && !( elementName in CKEDITOR.dtd.$nonBodyContent )  )
    118120                                {
    119121                                        var savedCurrent = currentNode;
    120122
     
    180182                        }
    181183
    182184                        var currentName = currentNode.name,
    183                                 currentDtd = ( currentName && CKEDITOR.dtd[ currentName ] ) || ( currentNode._.isBlockLike ? CKEDITOR.dtd.div : CKEDITOR.dtd.span );
     185                                currentDtd = currentName &&
     186                                             ( CKEDITOR.dtd[ currentName ]
     187                                                       || ( currentNode._.isBlockLike ? CKEDITOR.dtd.div : CKEDITOR.dtd.span ) );
    184188
    185189                        // If the element cannot be child of the current element.
    186                         if ( !element.isUnknown && !currentNode.isUnknown && !currentDtd[ tagName ] )
     190                        if ( currentDtd   // Fragment could receive any elements.
     191                                 && !element.isUnknown && !currentNode.isUnknown && !currentDtd[ tagName ] )
    187192                        {
    188                                 // If this is the fragment node, just ignore this tag and add
    189                                 // its children.
    190                                 if ( !currentName )
    191                                         return;
    192193
    193194                                var reApply = false,
    194195                                        addPoint;   // New position to start adding nodes.
     
    330331                                        index--;
    331332                                }
    332333                        }
     334
     335                        if( tagName == 'body' )
     336                                fixForBody = false;
    333337                };
    334338
    335339                parser.onText = function( text )
     
    345349
    346350                        checkPending();
    347351
    348                         if ( fixForBody && !currentNode.type )
     352                        if ( fixForBody
     353                                 && CKEDITOR.tools.trim( text )
     354                                 && ( !currentNode.type || currentNode.name == 'body' ) )
    349355                                this.onTagOpen( fixForBody, {} );
    350356
    351357                        // Shrinking consequential spaces into one single for all elements
     
    375381                        var parent = currentNode.parent,
    376382                                node = currentNode;
    377383
    378                         if ( fixForBody && !parent.type && !CKEDITOR.dtd.$body[ node.name ] )
     384                        if ( fixForBody
     385                                 && ( !parent.type || parent.name == 'body' )
     386                                 && !CKEDITOR.dtd.$body[ node.name ] )
    379387                        {
    380388                                currentNode = parent;
    381389                                parser.onTagOpen( fixForBody, {} );
     
    444452                 */
    445453                writeHtml : function( writer, filter )
    446454                {
     455                        // Filtering the root fragment.
     456                        if ( !this.name )
     457                                filter && filter.onFragment( this );
     458
    447459                        for ( var i = 0, len = this.children.length ; i < len ; i++ )
    448460                                this.children[i].writeHtml( writer, filter );
    449461                }
  • _source/plugins/htmldataprocessor/plugin.js

     
    206206                return html.replace( protectAttributeRegex, '$& _cke_saved_$1' );
    207207        }
    208208
    209         var protectStyleTagsRegex = /<(style)(?=[ >])[^>]*>[^<]*<\/\1>/gi;
    210         var encodedTagsRegex = /<cke:encoded>([^<]*)<\/cke:encoded>/gi;
     209        var protectTagContentsRegex = /<(style)(?=[ >])[^>]*>[^<]*<\/\1>|<(:?link|meta|base).*?>/gi,
     210                encodedTagsRegex = /<cke:encoded>([^<]*)<\/cke:encoded>/gi;
     211
     212        var shelveTagNamesRegex = /(<\/?)((?:html|body|head|title).*?>)/gi,
     213                unshelveTagNamesRegex = /(<\/?)cke_shelved:([^>]*>)/gi;
     214
    211215        var protectElementNamesRegex = /(<\/?)((?:object|embed|param)[\s\S]*?>)/gi;
    212216        var protectSelfClosingRegex = /<cke:(param|embed)([\s\S]*?)\/?>/gi;
    213217
    214         function protectStyleTagsMatch( match )
     218        function encodeMatched( match )
    215219        {
    216220                return '<cke:encoded>' + encodeURIComponent( match ) + '</cke:encoded>';
    217221        }
     222        function unprotectEncodedTagsMatch( match, encoded )
     223        {
     224                return decodeURIComponent( encoded );
     225        }
    218226
    219         function protectStyleTags( html )
     227        function protectTagContents( html )
    220228        {
    221                 return html.replace( protectStyleTagsRegex, protectStyleTagsMatch );
     229                return html.replace( protectTagContentsRegex, encodeMatched );
    222230        }
    223         function protectElementsNames( html )
     231        function unprotectTagContents( html )
    224232        {
    225                 return html.replace( protectElementNamesRegex, '$1cke:$2');
     233                return html.replace( encodedTagsRegex, unprotectEncodedTagsMatch );
    226234        }
    227         function protectSelfClosingElements( html )
     235
     236        function shelveTagNames( html, isUnShelve )
    228237        {
    229                 return html.replace( protectSelfClosingRegex, '<cke:$1$2></cke:$1>' );
     238                return html.replace( shelveTagNamesRegex, '$1cke_shelved:$2' );
    230239        }
    231240
    232         function unprotectEncodedTagsMatch( match, encoded )
     241        function unShelveTagNames( html )
    233242        {
    234                 return decodeURIComponent( encoded );
     243                return html.replace( unshelveTagNamesRegex, '$1$2' );
    235244        }
    236245
    237         function unprotectEncodedTags( html )
     246        function protectElementsNames( html )
    238247        {
    239                 return html.replace( encodedTagsRegex, unprotectEncodedTagsMatch );
     248                return html.replace( protectElementNamesRegex, '$1cke:$2');
    240249        }
     250        function protectSelfClosingElements( html )
     251        {
     252                return html.replace( protectSelfClosingRegex, '<cke:$1$2></cke:$1>' );
     253        }
    241254
    242255        function protectSource( data, protectRegexes )
    243256        {
     
    295308                        dataProcessor.dataFilter.addRules( defaultDataBlockFilterRules );
    296309                        dataProcessor.htmlFilter.addRules( defaultHtmlFilterRules );
    297310                        dataProcessor.htmlFilter.addRules( defaultHtmlBlockFilterRules );
    298                 }
    299         });
    300311
    301         CKEDITOR.htmlDataProcessor = function( editor )
    302         {
    303                 this.editor = editor;
     312                        // Full page specialized filters.
     313                        dataProcessor.fullPageHtmlFilter = dataProcessor.htmlFilter.clone();
     314                        dataProcessor.fullPageDataFilter = dataProcessor.dataFilter.clone();
    304315
    305                 this.writer = new CKEDITOR.htmlWriter();
    306                 this.dataFilter = new CKEDITOR.htmlParser.filter();
    307                 this.htmlFilter = new CKEDITOR.htmlParser.filter();
    308         };
    309 
    310         CKEDITOR.htmlDataProcessor.prototype =
    311         {
    312                 toHtml : function( data, fixForBody )
    313                 {
    314                         // The source data is already HTML, but we need to clean
    315                         // it up and apply the filter.
    316 
    317                         data = protectSource( data, this.editor.config.protectedSource );
     316                        // The source data is already HTML, but we need to clean it up.
     317                        dataProcessor.on( 'htmlPreProcess', function( evt )
     318                        {
     319                                var data = evt.data;
     320                                data = protectSource( data, this.editor.config.protectedSource );
    318321
    319                         // Before anything, we must protect the URL attributes as the
    320                         // browser may changing them when setting the innerHTML later in
    321                         // the code.
    322                         data = protectAttributes( data );
     322                                // Before anything, we must protect the URL attributes as the
     323                                // browser may changing them when setting the innerHTML later in
     324                                // the code.
     325                                data = protectAttributes( data );
    323326
    324                         // IE remvoes style tags from innerHTML. (#3710).
    325                         if ( CKEDITOR.env.ie )
    326                                 data = protectStyleTags( data );
     327                                // IE remvoes style tags from innerHTML. (#3710).
     328                                if ( CKEDITOR.env.ie )
     329                                        data = protectTagContents( data );
    327330
    328                         // Certain elements has problem to go through DOM operation, protect
    329                         // them by prefixing 'cke' namespace.(#3591)
    330                         data = protectElementsNames( data );
     331                                // Certain elements has problem to go through DOM operation, protect
     332                                // them by prefixing 'cke' namespace.(#3591)
     333                                data = protectElementsNames( data );
    331334
    332                         // All none-IE browsers ignore self-closed custom elements,
    333                         // protecting them into open-close.(#3591)
    334                         data = protectSelfClosingElements( data );
     335                                // All none-IE browsers ignore self-closed custom elements,
     336                                // protecting them into open-close.(#3591)
     337                                data = protectSelfClosingElements( data );
    335338
    336                         // Call the browser to help us fixing a possibly invalid HTML
    337                         // structure.
    338                         var div = document.createElement( 'div' );
    339                         // Add fake character to workaround IE comments bug. (#3801)
    340                         div.innerHTML = 'a' + data;
    341                         data = div.innerHTML.substr( 1 );
     339                                data = shelveTagNames( data );
     340                                // Call the browser to help us fixing a possibly invalid HTML
     341                                // structure.
     342                                var div = new CKEDITOR.dom.element( 'div' );
     343                                // Add fake character to workaround IE comments bug. (#3801)
     344                                div.setHtml( 'a' + data );
     345                                data = div.getHtml().substr( 1 );
    342346
    343                         if ( CKEDITOR.env.ie )
    344                                 data = unprotectEncodedTags( data );
     347                                data = unShelveTagNames( data );
     348                                if ( CKEDITOR.env.ie )
     349                                        data = unprotectTagContents( data );
    345350
    346                         // Now use our parser to make further fixes to the structure, as
    347                         // well as apply the filter.
    348                         var fragment = CKEDITOR.htmlParser.fragment.fromHtml( data, fixForBody ),
    349                                 writer = new CKEDITOR.htmlParser.basicWriter();
     351                                evt.data = data;
     352                        } );
     353                }
     354        });
    350355
    351                         fragment.writeHtml( writer, this.dataFilter );
     356        CKEDITOR.htmlDataProcessor = function( editor )
     357        {
     358                this.editor = editor;
    352359
    353                         return writer.getHtml( true );
    354                 },
     360                this.writer = new CKEDITOR.htmlWriter();
     361                this.basicWriter = new CKEDITOR.htmlParser.basicWriter();
     362                this.dataFilter = new CKEDITOR.htmlParser.filter();
     363                this.htmlFilter = new CKEDITOR.htmlParser.filter();
     364        };
    355365
    356                 toDataFormat : function( html, fixForBody )
    357                 {
    358                         var writer = this.writer,
    359                                 fragment = CKEDITOR.htmlParser.fragment.fromHtml( html, fixForBody );
     366        CKEDITOR.htmlDataProcessor.prototype =
     367        {
     368                process : function( type, data, filter, writer, fixForBody )
     369                {
     370                        data = this.fire( type + 'PreProcess', data );
    360371
     372                        // Now use our parser to make fixes to the structure, as
     373                        // well as apply the filter.
     374                        var fragment = CKEDITOR.htmlParser.fragment.fromHtml( data, fixForBody );
    361375                        writer.reset();
     376                        fragment.writeHtml( writer, filter );
     377                        data = writer.getHtml( true );
    362378
    363                         fragment.writeHtml( writer, this.htmlFilter );
     379                        return this.fire( type + 'PostProcess', data );
     380                },
    364381
    365                         return writer.getHtml( true );
     382                toFullPageHtml : function( data, fixForBody )
     383                {
     384                        data = this.fire( 'fullPageHtmlPreProcess', data );
     385                        data = this.process( 'html', data, this.fullPageDataFilter, this.basicWriter, fixForBody );
     386                        return this.fire( 'fullPageHtmlPostProcess', data )
     387                },
     388
     389                toFullPageData : function( data, fixForBody )
     390                {
     391                        data = this.fire( 'fullPageDataPreProcess', data );
     392                        data = this.process( 'dataFormat', data, this.fullPageHtmlFilter, this.writer, fixForBody );
     393                        return this.fire( 'fullPageDataPostProcess', data );
     394                },
     395
     396                toHtml : function( data, fixForBody )
     397                {
     398                        return this.process( 'html', data, this.dataFilter, this.basicWriter, fixForBody );
     399                },
     400
     401                toDataFormat : function( html, fixForBody )
     402                {
     403                        return this.process( 'dataFormat', html, this.htmlFilter, this.writer, fixForBody );
    366404                }
    367405        };
     406
     407        CKEDITOR.event.implementOn( CKEDITOR.htmlDataProcessor.prototype, true );
    368408})();
    369409
    370410/**
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy