react-quill icon indicating copy to clipboard operation
react-quill copied to clipboard

so many features don't show styles in html

Open simon-zhangmuye opened this issue 2 years ago • 24 comments

heading styles blockquote code align indent list image

simon-zhangmuye avatar Jun 03 '22 04:06 simon-zhangmuye

@simon-zhangmuye Did you find a solution to this problem?

EDIT: I found out that you need to add the css class "ql-editor" on the root component of the html block, where you quill html code

maxstue avatar Aug 04 '22 09:08 maxstue

@maxstue Thanks. I will take a look at it.

simon-zhangmuye avatar Aug 10 '22 15:08 simon-zhangmuye

@maxstue image image

simon-zhangmuye avatar Aug 10 '22 15:08 simon-zhangmuye

@simon-zhangmuye I'm sorry to hear that it didn't help. In my project it helped fixing it for deeper lists. I hope you find a solution :)

maxstue avatar Aug 11 '22 18:08 maxstue

@maxstue Thanks.

simon-zhangmuye avatar Aug 12 '22 03:08 simon-zhangmuye

@simon-zhangmuye last idea: upgrade to version 2.0, which came out a couple of days a ago

maxstue avatar Aug 12 '22 05:08 maxstue

@maxstue @zenoamaro Thank you maxtue. I face a problem which cannot be solved by quill. When I upload an image to backend and get a URL, I insert it to the HTML string.

quill.insertEmbed(range.index, "image", url, Quill.sources.USER);
quill.formatText(range.index + 1, 1, {
  height: "auto",
  width: "auto",
});

lALPGP5wKtIuHO_NAdPNBkI_1602_467 Here is what it looks like. But when I try to resize the image, I can only resize it a little bit since when the size of image changes, it will rerender the editor. The size of the image can be changed but only a little bit. lALPGQWLKBu_3onNAbzNBio_1578_444 Do you know how to fix this issue? This issue has been bothering me for a long time.

simon-zhangmuye avatar Aug 12 '22 06:08 simon-zhangmuye

@simon-zhangmuye We had the exact same problem, after we upgraded to React 18. The fix was to upgrade to react-quill v2 (non beta). Luckily the fix for us was that easy, because the editor was acting really weird with non React 18 support.

maxstue avatar Aug 12 '22 06:08 maxstue

@maxstue I upgrade to react-quill v2 and use React 18. After uploading the image, the editor disappears. image

simon-zhangmuye avatar Aug 12 '22 07:08 simon-zhangmuye

Here is my quill editor code.

import React, { useState, useRef } from "react";
import ReactQuill, { Quill } from "react-quill";
import * as Emoji from "quill-emoji";
import "react-quill/dist/quill.snow.css";
import "quill-emoji/dist/quill-emoji.css";

import ResizeModule from "@ssumo/quill-resize-module";
import { getDownloadURL, ref, uploadBytes } from "firebase/storage";
import { message } from "antd";
import { uuidv4 } from "@firebase/util";
import { myStorage } from "../firebaseConfig";
import Compressor from "compressorjs";


Quill.register("modules/resize", ResizeModule);
Quill.register("modules/emoji", Emoji);

function QuillEditor() {
  const [value, setValue] = useState("");
  let quillRef = useRef();

  function fileCompress(file) {
    return new Promise((resolve, reject) => {
      new Compressor(file, {
        quality: 0.5,
        maxWidth: 1000,
        maxHeight: 1000,
        success(file) {
          return resolve({ success: true, file: file });
        },
        error(err) {
          return resolve({ success: false, file: file });
        },
      });
    });
  }

  function imageUploadHandler() {
    const input = document.createElement("input");
    input.setAttribute("type", "file");
    input.setAttribute("accept", "image/png, image/gif, image/jpeg");
    input.onchange = async (e) => {
      const file = e.target.files[0];
      const maxSize = 1024 * 1024 * 5;
      const minSize = 1024 * 2;
      if (file.size > maxSize || file.size < minSize) {
        message.error("Uploaded image size is from 2KB to 5MB!");
        return;
      }
      const fileReader = new FileReader();
      fileReader.onloadend = () => {
        if (fileReader.result) {
          const view = new DataView(fileReader.result);
          const first4Byte = view.getUint32(0, false);
          const hexValue = Number(first4Byte).toString(16);
          if (!["ffd8ffe0", "89504e47", "47494638"].includes(hexValue)) {
            message.error("Image type are not PNG, GIF, JEPG!");
          }
        }
      };
      fileReader.readAsArrayBuffer(file);
      const compressState = await fileCompress(file);
      console.log(compressState);
      if (compressState.success) {
        const uuid = uuidv4();
        const imageRef = ref(myStorage, uuid + "/" + file.name);
        uploadBytes(imageRef, compressState.file, { contentType: file.type })
          .then((res) => {
            getDownloadURL(res.ref).then((url) => {
              const quill = quillRef.getEditor();
              const range = quill.getSelection(true);
              quill.insertEmbed(range.index, "image", url, Quill.sources.USER);
              quill.formatText(range.index, range.index + 1, {
                height: "auto",
                width: "auto",
              });
            });
          })
          .catch((error) => {
            message.error(error);
          });
      }
    };
    input.click();
  }

  const toolbarOptions = {
    container: [
      [
        { header: [1, 2, 3, 4, 5, 6, false] },
        "bold",
        "italic",
        "underline",
        "strike",
        { color: [] },
        { background: [] },
        "emoji",
        "blockquote",
        "code-block",
      ], // toggled buttons
      [{ align: [] }, { indent: "-1" }, { indent: "+1" }], // superscript/subscript
      [{ list: "ordered" }, { list: "bullet" }], // outdent/indent
      ["image", "video"],
      ["clean"], // remove formatting button
    ],
    handlers: {
      image: imageUploadHandler,
    },
  };

  const modules = {
    toolbar: toolbarOptions,
    "emoji-toolbar": true,
    "emoji-textarea": false,
    "emoji-shortname": true,
    resize: {
      locale: {
        altTip: "hold alt to resize",
        floatLeft: "left",
        floatRight: "right",
        center: "center",
        restore: "restore",
      },
    },
  };

  return (
    <div className="flex justify-center divide-x-[90px] divide-white">
      <ReactQuill
        theme="snow"
        ref={(el) => {
          quillRef = el;
        }}
        className="w-[500px] h-[300px]"
        value={value}
        onChange={setValue}
        modules={modules}
      />
      <div className="ql-snow">
        <div
          className="ql-editor mt-16 w-[500px] h-[300px]"
          dangerouslySetInnerHTML={{ __html: value }}
        />
      </div>
      <div className="w-[500px] h-[300px] overflow-y-auto">{value}</div>
    </div>
  );
}

