Sign in
Log inSign up
How to change the default WYSIWYG to Quill Editor

How to change the default WYSIWYG to Quill Editor

Shada Wehbe's photo
Shada Wehbe
·Mar 10, 2022·

6 min read

Many of you don't want to settle for the default WYSIWYG editor in Strapi. This is why you are looking to change the current editor. With any luck, you will come across the excellent tutorial from Soupette, which teaches you how to change the default editor to CKEditor.

It turns out that, according to our analytics and the number of requests on our slack, this tutorial is highly requested and an important resource for you or your team. It was obvious to offer a second tutorial allowing you, this time, to use the Quill editor, more specifically react-quill.

To do this, we will create a new Field in the administration panel! Nothing very complicated and it won't take you more than 5 min.

Let's dive in!

Note: You should know that quill is an HTML editor, not a Markdown one. Be careful when changing editors on an existing app. If you have existing content in Markdown then you will need to convert it to HTML.

The first thing to do is to take an existing Strapi project. For my part, I will simply create a new one.

Using yarn:

yarn create strapi-app strapi-quill-editor --quickstart

Or npm:

npx create-strapi-app@latest strapi-quill-editor --quickstart

Now, I will create my admin user and a very simple collection type with a rich text field.

Quill-editor-Strapi

Quill-editor-Strapi

Quill-editor-Strapi

You can shut down your Strapi server in the terminal by pressing Ctrl+C.

As I said earlier, we will create a new field in the administration panel to change our editor.

  • Start by generating a new plugin, yarn strapitime, generate and press "Enter”.
  • An interactive shell will show. Select “Plugin” from the list of available options, then press “Enter”.
  • The shell prompts you to enter a plugin name, type wysiwyg for the plugin name and hit the enter key again.
  • Your shell will generate a piece of code like below. Copy that to your plugins configurations file, which you can find in "Your Project's name"/config/plugins.js
module.exports = {
// ...
'wysiwyg': {
enabled: true,
resolve: './src/plugins/wysiwyg'
},
// ...
};

Tip: If the plugins.js file is not available in that directory create it yourself and make sure the file naming is the same otherwise your plugin will not work.

  • Dive into this plugin folder cd src/plugins/wysiwyg and install react-quill:
    #using yarn
    yarn add react-quill

    #using npm
    npm install react-quill

Let's launch our server in --watch-admin to run the front-end development tool.

# Go back to the Strapi root folder;
cd ../../..
# and run;
yarn develop --watch-admin

Create Components:

In this part we will create only two components:

  • Wysiwyg, which will wrap the QuillEditor alongside the Strapi MediaLib, for easy and efficient media uploads to our QuillEditor.
  • QuillEditor, which will be the implementation of the new WYSIWYG.

Let’s Create a WYSIWYG Wrapper:

  • Create a .src\plugins\wysiwyg\admin\src\components\Wysiwyg\index.js file.
  • Before you paste the code provided below, here is what you need to know about our WYSIWYG wrapper:
    • Our WYSIWYG editor makes use of the Strapi MediaLib to upload files to it instead of its default Quill Editor media uploader module.
    • To achieve the mentioned functionality, we destructure the Strapi MediaLib component from the useLibrary hook.
    • We will then access our Strapi MediaLib right from our Quill Editor using a button.
    • When clicked, this button opens up a Strapi MediaLib Dialog, giving you access to all the media files you have uploaded to Strapi MediaLib right at your disposal.

Let’s move on to copying and pasting. Copy the code below into your index.js file.

    import React, { useState } from 'react';
    import {
        Button,
        Stack,
        Flex,
        Field,
        FieldLabel,
    } from '@strapi/design-system';
    import { useLibrary, prefixFileUrlWithBackendUrl } from '@strapi/helper-plugin';
    import Editor from '../QuillEditor';

    const Wysiwyg = ({ name, onChange, value }) => {
        const [showMediaLibDialog, setShowMediaLibDialog] = useState(false);
        const { components } = useLibrary();
        const MediaLibDialog = components['media-library'];

        const handleToggleMediaLibDialog = () => {
            setShowMediaLibDialog(!showMediaLibDialog);
        };

        const handleSelectAssets = (files) => {
            const formattedFiles = files.map(file => ({
                alt: file.alternativeText || file.name,
                url: prefixFileUrlWithBackendUrl(file.url),
                mime: file.mime,
            }));
            const images = formattedFiles.map(image => `<image src='${image.url}' alt='${image.alt}'>`).join();
            onChange({
                target: {
                    name: name,
                    value: value + images
                }
            });
            handleToggleMediaLibDialog();
        };

        return (
            <div>
                <Field name={name}>
                    <Button variant="secondary" onClick={handleToggleMediaLibDialog}>
                        MediaLib
                    </Button>
                    <Stack size={2} padding={2}>
                        <Flex>
                            <FieldLabel>{name}</FieldLabel>
                        </Flex>
                        <Editor name={name} onChange={onChange} value={value} />
                    </Stack>
                    {
                        showMediaLibDialog
                            &&
                        <MediaLibDialog
                            onClose={handleToggleMediaLibDialog}
                            onSelectAssets={handleSelectAssets}
                        />
                    }
                </Field>
            </div>
        );
    };
    export default Wysiwyg;

