docs: function( editor ) {
  			var textificationFilter;
  
  			initClipboard( editor );
  
  			CKEDITOR.dialog.add( 'paste', CKEDITOR.getUrl( this.path + 'dialogs/paste.js' ) );
  
  			editor.on( 'paste', function( evt ) {
  				var data = evt.data.dataValue,
  					blockElements = CKEDITOR.dtd.$block;
  
  				// Filter webkit garbage.
  				if ( data.indexOf( 'Apple-' ) > -1 ) {
  					// Replace special webkit's &nbsp; with simple space, because webkit
  					// produces them even for normal spaces.
  					data = data.replace( /<span class="Apple-converted-space">&nbsp;<\/span>/gi, ' ' );
  
  					// Strip <span> around white-spaces when not in forced 'html' content type.
  					// This spans are created only when pasting plain text into Webkit,
  					// but for safety reasons remove them always.
  					if ( evt.data.type != 'html' )
  						data = data.replace( /<span class="Apple-tab-span"[^>]*>([^<]*)<\/span>/gi, function( all, spaces ) {
  						// Replace tabs with 4 spaces like Fx does.
  						return spaces.replace( /\t/g, '&nbsp;&nbsp; &nbsp;' );
  					} );
  
  					// This br is produced only when copying & pasting HTML content.
  					if ( data.indexOf( '<br class="Apple-interchange-newline">' ) > -1 ) {
  						evt.data.startsWithEOL = 1;
  						evt.data.preSniffing = 'html'; // Mark as not text.
  						data = data.replace( /<br class="Apple-interchange-newline">/, '' );
  					}
  
  					// Remove all other classes.
  					data = data.replace( /(<[^>]+) class="Apple-[^"]*"/gi, '$1' );
  				}
  
  				// Strip editable that was copied from inside. (#9534)
  				if ( data.match( /^<[^<]+cke_(editable|contents)/i ) ) {
  					var tmp,
  						editable_wrapper,
  						wrapper = new CKEDITOR.dom.element( 'div' );
  
  					wrapper.setHtml( data );
  					// Verify for sure and check for nested editor UI parts. (#9675)
  					while ( wrapper.getChildCount() == 1 &&
  							( tmp = wrapper.getFirst() ) &&
  							tmp.type == CKEDITOR.NODE_ELEMENT &&	// Make sure first-child is element.
  							( tmp.hasClass( 'cke_editable' ) || tmp.hasClass( 'cke_contents' ) ) ) {
  						wrapper = editable_wrapper = tmp;
  					}
  
  					// If editable wrapper was found strip it and bogus <br> (added on FF).
  					if ( editable_wrapper )
  						data = editable_wrapper.getHtml().replace( /<br>$/i, '' );
  				}
  
  				if ( CKEDITOR.env.ie ) {
  					// &nbsp; <p> -> <p> (br.cke-pasted-remove will be removed later)
  					data = data.replace( /^&nbsp;(?: |\r\n)?<(\w+)/g, function( match, elementName ) {
  						if ( elementName.toLowerCase() in blockElements ) {
  							evt.data.preSniffing = 'html'; // Mark as not a text.
  							return '<' + elementName;
  						}
  						return match;
  					} );
  				} else if ( CKEDITOR.env.webkit ) {
  					// </p><div><br></div> -> </p><br>
  					// We don't mark br, because this situation can happen for htmlified text too.
  					data = data.replace( /<\/(\w+)><div><br><\/div>$/, function( match, elementName ) {
  						if ( elementName in blockElements ) {
  							evt.data.endsWithEOL = 1;
  							return '</' + elementName + '>';
  						}
  						return match;
  					} );
  				} else if ( CKEDITOR.env.gecko ) {
  					// Firefox adds bogus <br> when user pasted text followed by space(s).
  					data = data.replace( /(\s)<br>$/, '$1' );
  				}
  
  				evt.data.dataValue = data;
  			}, null, null, 3 );
  
  			editor.on( 'paste', function( evt ) {
  				var dataObj = evt.data,
  					type = dataObj.type,
  					data = dataObj.dataValue,
  					trueType,
  					// Default is 'html'.
  					defaultType = editor.config.clipboard_defaultContentType || 'html';
  
  				// If forced type is 'html' we don't need to know true data type.
  				if ( type == 'html' || dataObj.preSniffing == 'html' )
  					trueType = 'html';
  				else
  					trueType = recogniseContentType( data );
  
  				// Unify text markup.
  				if ( trueType == 'htmlifiedtext' )
  					data = htmlifiedTextHtmlification( editor.config, data );
  				// Strip presentional markup & unify text markup.
  				else if ( type == 'text' && trueType == 'html' ) {
  					// Init filter only if needed and cache it.
  					data = htmlTextification( editor.config, data, textificationFilter || ( textificationFilter = getTextificationFilter( editor ) ) );
  				}
  
  				if ( dataObj.startsWithEOL )
  					data = '<br data-cke-eol="1">' + data;
  				if ( dataObj.endsWithEOL )
  					data += '<br data-cke-eol="1">';
  
  				if ( type == 'auto' )
  					type = ( trueType == 'html' || defaultType == 'html' ) ? 'html' : 'text';
  
  				dataObj.type = type;
  				dataObj.dataValue = data;
  				delete dataObj.preSniffing;
  				delete dataObj.startsWithEOL;
  				delete dataObj.endsWithEOL;
  			}, null, null, 6 );
  
  			// Inserts processed data into the editor at the end of the
  			// events chain.
  			editor.on( 'paste', function( evt ) {
  				var data = evt.data;
  
  				editor.insertHtml( data.dataValue, data.type );
  
  				// Deferr 'afterPaste' so all other listeners for 'paste' will be fired first.
  				setTimeout( function() {
  					editor.fire( 'afterPaste' );
  				}, 0 );
  			}, null, null, 1000 );
  
  			editor.on( 'pasteDialog', function( evt ) {
  				// TODO it's possible that this setTimeout is not needed any more,
  				// because of changes introduced in the same commit as this comment.
  				// Editor.getClipboardData adds listner to the dialog's events which are
  				// fired after a while (not like 'showDialog').
  				setTimeout( function() {
  					// Open default paste dialog.
  					editor.openDialog( 'paste', evt.data );
  				}, 0 );
  			} );
  		}