ckeditor5 icon indicating copy to clipboard operation
ckeditor5 copied to clipboard

Possible to make editor.getData() returns content with inline styles?

Open nakupanda opened this issue 6 years ago • 42 comments

Hi,

Thanks for the new CKEditor (to me it's new).

Here is my question:

When inserting tables, we get content by editor.getData() like:

<figure class="table"><table><tbody><tr><td>....... <table></figure>

In my case, what I actually want is:

<table style="border: 1px solid #ccc...">....</table>

The reason is that the content will be used again in another WYSIWYG editor and finally sent as email and we expect who received the email would see a decently styled email.

Any help would be appreciated.


If you'd like to see this feature implemented, add 👍 to this post.

nakupanda avatar Mar 13 '19 07:03 nakupanda

Hello, @nakupanda! Basically, it's possible to achieve the result you mentioned, but it requires changing all downcast converters.

I'll confirm your issue as a feature request. We might create API for this purpose and the feature could be called "inlining styles". Anyway, we can't declare any ETA for this one right now.

Mgsy avatar Mar 14 '19 11:03 Mgsy

@Mgsy Great! Thank you for looking at this.

For now I'm switching back to CKEditor 4 for my purpose.

nakupanda avatar Mar 15 '19 02:03 nakupanda

Hi @Mgsy ,I think this feautre is very important.May I know when this feature will be supported? Thanks.

ghost avatar Sep 24 '19 06:09 ghost

Hi @Mgsy ,I think this feautre is very important.May I know when this feature will be supported? Thanks.

Hi @mengjoel, we understand that this feature might be important for you. However, unfortunately, due to other priorities, we don't have ETA for it.

Feel free to add 👍 to the first post, it will allow us to track a popularity of this request.

Mgsy avatar Nov 28 '19 16:11 Mgsy

The same goes for images. This is especially important if they are to be used in email templates.

jswiderski avatar Nov 29 '19 10:11 jswiderski

May I know when this feature will be supported? Thanks.

0uergujiaming avatar Jun 01 '20 09:06 0uergujiaming

I like the case mentioned in #8004 by @justlester:

Hi! I am using the CKEditor 5 for creating email content.
When I get output data from the editor, the image output in HTML have class styles of "image-style-right":

<figure class="image image_resized image-style-align-right" style="width:484px;">
<img src="https://c.cksource.com/a/1/img/docs/sample-image-bilingual-personality-disorder.jpg">
<figcaption>One language, one person.</figcaption>
</figure>

What I need is:

<figure style="width:484px; float:right;margin: 16px 0 16px 24px;">
<img style="width:100%" src="https://c.cksource.com/a/1/img/docs/sample-image-bilingual-personality-disorder.jpg">
<figcaption style="text-align:center; padding: .6em;font-size: .75em;">One language, one person.</figcaption>
</figure>

Without the styles, I can't display the image properly. I read the documentation but I'm not sure what APIs I will be using.

What it shows is that it's not only about the <figure> itself but also about all the elements inside that might've been styled by a selector consisting of figure.image.

IMO, the same applies to all styles that might've been applied to the content. That includes styles for p, h1, blockquote, etc. The editor does not come with styles for these elements, but the page on which it is integrated usually does. And when trying to reflect the same styles in an email or a different medium (we had the same problem with export to PDF), it's best if these styles are inlined.

Therefore, I think we should consider a mechanism capable of inlining an entire set of styles. It'd be best if it simply combined output HTML + stylesheets.

Reinmar avatar Sep 22 '20 10:09 Reinmar

I too use the ckeditor5 to generate HTML for sending as email content. Without the styling inline the recipient doesn't get what we see on screen.

djkarlos avatar Sep 24 '20 12:09 djkarlos

I temporarily got around this issue with juice:

  • First, I've removed ck-content prefix from Content Styles and stored it for later use:
const styles = `<styles>
:root {
    --ck-color-mention-background: hsla(341, 100%, 30%, 0.1);
    --ck-color-mention-text: hsl(341, 100%, 30%);
    --ck-highlight-marker-blue: hsl(201, 97%, 72%);
    --ck-highlight-marker-green: hsl(120, 93%, 68%);
    --ck-highlight-marker-pink: hsl(345, 96%, 73%);
    --ck-highlight-marker-yellow: hsl(60, 97%, 73%);
    --ck-highlight-pen-green: hsl(112, 100%, 27%);
    --ck-highlight-pen-red: hsl(0, 85%, 49%);
    --ck-image-style-spacing: 1.5em;
    --ck-todo-list-checkmark-size: 16px;
}

/* ckeditor5-highlight/theme/highlight.css */
.marker-yellow {
    background-color: var(--ck-highlight-marker-yellow);
}

/* and so on.. */
</styles>`;
  • Installed juice: yarn add juice;
  • and lastly, converted what was typed into inline styles:
import InlineEditor from '@ckeditor/ckeditor5-editor-inline/src/inlineeditor';
import CKEditor from '@ckeditor/ckeditor5-react';
import juice from 'juice';

<CKEditor
  editor={InlineEditor}
  data=""
  onChange={(event, editor) => {
    const data = editor.getData();

    console.log(juice.inlineContent(data, styles));
  }}
/>

Worked weel when using CKEDITOR plugins and sending inlined datas as email body.

ps: base64 images doesn't works with major email clients, so I've disabled inline images as this are not one of my requirements ps2: I will be glad to see an official solution

ogabrielsantos avatar Oct 04 '20 04:10 ogabrielsantos

en.. and i very hope support this feature.

xiongsongsong avatar Nov 18 '20 15:11 xiongsongsong

We have a need to use the contents of the editor as the body of emails. Most Email clients ignore any non-in-line CSS so we are very interested in an option to output all in-line styles. Thank you!

dmboucher avatar Nov 18 '20 17:11 dmboucher

I was panicking that juice was not working in my nuxt project, the installation failed, but when i reinstall the node_modules i was able to install juice.js 7.00 version currently

jerickcm avatar Nov 30 '20 23:11 jerickcm

I was able to create a temporary solution with Vue2 based from @ogabrielsantos's answer. I created a custom component with the following plugins:

  1. @ckeditor/ckeditor5-vue2
  2. juice (needed to convert styles to inline styles)
  3. postcss-css-variables (needed to convert css variables to static values)
Vue.component('ckeditor5-textarea',{
    template: /*html*/`
        <ckeditor :editor="editorBuild" :config="config" v-model="innerEditorValue" @ready="onEditorReady" @input="onEditorChange"></ckeditor>
    `,
    components: {
        ckeditor: CKEditorSource.Vue2CKEditor.component
    },
    props: {
        value: {
            type: String,
            default: ''
        },
        config: {
            type: Object,
            default: ()=>({
                toolbar: {
                    items: [
                        'undo',
                        'redo',
                        '|',
                        'removeFormat',
                        'bold',
                        'italic',
                        'underline',
                        'link',
                        'numberedList',
                        'bulletedList',
                    ],
                },
            })
        }
    },
    data(){
        return {
            editorBuild: CKEditorSource.Editor,
            lastValue: '',
            innerEditorValue: '', 
            editorStyles: '',      
        }
    },  
    mounted() {
         //get ckeditor styles, convert css variables to static using postcss-css-variables
        //and save to editorStyles for later use
        var stylesObj = Array.from(document.getElementsByTagName('style')).find(x=>x.hasAttribute("data-cke"));
        this.editorStyles = CKEditorSource.EditorUtils.postcss([CKEditorSource.EditorUtils.cssvariables()]).process((stylesObj ? stylesObj.innerHTML : '')).css;
    },
    watch: {
        value(newVal,oldVal){
              //prevents undo stack from clearing unless new value is being passed to v-model
            if(newVal !== oldVal && newVal !== this.lastValue){
                this.innerEditorValue = (newVal || '');
            }
        }
    },
    methods: {
        onEditorReady(editor){
            //set editor value after created
            this.innerEditorValue = this.value || '';
            this.$emit('ready',editor);
        },
        onEditorChange(value){
            //with the editorStyles, convert using juice
           //and emit back the value with the inline style
            var htmlWithInlineStyles = CKEditorSource.EditorUtils.juice.inlineContent(`<div class="ck-content">${value}</div>`,this.editorStyles);
            var div = document.createElement('div'); 
            div.innerHTML = htmlWithInlineStyles;
            var currentData = div.firstChild ? div.firstChild.innerHTML : '';
            //set the lastValue 
            var d = this.lastValue = currentData;
            this.$emit('input',d);
        },
    },
});

justlester avatar Dec 17 '20 06:12 justlester

for me installing Juice with ckeditor 5 version 28.0.0 cause the ckeditor to not display on the page after building the js file. why couldnt it be built simplier, like emailStyleFormat: true or false (if false use the bootstrap classes, else used the styling for Outlook). All I want is to see the colors (font colors, background colors, table borders and highlight colors) to be supported with Outlook emails.

what's the easiest method (how to downcast in using legacy styling instead)

zomby22 avatar Jun 21 '21 13:06 zomby22

Any status update on this request? Seems like a potential blocker to using CKEditor5 if the purpose is to create emails. Has any work arounds been established to support this email build use case in 5?

jesstrable avatar Oct 13 '21 22:10 jesstrable

This feature is very important! Please help us get this thing faster, breaking changes between ck4 and ck5 should be prioritize...

** After further checking it seems most classes are required with .ck.ck-content and when showing them on other screens/emails style must be added... This is a problem to solve as soon as possible...

kuku711 avatar Nov 09 '21 14:11 kuku711

I think this feature is very important. At least for web we can solve this issue with adding full css to our document. What about mobile application? Because rich text content can be rendered also for mobile devices.

rasimatics avatar Feb 04 '22 16:02 rasimatics

Hi, it's 2022 and this is still a feature that is not in the editor? I'm frankly astonished that this is not included as default prop to react component / setting in the CKEditor. You even advertise the editor as being suitable for email content.

What's going on? 3 years later?

ortonomy avatar Jul 15 '22 03:07 ortonomy

This is blocking issue for us to start using CKEditor5 to compose email templates. I don't see the point of composing html with css classes that are only defined in the scope of CKEditor5, and are not included in the final html result.

Or you include the css classes definitions as part of the html result inside <style> or you include all of those as inline styles as <table style="..."> If not the html composed it's only properly visible inside the CKEditor5 box, but not outside of it..

sluc23 avatar Sep 01 '22 11:09 sluc23

I want to add my comment that this is a really important feature. I just finished implementing email templates using ckeditor5 before realizing that styles don't translate over into email clients. Inlining the styles is extremely important for content portability beyond just the email use case. Hopefully we will hear an update on this request soon...

rferons avatar Feb 01 '23 18:02 rferons

hi, this is my temporary solution 😁

  1. get content styles.
  2. get editor content value.
  3. use juice convert styles to inline styles.
import juice from 'juice';

const CkeditorUtil = {
  getEditorStyles() {
    const cssTexts = [], rootCssTexts = [];
    
    for (const styleSheets of document.styleSheets) {
      if (styleSheets.ownerNode.hasAttribute('data-cke')) {
        for (const cssRule of styleSheets['cssRules']) {
          if (cssRule.cssText.indexOf('.ck-content') !== -1) {
            cssTexts.push(cssRule.cssText);
          } else if (cssRule.cssText.indexOf(':root') !== -1) {
            rootCssTexts.push(cssRule.cssText);
          }
        }
      }
    }

    return cssTexts.length ? [...rootCssTexts, ...cssTexts].join(' ').trim() : '';
  },
  getContentWithLineStyles(editorContent) {
    return juice.inlineContent(`<div class="ck-content">${editorContent}<div>`, CkeditorUtil.getEditorStyles());
  }
};

export default CkeditorUtil;
// convert
CkeditorUtil.getContentWithLineStyles(editorContent);

if you needed to convert css variables to static values, You can refer to this code.

ekoooo avatar Feb 03 '23 04:02 ekoooo

This feature is really important. I don't understand how it got such a negative response. Also, this problem has been going on for a long time. Up to 3 years long.

OzgurAkinci avatar Feb 19 '23 17:02 OzgurAkinci

Is there any update for this feature??

ashishforgrz avatar Jul 13 '23 11:07 ashishforgrz

As for the temp fix using juice to dynamically inject inline styles suggested by @ogabrielsantos, I see there might be an issue regarding the format of injected inline styles.

  1. CKE5 internally shrinks inline styles and outputs them compressed: styles="font-weight:10px;color:black".
  2. Unlike juice that injects in a standard CSS way with white-spaces between CSS properties: styles="font-weight: 10px; color: black".

Is there someone who synchronized inline handling between CKE5 and juice approaches, or any reliable way to achieve it without RegExp? Otherwise, it would trigger redundant value update (CKE5 content data). Especially if React or similar has been used, onChange would change the output value each time with juice, then CKE5 compresses the injected styles back.

AliaksandrBortnik avatar Jul 17 '23 12:07 AliaksandrBortnik

This feature would really be great. Looking forward to it being implemented.

ferreira-tb avatar Oct 20 '23 22:10 ferreira-tb

Bump! We've been waiting for this feature for ages. The CKEditor community really needs this!

o-yanchenko avatar Nov 23 '23 20:11 o-yanchenko

+1

NvanWeeghel avatar Feb 09 '24 12:02 NvanWeeghel

Been waiting so long for this, please make this happen soon.

edwardbryant avatar Mar 06 '24 18:03 edwardbryant

Estuve revisando y aun no esta esa funcion, realmente es importante, consideo que lo hacen para que se pague la licencia premium para exportar en pdf y en word :(

Alejjito avatar Mar 13 '24 21:03 Alejjito

Looking forward to it being implemented.

ilapavuluri avatar Apr 18 '24 06:04 ilapavuluri