export default QuillEditor;

simon-zhangmuye avatar Aug 12 '22 07:08 simon-zhangmuye

@simon-zhangmuye Your modules and in you case your toolbaroptions should be wrapped inside of a "usememo" with "[]" or "[quillRef]" as dependency

if your editor just disappears, it sounds like it is crashing. Are there any errors in the browser logs?

maxstue avatar Aug 12 '22 08:08 maxstue

@maxstue It gives me this warning. @zenoamaro image Not just image, the editor crashes when I input any content. image I remove custom image handlers, then it works. image Do you know why this happens?

simon-zhangmuye avatar Aug 12 '22 14:08 simon-zhangmuye

@maxstue I am trying useMemo now and see if it works.

simon-zhangmuye avatar Aug 12 '22 14:08 simon-zhangmuye

@maxstue It works. Thank you so much maxstue. You are my hero.

simon-zhangmuye avatar Aug 12 '22 14:08 simon-zhangmuye

@simon-zhangmuye Glad i could help :) I struggled a lot with this myself so, maybe the docs should include more information like this.

maxstue avatar Aug 12 '22 19:08 maxstue

@maxstue Hey maxstue, you have this issue. Upload an image and then delete it, and the quillRef becomes null and crashes

simon-zhangmuye avatar Aug 12 '22 19:08 simon-zhangmuye

@simon-zhangmuye I never had that issue. But I read a couple of days ago that you only should use ".getEditor()" if you want to read data and use ".editor" if you want to read and/or manipulate data. If that doesn't help try to log the state of quill before/during and after the call to firebase and to see what happens.

maxstue avatar Aug 12 '22 20:08 maxstue

@maxstue It works. Thank you so much.

simon-zhangmuye avatar Aug 12 '22 20:08 simon-zhangmuye

@maxstue Hey maxstue. Sorry to bother you again. I use useState to control the value of Quill and when I try to resize the image or align it to a different position. The value of Quill doesn't change until I input a letter. Do you know how to fix this issue? Thanks a lot. image

https://www.vidline.com/share/V0X85HL5N6/9090c5e86ef8332ec8ae9a08f5113032

simon-zhangmuye avatar Aug 14 '22 22:08 simon-zhangmuye

I type enter then the value updates. Then image moves to the center.

simon-zhangmuye avatar Aug 14 '22 22:08 simon-zhangmuye

I find out a way to solve this issue. Try another plugin quill-image-resize-module-react and it works.

simon-zhangmuye avatar Aug 15 '22 02:08 simon-zhangmuye

@simon-zhangmuye Sorry for the late response. It sounds like the change is not properly triggering a usestate update 🤔 But glad you found a solution.

Quill is not the best editor for react compatibility, maybe take alook at metas new react editor lexical. It is still in alpha but it looks promising. Or tiptap looks great as well

maxstue avatar Aug 15 '22 19:08 maxstue

Mine worked after wrapping it with an element that have ql-snow class <main className="ql-snow"> <div className="ql-editor">{parse(htmlcontent)}</div> </main>

alicalimli avatar Oct 13 '23 12:10 alicalimli

For me, the bellow code is working fully perfectly including all styles.

<div className="ql-snow w-full mt-16 "> <strong>Editor Response:</strong> <div className="ql-editor" dangerouslySetInnerHTML={{__html: value}} /> </div>

shahriarsajeeb avatar Dec 22 '23 19:12 shahriarsajeeb