Ticket #2886: 2886_3.patch

File 2886_3.patch, 10.5 KB (added by Martin Kou, 10 years ago)
  • _source/plugins/htmldataprocessor/plugin.js

     
    55
    66(function()
    77{
     8        function extendBlocksForDisplay( block )
     9        {
     10                if ( !block.addedBlockExtensor )
     11                {
     12                        if ( !CKEDITOR.env.ie )
     13                                block.children.push( new CKEDITOR.htmlParser.element( 'br', {} ) );
     14                        else
     15                                block.children.push( new CKEDITOR.htmlParser.text( '\xa0' ) );
     16
     17                        block.addedBlockExtensor = true;
     18                }
     19        }
     20
     21        function extendBlocksForOutput( block )
     22        {
     23                block.children.push( new CKEDITOR.htmlParser.text( '\xa0' ) );
     24        }
     25
    826        var defaultDataFilterRules =
    927        {
    1028                elementNames :
     
    1836                        // Event attributes (onXYZ) must not be directly set. They can become
    1937                        // active in the editing area (IE|WebKit).
    2038                        [ ( /^on/ ), '_cke_pa_on' ]
    21                 ]
     39                ],
     40
     41                lastNodeOfBlock :
     42                {
     43                        br : extendBlocksForDisplay
     44                },
     45
     46                emptyBlock :
     47                {
     48                        $ : extendBlocksForDisplay
     49                }
    2250        };
    2351
    2452        /**
     
    3361        };
    3462
    3563        var defaultHtmlFilterRules =
    36                 {
    37                         elementNames :
    38                         [
    39                                 // Remove the "cke:" namespace prefix.
    40                                 [ ( /^cke:/ ), '' ],
     64        {
     65                elementNames :
     66                [
     67                        // Remove the "cke:" namespace prefix.
     68                        [ ( /^cke:/ ), '' ],
    4169
    42                                 // Ignore <?xml:namespace> tags.
    43                                 [ ( /^\?xml:namespace$/ ), '' ]
    44                         ],
     70                        // Ignore <?xml:namespace> tags.
     71                        [ ( /^\?xml:namespace$/ ), '' ]
     72                ],
    4573
    46                         attributeNames :
    47                         [
    48                                 // Attributes saved for changes and protected attributes.
    49                                 [ ( /^_cke_(saved|pa)_/ ), '' ],
     74                attributeNames :
     75                [
     76                        // Attributes saved for changes and protected attributes.
     77                        [ ( /^_cke_(saved|pa)_/ ), '' ],
    5078
    51                                 // All "_cke" attributes are to be ignored.
    52                                 [ ( /^_cke.*/ ), '' ]
    53                         ],
     79                        // All "_cke" attributes are to be ignored.
     80                        [ ( /^_cke.*/ ), '' ]
     81                ],
    5482
    55                         elements :
     83                elements :
     84                {
     85                        embed : function( element )
    5686                        {
    57                                 embed : function( element )
    58                                 {
    59                                         var parent = element.parent;
     87                                var parent = element.parent;
    6088
    61                                         // If the <embed> is child of a <object>, copy the width
    62                                         // and height attributes from it.
    63                                         if ( parent && parent.name == 'object' )
    64                                         {
    65                                                 element.attributes.width = parent.attributes.width;
    66                                                 element.attributes.height = parent.attributes.height;
    67                                         }
    68                                 },
    69 
    70                                 img : function( element )
     89                                // If the <embed> is child of a <object>, copy the width
     90                                // and height attributes from it.
     91                                if ( parent && parent.name == 'object' )
    7192                                {
    72                                         var attribs = element.attributes;
     93                                        element.attributes.width = parent.attributes.width;
     94                                        element.attributes.height = parent.attributes.height;
     95                                }
     96                        },
    7397
    74                                         if ( attribs._cke_saved_name )
    75                                                 delete attribs.name;
    76                                         if ( attribs._cke_saved_src )
    77                                                 delete attribs.src;
    78                                 },
     98                        img : function( element )
     99                        {
     100                                var attribs = element.attributes;
    79101
    80                                 a : function( element )
    81                                 {
    82                                         var attribs = element.attributes;
     102                                if ( attribs._cke_saved_name )
     103                                        delete attribs.name;
     104                                if ( attribs._cke_saved_src )
     105                                        delete attribs.src;
     106                        },
    83107
    84                                         if ( attribs._cke_saved_name )
    85                                                 delete attribs.name;
    86                                         if ( attribs._cke_saved_href )
    87                                                 delete attribs.href;
    88                                 },
     108                        a : function( element )
     109                        {
     110                                var attribs = element.attributes;
    89111
    90                                 input : removeName,
    91                                 textarea : removeName,
    92                                 select : removeName,
    93                                 form : removeName
     112                                if ( attribs._cke_saved_name )
     113                                        delete attribs.name;
     114                                if ( attribs._cke_saved_href )
     115                                        delete attribs.href;
    94116                        },
    95117
    96                         attributes :
     118                        input : removeName,
     119                        textarea : removeName,
     120                        select : removeName,
     121                        form : removeName
     122                },
     123
     124                attributes :
     125                {
     126                        'class' : function( value, element )
    97127                        {
    98                                 'class' : function( value, element )
    99                                 {
    100                                         // Remove all class names starting with "cke_".
    101                                         return CKEDITOR.tools.ltrim( value.replace( /(?:^|\s+)cke_[^\s]*/g, '' ) ) || false;
    102                                 }
     128                                // Remove all class names starting with "cke_".
     129                                return CKEDITOR.tools.ltrim( value.replace( /(?:^|\s+)cke_[^\s]*/g, '' ) ) || false;
    103130                        }
    104                 };
     131                },
    105132
     133                lastNodeOfBlock :
     134                {
     135                        br : extendBlocksForOutput
     136                },
     137
     138                emptyBlock :
     139                {
     140                        $ : extendBlocksForOutput
     141                }
     142        };
     143
    106144        if ( CKEDITOR.env.ie )
    107145        {
    108146                // IE outputs style attribute in capital letters. We should convert
  • _source/core/htmlparser/filter.js

     
    55
    66(function()
    77{
     8        function applyElementFilter( filters, element, filterArgs, callback )
     9        {
     10                var filter, ret;
     11
     12                for ( var i = 0 ; i < 2 ; i++ )
     13                {
     14                        filter = filters[ i ];
     15                        if ( filter )
     16                        {
     17                                ret = filter.filter.apply( filter, filterArgs );
     18
     19                                if ( ret === false )
     20                                        return null;
     21
     22                                if ( ret && ret != block )
     23                                        return callback.call( this, ret );
     24                        }
     25                }
     26
     27                return element;
     28        }
     29
    830        CKEDITOR.htmlParser.filter = CKEDITOR.tools.createClass(
    931        {
    1032                $ : function( rules )
     
    1436                                elementNames : [],
    1537                                attributeNames : [],
    1638                                elements : { $length : 0 },
    17                                 attributes : { $length : 0 }
     39                                attributes : { $length : 0 },
     40                                lastNodeOfBlock : { $length : 0 },
     41                                emptyBlock : { $length : 0 }
    1842                        };
    1943
    2044                        if ( rules )
     
    4064                                // Add the attributes.
    4165                                addNamedItems( this._.attributes, rules.attributes, priority );
    4266
     67                                // Add the last node handlers.
     68                                addNamedItems( this._.lastNodeOfBlock, rules.lastNodeOfBlock, priority );
     69
     70                                // Add empty block handlers.
     71                                addNamedItems( this._.emptyBlock, rules.emptyBlock, priority );
     72
    4373                                // Add the text.
    4474                                this._.text = transformNamedItem( this._.text, rules.text, priority ) || this._.text;
    4575
     
    74104                                // We must apply filters set to the specific element name as
    75105                                // well as those set to the generic $ name. So, add both to an
    76106                                // array and process them in a small loop.
    77                                 var filters = [ this._.elements[ element.name ], this._.elements.$ ],
    78                                         filter, ret;
    79 
    80                                 for ( var i = 0 ; i < 2 ; i++ )
    81                                 {
    82                                         filter = filters[ i ];
    83                                         if ( filter )
    84                                         {
    85                                                 ret = filter.filter( element, this );
    86 
    87                                                 if ( ret === false )
    88                                                         return null;
    89 
    90                                                 if ( ret && ret != element )
    91                                                         return this.onElement( ret );
    92                                         }
    93                                 }
    94 
    95                                 return element;
     107                                var filters = [ this._.elements[ element.name ], this._.elements.$ ];
     108                                return applyElementFilter.call( this, filters, element, [ element, this ], this.onElement );
    96109                        },
    97110
    98111                        onAttribute : function( element, name, value )
     
    111124                                }
    112125
    113126                                return value;
     127                        },
     128
     129                        onLastNodeOfBlock : function( block, lastNode )
     130                        {
     131                                var filter = this._.lastNodeOfBlock[ lastNode.name || lastNode.type ];
     132
     133                                if ( filter )
     134                                {
     135                                        var retval = filter.filter( block, lastNode, this );
     136
     137                                        if ( retval === false )
     138                                                return false;
     139
     140                                        if ( typeof retval != 'undefined' )
     141                                                return retval;
     142                                }
     143
     144                                return lastNode;
     145                        },
     146
     147                        onEmptyBlock : function( block )
     148                        {
     149                                var filters = [ this._.emptyBlock[ block.name ], this._.emptyBlock.$ ];
     150                                return applyElementFilter.call( this, filters, block, [ block, this ], this.onEmptyBlock );
    114151                        }
    115152                }
    116153        });
  • _source/core/htmlparser/element.js

     
    121121
    122122                                        element.name = writeName;
    123123
     124                                        if ( this._.isBlockLike && this.children.length < 1 )
     125                                        {
     126                                                if ( !( element = filter.onEmptyBlock( element ) ) )
     127                                                        return;
     128                                        }
     129
    124130                                        if ( !( element = filter.onElement( element ) ) )
    125131                                                return;
    126132
  • _source/core/htmlparser/fragment.js

     
    4747                        {table:1,ul:1,ol:1,dl:1},
    4848                        CKEDITOR.dtd.table, CKEDITOR.dtd.ul, CKEDITOR.dtd.ol, CKEDITOR.dtd.dl );
    4949
     50        // Regex to scan for &nbsp; at the end of blocks, which is actually placeholders.
     51        var tailNbspRegex = /^[\t\r\n ]*&nbsp;$/;
     52
    5053        /**
    5154         * Creates a {@link CKEDITOR.htmlParser.fragment} from an HTML string.
    5255         * @param {String} fragmentHtml The HTML to be parsed, filling the fragment.
     
    117120                                        currentNode = savedCurrent;
    118121                        }
    119122
    120                         // Rtrim empty spaces on block end boundary. (#3585)
    121123                        if ( element._.isBlockLike )
    122124                        {
    123 
    124                                 var length = element.children.length,
    125                                         lastChild = element.children[ length - 1 ],
     125                                // Rtrim empty spaces on block end boundary. (#3585)
     126                                var children = element.children,
     127                                        lastChild = children[ children.length - 1 ],
    126128                                        text;
    127129                                if ( lastChild && lastChild.type == CKEDITOR.NODE_TEXT )
    128130                                {
    129131                                        if ( !( text = CKEDITOR.tools.rtrim( lastChild.value ) ) )
    130                                                 element.children.length = length -1;
     132                                                children.pop();
    131133                                        else
    132134                                                lastChild.value = text;
    133135                                }
     136                       
     137                                // If the current node is a block, and the current browser is not IE; then
     138                                // search for and remove the tailing BR node, if any. (#2862)
     139                                lastChild = children[ children.length - 1 ];
     140                                if ( lastChild )
     141                                {
     142                                        if ( !CKEDITOR.env.ie && lastChild.type == CKEDITOR.NODE_ELEMENT && lastChild.name == 'br' )
     143                                                children.pop();
     144                                        if ( lastChild.type == CKEDITOR.NODE_TEXT && tailNbspRegex.test( lastChild.value ) )
     145                                                children.pop();
     146                                }
    134147                        }
    135148
    136149                        target.add( element );
     
    394407                 */
    395408                writeHtml : function( writer, filter )
    396409                {
    397                         for ( var i = 0, len = this.children.length ; i < len ; i++ )
     410                        var isBlockLike = ( this.type == CKEDITOR.NODE_ELEMENT && this._.isBlockLike );
     411
     412                        for ( var i = 0 ; i < this.children.length ; i++ )
     413                        {
     414                                // Apply filter on the last node of a block.
     415                                if ( isBlockLike && i == this.children.length - 1 )
     416                                {
     417                                        var retval = filter.onLastNodeOfBlock( this, this.children[i] );
     418                                        if ( !retval )
     419                                                break;
     420                                        this.children[i] = retval;
     421                                }
     422
    398423                                this.children[i].writeHtml( writer, filter );
     424                        }
    399425                }
    400426        };
    401427})();
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy