Ticket #1427: 1427.patch

File 1427.patch, 15.7 KB (added by Garry Yao, 15 years ago)
  • _source/plugins/clipboard/plugin.js

     
    126126
    127127                                if ( editor.fire( 'beforePaste' ) )
    128128                                        event.cancel();
    129 
     129                                // Simulate native 'paste' event for Opera/Firefox2.
     130                                else if( CKEDITOR.env.opera
     131                                                 || CKEDITOR.env.gecko && CKEDITOR.env.version < 10900 )
     132                                        editor.document.getBody().fire( 'paste' );
     133                                       
    130134                                setTimeout( function()
    131135                                        {
    132136                                                editor.fire( 'saveSnapshot' );          // Save after paste
     
    147151                }
    148152        };
    149153
     154        // Allow to peek clipboard content by redirecting the
     155        // pasting content into a temporary bin and grab the content of it.
     156        function getPasteBin( evt, callback ) {
     157
     158                var doc = this.document;
     159
     160                // Avoid recursions on 'paste' event for IE.
     161                if( CKEDITOR.env.ie && doc.getById( 'cke_pastebin' ) )
     162                        return;
     163
     164                var sel = this.getSelection(),
     165                        range = new CKEDITOR.dom.range( doc );
     166
     167                // Create container to paste into
     168                var pastebin = CKEDITOR.dom.element.createFromHtml( '<div id="cke_pastebin">&nbsp;</div>', doc );
     169                doc.getBody().append( pastebin );
     170
     171                // Position the bin exactly at the position of the selected element
     172                // to avoid any subsequent document scroll.
     173                var position = sel.getStartElement().getDocumentPosition();
     174                pastebin.setStyles( {
     175                        position : 'absolute',
     176                        left : '-1000px',
     177                        top : position.y + 'px',
     178                        width : '1px',
     179                        height : '1px',
     180                        overflow : 'hidden'
     181                } );
     182
     183                if ( CKEDITOR.env.ie )
     184                {
     185                        // Select the container
     186                        var ieRange = doc.getBody().$.createTextRange();
     187                        ieRange.moveToElementText( pastebin.$ );
     188                        // Re-direct the paste target, will fire another 'paste' event.
     189                        ieRange.execCommand( 'Paste' );
     190                        pastebin.remove();
     191                        evt.data.preventDefault();
     192                        callback( pastebin );
     193                }
     194                else
     195                {
     196                        var bms = sel.createBookmarks();
     197                        range.selectNodeContents( pastebin );
     198                        range.select();
     199                        // Wait a while and grab the pasted contents
     200                        window.setTimeout( function() {
     201
     202                                pastebin.remove();
     203
     204                                // Grab the HTML contents
     205                                // We need to look for a apple style wrapper on webkit it also adds a div wrapper if you copy/paste the body of the editor.
     206                                // Remove hidden div and restore selection
     207                                var bogusSpan;
     208                                pastebin = ( CKEDITOR.env.webkit
     209                                                 && ( bogusSpan = pastebin.getFirst() )
     210                                                 && ( bogusSpan.is && bogusSpan.hasClass( 'Apple-style-span' ) ) ?
     211                                                  bogusSpan : pastebin );
     212
     213                                // Restore the old selection
     214                                sel.selectBookmarks( bms );
     215                                callback( pastebin );
     216
     217                        }, 0 );
     218                }
     219        };
     220
     221
    150222        // Register the plugin.
    151223        CKEDITOR.plugins.add( 'clipboard',
    152224                {
    153225                        init : function( editor )
    154226                        {
     227                                // Provide default 'html' paste handler.
     228                                editor.on( 'paste', function( evt )
     229                                {
     230                                        editor.insertHtml( evt.data[ 'html' ] );
     231                                } );
     232
    155233                                function addButtonCommand( buttonName, commandName, command, ctxMenuOrder )
    156234                                {
    157235                                        var lang = editor.lang[ commandName ];
     
    184262
    185263                                editor.on( 'key', onKey, editor );
    186264
     265                                if( editor.config.autoDetectPaste )
     266                                        editor.on( 'contentDom', function()
     267                                        {
     268                                                var body = editor.document.getBody();
     269                                                body.on( 'paste', function( evt )
     270                                                {
     271                                                        getPasteBin.call( editor, evt, function ( pasteBin )
     272                                                        {
     273                                                                var html = pasteBin.getHtml(),
     274                                                                        dataTransfer =
     275                                                                        {
     276                                                                                'html' : html
     277                                                                        };
     278                                                               
     279                                                                editor.fire( 'paste', dataTransfer );
     280                                                                editor.fire( 'saveSnapshot' );          // Save after paste
     281                                                        } );
     282                                                } );
     283
     284                                        } );
     285
    187286                                // If the "contextmenu" plugin is loaded, register the listeners.
    188287                                if ( editor.contextMenu )
    189288                                {
     
    206305                        }
    207306                });
    208307})();
     308
     309/**
     310 * Whether to automatically choose the right format when pasting based on the
     311 * detection of content text OR just leave it to the browser's default paste behavior.
     312 * @type Boolean
     313 * @default true
     314 * @example
     315 * config.autoDetectPaste = false;
     316 */
     317CKEDITOR.config.autoDetectPaste = true;
  • _source/plugins/pastefromword/dialogs/pastefromword.js

     
    2727                                        + 'dialog.fire( "iframeAdded", { iframe : iframe } );'
    2828                                + '};'
    2929                                + '</script><style>body { margin: 3px; height: 95%; } </style><body></body>',
    30                 cleanWord : function( editor, html, ignoreFont, removeStyles )
    31                 {
    32                         // Remove comments [SF BUG-1481861].
    33                         html = html.replace(/<\!--[\s\S]*?-->/g, '' ) ;
    34 
    35                         html = html.replace(/<o:p>\s*<\/o:p>/g, '') ;
    36                         html = html.replace(/<o:p>[\s\S]*?<\/o:p>/g, '&nbsp;') ;
    37 
    38                         // Remove mso-xxx styles.
    39                         html = html.replace( /\s*mso-[^:]+:[^;"]+;?/gi, '' ) ;
    40 
    41                         // Remove margin styles.
    42                         html = html.replace( /\s*MARGIN: 0(?:cm|in) 0(?:cm|in) 0pt\s*;/gi, '' ) ;
    43                         html = html.replace( /\s*MARGIN: 0(?:cm|in) 0(?:cm|in) 0pt\s*"/gi, "\"" ) ;
    44 
    45                         html = html.replace( /\s*TEXT-INDENT: 0cm\s*;/gi, '' ) ;
    46                         html = html.replace( /\s*TEXT-INDENT: 0cm\s*"/gi, "\"" ) ;
    47 
    48                         html = html.replace( /\s*TEXT-ALIGN: [^\s;]+;?"/gi, "\"" ) ;
    49 
    50                         html = html.replace( /\s*PAGE-BREAK-BEFORE: [^\s;]+;?"/gi, "\"" ) ;
    51 
    52                         html = html.replace( /\s*FONT-VARIANT: [^\s;]+;?"/gi, "\"" ) ;
    53 
    54                         html = html.replace( /\s*tab-stops:[^;"]*;?/gi, '' ) ;
    55                         html = html.replace( /\s*tab-stops:[^"]*/gi, '' ) ;
    56 
    57                         // Remove FONT face attributes.
    58                         if ( ignoreFont )
    59                         {
    60                                 html = html.replace( /\s*face="[^"]*"/gi, '' ) ;
    61                                 html = html.replace( /\s*face=[^ >]*/gi, '' ) ;
    62 
    63                                 html = html.replace( /\s*FONT-FAMILY:[^;"]*;?/gi, '' ) ;
    64                         }
    65 
    66                         // Remove Class attributes
    67                         html = html.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi, "<$1$3") ;
    68 
    69                         // Remove styles.
    70                         if ( removeStyles )
    71                                 html = html.replace( /<(\w[^>]*) style="([^\"]*)"([^>]*)/gi, "<$1$3" ) ;
    72 
    73                         // Remove style, meta and link tags
    74                         html = html.replace( /<STYLE[^>]*>[\s\S]*?<\/STYLE[^>]*>/gi, '' ) ;
    75                         html = html.replace( /<(?:META|LINK)[^>]*>\s*/gi, '' ) ;
    76 
    77                         // Remove empty styles.
    78                         html =  html.replace( /\s*style="\s*"/gi, '' ) ;
    79 
    80                         html = html.replace( /<SPAN\s*[^>]*>\s*&nbsp;\s*<\/SPAN>/gi, '&nbsp;' ) ;
    81 
    82                         html = html.replace( /<SPAN\s*[^>]*><\/SPAN>/gi, '' ) ;
    83 
    84                         // Remove Lang attributes
    85                         html = html.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3") ;
    86 
    87                         html = html.replace( /<SPAN\s*>([\s\S]*?)<\/SPAN>/gi, '$1' ) ;
    88 
    89                         html = html.replace( /<FONT\s*>([\s\S]*?)<\/FONT>/gi, '$1' ) ;
    90 
    91                         // Remove XML elements and declarations
    92                         html = html.replace(/<\\?\?xml[^>]*>/gi, '' ) ;
    93 
    94                         // Remove w: tags with contents.
    95                         html = html.replace( /<w:[^>]*>[\s\S]*?<\/w:[^>]*>/gi, '' ) ;
    96 
    97                         // Remove Tags with XML namespace declarations: <o:p><\/o:p>
    98                         html = html.replace(/<\/?\w+:[^>]*>/gi, '' ) ;
    99 
    100                         html = html.replace( /<(U|I|STRIKE)>&nbsp;<\/\1>/g, '&nbsp;' ) ;
    101 
    102                         html = html.replace( /<H\d>\s*<\/H\d>/gi, '' ) ;
    103 
    104                         // Remove "display:none" tags.
    105                         html = html.replace( /<(\w+)[^>]*\sstyle="[^"]*DISPLAY\s?:\s?none[\s\S]*?<\/\1>/ig, '' ) ;
    106 
    107                         // Remove language tags
    108                         html = html.replace( /<(\w[^>]*) language=([^ |>]*)([^>]*)/gi, "<$1$3") ;
    109 
    110                         // Remove onmouseover and onmouseout events (from MS Word comments effect)
    111                         html = html.replace( /<(\w[^>]*) onmouseover="([^\"]*)"([^>]*)/gi, "<$1$3") ;
    112                         html = html.replace( /<(\w[^>]*) onmouseout="([^\"]*)"([^>]*)/gi, "<$1$3") ;
    113 
    114                         if ( editor.config.pasteFromWordKeepsStructure )
    115                         {
    116                                 // The original <Hn> tag send from Word is something like this: <Hn style="margin-top:0px;margin-bottom:0px">
    117                                 html = html.replace( /<H(\d)([^>]*)>/gi, '<h$1>' ) ;
    118 
    119                                 // Word likes to insert extra <font> tags, when using MSIE. (Wierd).
    120                                 html = html.replace( /<(H\d)><FONT[^>]*>([\s\S]*?)<\/FONT><\/\1>/gi, '<$1>$2<\/$1>' );
    121                                 html = html.replace( /<(H\d)><EM>([\s\S]*?)<\/EM><\/\1>/gi, '<$1>$2<\/$1>' );
    122                         }
    123                         else
    124                         {
    125                                 html = html.replace( /<H1([^>]*)>/gi, '<div$1><b><font size="6">' ) ;
    126                                 html = html.replace( /<H2([^>]*)>/gi, '<div$1><b><font size="5">' ) ;
    127                                 html = html.replace( /<H3([^>]*)>/gi, '<div$1><b><font size="4">' ) ;
    128                                 html = html.replace( /<H4([^>]*)>/gi, '<div$1><b><font size="3">' ) ;
    129                                 html = html.replace( /<H5([^>]*)>/gi, '<div$1><b><font size="2">' ) ;
    130                                 html = html.replace( /<H6([^>]*)>/gi, '<div$1><b><font size="1">' ) ;
    131 
    132                                 html = html.replace( /<\/H\d>/gi, '<\/font><\/b><\/div>' ) ;
    133 
    134                                 // Transform <P> to <DIV>
    135                                 var re = new RegExp( '(<P)([^>]*>[\\s\\S]*?)(<\/P>)', 'gi' ) ;  // Different because of a IE 5.0 error
    136                                 html = html.replace( re, '<div$2<\/div>' ) ;
    137 
    138                                 // Remove empty tags (three times, just to be sure).
    139                                 // This also removes any empty anchor
    140                                 html = html.replace( /<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, '' ) ;
    141                                 html = html.replace( /<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, '' ) ;
    142                                 html = html.replace( /<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, '' ) ;
    143                         }
    144 
    145                         return html ;
    146                 },
    14730                onShow : function()
    14831                {
    14932                        // To avoid JAWS putting virtual cursor back to the editor document,
     
    21396                                doc.close();
    21497                        }
    21598                },
     99                cleanWord : CKEDITOR.plugins.pastefromword.cleanWord,
    216100                onOk : function()
    217101                {
    218102                        var container = this.getContentElement( 'general', 'editing_area' ).getElement(),
     
    303187                        }
    304188                ]
    305189        };
    306 } );
     190        } );
  • _source/plugins/pastefromword/plugin.js

     
    99        {
    1010                // Register the command.
    1111                editor.addCommand( 'pastefromword', new CKEDITOR.dialogCommand( 'pastefromword' ) );
     12                // Register the dialog.
     13                CKEDITOR.dialog.add( 'pastefromword', this.path + 'dialogs/pastefromword.js' );
    1214
    1315                // Register the toolbar button.
    1416                editor.ui.addButton( 'PasteFromWord',
     
    1719                                command : 'pastefromword'
    1820                        } );
    1921
    20                 // Register the dialog.
    21                 CKEDITOR.dialog.add( 'pastefromword', this.path + 'dialogs/pastefromword.js' );
    22         }
     22                var config = editor.config;
     23                editor.on( 'paste', function( evt )
     24                {
     25                        var mswordHtml;
     26                        // MS-WORD format sniffing.
     27                        if ( ( mswordHtml = evt.data[ 'html' ] )
     28                                 && /(class=\"?Mso|style=\"[^\"]*\bmso\-|w:WordDocument)/.test( mswordHtml ) )
     29                        {
     30                                // Perform cleaning with default configuration.
     31                                editor.insertHtml(
     32                                        CKEDITOR.plugins.pastefromword.cleanWord(
     33                                                editor, mswordHtml,
     34                                                config.pasteFromWordIgnoreFontFace,
     35                                                config.pasteFromWordRemoveStyle));
     36
     37                                // Cancel other html paste handlers.
     38                                evt.cancel();
     39                        }
     40                }, null, null, 9 );
     41
     42        }
    2343} );
    2444
     45CKEDITOR.plugins.pastefromword =
     46{
     47        cleanWord : function( editor, html, ignoreFont, removeStyles )
     48        {
     49                // Remove comments [SF BUG-1481861].
     50                html = html.replace(/<\!--[\s\S]*?-->/g, '' ) ;
     51
     52                html = html.replace(/<o:p>\s*<\/o:p>/g, '') ;
     53                html = html.replace(/<o:p>[\s\S]*?<\/o:p>/g, '&nbsp;') ;
     54
     55                // Remove mso-xxx styles.
     56                html = html.replace( /\s*mso-[^:]+:[^;"]+;?/gi, '' ) ;
     57
     58                // Remove margin styles.
     59                html = html.replace( /\s*MARGIN: 0(?:cm|in) 0(?:cm|in) 0pt\s*;/gi, '' ) ;
     60                html = html.replace( /\s*MARGIN: 0(?:cm|in) 0(?:cm|in) 0pt\s*"/gi, "\"" ) ;
     61
     62                html = html.replace( /\s*TEXT-INDENT: 0cm\s*;/gi, '' ) ;
     63                html = html.replace( /\s*TEXT-INDENT: 0cm\s*"/gi, "\"" ) ;
     64
     65                html = html.replace( /\s*TEXT-ALIGN: [^\s;]+;?"/gi, "\"" ) ;
     66
     67                html = html.replace( /\s*PAGE-BREAK-BEFORE: [^\s;]+;?"/gi, "\"" ) ;
     68
     69                html = html.replace( /\s*FONT-VARIANT: [^\s;]+;?"/gi, "\"" ) ;
     70
     71                html = html.replace( /\s*tab-stops:[^;"]*;?/gi, '' ) ;
     72                html = html.replace( /\s*tab-stops:[^"]*/gi, '' ) ;
     73
     74                // Remove FONT face attributes.
     75                if ( ignoreFont )
     76                {
     77                        html = html.replace( /\s*face="[^"]*"/gi, '' ) ;
     78                        html = html.replace( /\s*face=[^ >]*/gi, '' ) ;
     79
     80                        html = html.replace( /\s*FONT-FAMILY:[^;"]*;?/gi, '' ) ;
     81                }
     82
     83                // Remove Class attributes
     84                html = html.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi, "<$1$3") ;
     85
     86                // Remove styles.
     87                if ( removeStyles )
     88                        html = html.replace( /<(\w[^>]*) style="([^\"]*)"([^>]*)/gi, "<$1$3" ) ;
     89
     90                // Remove style, meta and link tags
     91                html = html.replace( /<STYLE[^>]*>[\s\S]*?<\/STYLE[^>]*>/gi, '' ) ;
     92                html = html.replace( /<(?:META|LINK)[^>]*>\s*/gi, '' ) ;
     93
     94                // Remove empty styles.
     95                html =  html.replace( /\s*style="\s*"/gi, '' ) ;
     96
     97                html = html.replace( /<SPAN\s*[^>]*>\s*&nbsp;\s*<\/SPAN>/gi, '&nbsp;' ) ;
     98
     99                html = html.replace( /<SPAN\s*[^>]*><\/SPAN>/gi, '' ) ;
     100
     101                // Remove Lang attributes
     102                html = html.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3") ;
     103
     104                html = html.replace( /<SPAN\s*>([\s\S]*?)<\/SPAN>/gi, '$1' ) ;
     105
     106                html = html.replace( /<FONT\s*>([\s\S]*?)<\/FONT>/gi, '$1' ) ;
     107
     108                // Remove XML elements and declarations
     109                html = html.replace(/<\\?\?xml[^>]*>/gi, '' ) ;
     110
     111                // Remove w: tags with contents.
     112                html = html.replace( /<w:[^>]*>[\s\S]*?<\/w:[^>]*>/gi, '' ) ;
     113
     114                // Remove Tags with XML namespace declarations: <o:p><\/o:p>
     115                html = html.replace(/<\/?\w+:[^>]*>/gi, '' ) ;
     116
     117                html = html.replace( /<(U|I|STRIKE)>&nbsp;<\/\1>/g, '&nbsp;' ) ;
     118
     119                html = html.replace( /<H\d>\s*<\/H\d>/gi, '' ) ;
     120
     121                // Remove "display:none" tags.
     122                html = html.replace( /<(\w+)[^>]*\sstyle="[^"]*DISPLAY\s?:\s?none[\s\S]*?<\/\1>/ig, '' ) ;
     123
     124                // Remove language tags
     125                html = html.replace( /<(\w[^>]*) language=([^ |>]*)([^>]*)/gi, "<$1$3") ;
     126
     127                // Remove onmouseover and onmouseout events (from MS Word comments effect)
     128                html = html.replace( /<(\w[^>]*) onmouseover="([^\"]*)"([^>]*)/gi, "<$1$3") ;
     129                html = html.replace( /<(\w[^>]*) onmouseout="([^\"]*)"([^>]*)/gi, "<$1$3") ;
     130
     131                if ( editor.config.pasteFromWordKeepsStructure )
     132                {
     133                        // The original <Hn> tag send from Word is something like this: <Hn style="margin-top:0px;margin-bottom:0px">
     134                        html = html.replace( /<H(\d)([^>]*)>/gi, '<h$1>' ) ;
     135
     136                        // Word likes to insert extra <font> tags, when using MSIE. (Wierd).
     137                        html = html.replace( /<(H\d)><FONT[^>]*>([\s\S]*?)<\/FONT><\/\1>/gi, '<$1>$2<\/$1>' );
     138                        html = html.replace( /<(H\d)><EM>([\s\S]*?)<\/EM><\/\1>/gi, '<$1>$2<\/$1>' );
     139                }
     140                else
     141                {
     142                        html = html.replace( /<H1([^>]*)>/gi, '<div$1><b><font size="6">' ) ;
     143                        html = html.replace( /<H2([^>]*)>/gi, '<div$1><b><font size="5">' ) ;
     144                        html = html.replace( /<H3([^>]*)>/gi, '<div$1><b><font size="4">' ) ;
     145                        html = html.replace( /<H4([^>]*)>/gi, '<div$1><b><font size="3">' ) ;
     146                        html = html.replace( /<H5([^>]*)>/gi, '<div$1><b><font size="2">' ) ;
     147                        html = html.replace( /<H6([^>]*)>/gi, '<div$1><b><font size="1">' ) ;
     148
     149                        html = html.replace( /<\/H\d>/gi, '<\/font><\/b><\/div>' ) ;
     150
     151                        // Transform <P> to <DIV>
     152                        var re = new RegExp( '(<P)([^>]*>[\\s\\S]*?)(<\/P>)', 'gi' ) ;  // Different because of a IE 5.0 error
     153                        html = html.replace( re, '<div$2<\/div>' ) ;
     154
     155                        // Remove empty tags (three times, just to be sure).
     156                        // This also removes any empty anchor
     157                        html = html.replace( /<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, '' ) ;
     158                        html = html.replace( /<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, '' ) ;
     159                        html = html.replace( /<([^\s>]+)(\s[^>]*)?>\s*<\/\1>/g, '' ) ;
     160                }
     161
     162                return html ;
     163        }
     164}
     165
    25166/**
    26167 * Whether the "Ignore font face definitions" checkbox is enabled by default in
    27168 * the Paste from Word dialog.
© 2003 – 2022, CKSource sp. z o.o. sp.k. All rights reserved. | Terms of use | Privacy policy