Open nakupanda opened 5 years ago
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 Great! Thank you for looking at this.
For now I'm switching back to CKEditor 4 for my purpose.
Hi @Mgsy ,I think this feautre is very important.May I know when this feature will be supported? Thanks.
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.
The same goes for images. This is especially important if they are to be used in email templates.
May I know when this feature will be supported? Thanks.
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.
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.
I temporarily got around this issue with juice:
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>`;
yarn add juice
;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
en.. and i very hope support this feature.
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!
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
I was able to create a temporary solution with Vue2 based from @ogabrielsantos's answer. I created a custom component with the following plugins:
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);
},
},
});
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)
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?
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...
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.
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?
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..
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...
hi, this is my temporary solution 😁
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.
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.
Is there any update for this feature??
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.
styles="font-weight:10px;color:black"
.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.
This feature would really be great. Looking forward to it being implemented.
Bump! We've been waiting for this feature for ages. The CKEditor community really needs this!
+1
Been waiting so long for this, please make this happen soon.
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 :(
Looking forward to it being implemented.
Any update? Wanted this feature
I recently encountered similar issue. To address this, I developed a custom plugin that overrides the 'insertTable' command's default behavior. Upon executing the 'insertTable' command, my plugin not only inserts the table but also applies predefined styles directly to the table and its cells. The Approach: My solution involves setting an observer on the 'insertTable' command. When a table is inserted, the plugin programmatically invokes style commands, such as TableBorderStyleCommand and TableCellBorderStyleCommand, ensuring the styles are applied inline. I'm sharing the core part of my custom plugin below, hoping it might help others facing similar challenges:
setObserver(): void {
const editor = this.editor;
const insertTableCommand = editor.commands.get('insertTable');
// Store the original execute method
const originalExecute = insertTableCommand.execute.bind(insertTableCommand);
// Override the execute method
insertTableCommand.execute = (options?) => {
// Call the original execute method to actually insert the table
originalExecute(options);
// Apply styles to the newly inserted table
this.applyStylesToTable(editor);
// Apply styles to all the cells in the newly inserted table
this.applyStylesToTableCells(editor);
};
}
applyStylesToTable(editor: Editor): void {
const commands = editor.commands;
// Apply the border styles
commands.get('tableBorderStyle')?.execute({ value: 'solid' });
}
applyStylesToTableCells(editor: Editor): void {
const commands: CommandCollection = editor.commands;
// Get the newly created table element in the document.
const table = this.getCreatedTable(editor);
if (table) {
// Select all table cells
this.selectAllCells(editor, table);
// Apply the border styles
(commands.get('tableCellBorderStyle') as TableCellBorderStyleCommand)?.execute({ value: 'solid' });
// Select first cell of the table (so as to maintain the previous behavior of having first cell as selected after inserting a table)
this.selectFirstCell(editor, table);
}
}
This custom plugin effectively solves the issue by ensuring that every table inserted through the editor comes with the desired inline styles, fulfilling the requirements for direct HTML styling. I hope this solution proves useful to others in the community. Feedback or suggestions for improvement are welcome!
Best regards, Venkatesh
Is there any update. ? Anybody have the idea for save output and render it on pdf with content style ?
5 years later... CKEditor team still has other higher priorities.
Hey, we appreciate all the pings, we have plans to jump to this topic this year, so stay tuned.
+1
+1
🆙
+1
+5
+99999999999999999
let's do it, please
+2
You can get HTML like this: editor.sourceElement.innerHTML
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:
In my case, what I actually want is:
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.