Search code examples
node.jsreactjsckeditorckeditor5

Need help uploading images via CKEditor5 in a MERN stack app


I've seen several people ask this question before, but none have the issue I have.

I've been using CKEditor for my web app for a while with no issues, but I recently noticed that image uploads don't work. When I tried uploading, I got this error in the browser:

filerepository-no-upload-adapter 
Read more: https://ckeditor.com/docs/ckeditor5/latest/support/error-codes.html#error-filerepository-no-upload-adapter

So I went and checked the docs, and went ahead and npm installed @ckeditor/ckeditor5-upload.

Thus, I imported the Simple Upload Adapter:

import { SimpleUploadAdapter } from '@ckeditor/ckeditor5-upload';

And my editor:

<CKEditor
              editor={ClassicEditor}
              data={initialData}
              plugins={[ SimpleUploadAdapter]}
              config={{
                simpleUpload: {
                  uploadUrl: `${process.env.REACT_APP_API_URL_LOCAL}/api/images/upload`
                }
              }}
              // etc etc

If you're curious, I'm trying to upload the images to Cloudinary with my backend controller:

exports.uploadImage = async (req, res) => {
  try {
    const result = await new Promise((resolve, reject) => {
      const uploadStream = cloudinary.uploader.upload_stream(
        { resource_type: 'image' },
        (error, result) => {
          if (error) reject(error);
          else resolve(result);
        }
      );

      streamifier.createReadStream(req.file.buffer).pipe(uploadStream);
    });

    // Respond with the URL of the uploaded image
    res.json({ default: result.url });
  } catch (err) {
    console.log("Error uploading image: ", err);
    res.status(500).send(err);
  }
};

I have tested this code and can confirm that there are no issues there.

However, the issue I'm facing is in my client-side compiler, caused by the SimpleUploadAdapter import, which reads as follows:

./node_modules/@ckeditor/ckeditor5-ui/theme/components/colorselector/colorselector.css (./node_modules/css-loader/dist/cjs.js??ref--6-oneOf-3-1!./node_modules/postcss-loader/src??postcss!./node_modules/@ckeditor/ckeditor5-ui/theme/components/colorselector/colorselector.css)
Module not found: Can't resolve './@ckeditor/ckeditor5-ui/theme/mixins/_dir.css' in 'C:\Users\Owner\Documents\Scenario\client\node_modules\@ckeditor\ckeditor5-ui\theme\components\colorselector'

I have never run into this issue before and am very confused as to what to do. Why is the SimpleUploadAdapter trying to find _dir.css? I run into the same issue when I try to import Base64UploadAdapter from ckeditor5-upload.

I've tried deleting my package-lock.json and node_modules folder, and reinstalling all my packages (just to make sure nothing got corrupted while installing), and that didn't help at all.

Additional information: I created my app via Create React App, thus I do not have a webpack. Do I need to mess around with react-app-rewired to modify the underlying webpack configuration?

Also, here are my ckeditor versions in my package.json, in case this may be useful:

 "dependencies": {
    "@ckeditor/ckeditor5-build-classic": "^39.0.1",
    "@ckeditor/ckeditor5-react": "^6.1.0",
    "@ckeditor/ckeditor5-upload": "^39.0.1",
    //...

And finally, since the error stemmed from /node_modules/@ckeditor/.../components/colorselector, here's my colorselector.css from my node modules:

/*
 * Copyright (c) 2003-2023, CKSource Holding sp. z o.o. All rights reserved.
 * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
 */

@import "@ckeditor/ckeditor5-ui/theme/mixins/_dir.css";

.ck.ck-color-selector {
    /* View fragment with color grids. */
    & .ck-color-grids-fragment {
        & .ck-button.ck-color-selector__remove-color,
        & .ck-button.ck-color-selector__color-picker {
            display: flex;
            align-items: center;

            @mixin ck-dir rtl {
                justify-content: flex-start;
            }
        }
    }

    /* View fragment with a color picker. */
    & .ck-color-picker-fragment {
        & .ck.ck-color-selector_action-bar {
            display: flex;
            flex-direction: row;
            justify-content: space-around;

            & .ck-button-save,
            & .ck-button-cancel {
                flex: 1
            }
        }
    }
}

Any help would be appreciated--I'm at a bit of a loss right now, since most of the guides online are for PHP or Angular


Solution

  • Figured it out:

    import { CKEditor } from '@ckeditor/ckeditor5-react';
    import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
    import { CKFinderUploadAdapter, MediaEmbed } from '@ckeditor/ckeditor5-build-classic';
    
    <CKEditor
        editor={ClassicEditor}
        data={initialData}
        plugins={[CKFinderUploadAdapter, MediaEmbed]}
        config={{
            ckfinder: {
                uploadUrl: `${process.env.REACT_APP_API_URL_LOCAL}/api/images/upload`
            },
            mediaEmbed: {
                elementName: 'iframe',
            }
        }}
    
    //etc