Ticket #3188: 3188.patch
File 3188.patch, 16.5 KB (added by , 14 years ago) |
---|
-
_source/plugins/htmldataprocessor/plugin.js
43 43 44 44 elements : 45 45 { 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 46 55 embed : function( element ) 47 56 { 48 57 var parent = element.parent; … … 129 138 CKEDITOR.htmlDataProcessor = function() 130 139 { 131 140 this.writer = new CKEDITOR.htmlWriter(); 141 // Disable indentation on <pre>. 142 this.writer.setRules( 'pre', 143 { 144 indent: false 145 } ); 132 146 this.dataFilter = new CKEDITOR.htmlParser.filter(); 133 147 this.htmlFilter = new CKEDITOR.htmlParser.filter(); 134 148 }; -
_source/plugins/styles/plugin.js
102 102 : 103 103 CKEDITOR.STYLE_INLINE; 104 104 105 // Register custom style processer. 106 if ( typeof styleDefinition.processor == 'function') 107 this[ this.type == CKEDITOR.STYLE_INLINE ? 'processRange' : 'processBlock' ] 108 = styleDefinition.processor; 109 105 110 this._ = 106 111 { 107 112 definition : styleDefinition … … 243 248 } 244 249 } 245 250 return false; 246 } 251 }, 252 // Custom style processing callbacks. 253 processBlock : null, 254 processRange : null 247 255 }; 248 256 249 257 // Build the cssText based on the styles definition. … … 271 279 if ( stylesText.length ) 272 280 { 273 281 stylesText = normalizeCssText( stylesText ); 274 282 275 283 if ( stylesText.length ) 276 284 stylesText = stylesText.replace( semicolonFixRegex, ';' ); 277 285 } … … 471 479 parent = parent.getParent(); 472 480 } 473 481 474 if ( styleNode ) 482 // Delegate to customize inline style processing. 483 if ( this.processRange ) 484 this.processRange( styleRange, styleNode ); 485 else 475 486 { 476 487 // Move the contents of the range to the style element. 477 488 styleRange.extractContents().appendTo( styleNode ); … … 629 640 630 641 function applyBlockStyle( range ) 631 642 { 632 // Bookmark the range so we can re-select it after processing.633 var bookmark = range.createBookmark( );643 // Creating serialiable bookmarks to re-select ranges later. 644 var bookmark = range.createBookmark( true ); 634 645 635 646 var iterator = range.createIterator(); 636 647 iterator.enforceRealBlocks = true; … … 644 655 // Create the new node right before the current one. 645 656 var newBlock = getElement( this, doc ); 646 657 647 // Check if we are changing from/to <pre>. 648 // var newBlockIsPre = newBlock.nodeName.IEquals( 'pre' ); 649 // var blockIsPre = block.nodeName.IEquals( 'pre' ); 650 651 // var toPre = newBlockIsPre && !blockIsPre; 652 // var fromPre = !newBlockIsPre && blockIsPre; 653 654 // Move everything from the current node to the new one. 655 // if ( toPre ) 656 // newBlock = this._ToPre( doc, block, newBlock ); 657 // else if ( fromPre ) 658 // newBlock = this._FromPre( doc, block, newBlock ); 659 // else // Convering from a regular block to another regular block. 658 // Delegate to custom block style processing. 659 if( this.processBlock ) 660 this.processBlock( block, newBlock ); 661 else 662 { 660 663 block.moveChildren( newBlock ); 661 662 // Replace the current block. 663 newBlock.insertBefore( block ); 664 block.remove(); 665 666 // Complete other tasks after inserting the node in the DOM. 667 // if ( newBlockIsPre ) 668 // { 669 // if ( previousPreBlock ) 670 // this._CheckAndMergePre( previousPreBlock, newBlock ) ; // Merge successive <pre> blocks. 671 // previousPreBlock = newBlock; 672 // } 673 // else if ( fromPre ) 674 // this._CheckAndSplitPre( newBlock ) ; // Split <br><br> in successive <pre>s. 664 // Replace the current block. 665 newBlock.insertBefore( block ); 666 block.remove(); 667 } 675 668 } 676 669 677 670 range.moveToBookmark( bookmark ); -
_source/plugins/format/plugin.js
2 2 Copyright (c) 2003-2009, CKSource - Frederico Knabben. All rights reserved. 3 3 For licensing, see LICENSE.html or http://ckeditor.com/license 4 4 */ 5 ( function(){ 6 CKEDITOR.plugins.add( 'format', 7 { 8 requires : [ 'richcombo', 'styles' ], 9 10 init : function( editor ) 11 { 12 var config = editor.config, 13 lang = editor.lang.format; 5 14 6 CKEDITOR.plugins.add( 'format', 7 { 8 requires : [ 'richcombo', 'styles' ], 15 // Gets the list of tags from the settings. 16 var tags = config.format_tags.split( ';' ), 17 // Whether <pre> switching logic is needed. 18 hasPreFormat = !!config.format_pre; 9 19 10 init : function( editor ) 11 { 12 var config = editor.config, 13 lang = editor.lang.format; 20 // Special treatment for <pre> blocks is needed, which makes it possible 21 // to switch forth and back to <p>, with format well preserved, and 22 // merging/splitting adjacent when necessary.(#3188) 23 function processPre( block, newBlock ) 24 { 25 var doc = editor.document; 26 // Create the new node right before the current one. 27 // Check if we are changing from/to <pre>. 28 var newBlockIsPre = newBlock.is( 'pre' ); 29 var blockIsPre = block.is( 'pre' ); 30 31 var isToPre = newBlockIsPre && !blockIsPre; 32 var isFromPre = !newBlockIsPre && blockIsPre; 33 34 // Move everything from the current node to the new one. 35 if ( isToPre ) 36 newBlock = toPre( block, newBlock, doc ); 37 else if ( isFromPre ) 38 newBlock = fromPre( block, newBlock ); 39 40 newBlock.replace( block ); 14 41 15 // Gets the list of tags from the settings. 16 var tags = config.format_tags.split( ';' ); 42 if ( newBlockIsPre ) 43 // Merge successive <pre> blocks. 44 mergePre( newBlock ); 45 else if ( isFromPre ) 46 // Split <br><br> in successive <pre>s. 47 splitIntoBlocks( newBlock, doc ); 17 48 18 // Create style objects for all defined styles.19 var styles = {};20 for ( var i = 0 ; i < tags.length ; i++ )21 {22 var tag = tags[ i ];23 styles[ tag ] = new CKEDITOR.style( config[ 'format_' + tag ] );24 }25 49 26 editor.ui.addRichCombo( 'Format', 50 }; 51 // Create style objects for all defined styles. 52 var styles = {}; 53 for ( var i = 0 ; i < tags.length ; i++ ) 27 54 { 28 label : lang.label, 29 title : lang.panelTitle, 30 voiceLabel : lang.voiceLabel, 31 className : 'cke_format', 32 multiSelect : false, 55 var tag = tags[ i ], 56 tagDef = config[ 'format_' + tag ]; 57 58 if ( hasPreFormat ) 59 // Now the <pre> pre-processor is attaching to each block style. 60 tagDef.processor = processPre; 33 61 34 panel : 35 { 36 css : [ config.contentsCss, CKEDITOR.getUrl( editor.skinPath + 'editor.css' ) ], 37 voiceLabel : lang.panelVoiceLabel 38 }, 62 styles[ tag ] = new CKEDITOR.style( tagDef ); 63 } 39 64 40 init : function()65 editor.ui.addRichCombo( 'Format', 41 66 { 42 this.startGroup( lang.panelTitle ); 67 label : lang.label, 68 title : lang.panelTitle, 69 voiceLabel : lang.voiceLabel, 70 className : 'cke_format', 71 multiSelect : false, 43 72 44 for ( var tag in styles )73 panel : 45 74 { 46 var label = lang[ 'tag_' + tag ]; 75 css : [ config.contentsCss, CKEDITOR.getUrl( editor.skinPath + 'editor.css' ) ], 76 voiceLabel : lang.panelVoiceLabel 77 }, 47 78 48 // Add the tag entry to the panel list. 49 this.add( tag, '<' + tag + '>' + label + '</' + tag + '>', label ); 50 } 51 }, 79 init : function() 80 { 81 this.startGroup( lang.panelTitle ); 52 82 53 onClick : function( value ) 54 { 55 editor.focus(); 56 editor.fire( 'saveSnapshot' ); 83 for ( var tag in styles ) 84 { 85 var label = lang[ 'tag_' + tag ]; 57 86 58 styles[ value ].apply( editor.document ); 87 // Add the tag entry to the panel list. 88 this.add( tag, '<' + tag + '>' + label + '</' + tag + '>', label ); 89 } 90 }, 59 91 60 editor.fire( 'saveSnapshot' ); 61 }, 92 onClick : function( value ) 93 { 94 editor.focus(); 95 editor.fire( 'saveSnapshot' ); 62 96 63 onRender : function() 64 { 65 editor.on( 'selectionChange', function( ev ) 66 { 67 var currentTag = this.getValue(); 97 styles[ value ].apply( editor.document ); 68 98 69 var elementPath = ev.data.path; 99 editor.fire( 'saveSnapshot' ); 100 }, 70 101 71 for ( var tag in styles ) 102 onRender : function() 103 { 104 editor.on( 'selectionChange', function( ev ) 72 105 { 73 if ( styles[ tag ].checkActive( elementPath ) ) 106 var currentTag = this.getValue(); 107 108 var elementPath = ev.data.path; 109 110 for ( var tag in styles ) 74 111 { 75 if ( tag != currentTag ) 76 this.setValue( tag, editor.lang.format[ 'tag_' + tag ] ); 77 return; 112 if ( styles[ tag ].checkActive( elementPath ) ) 113 { 114 if ( tag != currentTag ) 115 this.setValue( tag, editor.lang.format[ 'tag_' + tag ] ); 116 return; 117 } 78 118 } 79 } 119 120 // If no styles match, just empty it. 121 this.setValue( '' ); 122 }, 123 this); 124 } 125 }); 126 } 127 }); 80 128 81 // If no styles match, just empty it. 82 this.setValue( '' ); 83 }, 84 this); 85 } 86 }); 129 /** 130 * Merge a <pre> block with a previous sibling if available. 131 */ 132 function mergePre( preBlock ) 133 { 134 var previousBlock; 135 if ( !( ( previousBlock = preBlock.getPreviousSourceNode( true, CKEDITOR.NODE_ELEMENT ) ) 136 && previousBlock.is 137 && previousBlock.is( 'pre') ) ) 138 return; 139 140 // Merge the previous <pre> block contents into the current <pre> 141 // block. 142 // 143 // Another thing to be careful here is that currentBlock might contain 144 // a '\n' at the beginning, and previousBlock might contain a '\n' 145 // towards the end. These new lines are not normally displayed but they 146 // become visible after merging. 147 var mergedHtml = previousBlock.getHtml().replace( /\n$/, '' ) + '\n\n' + 148 preBlock.getHtml().replace( /^\n/, '' ) ; 149 150 // Krugle: IE normalizes innerHTML from <pre>, breaking whitespaces. 151 if ( CKEDITOR.env.ie ) 152 preBlock.$.outerHTML = '<pre>' + mergedHtml + '</pre>'; 153 else 154 preBlock.setHtml( mergedHtml ); 155 156 previousBlock.remove(); 87 157 } 88 });89 158 159 function splitIntoBlocks( newBlock, doc ) 160 { 161 var duoBrRegex = /(:?<br\b[^>]*>)\s*(:?<br\b[^>]*>)/gi, 162 blockName = newBlock.getName(), 163 splitedHtml = newBlock.getOuterHtml().replace( 164 duoBrRegex, function() 165 { 166 return '<' + blockName + '/>' + '<' + blockName + '>'; 167 } 168 ); 169 var temp = doc.createElement( 'div' ); 170 temp.setHtml( splitedHtml ); 171 temp.replace( newBlock ); 172 temp.remove( true ); 173 } 174 175 /** 176 * Converting from a PRE block to a non-PRE block in formatting operations. 177 */ 178 function fromPre( block, newBlock ) 179 { 180 var blockHtml = block.getHtml(); 181 182 // Trim the first and last linebreaks immediately after and before <pre>, </pre>, 183 // if they exist. 184 // This is done because the linebreaks are not rendered. 185 blockHtml = blockHtml.replace( /(\r\n|\r)/g, '\n' ) ; 186 blockHtml = blockHtml.replace( /^[ \t]*\n/, '' ) ; 187 blockHtml = blockHtml.replace( /\n$/, '' ) ; 188 189 // 1. Convert spaces or tabs at the beginning or at the end to 190 blockHtml = blockHtml.replace( /^[ \t]+|[ \t]+$/g, function( match, offset, s ) 191 { 192 if ( match.length == 1 ) // one space, preserve it 193 return ' ' ; 194 else if ( offset == 0 ) // beginning of block 195 return new Array( match.length ).join( ' ' ) + ' ' ; 196 else // end of block 197 return ' ' + new Array( match.length ).join( ' ' ) ; 198 } ) ; 199 200 // 2. Convert \n to <BR>. 201 // 3. Convert contiguous (i.e. non-singular) spaces or tabs to 202 blockHtml = blockHtml.replace( /\n/g, '<br>' ) ; 203 blockHtml = blockHtml.replace( /[ \t]{2,}/g, 204 function ( match ) 205 { 206 return new Array( match.length ).join( ' ' ) + ' ' ; 207 } ) ; 208 newBlock.setHtml( blockHtml ); 209 return newBlock ; 210 } 211 212 /** 213 * Converting from a non-PRE block to a PRE block in formatting operations. 214 */ 215 function toPre( block, newBlock, doc ) 216 { 217 // Handle converting from a regular block to a <pre> block. 218 var preHtml = CKEDITOR.tools.trim( block.getHtml() ); 219 220 // 1. Delete ANSI whitespaces immediately before and after <BR> because 221 // they are not visible. 222 // 2. Mark down any <BR /> nodes here so they can be turned into \n in 223 // the next step and avoid being compressed. 224 preHtml = preHtml.replace( /[ \t\r\n]*(<br[^>]*>)[ \t\r\n]*/gi, '$1' ); 225 // 3. Compress other ANSI whitespaces since they're only visible as one 226 // single space previously. 227 // 4. Convert to spaces since is no longer needed in <PRE>. 228 preHtml = preHtml.replace( /([ \t\n\r]+| )/g, ' ' ); 229 // 5. Convert any <BR /> to \n. This must not be done earlier because 230 // the \n would then get compressed. 231 preHtml = preHtml.replace( /<br\b[^>]*>/gi, '\n' ); 232 233 // Krugle: IE normalizes innerHTML to <pre>, breaking whitespaces. 234 if ( CKEDITOR.env.ie ) 235 { 236 var temp = doc.createElement( 'div' ); 237 temp.append( newBlock ); 238 newBlock.$.outerHTML = '<pre>\n' + preHtml + '</pre>'; 239 newBlock = temp.getFirst().remove(); 240 } 241 else 242 newBlock.setHtml( preHtml ); 243 244 return newBlock; 245 } 246 247 248 })(); 90 249 CKEDITOR.config.format_tags = 'p;h1;h2;h3;h4;h5;h6;pre;address;div'; 91 250 92 251 CKEDITOR.config.format_p = { element : 'p' }; -
_source/core/htmlparser/element.js
124 124 if ( !( element = filter.onElement( element ) ) ) 125 125 return; 126 126 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 ) 128 134 break; 129 135 130 136 writeName = element.name; -
_source/core/htmlparser/text.js
5 5 6 6 (function() 7 7 { 8 var spacesRegex = /[\t\r\n ]{2,}|[\t\r\n]/g;9 8 10 9 /** 11 10 * A lightweight representation of HTML text. … … 19 18 * @type String 20 19 * @example 21 20 */ 22 this.value = value .replace( spacesRegex, ' ' );21 this.value = value; 23 22 24 23 /** @private */ 25 24 this._ = -
_source/core/htmlparser/fragment.js
47 47 {table:1,ul:1,ol:1,dl:1}, 48 48 CKEDITOR.dtd.table, CKEDITOR.dtd.ul, CKEDITOR.dtd.ol, CKEDITOR.dtd.dl ); 49 49 50 // Whitespaces within text node is required to be striped off. 51 var spacesRegex = /[\t\r\n ]{2,}|[\t\r\n]/g; 50 52 /** 51 53 * Creates a {@link CKEDITOR.htmlParser.fragment} from an HTML string. 52 54 * @param {String} fragmentHtml The HTML to be parsed, filling the fragment. … … 286 288 if ( fixForBody && !currentNode.type ) 287 289 this.onTagOpen( 'p', {} ); 288 290 291 // Preserve whitespace, tabs, and carriage returns on <pre> element. 292 if ( currentNode.name != 'pre' ) 293 text = text.replace( spacesRegex, '' ); 294 289 295 currentNode.add( new CKEDITOR.htmlParser.text( text ) ); 290 296 }; 291 297 -
_source/core/htmlparser/filter.js
87 87 if ( ret === false ) 88 88 return null; 89 89 90 // Element might been transformed into text node. 91 if( ret && ret.type == CKEDITOR.NODE_TEXT ) 92 return this.onText( ret.value ); 93 90 94 if ( ret && ret != element ) 91 95 return this.onElement( ret ); 92 96 }