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.
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
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!