Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent CKEditor replacing spaces with  ?

Tags:

ckeditor

I'm facing an issue with CKEditor 4, I need to have an output without any html entity so I added config.entities = false; in my config, but some   appear when

  • an inline tag is inserted: the space before is replaced with  
  • text is pasted: every space is replaced with   even with config.forcePasteAsPlainText = true;

You can check that on any demo by typing

test test

eg.

Do you know how I can prevent this behaviour?

Thanks!

like image 351
MatTheCat Avatar asked Jan 25 '13 14:01

MatTheCat


3 Answers

Based on Reinmars accepted answer and the Entities plugin I created a small plugin with an HTML filter which removes redundant   entities. The regular expression could be improved to suit other situations, so please edit this answer.

/*
 * Remove   entities which were inserted ie. when removing a space and
 * immediately inputting a space.
 *
 * NB: We could also set config.basicEntities to false, but this is stongly
 * adviced against since this also does not turn ie. < into &lt;.
 * @link http://stackoverflow.com/a/16468264/328272
 *
 * Based on StackOverflow answer.
 * @link http://stackoverflow.com/a/14549010/328272
 */
CKEDITOR.plugins.add('removeRedundantNBSP', {
  afterInit: function(editor) {
    var config = editor.config,
      dataProcessor = editor.dataProcessor,
      htmlFilter = dataProcessor && dataProcessor.htmlFilter;

    if (htmlFilter) {
      htmlFilter.addRules({
        text: function(text) {
          return text.replace(/(\w)&nbsp;/g, '$1 ');
        }
      }, {
        applyToAll: true,
        excludeNestedEditable: true
      });
    }
  }
});
like image 70
lmeurs Avatar answered Nov 09 '22 08:11

lmeurs


These entities:

// Base HTML entities.
var htmlbase = 'nbsp,gt,lt,amp';

Are an exception. To get rid of them you can set basicEntities: false. But as docs mention this is an insecure setting. So if you only want to remove &nbsp;, then I should just use regexp on output data (e.g. by adding listener for #getData) or, if you want to be more precise, add your own rule to htmlFilter just like entities plugin does here.

like image 10
Reinmar Avatar answered Nov 09 '22 06:11

Reinmar


Remove all &nbsp; but not <tag>&nbsp;</tag> with Javascript Regexp

This is especially helpful with CKEditor as it creates lines like <p>&nbsp;</p>, which you might want to keep.

Background: I first tried to make a one-liner Javascript using lookaround assertions. It seems you can't chain them, at least not yet. My first approach was unsuccesful:

return text.replace(/(?<!\>)&nbsp;(?!<\/)/gi, " ")

// Removes &nbsp; but not <p>&nbsp;</p>
// It works, but does not remove `<p>&nbsp; blah &nbsp;</p>`.

Here is my updated working one-liner code:

return text.replace(/(?<!\>\s.)(&nbsp;(?!<\/)|(?<!\>)&nbsp;<\/p>)/gi, " ")

This works as intended. You can test it here.

However, this is a shady practise as lookarounds are not fully supported by some browsers.

Read more about Assertions.

What I ended up using in my production code: I ended up doing a bit hacky approach with multiple replace(). This should work on all browsers.

.trim()                                                            // Remove whitespaces
.replace(/\u00a0/g, " ")                                           // Remove unicode non-breaking space
.replace(/((<\w+>)\s*(&nbsp;)\s*(<\/\w+>))/gi, "$2<!--BOOM-->$4")  // Replace empty nbsp tags with BOOM
.replace(/&nbsp;/gi, " ")                                          // remove all &nbsp;
.replace(/((<\w+>)\s*(<!--BOOM-->)\s*(<\/\w+>))/gi, "$2&nbsp;$4")  // Replace BOOM back to empty tags

If you have a better suggestion, I would be happy to hear 😊.

like image 1
Taikahessu Avatar answered Nov 09 '22 07:11

Taikahessu