@@ -47,6 +47,11 @@ import ImagePlugin from '@ckeditor/ckeditor5-image/src/image.js'
4747import FindAndReplace from ' @ckeditor/ckeditor5-find-and-replace/src/findandreplace.js'
4848import ImageResizePlugin from ' @ckeditor/ckeditor5-image/src/imageresize.js'
4949import ImageUploadPlugin from ' @ckeditor/ckeditor5-image/src/imageupload.js'
50+ import ImageStylePlugin from ' @ckeditor/ckeditor5-image/src/imagestyle.js'
51+ import ImageToolbarPlugin from ' @ckeditor/ckeditor5-image/src/imagetoolbar' ;
52+ import ImageUtilsPlugin from ' @ckeditor/ckeditor5-image/src/imageutils' ;
53+ import ImageCaptionPlugin from ' @ckeditor/ckeditor5-image/src/imagecaption' ;
54+ import ImageTextAlternativePlugin from ' @ckeditor/ckeditor5-image/src/imagetextalternative' ;
5055import GeneralHtmlSupport from ' @ckeditor/ckeditor5-html-support/src/generalhtmlsupport.js'
5156import { DropdownView } from ' @ckeditor/ckeditor5-ui'
5257import MailPlugin from ' ../ckeditor/mail/MailPlugin.js'
@@ -129,6 +134,11 @@ export default {
129134 ImagePlugin,
130135 ImageUploadPlugin,
131136 ImageResizePlugin,
137+ ImageStylePlugin,
138+ ImageToolbarPlugin,
139+ ImageUtilsPlugin,
140+ ImageCaptionPlugin,
141+ ImageTextAlternativePlugin,
132142 ListProperties,
133143 FontPlugin,
134144 RemoveFormat,
@@ -196,6 +206,18 @@ export default {
196206 },
197207 ],
198208 },
209+ image: {
210+ toolbar: [
211+ ' imageStyle:alignLeft' ,
212+ ' imageStyle:alignCenter' ,
213+ ' imageStyle:alignRight' ,
214+ ' |' ,
215+ ' imageTextAlternative' ,
216+ ],
217+ styles: [
218+ ' alignLeft' , ' alignCenter' , ' alignRight' ,
219+ ],
220+ },
199221 },
200222 }
201223 },
@@ -278,6 +300,44 @@ export default {
278300
279301 return itemElement
280302 },
303+ convertImageClassesToInlineStyles (html ) {
304+ const div = document .createElement (' div' );
305+ div .innerHTML = html;
306+
307+ div .querySelectorAll (' figure.image' ).forEach (figure => {
308+ // Keep the original style attribute
309+ let baseStyle = figure .getAttribute (' style' ) || ' ' ;
310+ let alignmentStyle = ' display:block;margin-top:1em;margin-bottom:1em;' ;
311+
312+ if (figure .classList .contains (' image-style-align-left' )) {
313+ alignmentStyle += ' margin-left:0;margin-right:auto;' ;
314+ } else if (figure .classList .contains (' image-style-align-right' )) {
315+ alignmentStyle += ' margin-left:auto;margin-right:0;' ;
316+ } else if (figure .classList .contains (' image-style-align-center' )) {
317+ alignmentStyle += ' margin-left:auto;margin-right:auto;text-align:center;' ;
318+ }
319+
320+ // Combine original styles with alignment styles
321+ const combinedStyle = ` ${ baseStyle .trim ()}${ ! baseStyle .endsWith (' ;' ) ? ' ;' : ' ' }${ alignmentStyle} ` ;
322+ figure .setAttribute (' style' , combinedStyle);
323+
324+ // IMPORTANT: Do NOT remove alignment classes
325+ // so CKEditor can reuse them when reopening the content
326+
327+ // Adjust the <img> inside the figure to ensure correct display in email clients
328+ const img = figure .querySelector (' img' );
329+ if (img) {
330+ const baseImgStyle = img .getAttribute (' style' ) || ' ' ;
331+ const imgStyle = ' display:block;margin:0 auto;max-width:100%;height:auto;border:0;' ;
332+ img .setAttribute (
333+ ' style' ,
334+ ` ${ baseImgStyle .trim ()}${ ! baseImgStyle .endsWith (' ;' ) ? ' ;' : ' ' }${ imgStyle} `
335+ );
336+ }
337+ });
338+
339+ return div .innerHTML ;
340+ },
281341 overrideDropdownPositionsToNorth (editor , toolbarView ) {
282342 const {
283343 south , north , southEast , southWest , northEast , northWest ,
0 commit comments