Ticket #3188: 3188_2.patch

File 3188_2.patch, 9.9 KB (added by Garry Yao, 10 years ago)
  • _source/core/htmlparser/element.js

     
    124124                                        if ( !( element = filter.onElement( element ) ) )
    125125                                                return;
    126126
    127                                         if ( element.name == writeName )
     127                                        // Element already get serialized.
     128                                        if ( typeof element == 'string')
     129                                        {
     130                                                writer.write( element );
     131                                                return;
     132                                        }
     133                                        else if ( element.name == writeName )
    128134                                                break;
    129135
    130136                                        writeName = element.name;
  • _source/plugins/styles/plugin.js

     
    623623
    624624        function applyBlockStyle( range )
    625625        {
    626                 // Bookmark the range so we can re-select it after processing.
    627                 var bookmark = range.createBookmark();
     626                // Creating serialiable bookmarks to re-select ranges later.
     627                var bookmark = range.createBookmark( true );
    628628
    629629                var iterator = range.createIterator();
    630630                iterator.enforceRealBlocks = true;
     
    635635
    636636                while( ( block = iterator.getNextParagraph() ) )                // Only one =
    637637                {
    638                         // Create the new node right before the current one.
    639638                        var newBlock = getElement( this, doc );
     639                        replaceBlock( block, newBlock, doc );
     640                }
    640641
    641                         // Check if we are changing from/to <pre>.
    642 //                      var newBlockIsPre       = newBlock.nodeName.IEquals( 'pre' );
    643 //                      var blockIsPre          = block.nodeName.IEquals( 'pre' );
     642                range.moveToBookmark( bookmark );
     643        }
     644
     645        // Replace the orignal block with new one, also contains special treatment
     646        // for <pre> blocks is needed, which makes it possible to switch forth and
     647        // back to <p>, with format well preserved, and merging/splitting adjacent
     648        // when necessary.(#3188)
     649        function replaceBlock( block, newBlock, document )
     650        {
     651                // Create the new node right before the current one.
     652                // Check if we are changing from/to <pre>.
     653                var newBlockIsPre       = newBlock.is( 'pre' );
     654                var blockIsPre          = block.is( 'pre' );
    644655
    645 //                      var toPre       = newBlockIsPre && !blockIsPre;
    646 //                      var fromPre     = !newBlockIsPre && blockIsPre;
     656                var isToPre     = newBlockIsPre && !blockIsPre;
     657                var isFromPre   = !newBlockIsPre && blockIsPre;
    647658
    648                         // Move everything from the current node to the new one.
    649 //                      if ( toPre )
    650 //                              newBlock = this._ToPre( doc, block, newBlock );
    651 //                      else if ( fromPre )
    652 //                              newBlock = this._FromPre( doc, block, newBlock );
    653 //                      else    // Convering from a regular block to another regular block.
    654                                 block.moveChildren( newBlock );
     659                // Move everything from the current node to the new one.
     660                if ( isToPre )
     661                        newBlock = toPre( block, newBlock, document );
     662                else if ( isFromPre )
     663                        newBlock = fromPre( block, newBlock );
    655664
    656                         // Replace the current block.
    657                         newBlock.insertBefore( block );
    658                         block.remove();
    659 
    660                         // Complete other tasks after inserting the node in the DOM.
    661 //                      if ( newBlockIsPre )
    662 //                      {
    663 //                              if ( previousPreBlock )
    664 //                                      this._CheckAndMergePre( previousPreBlock, newBlock ) ;  // Merge successive <pre> blocks.
    665 //                              previousPreBlock = newBlock;
    666 //                      }
    667 //                      else if ( fromPre )
    668 //                              this._CheckAndSplitPre( newBlock ) ;    // Split <br><br> in successive <pre>s.
    669                 }
     665                newBlock.replace( block );
     666                if ( newBlockIsPre )
     667                        // Merge successive <pre> blocks.
     668                        mergePre( newBlock );
     669                else if ( isFromPre )
     670                        // Split <br><br> in successive <pre>s.
     671                        splitIntoBlocks( newBlock, document );
     672               
     673        };
     674
     675        /**
     676         * Merge a <pre> block with a previous sibling if available.
     677         */
     678        function mergePre( preBlock )
     679        {
     680                var previousBlock;
     681                if ( !( ( previousBlock = preBlock.getPreviousSourceNode( true, CKEDITOR.NODE_ELEMENT ) )
     682                                 && previousBlock.is
     683                                 && previousBlock.is( 'pre') ) )
     684                        return;
     685
     686                // Merge the previous <pre> block contents into the current <pre>
     687                // block.
     688                //
     689                // Another thing to be careful here is that currentBlock might contain
     690                // a '\n' at the beginning, and previousBlock might contain a '\n'
     691                // towards the end. These new lines are not normally displayed but they
     692                // become visible after merging.
     693                var mergedHtml = previousBlock.getHtml().replace( /\n$/, '' ) + '\n\n' +
     694                                preBlock.getHtml().replace( /^\n/, '' ) ;
     695
     696                // Krugle: IE normalizes innerHTML from <pre>, breaking whitespaces.
     697                if ( CKEDITOR.env.ie )
     698                        preBlock.$.outerHTML = '<pre>' + mergedHtml + '</pre>';
     699                else
     700                        preBlock.setHtml( mergedHtml );
     701
     702                previousBlock.remove();
     703        }
    670704
    671                 range.moveToBookmark( bookmark );
    672         }
     705        function splitIntoBlocks( newBlock, doc )
     706        {
     707                var duoBrRegex = /(:?<br\b[^>]*>)\s*(:?<br\b[^>]*>)/gi,
     708                        blockName = newBlock.getName(),
     709                        splitedHtml = newBlock.getOuterHtml().replace(
     710                                duoBrRegex, function()
     711                                        {
     712                                          return '</' + blockName + '>' + '<' + blockName + '>';
     713                                        }
     714                                );
    673715
     716                var temp = doc.createElement( 'div' );
     717                temp.setHtml( splitedHtml );
     718                temp.replace( newBlock );
     719                temp.remove( true );
     720        }
     721
     722        /**
     723         * Converting from a PRE block to a non-PRE block in formatting operations.
     724         */
     725        function fromPre( block, newBlock )
     726        {
     727                var blockHtml = block.getHtml();
     728
     729                // Trim the first and last linebreaks immediately after and before <pre>, </pre>,
     730                // if they exist.
     731                // This is done because the linebreaks are not rendered.
     732                blockHtml = blockHtml.replace( /(\r\n|\r)/g, '\n' ) ;
     733                blockHtml = blockHtml.replace( /^[ \t]*\n/, '' ) ;
     734                blockHtml = blockHtml.replace( /\n$/, '' ) ;
     735
     736                // 1. Convert spaces or tabs at the beginning or at the end to &nbsp;
     737                blockHtml = blockHtml.replace( /^[ \t]+|[ \t]+$/g, function( match, offset, s )
     738                                {
     739                                        if ( match.length == 1 )        // one space, preserve it
     740                                                return '&nbsp;' ;
     741                                        else if ( offset == 0 )         // beginning of block
     742                                                return new Array( match.length ).join( '&nbsp;' ) + ' ' ;
     743                                        else                            // end of block
     744                                                return ' ' + new Array( match.length ).join( '&nbsp;' ) ;
     745                                } ) ;
     746
     747                // 2. Convert \n to <BR>.
     748                // 3. Convert contiguous (i.e. non-singular) spaces or tabs to &nbsp;
     749                blockHtml = blockHtml.replace( /\n/g, '<br>' ) ;
     750                blockHtml = blockHtml.replace( /[ \t]{2,}/g,
     751                                function ( match )
     752                                {
     753                                        return new Array( match.length ).join( '&nbsp;' ) + ' ' ;
     754                                } ) ;
     755                newBlock.setHtml( blockHtml );
     756                return newBlock ;
     757        }
     758
     759        /**
     760         * Converting from a non-PRE block to a PRE block in formatting operations.
     761         */
     762        function toPre( block, newBlock, document )
     763        {
     764                // Handle converting from a regular block to a <pre> block.
     765                var preHtml = CKEDITOR.tools.trim( block.getHtml() );
     766
     767                // 1. Delete ANSI whitespaces immediately before and after <BR> because
     768                //    they are not visible.
     769                // 2. Mark down any <BR /> nodes here so they can be turned into \n in
     770                //    the next step and avoid being compressed.
     771                preHtml = preHtml.replace( /[ \t\r\n]*(<br[^>]*>)[ \t\r\n]*/gi, '$1' );
     772                // 3. Compress other ANSI whitespaces since they're only visible as one
     773                //    single space previously.
     774                // 4. Convert &nbsp; to spaces since &nbsp; is no longer needed in <PRE>.
     775                preHtml = preHtml.replace( /([ \t\n\r]+|&nbsp;)/g, ' ' );
     776                // 5. Convert any <BR /> to \n. This must not be done earlier because
     777                //    the \n would then get compressed.
     778                preHtml = preHtml.replace( /<br\b[^>]*>/gi, '\n' );
     779
     780                // Krugle: IE normalizes innerHTML to <pre>, breaking whitespaces.
     781                if ( CKEDITOR.env.ie )
     782                {
     783                        var temp = document.createElement( 'div' );
     784                        temp.append( newBlock );
     785                        newBlock.$.outerHTML =  '<pre>\n' + preHtml + '</pre>';
     786                        newBlock = temp.getFirst().remove();
     787                }
     788                else
     789                        newBlock.setHtml( preHtml );
     790
     791                return newBlock;
     792        }
     793
    674794        // Removes a style from an element itself, don't care about its subtree.
    675795        function removeFromElement( style, element )
    676796        {
  • _source/core/htmlparser/text.js

     
    1918                 * @type String
    2019                 * @example
    2120                 */
    22                 this.value = value.replace( spacesRegex, ' ' );
     21                this.value = value;
    2322
    2423                /** @private */
    2524                this._ =
  • _source/core/htmlparser/filter.js

     
    8787                                                if ( ret === false )
    8888                                                        return null;
    8989
     90                                                // Element might been transformed into text node.
     91                                                if( ret && ret.type == CKEDITOR.NODE_TEXT )
     92                                                        return this.onText( ret.value );
     93                                               
    9094                                                if ( ret && ret != element )
    9195                                                        return this.onElement( ret );
    9296                                        }
  • _source/plugins/htmldataprocessor/plugin.js

     
    4343
    4444                        elements :
    4545                        {
     46                                br : function( element )
     47                                {
     48                                        // Gecko had been replacing all linebreaks into <br>s, which
     49                                        // are required to be restored here.
     50                                        if ( element.parent.name == 'pre' )
     51                                                element =  new CKEDITOR.htmlParser.text( '\n' );
     52                                        return element;
     53                                },
     54
    4655                                embed : function( element )
    4756                                {
    4857                                        var parent = element.parent;
     
    129138        CKEDITOR.htmlDataProcessor = function()
    130139        {
    131140                this.writer = new CKEDITOR.htmlWriter();
     141                // Disable indentation on <pre>.
     142                this.writer.setRules( 'pre',
     143                {
     144                  indent: false
     145                } );
    132146                this.dataFilter = new CKEDITOR.htmlParser.filter();
    133147                this.htmlFilter = new CKEDITOR.htmlParser.filter();
    134148        };
© 2003 – 2019 CKSource – Frederico Knabben. All rights reserved. | Terms of use | Privacy policy