[DrupalImage] Image be displayed even if it upload fail in CKEditor 5

Created on 30 November 2023, 12 months ago
Updated 6 December 2023, 12 months ago

Problem/Motivation

Image can be displayed (Shouldn't be displayed) even if it upload fail because the image be encode to base64 format first and be displayed, then drupal run some validation and creating the image file.

Steps to reproduce

1. Set image file size limit in /admin/config/content/formats/manage/basic_html?destination=/admin/config/content/formats

2. Upload big image in Ckeditor5

๐Ÿ› Bug report
Status

Needs work

Version

11.0 ๐Ÿ”ฅ

Component
CKEditor 5ย  โ†’

Last updated about 15 hours ago

Created by

๐Ÿ‡จ๐Ÿ‡ณChina lawxen

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

  • JavaScript

    Affects the content, performance, or handling of Javascript.

Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @lawxen
  • ๐Ÿ‡จ๐Ÿ‡ณChina lawxen
  • ๐Ÿ‡จ๐Ÿ‡ณChina lawxen
  • ๐Ÿ‡ง๐Ÿ‡ชBelgium wim leers Ghent ๐Ÿ‡ง๐Ÿ‡ช๐Ÿ‡ช๐Ÿ‡บ

    Thanks for the bug report!

    EDIT: Ah, by uploading an image larger than the allowed file size?

  • ๐Ÿ‡จ๐Ÿ‡ณChina lawxen

    EDIT: Ah, by uploading an image larger than the allowed file size?

    Yes

  • ๐Ÿ‡จ๐Ÿ‡ณChina lawxen

    I'm wondering if this can quick fix the problem in project:
    Changing the config of ckeditor5_imageUpload in a custom module, using Simple upload adapter instead of the default Base64 image upload adapter(Not sure about the default upload adapter)

  • ๐Ÿ‡จ๐Ÿ‡ณChina lawxen

    Problem casued here:
    web/core/node_modules/@ckeditor/ckeditor5-image/src/imageupload/imageuploadediting.js

        /**
         * Reads and uploads an image.
         *
         * The image is read from the disk and as a Base64-encoded string it is set temporarily to
         * `image[src]`. When the image is successfully uploaded, the temporary data is replaced with the target
         * image's URL (the URL to the uploaded image on the server).
         */
        _readAndUpload(loader) {
            const editor = this.editor;
            const model = editor.model;
            const t = editor.locale.t;
            const fileRepository = editor.plugins.get(FileRepository);
            const notification = editor.plugins.get(Notification);
            const imageUtils = editor.plugins.get('ImageUtils');
            const imageUploadElements = this._uploadImageElements;
            model.enqueueChange({ isUndoable: false }, writer => {
                writer.setAttribute('uploadStatus', 'reading', imageUploadElements.get(loader.id));
            });
            return loader.read()
                .then(() => {
                const promise = loader.upload();
                const imageElement = imageUploadElements.get(loader.id);
                // Force reโ€“paint in Safari. Without it, the image will display with a wrong size.
                // https://github.com/ckeditor/ckeditor5/issues/1975
                /* istanbul ignore next -- @preserve */
                if (env.isSafari) {
                    const viewFigure = editor.editing.mapper.toViewElement(imageElement);
                    const viewImg = imageUtils.findViewImgElement(viewFigure);
                    editor.editing.view.once('render', () => {
                        // Early returns just to be safe. There might be some code ran
                        // in between the outer scope and this callback.
                        if (!viewImg.parent) {
                            return;
                        }
                        const domFigure = editor.editing.view.domConverter.mapViewToDom(viewImg.parent);
                        if (!domFigure) {
                            return;
                        }
                        const originalDisplay = domFigure.style.display;
                        domFigure.style.display = 'none';
                        // Make sure this line will never be removed during minification for having "no effect".
                        domFigure._ckHack = domFigure.offsetHeight;
                        domFigure.style.display = originalDisplay;
                    });
                }
                model.enqueueChange({ isUndoable: false }, writer => {
                    writer.setAttribute('uploadStatus', 'uploading', imageElement);
                });
                return promise;
            })
                .then(data => {
                model.enqueueChange({ isUndoable: false }, writer => {
                    const imageElement = imageUploadElements.get(loader.id);
                    writer.setAttribute('uploadStatus', 'complete', imageElement);
                    this.fire('uploadComplete', { data, imageElement });
                });
                clean();
            })
                .catch(error => {
                // If status is not 'error' nor 'aborted' - throw error because it means that something else went wrong,
                // it might be generic error and it would be real pain to find what is going on.
                if (loader.status !== 'error' && loader.status !== 'aborted') {
                    throw error;
                }
                // Might be 'aborted'.
                if (loader.status == 'error' && error) {
                    notification.showWarning(error, {
                        title: t('Upload failed'),
                        namespace: 'upload'
                    });
                }
                // Permanently remove image from insertion batch.
                model.enqueueChange({ isUndoable: false }, writer => {
                    writer.remove(imageUploadElements.get(loader.id));
                });
                clean();
            });
            function clean() {
                model.enqueueChange({ isUndoable: false }, writer => {
                    const imageElement = imageUploadElements.get(loader.id);
                    writer.removeAttribute('uploadId', imageElement);
                    writer.removeAttribute('uploadStatus', imageElement);
                    imageUploadElements.delete(loader.id);
                });
                fileRepository.destroyLoader(loader);
            }
        }
    
  • Status changed to Needs review 12 months ago
  • ๐Ÿ‡จ๐Ÿ‡ณChina lawxen

    Marked as 'needs review' and Backup patch of the MR

  • It failed coding standards

  • ๐Ÿ‡จ๐Ÿ‡ณChina lawxen

    @cilefen

    It failed coding standards

    Fixed ๐Ÿ˜Š

  • Status changed to Needs work 12 months ago
  • ๐Ÿ‡บ๐Ÿ‡ธUnited States smustgrave

    Moving to NW for the test coverage

Production build 0.71.5 2024