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.
yarn strapi generate
and press "Enter”.wysiwyg
for the plugin name and hit the enter key again."Your Project's name"/config/plugins.js
1module.exports = {
2// ...
3'wysiwyg': {
4enabled: true,
5resolve: './src/plugins/wysiwyg'
6},
7// ...
8};
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.
src/plugins/wysiwyg
and install react-quill: 1 #using yarn
2 yarn add react-quill
3
4 #using npm
5 npm install react-quill
Let's launch our server in --watch-admin
to run the front-end development tool.
1# Go back to the Strapi root folder;
2cd ../../..
3# and run;
4yarn develop --watch-admin
Create Components:
In this part we will create only two components:
Let’s Create a WYSIWYG Wrapper:
.src\plugins\wysiwyg\admin\src\components\Wysiwyg\index.js
file.useLibrary
hook.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.
1 import React, { useState } from 'react';
2 import {
3 Button,
4 Stack,
5 Flex,
6 Field,
7 FieldLabel,
8 } from '@strapi/design-system';
9 import { useLibrary, prefixFileUrlWithBackendUrl } from '@strapi/helper-plugin';
10 import Editor from '../QuillEditor';
11
12 const Wysiwyg = ({ name, onChange, value }) => {
13 const [showMediaLibDialog, setShowMediaLibDialog] = useState(false);
14 const { components } = useLibrary();
15 const MediaLibDialog = components['media-library'];
16
17 const handleToggleMediaLibDialog = () => {
18 setShowMediaLibDialog(!showMediaLibDialog);
19 };
20
21 const handleSelectAssets = (files) => {
22 const formattedFiles = files.map(file => ({
23 alt: file.alternativeText || file.name,
24 url: prefixFileUrlWithBackendUrl(file.url),
25 mime: file.mime,
26 }));
27 const images = formattedFiles.map(image => `<image src='${image.url}' alt='${image.alt}'>`).join();
28 onChange({
29 target: {
30 name: name,
31 value: value + images
32 }
33 });
34 handleToggleMediaLibDialog();
35 };
36
37 return (
38 <div>
39 <Field name={name}>
40 <Button variant="secondary" onClick={handleToggleMediaLibDialog}>
41 MediaLib
42 </Button>
43 <Stack size={2} padding={2}>
44 <Flex>
45 <FieldLabel>{name}</FieldLabel>
46 </Flex>
47 <Editor name={name} onChange={onChange} value={value} />
48 </Stack>
49 {
50 showMediaLibDialog
51 &&
52 <MediaLibDialog
53 onClose={handleToggleMediaLibDialog}
54 onSelectAssets={handleSelectAssets}
55 />
56 }
57 </Field>
58 </div>
59 );
60 };
61 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:
.src\plugins\wysiwyg\admin\src\components\QuillEditor\index.js
file containing the following:1 import React from 'react';
2 import ReactQuill from 'react-quill';
3 import 'react-quill/dist/quill.snow.css';
4 const Editor = ({ onChange, name, value }) => {
5
6 const modules = {
7 toolbar: [
8 [{ 'header': '1' }, { 'header': '2' }, { 'font': [] }],
9 [{ size: [] }],
10 ['bold', 'italic', 'underline', 'strike', 'blockquote'],
11 [{ 'list': 'ordered' }, { 'list': 'bullet' }, { 'indent': '-1' }, { 'indent': '+1' }],
12 ['link'],
13 ['clean']
14 ],
15 }
16 return (
17 <ReactQuill
18 theme="snow"
19 value={value}
20 modules={modules}
21 onChange={(content, event, editor) => {
22 onChange({ target: { name, value: content } });
23 }}
24 />
25 );
26 };
27 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:
.src\plugins\wysiwyg\admin\src\components\QuillEditor\index.js
with the following code:1 import pluginPkg from '../../package.json';
2 import pluginId from './pluginId';
3 import Initializer from './components/Initializer';
4 import Wysiwyg from './components/Wysiwyg';
5
6 const name = pluginPkg.strapi.name;
7
8 export default {
9 register(app) {
10 app.registerPlugin({
11 id: pluginId,
12 initializer: Initializer,
13 isReady: false,
14 name,
15 });
16 app.addFields({type: 'wysiwyg', Component: Wysiwyg});
17 },
18 };
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.
yarn build
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:
1 import React from 'react';
2 import {
3 Stack,
4 Flex,
5 Field,
6 FieldLabel,
7 } from '@strapi/design-system';
8 import Editor from '../QuillEditor';
9
10 const Wysiwyg = ({ name, onChange, value }) => {
11 return (
12 <div>
13 <Field name={name}>
14 <Stack size={2} padding={2}>
15 <Flex>
16 <FieldLabel>{name}</FieldLabel>
17 </Flex>
18 <Editor name={name} onChange={onChange} value={value} />
19 </Stack>
20 </Field>
21 </div>
22 );
23 };
24
25 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:
1 const modules = {
2 toolbar: [
3 [{ 'header': '1'}, {'header': '2'}, { 'font': [] }],
4 [{size: []}],
5 ['bold', 'italic', 'underline','strike', 'blockquote'],
6 [{'list': 'ordered'}, {'list': 'bullet'}, {'indent': '-1'}, {'indent': '+1'}],
7 ['link', 'image'],
8 ['clean']
9 ],
10 }
yarn build
yarn develop
Link to Source Code:
That's it. You should be able to use Quill editor now!
Maxime started to code in 2015 and quickly joined the Growth team of Strapi. He particularly likes to create useful content for the awesome Strapi community. Send him a meme on Twitter to make his day: @MaxCastres