quill icon indicating copy to clipboard operation
quill copied to clipboard

Pasting html content (e-mail) partially remove css ( on images )

Open guilhemwishibam opened this issue 7 years ago • 12 comments

Lastest version of quill, Im using quill to answers to mails Pasting my mail content [html] with editor.clipboard.dangerouslyPasteHTML();

My html content is fine, but when pasted, all inline css on images are removed

Do i miss any configuration ? This is my Quill config

var toolbarOptions = [
 ['bold', 'italic', 'underline', 'strike'],        // toggled buttons
 ['blockquote', 'code-block'],

 [{ 'header': 1 }, { 'header': 2 }],               // custom button values
 [{ 'list': 'ordered'}, { 'list': 'bullet' }],
 [{ 'script': 'sub'}, { 'script': 'super' }],      // superscript/subscript
 [{ 'indent': '-1'}, { 'indent': '+1' }],          // outdent/indent
 [{ 'direction': 'rtl' }],                         // text direction

 [{ 'size': ['small', false, 'large', 'huge'] }],  // custom dropdown
 [{ 'header': [1, 2, 3, 4, 5, 6, false] }],
 ['link', 'image'],
 [{ 'color': [] }, { 'background': [] }],          // dropdown with defaults from theme
 [{ 'font': [] }],
 [{ 'align': [] }],

 ['clean']                                         // remove formatting button
];
 var options = {
   debug: 'info',
   modules: {
     toolbar: toolbarOptions,
     clipboard: {
       matchVisual: false,
       matchers: [
       ]
     }
   },
   placeholder: 'Compose an epic...',
   readOnly: false,
   theme: 'snow'
 };
 var editor = new Quill('#message_tiny', options);`

html to had : <img src="https://img.jpg" width="600" height="200" style="width:600px;height:200px;"> result: <img src="https://img.jpg">

Platforms:

Mac Osx, Chrome 63.0.3239.84

Version: Quill version : "1.3.4"

guilhemwishibam avatar Jan 03 '18 13:01 guilhemwishibam

Show an example of HTML you are trying to paste and fill in the rest of the info requested in the issue template.

benbro avatar Jan 03 '18 13:01 benbro

Html like this one

<img src="https://img.jpg" width="600" height="200" style="width:600px;height:200px;">

guilhemwishibam avatar Jan 03 '18 13:01 guilhemwishibam

I'm having the same issue over here.

If I paste HTML into the editor, all the inline CSS is lost and the HTML elements are converted to paragraphs and simpler element types.

Example:

<div style="width:375px">
    <div style="width:375px;margin-bottom:20px">
        <div style="margin:20px;float:left">
            <img src="www.dummy-data-img.com">
        </div>
        <div>
            <h1 style="font-family:OpenSans-Bold,sans-serif;font-size:18px;color:rgb(85,186,231);font-weight:normal;margin:0px">
                Foo Foo
            </h1>
            <h2 style="font-family:OpenSans-SemiBold,sans-serif;font-size:14px;color:rgb(102,102,102);margin:0px 0px 7px;font-weight:normal">
                Web Developer
            </h2>
            <h3 style="font-family:OpenSans-SemiBold,sans-serif;font-size:12px;color:rgb(102,102,102);margin:0px 0px 3px;font-weight:normal">
                9000005500
            </h3>
            <h3 style="font-family:OpenSans-SemiBold,sans-serif;font-size:12px;color:rgb(102,102,102);margin:0px;font-weight:normal">
                <a href="mailto:[email protected]" target="_blank">[email protected]</a>
            </h3>
            <div style="width:375px">
                <p style="font-family:LucidaGrande;font-size:8px;color:rgb(102,102,102)">
                    Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy
                </p>
            </div>
        </div>
    </div>
</div>

Is converted to:

<div class="ql-editor" contenteditable="true" data-placeholder="Insert text here ...">
    <p><img
        src="www.dummy-data-img.com">
</p>
    <h1></h1>
    <h2>Web Developer</h2>
    <h3>(+351) 918 410 053</h3>
    <h3><a href="mailto:[email protected]" target="_blank">[email protected]</a></h3>
    <p><br></p>
    <p>Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy Dummy</p>
</div>

Is there any way of allowing the pasting of HTML as it is or it's just a missing feature/bug?

Platforms: Ubuntu Gnome LTS, Chrome 63.0.3239.132

Version: Quill version : "1.1.5"

freitasskeeled avatar Jan 15 '18 14:01 freitasskeeled

@guilhemwishibam By specifying matchers: [] you are losing all the defaults. The expected output is <img src="https://img.jpg" width="600" height="200"> if you use the default configuration.

@freitasskeeled Quill does not allow arbitrary HTML in its contents as it is not safe from a user experience or bug free perspective. Allowing arbitrary HTML is why the previous generation of rich text editors gained their notoriety for bugginess and why Quill was built and became popular. Quill does provide a way for to safely paste new content through its Clipboard APIs: https://quilljs.com/docs/modules/clipboard. If you find this too onerous and would rather risk the occasional bugs, other said editors still exist and are also open source.

jhchen avatar Jan 18 '18 09:01 jhchen

@jhchen Thank you for the feedback. Is it possible to enable the pasting of HTML with inline CSS at all? I understand what you meant but I'm not talking about script tags with potential open door to attacks.

freitasskeeled avatar Jan 19 '18 09:01 freitasskeeled

@freitasskeeled No this is not possible. I'm not talking about safety from a security perspective -- I'm talking about safely from a bug free perspective. Browsers decide to do very peculiar things with the most innocuous modifications.

jhchen avatar Jan 22 '18 18:01 jhchen

OK... I've tried all sorts of solutions. I created and registered custom format blots and attributors. I was unsuccessful registering anything that would allow an img tag to have a very specific set of attributes.
I understand the philosophy behind deltas and totally agree. What an incredible solution! I was unable to find any examples for clipboard or documentation for deltas that demonstrate how one can extend what is recognized.
If I understand the principle of Deltas, it would be ideal to represent the alignment of an image using an 'align' attribute. Then, when formatting the dom, the formatter would emit the appropriate style="float:left; margin:1em" during conversion. I was unable to produce this using a custom formatter. You can see one attempt here: CodePen ReactQuill Custom Blot Eventually, I forked Quill and made the necessary changes in the default Image blot. This worked!

Here is the diff:

@@ -1,20 +1,36 @@
 import Parchment from 'parchment';
 import { sanitize } from '../formats/link';
 
+// override attributes to support image attributes.
+//  alt, width, height, and style alignment )
+// TODO: make checks to ensure style only contains the desired declarations
+//      float; margin; display;
 const ATTRIBUTES = [
+  'src',
   'alt',
   'height',
-  'width'
+  'width',
+  'style'
 ];
 
 
 class Image extends Parchment.Embed {
+
   static create(value) {
-    let node = super.create(value);
+    const imageNode = ATTRIBUTES.reduce(function(node, attribute) {
+      const attrPresent = Object.prototype.hasOwnProperty.call(value, attribute);
+      if (attrPresent) {
+        node.setAttribute(attribute, value[attribute]);
+      }
+      return node;
+    }, super.create(value));
+
+    // check for string only as in when uploading or dropping an image file
     if (typeof value === 'string') {
-      node.setAttribute('src', this.sanitize(value));
+      imageNode.setAttribute('src', this.sanitize(value));
     }
-    return node;
+
+    return imageNode;
   }
 
   static formats(domNode) {
 @@ -35,7 +51,12 @@ class Image extends Parchment.Embed {
   }
 
   static value(domNode) {
-    return domNode.getAttribute('src');
+    return ATTRIBUTES.reduce(function(formats, attribute) {
+      if (domNode.hasAttribute(attribute)) {
+        formats[attribute] = domNode.getAttribute(attribute);
+      }
+      return formats;
+    }, {});
   }
 
   format(name, value) {
     if (ATTRIBUTES.indexOf(name) > -1) {
       if (value) {
         this.domNode.setAttribute(name, value);
       } else {
         this.domNode.removeAttribute(name);
       }
     } else {
       super.format(name, value);
     }
   }
 }
 Image.blotName = 'image';
 Image.tagName = 'IMG';
 
 
 export default Image;

I would like to accomplish this in the proper way. Is there any way to allow these attributes to be retained on an img element through Quill?

The specific use case is that I need to align and resize images in html. The ImageResize module and retain the html changes made by that utility. The issue is posted here.

levous avatar Feb 22 '18 22:02 levous

enable the pasting of HTML with inline CSS at all. is it can be a feature in config to open it ? some scene we need this feature

sunchenguang avatar Oct 12 '18 06:10 sunchenguang

A keepHTML blot could solve the problem:

import Quill from 'quill';
const BlockEmbed = Quill.import('blots/block/embed');

class keepHTML extends BlockEmbed {
  static create(node) {
    return node;
  }
  static value(node) {
    return node;
  }
};

keepHTML.blotName = 'keepHTML';
keepHTML.className = 'keepHTML';
keepHTML.tagName = 'div';

Quill.register(keepHTML);

What this does is that if any html node has "keepHTML" class, the whole html node will be preserved.

blackChef avatar Nov 23 '19 12:11 blackChef

It seems that the below is what causes the removal/change of CCS when using dangerouslyPasteHTML

static value(node) {
   return node;
}

fomson avatar Jan 22 '20 21:01 fomson

Hi,

I'm not able to copy the text inside the email from replies. Screenshot (81)

ShehnazShaik avatar Jan 30 '20 14:01 ShehnazShaik

A keepHTML blot could solve the problem:

import Quill from 'quill';
const BlockEmbed = Quill.import('blots/block/embed');

class keepHTML extends BlockEmbed {
  static create(node) {
    return node;
  }
  static value(node) {
    return node;
  }
};

keepHTML.blotName = 'keepHTML';
keepHTML.className = 'keepHTML';
keepHTML.tagName = 'div';

Quill.register(keepHTML);

What this does is that if any html node has "keepHTML" class, the whole html node will be preserved.

Yeah this won't work if you don't have control over the html being input into the quill editor. I'm looking for the correct quill configuration to allow for img style width/height to be converted to attributes width/height. So far the internet has failed me and this is the closest bug report. Any movement on this?

morecpq avatar Sep 02 '22 17:09 morecpq

I'm in the same position as you @morecpq. Pls @jhchen can you add this feature?

tyzion avatar Nov 17 '22 14:11 tyzion

5 years on this is still ongoing - @jhchen it'd be ideal if a boolean could be pass to preserve HTML attributes/classes, and explicit argument so that developers know it might lead to "bugginess" etc. :)

ThePeterMick avatar Feb 08 '23 14:02 ThePeterMick

@morecpq I don't know if this can actually help you, and it took me some time to understand how Blot works

Anyway, as blackChef suggested you can use Blots (more about Blots on quilljs guide section ) to modify the formats of html tags I use React, I don't know how you import quill editor in your project, but here's a very simple example on how to use blots to style img tags with "react-quill" npm package

https://codepen.io/tiziano-meola/pen/YzOzQZr

Hope this helps :)

tyzion avatar Feb 14 '23 13:02 tyzion

@morecpq I don't know if this can actually help you, and it took me some time to understand how Blot works

Anyway, as blackChef suggested you can use Blots (more about Blots on quilljs guide section ) to modify the formats of html tags I use React, I don't know how you import quill editor in your project, but here's a very simple example on how to use blots to style img tags with "react-quill" npm package

https://codepen.io/tiziano-meola/pen/YzOzQZr

Hope this helps :)

This solves my issue. Thanks a lot

namlh023 avatar Jan 27 '24 14:01 namlh023

Quill 2.0 has been released (announcement post) with many changes and fixes. If this is still an issue please create a new issue after reviewing our updated Contributing guide :pray:

quill-bot avatar Apr 17 '24 11:04 quill-bot