React rich text editor

there are many rich text editors, such as draft.js, quill.js, slate.js, etc.

quill is a good choice for me, because it is easy to use and opensource.

in the React, we can use react-quill.

basic use

the example code is:

import ReactQuill from "react-quill";
import "react-quill/dist/quill.snow.css";

const editorModules = {
  toolbar: [
    [{ header: [1, 2, false] }],
    ["bold", "italic", "underline", "strike", "blockquote"],
    [
      { list: "ordered" },
      { list: "bullet" },
      { indent: "-1" },
      { indent: "+1" },
    ],
    ["link", "image", "video"],
    ["clean"],
  ],
};

<ReactQuill theme="snow" modules={editorModules} />;

upload image

image and video is pasted link in above example.
if we want upload image, we can use https://github.com/noeloconnell/quill-image-uploader:

import ReactQuill, {Quill } from "react-quill";
...
import ImageUploader from "quill-image-uploader";

const editorModules = {
  toolbar: [
    ...
  ],
  imageUploader: {
    upload: (file) => {
      return new Promise((resolve, reject) => {
        const formData = new FormData();
        formData.append("image", file);
        fetch(`${your api}`, {
          method: "POST",
          body: formData,
        })
          .then((response) => response.json())
          .then((result) => {
            console.log(result);
            resolve(`${result.url}`);
          })
          .catch((error) => {
            reject("Upload failed");
            console.error("Error:", error);
          });
      });
    },
  },
};

backend api in python flask:

@bp.route('/', methods=('POST', ))
def upload_view():
    """上传图片
    """
    file = request.files['file']
    name, ext = os.path.splitext(file.filename)
    filename = name + datetime.now().strftime("%Y%m%d%H%M%S%f") + ext
    file.save(os.path.join(FILE_DIRECTORY, filename))
    return jsonify({"url": f"{bp.url_prefix}{filename}"})

upload image and video

what about video, we can use ngx-quill-upload, this library can handle both image and video.

...
import { ImageHandler, VideoHandler } from "ngx-quill-upload";

Quill.register("modules/videoHandler", VideoHandler);
Quill.register("modules/imageHandler", ImageHandler);

const uploadFile = (file) => {
  return new Promise((resolve, reject) => {
    const formData = new FormData();
    formData.append("file", file);
    fetch(`${your api}`, {
      method: "POST",
      body: formData,
    })
      .then((response) => response.json())
      .then((result) => {
        console.log(result);
        resolve(`${result.url}`);
      })
      .catch((error) => {
        reject("Upload failed");
        console.error("Error:", error);
      });
  });
};

const editorModules = {
  toolbar: [
    ...
  ],
  imageHandler: {
    upload: uploadFile,
  },
  videoHandler: {
    upload: uploadFile,
  },
}

...

backend code is same as above.