CKEditor is a great editor and the pastefromword plugin is very good. I'd like to have the filtering provided by the plugin applied to all pasted text. For example, when pasting from word, all fonts and sizes are stripped. This does not happen when pasting from an email.
That said, I came up with the following solution and posting it here to get some feedback. I'm wondering if I made it too plicated, or if there is an easier way. I kind of just copied the code from pastefromword/plugin.js.
via my custom config.js
...
CKEDITOR.config.pasteFromWordCleanupFile = '/pastefromword.js';
...
CKEDITOR.on( 'instanceReady', function( ev ) {
/**
* Paste event to apply Paste From Word filtering on all text.
*
* The pastefromword plugin will only process text that has tell-tale signs
* it is from Word. Use this hook to treat all pasted text as if
* it is ing from Word.
*
* This method is a slightly modified version of code found in
* plugins/pastefromword/plugin.js
*/
ev.editor.on( 'paste', function( evt ) {
var data = evt.data,
editor = evt.editor,
content;
/**
* "pasteFromWordHappened" is a custom property set in custom
* pastefromword.js, so that filtering does not happen twice for content
* actually ing from Word. It's a dirty hack I know.
*/
if( editor.pasteFromWordHappened ) {
// Reset property and exit paste event
editor.pasteFromWordHappened = 0;
return;
}
var loadRules = function( callback ) {
var isLoaded = CKEDITOR.cleanWord;
if( isLoaded ) {
callback();
}
else {
CKEDITOR.scriptLoader.load( CKEDITOR.config.pasteFromWordCleanupFile, callback, null, false, true );
}
return !isLoaded;
};
content = data['html'];
// No need to filter text if html tags are not presence, so perform a regex
// to test for html tags.
if( content && (/<[^<]+?>/).test(content) ) {
var isLazyLoad = loadRules( function(){
if( isLazyLoad ) {
editor.fire('paste', data);
}
else {
data[ 'html' ] = CKEDITOR.cleanWord( content, editor );
// Reset property or if user tries to paste again, it won't work
editor.pasteFromWordHappened = 0;
}
});
isLazyLoad && evt.cancel();
}
});
});
CKEditor is a great editor and the pastefromword plugin is very good. I'd like to have the filtering provided by the plugin applied to all pasted text. For example, when pasting from word, all fonts and sizes are stripped. This does not happen when pasting from an email.
That said, I came up with the following solution and posting it here to get some feedback. I'm wondering if I made it too plicated, or if there is an easier way. I kind of just copied the code from pastefromword/plugin.js.
via my custom config.js
...
CKEDITOR.config.pasteFromWordCleanupFile = '/pastefromword.js';
...
CKEDITOR.on( 'instanceReady', function( ev ) {
/**
* Paste event to apply Paste From Word filtering on all text.
*
* The pastefromword plugin will only process text that has tell-tale signs
* it is from Word. Use this hook to treat all pasted text as if
* it is ing from Word.
*
* This method is a slightly modified version of code found in
* plugins/pastefromword/plugin.js
*/
ev.editor.on( 'paste', function( evt ) {
var data = evt.data,
editor = evt.editor,
content;
/**
* "pasteFromWordHappened" is a custom property set in custom
* pastefromword.js, so that filtering does not happen twice for content
* actually ing from Word. It's a dirty hack I know.
*/
if( editor.pasteFromWordHappened ) {
// Reset property and exit paste event
editor.pasteFromWordHappened = 0;
return;
}
var loadRules = function( callback ) {
var isLoaded = CKEDITOR.cleanWord;
if( isLoaded ) {
callback();
}
else {
CKEDITOR.scriptLoader.load( CKEDITOR.config.pasteFromWordCleanupFile, callback, null, false, true );
}
return !isLoaded;
};
content = data['html'];
// No need to filter text if html tags are not presence, so perform a regex
// to test for html tags.
if( content && (/<[^<]+?>/).test(content) ) {
var isLazyLoad = loadRules( function(){
if( isLazyLoad ) {
editor.fire('paste', data);
}
else {
data[ 'html' ] = CKEDITOR.cleanWord( content, editor );
// Reset property or if user tries to paste again, it won't work
editor.pasteFromWordHappened = 0;
}
});
isLazyLoad && evt.cancel();
}
});
});
Share
Improve this question
edited Aug 2, 2013 at 13:19
Brian
316 bronze badges
asked Mar 8, 2011 at 0:56
jbarreirosjbarreiros
1,1031 gold badge10 silver badges21 bronze badges
5
- I found this because I'm trying to solve a similar problem. How do you avoid having it strip all content, i.e. keeping the font and font color? – Kevin Commented Mar 18, 2011 at 18:26
- So you want CodeReview.StackExchange. or what? – random Commented Mar 18, 2011 at 20:30
- Kevin, in your custom config.js, set "config.pasteFromWordRemoveFontStyles" to false. Check out the ckeditor api for other settings. – jbarreiros Commented Mar 24, 2011 at 14:41
- random, I did not know that site existed. – jbarreiros Commented Mar 24, 2011 at 14:42
- thanks, I hadn't seen that config setting! Also, it seems to be always 'paste from word' filtering for me right now, though I haven't tested it thoroughly, just with c.extraPlugins = "autogrow,resize,pastefromword"; Maybe adding it as an extraplugin makes it always take effect? – Kevin Commented May 12, 2011 at 16:44
2 Answers
Reset to default 10I'm trying to do something similar. I want a CKEditor instance which applies HTML cleanup rules contained in the pastefromword plugin to everything I paste (mostly snippets of web articles). At the moment this only happens in the following two cases:
- User clicks the 'paste from word' toolbar icon
- User pastes content copied from MS Word itself
In the second case, CKEditor looks for signs of MS Word formatting. It does this by testing whatever you paste against the following regular expression:
/(class=\"?Mso|style=\"[^\"]*\bmso\-|w:WordDocument)/
If there's a match, it will be cleaned up. Otherwise it will paste as normal.
Not wanting to edit the plugin code, or duplicate it. Here's what I've e up with, based on jbarreiros's code:
CKEDITOR.on('instanceReady', function(ev) {
ev.editor.on('paste', function(evt) {
evt.data['html'] = '<!--class="Mso"-->'+evt.data['html'];
}, null, null, 9);
});
I haven't tested extensively, but this appears to work as expected (CKEditor 3.6.2).
What the code does is it registers a new listener for the paste event, just like the Paste from Word plugin. When it receives the pasted HTML, it simply prepends an HTML ment containing one of the strings the Paste from Word plugin looks for. The listener has a priority of 9 to ensure it runs before the plugin which will trigger the actual cleaning (default priority of 10).
My solution is in this blog entry: http://www.keyvan/2012/11/clean-up-html-on-paste-in-ckeditor/
Commenting on a old question: The issue at hand is not just word cleaning in CKEditor. Its also a matter of what the browser does when you ask for clip board content via javascript api. that differs heavily between IE, FF, Safari etc. Typically the non IE browsers will clean up the HTML themself, beofore giving the HTML to the browser. Thus removing a lot of formatting.