As you can see we are importing our Editor from ../QuillEditor. It doesn't exist yet, so let's create it.

Create the Editor:

  • Create a .src\plugins\wysiwyg\admin\src\components\QuillEditor\index.js file containing the following:
    import React from 'react';
    import ReactQuill from 'react-quill';
    import 'react-quill/dist/quill.snow.css';
    const Editor = ({ onChange, name, value }) => {

        const modules = {
            toolbar: [
                [{ 'header': '1' }, { 'header': '2' }, { 'font': [] }],
                [{ size: [] }],
                ['bold', 'italic', 'underline', 'strike', 'blockquote'],
                [{ 'list': 'ordered' }, { 'list': 'bullet' }, { 'indent': '-1' }, { 'indent': '+1' }],
                ['link'],
                ['clean']
            ],
        }
        return (
            <ReactQuill
                theme="snow"
                value={value}
                modules={modules}
                onChange={(content, event, editor) => {
                    onChange({ target: { name, value: content } });
                }}
            />
        );
    };
    export default Editor;

Since the goal of this plugin is to override the current WYSIWYG, we don't want it to be displayed in the administration panel but we need it to register our new field.

To do so, we will simply modify the front-end entry point of our plugin:

  • Replace the content of your .src\plugins\wysiwyg\admin\src\components\QuillEditor\index.js with the following code:
    import pluginPkg from '../../package.json';
    import pluginId from './pluginId';
    import Initializer from './components/Initializer';
    import Wysiwyg from './components/Wysiwyg';

    const name = pluginPkg.strapi.name;

    export default {
      register(app) {
        app.registerPlugin({
          id: pluginId,
          initializer: Initializer,
          isReady: false,
          name,
        });
        app.addFields({type: 'wysiwyg', Component: Wysiwyg});
      },
    };

Here, we are adding the WYSIWYG component and registering it as a new field.

If you already know Quill editor, you might have noticed that I didn't import the image module. It is because we are using a button for the MediaLib. Instead of having to click the image button to import all your images, you can simply upload all your assets in the MediaLib and then add them directly to your content using the button on the left side.

  • Now you can stop your server by pressing Ctrl+C and build your admin by running the following command:

yarn build

  • Run your Strapi app:

yarn develop

Quill-editor-Strapi

Quill-editor-Strapi

However, if you don't want to use the MediaLib, you simply need to paste the code below in your wrapper, here is the code of the wrapper without the MediaLib:

    import React from 'react';
    import {
        Stack,
        Flex,
        Field,
        FieldLabel,
    } from '@strapi/design-system';
    import Editor from '../QuillEditor';

    const Wysiwyg = ({ name, onChange, value }) => {
        return (
            <div>
                <Field name={name}>
                    <Stack size={2} padding={2}>
                        <Flex>
                            <FieldLabel>{name}</FieldLabel>
                        </Flex>
                        <Editor name={name} onChange={onChange} value={value} />
                    </Stack>
                </Field>
            </div>
        );
    };

    export default Wysiwyg;

Then, you simply need to add the image module in the Quill editor by updating the ./plugins/wysiwyg/admin/src/components/QuillEditor/index.js file:

    const modules = {
       toolbar: [
         [{ 'header': '1'}, {'header': '2'}, { 'font': [] }],
         [{size: []}],
         ['bold', 'italic', 'underline','strike', 'blockquote'],
         [{'list': 'ordered'}, {'list': 'bullet'}, {'indent': '-1'}, {'indent': '+1'}],
         ['link', 'image'],
         ['clean']
       ],
     }
  • Build again your admin by running the following command:

yarn build

  • Run your Strapi app:

yarn develop

Link to Source Code:

That's it. You should be able to use Quill editor now!